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