Differences Between: [Versions 311 and 402] [Versions 400 and 402] [Versions 401 and 402]
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 provider tests. 19 * 20 * @package block_comments 21 * @copyright 2018 Shamim Rezaie <shamim@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 namespace block_comments\privacy; 25 26 use core_privacy\local\metadata\collection; 27 use block_comments\privacy\provider; 28 use core_privacy\local\request\approved_userlist; 29 use stdClass; 30 31 defined('MOODLE_INTERNAL') || die(); 32 33 /** 34 * Privacy provider test for block_comments. 35 * 36 * @copyright 2018 Shamim Rezaie <shamim@moodle.com> 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 */ 39 class provider_test extends \core_privacy\tests\provider_testcase { 40 41 /** @var stdClass A student who is only enrolled in course1. */ 42 protected $student1; 43 44 /** @var stdClass A student who is only enrolled in course2. */ 45 protected $student2; 46 47 /** @var stdClass A student who is enrolled in both course1 and course2. */ 48 protected $student12; 49 50 /** @var stdClass A test course. */ 51 protected $course1; 52 53 /** @var stdClass A test course. */ 54 protected $course2; 55 56 protected function setUp(): void { 57 global $DB; 58 59 $this->resetAfterTest(); 60 $this->setAdminUser(); 61 62 // Create courses. 63 $generator = $this->getDataGenerator(); 64 $this->course1 = $generator->create_course(); 65 $this->course2 = $generator->create_course(); 66 67 // Create and enrol students. 68 $this->student1 = $generator->create_user(); 69 $this->student2 = $generator->create_user(); 70 $this->student12 = $generator->create_user(); 71 72 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 73 $generator->enrol_user($this->student1->id, $this->course1->id, $studentrole->id); 74 $generator->enrol_user($this->student2->id, $this->course2->id, $studentrole->id); 75 $generator->enrol_user($this->student12->id, $this->course1->id, $studentrole->id); 76 $generator->enrol_user($this->student12->id, $this->course2->id, $studentrole->id); 77 78 // Comment block on course pages. 79 $block = $this->add_comments_block_in_context(\context_course::instance($this->course1->id)); 80 $block = $this->add_comments_block_in_context(\context_course::instance($this->course2->id)); 81 } 82 83 /** 84 * Posts a comment on a given context. 85 * 86 * @param string $text The comment's text. 87 * @param \context $context The context on which we want to put the comment. 88 */ 89 protected function add_comment($text, \context $context) { 90 $args = new \stdClass; 91 $args->context = $context; 92 $args->area = 'page_comments'; 93 $args->itemid = 0; 94 $args->component = 'block_comments'; 95 $args->linktext = get_string('showcomments'); 96 $args->notoggle = true; 97 $args->autostart = true; 98 $args->displaycancel = false; 99 $comment = new \comment($args); 100 101 $comment->add($text); 102 } 103 104 /** 105 * Creates a comments block on a context. 106 * 107 * @param \context $context The context on which we want to put the block. 108 * @return \block_base The created block instance. 109 * @throws \coding_exception 110 */ 111 protected function add_comments_block_in_context(\context $context) { 112 global $DB; 113 114 $course = null; 115 116 $page = new \moodle_page(); 117 $page->set_context($context); 118 119 switch ($context->contextlevel) { 120 case CONTEXT_SYSTEM: 121 $page->set_pagelayout('frontpage'); 122 $page->set_pagetype('site-index'); 123 break; 124 case CONTEXT_COURSE: 125 $page->set_pagelayout('standard'); 126 $page->set_pagetype('course-view'); 127 $course = $DB->get_record('course', ['id' => $context->instanceid]); 128 $page->set_course($course); 129 break; 130 case CONTEXT_MODULE: 131 $page->set_pagelayout('standard'); 132 $mod = $DB->get_field_sql("SELECT m.name 133 FROM {modules} m 134 JOIN {course_modules} cm on cm.module = m.id 135 WHERE cm.id = ?", [$context->instanceid]); 136 $page->set_pagetype("mod-$mod-view"); 137 break; 138 case CONTEXT_USER: 139 $page->set_pagelayout('mydashboard'); 140 $page->set_pagetype('my-index'); 141 break; 142 default: 143 throw new coding_exception('Unsupported context for test'); 144 } 145 146 $page->blocks->load_blocks(); 147 148 $page->blocks->add_block_at_end_of_default_region('comments'); 149 150 // We need to use another page object as load_blocks() only loads the blocks once. 151 $page2 = new \moodle_page(); 152 $page2->set_context($page->context); 153 $page2->set_pagelayout($page->pagelayout); 154 $page2->set_pagetype($page->pagetype); 155 if ($course) { 156 $page2->set_course($course); 157 } 158 159 $page->blocks->load_blocks(); 160 $page2->blocks->load_blocks(); 161 $blocks = $page2->blocks->get_blocks_for_region($page2->blocks->get_default_region()); 162 $block = end($blocks); 163 164 $block = block_instance('comments', $block->instance); 165 166 return $block; 167 } 168 169 /** 170 * Test for provider::get_metadata(). 171 */ 172 public function test_get_metadata() { 173 $collection = new collection('block_comments'); 174 $newcollection = provider::get_metadata($collection); 175 $itemcollection = $newcollection->get_collection(); 176 $this->assertCount(1, $itemcollection); 177 178 $link = reset($itemcollection); 179 180 $this->assertEquals('core_comment', $link->get_name()); 181 $this->assertEmpty($link->get_privacy_fields()); 182 $this->assertEquals('privacy:metadata:core_comment', $link->get_summary()); 183 } 184 185 /** 186 * Test for provider::get_contexts_for_userid() when user had not posted any comments.. 187 */ 188 public function test_get_contexts_for_userid_no_comment() { 189 $this->setUser($this->student1); 190 $coursecontext1 = \context_course::instance($this->course1->id); 191 $this->add_comment('New comment', $coursecontext1); 192 193 $this->setUser($this->student2); 194 $contextlist = provider::get_contexts_for_userid($this->student2->id); 195 $this->assertCount(0, $contextlist); 196 } 197 198 /** 199 * Test for provider::get_contexts_for_userid(). 200 */ 201 public function test_get_contexts_for_userid() { 202 $coursecontext1 = \context_course::instance($this->course1->id); 203 $coursecontext2 = \context_course::instance($this->course2->id); 204 205 $this->setUser($this->student12); 206 $this->add_comment('New comment', $coursecontext1); 207 $this->add_comment('New comment', $coursecontext1); 208 $this->add_comment('New comment', $coursecontext2); 209 210 $contextlist = provider::get_contexts_for_userid($this->student12->id); 211 $this->assertCount(2, $contextlist); 212 213 $contextids = $contextlist->get_contextids(); 214 $this->assertEqualsCanonicalizing([$coursecontext1->id, $coursecontext2->id], $contextids); 215 } 216 217 /** 218 * Test for provider::export_user_data() when the user has not posted any comments. 219 */ 220 public function test_export_for_context_no_comment() { 221 $coursecontext1 = \context_course::instance($this->course1->id); 222 $coursecontext2 = \context_course::instance($this->course2->id); 223 224 $this->setUser($this->student1); 225 $this->add_comment('New comment', $coursecontext1); 226 227 $this->setUser($this->student2); 228 229 $this->setUser($this->student2); 230 $this->export_context_data_for_user($this->student2->id, $coursecontext2, 'block_comments'); 231 $writer = \core_privacy\local\request\writer::with_context($coursecontext2); 232 $this->assertFalse($writer->has_any_data()); 233 234 } 235 236 /** 237 * Test for provider::export_user_data(). 238 */ 239 public function test_export_for_context() { 240 $coursecontext1 = \context_course::instance($this->course1->id); 241 $coursecontext2 = \context_course::instance($this->course2->id); 242 243 $this->setUser($this->student12); 244 $this->add_comment('New comment', $coursecontext1); 245 $this->add_comment('New comment', $coursecontext1); 246 $this->add_comment('New comment', $coursecontext2); 247 248 // Export all of the data for the context. 249 $this->export_context_data_for_user($this->student12->id, $coursecontext1, 'block_comments'); 250 $writer = \core_privacy\local\request\writer::with_context($coursecontext1); 251 $this->assertTrue($writer->has_any_data()); 252 } 253 254 /** 255 * Test for provider::delete_data_for_all_users_in_context(). 256 */ 257 public function test_delete_data_for_all_users_in_context() { 258 global $DB; 259 260 $coursecontext1 = \context_course::instance($this->course1->id); 261 $coursecontext2 = \context_course::instance($this->course2->id); 262 263 $this->setUser($this->student1); 264 $this->add_comment('New comment', $coursecontext1); 265 266 $this->setUser($this->student2); 267 $this->add_comment('New comment', $coursecontext2); 268 269 $this->setUser($this->student12); 270 $this->add_comment('New comment', $coursecontext1); 271 $this->add_comment('New comment', $coursecontext1); 272 $this->add_comment('New comment', $coursecontext2); 273 274 // Before deletion, we should have 3 comments in $coursecontext1 and 2 comments in $coursecontext2. 275 $this->assertEquals( 276 3, 277 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext1->id]) 278 ); 279 $this->assertEquals( 280 2, 281 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext2->id]) 282 ); 283 284 // Delete data based on context. 285 provider::delete_data_for_all_users_in_context($coursecontext1); 286 287 // After deletion, the comments for $coursecontext1 should have been deleted. 288 $this->assertEquals( 289 0, 290 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext1->id]) 291 ); 292 $this->assertEquals( 293 2, 294 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext2->id]) 295 ); 296 } 297 298 /** 299 * Test for provider::delete_data_for_all_users_in_context() when there are also comments from other plugins. 300 */ 301 public function test_delete_data_for_all_users_in_context_with_comments_from_other_plugins() { 302 global $DB; 303 304 $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 305 $instance = $assigngenerator->create_instance(['course' => $this->course1]); 306 $cm = get_coursemodule_from_instance('assign', $instance->id); 307 $assigncontext = \context_module::instance($cm->id); 308 $assign = new \assign($assigncontext, $cm, $this->course1); 309 310 // Add a comments block in the assignment page. 311 $this->add_comments_block_in_context($assigncontext); 312 313 $submission = $assign->get_user_submission($this->student1->id, true); 314 315 $options = new \stdClass(); 316 $options->area = 'submission_comments'; 317 $options->course = $assign->get_course(); 318 $options->context = $assigncontext; 319 $options->itemid = $submission->id; 320 $options->component = 'assignsubmission_comments'; 321 $options->showcount = true; 322 $options->displaycancel = true; 323 324 $comment = new \comment($options); 325 $comment->set_post_permission(true); 326 327 $this->setUser($this->student1); 328 $comment->add('Comment from student 1'); 329 330 $this->add_comment('New comment', $assigncontext); 331 332 $this->setUser($this->student2); 333 $this->add_comment('New comment', $assigncontext); 334 335 // Before deletion, we should have 3 comments in $assigncontext. 336 // One comment is for the assignment submission and 2 are for the comments block. 337 $this->assertEquals( 338 3, 339 $DB->count_records('comments', ['contextid' => $assigncontext->id]) 340 ); 341 $this->assertEquals( 342 2, 343 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $assigncontext->id]) 344 ); 345 346 provider::delete_data_for_all_users_in_context($assigncontext); 347 348 // After deletion, the comments for $assigncontext in the comment block should have been deleted, 349 // but the assignment submission comment should be left. 350 $this->assertEquals( 351 1, 352 $DB->count_records('comments', ['contextid' => $assigncontext->id]) 353 ); 354 $this->assertEquals( 355 0, 356 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $assigncontext->id]) 357 ); 358 } 359 360 /** 361 * Test for provider::delete_data_for_user(). 362 */ 363 public function test_delete_data_for_user() { 364 global $DB; 365 366 $coursecontext1 = \context_course::instance($this->course1->id); 367 $coursecontext2 = \context_course::instance($this->course2->id); 368 369 $this->setUser($this->student1); 370 $this->add_comment('New comment', $coursecontext1); 371 372 $this->setUser($this->student2); 373 $this->add_comment('New comment', $coursecontext2); 374 375 $this->setUser($this->student12); 376 $this->add_comment('New comment', $coursecontext1); 377 $this->add_comment('New comment', $coursecontext1); 378 $this->add_comment('New comment', $coursecontext2); 379 380 // Before deletion, we should have 3 comments in $coursecontext1 and 2 comments in $coursecontext2, 381 // and 3 comments by student12 in $coursecontext1 and $coursecontext2 combined. 382 $this->assertEquals( 383 3, 384 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext1->id]) 385 ); 386 $this->assertEquals( 387 2, 388 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext2->id]) 389 ); 390 $this->assertEquals( 391 3, 392 $DB->count_records('comments', ['component' => 'block_comments', 'userid' => $this->student12->id]) 393 ); 394 395 $contextlist = new \core_privacy\local\request\approved_contextlist($this->student12, 'block_comments', 396 [$coursecontext1->id, $coursecontext2->id]); 397 provider::delete_data_for_user($contextlist); 398 399 // After deletion, the comments for the student12 should have been deleted. 400 $this->assertEquals( 401 1, 402 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext1->id]) 403 ); 404 $this->assertEquals( 405 1, 406 $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext2->id]) 407 ); 408 $this->assertEquals( 409 0, 410 $DB->count_records('comments', ['component' => 'block_comments', 'userid' => $this->student12->id]) 411 ); 412 } 413 414 /** 415 * Test for provider::delete_data_for_user() when there are also comments from other plugins. 416 */ 417 public function test_delete_data_for_user_with_comments_from_other_plugins() { 418 global $DB; 419 420 $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 421 $instance = $assigngenerator->create_instance(['course' => $this->course1]); 422 $cm = get_coursemodule_from_instance('assign', $instance->id); 423 $assigncontext = \context_module::instance($cm->id); 424 $assign = new \assign($assigncontext, $cm, $this->course1); 425 426 // Add a comments block in the assignment page. 427 $this->add_comments_block_in_context($assigncontext); 428 429 $submission = $assign->get_user_submission($this->student1->id, true); 430 431 $options = new \stdClass(); 432 $options->area = 'submission_comments'; 433 $options->course = $assign->get_course(); 434 $options->context = $assigncontext; 435 $options->itemid = $submission->id; 436 $options->component = 'assignsubmission_comments'; 437 $options->showcount = true; 438 $options->displaycancel = true; 439 440 $comment = new \comment($options); 441 $comment->set_post_permission(true); 442 443 $this->setUser($this->student1); 444 $comment->add('Comment from student 1'); 445 446 $this->add_comment('New comment', $assigncontext); 447 $this->add_comment('New comment', $assigncontext); 448 449 // Before deletion, we should have 3 comments in $assigncontext. 450 // one comment is for the assignment submission and 2 are for the comments block. 451 $this->assertEquals( 452 3, 453 $DB->count_records('comments', ['contextid' => $assigncontext->id]) 454 ); 455 456 $contextlist = new \core_privacy\local\request\approved_contextlist($this->student1, 'block_comments', 457 [$assigncontext->id]); 458 provider::delete_data_for_user($contextlist); 459 460 // After deletion, the comments for the student1 in the comment block should have been deleted, 461 // but the assignment submission comment should be left. 462 $this->assertEquals( 463 1, 464 $DB->count_records('comments', ['contextid' => $assigncontext->id]) 465 ); 466 $this->assertEquals( 467 0, 468 $DB->count_records('comments', ['component' => 'block_comments', 'userid' => $this->student1->id]) 469 ); 470 } 471 472 /** 473 * Test that only users within a course context are fetched. 474 * @group qtesttt 475 */ 476 public function test_get_users_in_context() { 477 $component = 'block_comments'; 478 479 $coursecontext1 = \context_course::instance($this->course1->id); 480 $coursecontext2 = \context_course::instance($this->course2->id); 481 482 $userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component); 483 provider::get_users_in_context($userlist1); 484 $this->assertCount(0, $userlist1); 485 486 $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component); 487 provider::get_users_in_context($userlist2); 488 $this->assertCount(0, $userlist2); 489 490 $this->setUser($this->student12); 491 $this->add_comment('New comment', $coursecontext1); 492 $this->add_comment('New comment', $coursecontext2); 493 $this->setUser($this->student1); 494 $this->add_comment('New comment', $coursecontext1); 495 496 // The list of users should contain user12 and user1. 497 provider::get_users_in_context($userlist1); 498 $this->assertCount(2, $userlist1); 499 $this->assertTrue(in_array($this->student1->id, $userlist1->get_userids())); 500 $this->assertTrue(in_array($this->student12->id, $userlist1->get_userids())); 501 502 // The list of users should contain user12. 503 provider::get_users_in_context($userlist2); 504 $this->assertCount(1, $userlist2); 505 $expected = [$this->student12->id]; 506 $actual = $userlist2->get_userids(); 507 $this->assertEquals($expected, $actual); 508 } 509 510 /** 511 * Test that data for users in approved userlist is deleted. 512 */ 513 public function test_delete_data_for_users() { 514 $component = 'block_comments'; 515 516 $coursecontext1 = \context_course::instance($this->course1->id); 517 $coursecontext2 = \context_course::instance($this->course2->id); 518 519 $this->setUser($this->student12); 520 $this->add_comment('New comment', $coursecontext1); 521 $this->add_comment('New comment', $coursecontext2); 522 $this->setUser($this->student1); 523 $this->add_comment('New comment', $coursecontext1); 524 525 $userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component); 526 provider::get_users_in_context($userlist1); 527 $this->assertCount(2, $userlist1); 528 529 $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component); 530 provider::get_users_in_context($userlist2); 531 $this->assertCount(1, $userlist2); 532 533 // Convert $userlist1 into an approved_contextlist. 534 $approvedlist1 = new approved_userlist($coursecontext1, $component, $userlist1->get_userids()); 535 // Delete using delete_data_for_user. 536 provider::delete_data_for_users($approvedlist1); 537 538 // Re-fetch users in coursecontext1. 539 $userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component); 540 provider::get_users_in_context($userlist1); 541 // The user data in coursecontext1 should be deleted. 542 $this->assertCount(0, $userlist1); 543 544 // Re-fetch users in coursecontext2. 545 $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component); 546 provider::get_users_in_context($userlist2); 547 // The user data in coursecontext2 should be still present. 548 $this->assertCount(1, $userlist2); 549 } 550 551 /** 552 * Test for provider::delete_data_for_user() when there are also comments from other plugins. 553 */ 554 public function test_delete_data_for_users_with_comments_from_other_plugins() { 555 $component = 'block_comments'; 556 557 $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 558 $instance = $assigngenerator->create_instance(['course' => $this->course1]); 559 $cm = get_coursemodule_from_instance('assign', $instance->id); 560 $assigncontext = \context_module::instance($cm->id); 561 $assign = new \assign($assigncontext, $cm, $this->course1); 562 563 // Add a comments block in the assignment page. 564 $this->add_comments_block_in_context($assigncontext); 565 566 $submission = $assign->get_user_submission($this->student1->id, true); 567 568 $options = new \stdClass(); 569 $options->area = 'submission_comments'; 570 $options->course = $assign->get_course(); 571 $options->context = $assigncontext; 572 $options->itemid = $submission->id; 573 $options->component = 'assignsubmission_comments'; 574 $options->showcount = true; 575 $options->displaycancel = true; 576 577 $comment = new \comment($options); 578 $comment->set_post_permission(true); 579 580 $this->setUser($this->student1); 581 $comment->add('Comment from student 1'); 582 583 $this->add_comment('New comment', $assigncontext); 584 $this->add_comment('New comment', $assigncontext); 585 586 $userlist1 = new \core_privacy\local\request\userlist($assigncontext, $component); 587 provider::get_users_in_context($userlist1); 588 $this->assertCount(1, $userlist1); 589 590 // Convert $userlist1 into an approved_contextlist. 591 $approvedlist = new approved_userlist($assigncontext, $component, $userlist1->get_userids()); 592 // Delete using delete_data_for_user. 593 provider::delete_data_for_users($approvedlist); 594 595 // Re-fetch users in assigncontext. 596 $userlist1 = new \core_privacy\local\request\userlist($assigncontext, $component); 597 provider::get_users_in_context($userlist1); 598 // The user data in assigncontext should be deleted. 599 $this->assertCount(0, $userlist1); 600 } 601 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body