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 * Privacy tests for core_comment. 18 * 19 * @package core_comment 20 * @category test 21 * @copyright 2018 Adrian Greeve <adrian@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 namespace core_comment\privacy; 25 26 defined('MOODLE_INTERNAL') || die(); 27 global $CFG; 28 29 require_once($CFG->dirroot . '/comment/locallib.php'); 30 require_once($CFG->dirroot . '/comment/lib.php'); 31 32 use core_privacy\local\request\approved_userlist; 33 use core_privacy\tests\provider_testcase; 34 use core_privacy\tests\request\approved_contextlist; 35 36 /** 37 * Unit tests for comment/classes/privacy/policy 38 * 39 * @copyright 2018 Adrian Greeve <adrian@moodle.com> 40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 41 */ 42 class provider_test extends provider_testcase { 43 44 protected function setUp(): void { 45 $this->resetAfterTest(); 46 } 47 48 /** 49 * Check the exporting of comments for a user id in a context. 50 */ 51 public function test_export_comments() { 52 $course = $this->getDataGenerator()->create_course(); 53 $context = \context_course::instance($course->id); 54 55 $comment = $this->get_comment_object($context, $course); 56 57 $user1 = $this->getDataGenerator()->create_user(); 58 $user2 = $this->getDataGenerator()->create_user(); 59 60 // Add comments. 61 $comments = []; 62 $firstcomment = 'This is the first comment'; 63 $this->setUser($user1); 64 $comment->add($firstcomment); 65 $comments[$user1->id] = $firstcomment; 66 67 $secondcomment = 'From the second user'; 68 $this->setUser($user2); 69 $comment->add($secondcomment); 70 $comments[$user2->id] = $secondcomment; 71 72 // Retrieve comments only for user1. 73 $this->setUser($user1); 74 $writer = \core_privacy\local\request\writer::with_context($context); 75 provider::export_comments($context, 'block_comments', 'page_comments', 0, []); 76 77 $data = $writer->get_data([get_string('commentsubcontext', 'core_comment')]); 78 $exportedcomments = $data->comments; 79 80 // There is only one comment made by this user. 81 $this->assertCount(1, $exportedcomments); 82 $comment = reset($exportedcomments); 83 $this->assertEquals($comments[$user1->id], format_string($comment->content, FORMAT_PLAIN)); 84 85 // Retrieve comments from any user. 86 provider::export_comments($context, 'block_comments', 'page_comments', 0, [], false); 87 88 $data = $writer->get_data([get_string('commentsubcontext', 'core_comment')]); 89 $exportedcomments = $data->comments; 90 91 // The whole conversation is two comments. 92 $this->assertCount(2, $exportedcomments); 93 foreach ($exportedcomments as $comment) { 94 $this->assertEquals($comments[$comment->userid], format_string($comment->content, FORMAT_PLAIN)); 95 } 96 } 97 98 /** 99 * Tests the deletion of all comments in a context. 100 */ 101 public function test_delete_comments_for_all_users() { 102 global $DB; 103 104 $course1 = $this->getDataGenerator()->create_course(); 105 $course2 = $this->getDataGenerator()->create_course(); 106 107 $coursecontext1 = \context_course::instance($course1->id); 108 $coursecontext2 = \context_course::instance($course2->id); 109 110 $user1 = $this->getDataGenerator()->create_user(); 111 $user2 = $this->getDataGenerator()->create_user(); 112 113 $comment1 = $this->get_comment_object($coursecontext1, $course1); 114 $comment2 = $this->get_comment_object($coursecontext2, $course2); 115 116 $this->setUser($user1); 117 $comment1->add('First comment for user 1 on comment 1'); 118 $comment2->add('First comment for user 1 on comment 2'); 119 $this->setUser($user2); 120 $comment1->add('First comment for user 2 on comment 1'); 121 $comment2->add('First comment for user 2 on comment 2'); 122 123 // Because of the way things are set up with validation, creating an entry with the same context in a different component 124 // or comment area is a huge pain. We're just going to jam entries into the table instead. 125 $record = (object) [ 126 'contextid' => $coursecontext1->id, 127 'component' => 'block_comments', 128 'commentarea' => 'other_comments', 129 'itemid' => 2, 130 'content' => 'Comment user 1 different comment area', 131 'format' => 0, 132 'userid' => $user1->id, 133 'timecreated' => time() 134 ]; 135 $DB->insert_record('comments', $record); 136 $record = (object) [ 137 'contextid' => $coursecontext1->id, 138 'component' => 'tool_dataprivacy', 139 'commentarea' => 'page_comments', 140 'itemid' => 2, 141 'content' => 'Comment user 1 different component', 142 'format' => 0, 143 'userid' => $user1->id, 144 'timecreated' => time() 145 ]; 146 $DB->insert_record('comments', $record); 147 148 // Delete only for the first context. All records in the comments table for this context should be removed. 149 provider::delete_comments_for_all_users($coursecontext1, 'block_comments', 'page_comments', 0); 150 // No records left here. 151 $this->assertCount(0, $comment1->get_comments()); 152 // All of the records are left intact here. 153 $this->assertCount(2, $comment2->get_comments()); 154 // Check the other comment area. 155 $result = $DB->get_records('comments', ['commentarea' => 'other_comments']); 156 $this->assertCount(1, $result); 157 $data = array_shift($result); 158 $this->assertEquals('other_comments', $data->commentarea); 159 // Check the different component, same commentarea. 160 $result = $DB->get_records('comments', ['component' => 'tool_dataprivacy']); 161 $this->assertCount(1, $result); 162 $data = array_shift($result); 163 $this->assertEquals('tool_dataprivacy', $data->component); 164 } 165 166 /** 167 * Tests the deletion of all comments in a context. 168 */ 169 public function test_delete_comments_for_all_users_select() { 170 global $DB; 171 172 $course1 = $this->getDataGenerator()->create_course(); 173 $course2 = $this->getDataGenerator()->create_course(); 174 175 $coursecontext1 = \context_course::instance($course1->id); 176 $coursecontext2 = \context_course::instance($course2->id); 177 178 $user1 = $this->getDataGenerator()->create_user(); 179 $user2 = $this->getDataGenerator()->create_user(); 180 181 $comment1 = $this->get_comment_object($coursecontext1, $course1); 182 $comment2 = $this->get_comment_object($coursecontext2, $course2); 183 184 $this->setUser($user1); 185 $comment1->add('First comment for user 1 on comment 1'); 186 $comment2->add('First comment for user 1 on comment 2'); 187 $this->setUser($user2); 188 $comment1->add('First comment for user 2 on comment 1'); 189 $comment2->add('First comment for user 2 on comment 2'); 190 191 // Because of the way things are set up with validation, creating an entry with the same context in a different component 192 // or comment area is a huge pain. We're just going to jam entries into the table instead. 193 $record = (object) [ 194 'contextid' => $coursecontext1->id, 195 'component' => 'block_comments', 196 'commentarea' => 'other_comments', 197 'itemid' => 2, 198 'content' => 'Comment user 1 different comment area', 199 'format' => 0, 200 'userid' => $user1->id, 201 'timecreated' => time() 202 ]; 203 $DB->insert_record('comments', $record); 204 $record = (object) [ 205 'contextid' => $coursecontext1->id, 206 'component' => 'tool_dataprivacy', 207 'commentarea' => 'page_comments', 208 'itemid' => 2, 209 'content' => 'Comment user 1 different component', 210 'format' => 0, 211 'userid' => $user1->id, 212 'timecreated' => time() 213 ]; 214 $DB->insert_record('comments', $record); 215 216 // Delete only for the first context. All records in the comments table for this context should be removed. 217 list($sql, $params) = $DB->get_in_or_equal([0, 1, 2, 3], SQL_PARAMS_NAMED); 218 provider::delete_comments_for_all_users_select($coursecontext1, 219 'block_comments', 'page_comments', $sql, $params); 220 // No records left here. 221 $this->assertCount(0, $comment1->get_comments()); 222 // All of the records are left intact here. 223 $this->assertCount(2, $comment2->get_comments()); 224 // Check the other comment area. 225 $result = $DB->get_records('comments', ['commentarea' => 'other_comments']); 226 $this->assertCount(1, $result); 227 $data = array_shift($result); 228 $this->assertEquals('other_comments', $data->commentarea); 229 // Check the different component, same commentarea. 230 $result = $DB->get_records('comments', ['component' => 'tool_dataprivacy']); 231 $this->assertCount(1, $result); 232 $data = array_shift($result); 233 $this->assertEquals('tool_dataprivacy', $data->component); 234 } 235 236 /** 237 * Tests deletion of comments for a specified user and contexts. 238 */ 239 public function test_delete_comments_for_user() { 240 global $DB; 241 242 $course1 = $this->getDataGenerator()->create_course(); 243 $course2 = $this->getDataGenerator()->create_course(); 244 $course3 = $this->getDataGenerator()->create_course(); 245 246 $coursecontext1 = \context_course::instance($course1->id); 247 $coursecontext2 = \context_course::instance($course2->id); 248 $coursecontext3 = \context_course::instance($course3->id); 249 250 $user1 = $this->getDataGenerator()->create_user(); 251 $user2 = $this->getDataGenerator()->create_user(); 252 253 $comment1 = $this->get_comment_object($coursecontext1, $course1); 254 $comment2 = $this->get_comment_object($coursecontext2, $course2); 255 $comment3 = $this->get_comment_object($coursecontext3, $course3); 256 257 $this->setUser($user1); 258 $comment1->add('First comment for user 1'); 259 $comment2->add('User 1 comment in second comment'); 260 261 $this->setUser($user2); 262 $comment2->add('User two replied in comment two'); 263 $comment3->add('Comment three for user 2.'); 264 265 // Because of the way things are set up with validation, creating an entry with the same context in a different component 266 // or comment area is a huge pain. We're just going to jam entries into the table instead. 267 $record = (object) [ 268 'contextid' => $coursecontext1->id, 269 'component' => 'block_comments', 270 'commentarea' => 'other_comments', 271 'itemid' => 2, 272 'content' => 'Comment user 1 different comment area', 273 'format' => 0, 274 'userid' => $user1->id, 275 'timecreated' => time() 276 ]; 277 $DB->insert_record('comments', $record); 278 $record = (object) [ 279 'contextid' => $coursecontext1->id, 280 'component' => 'tool_dataprivacy', 281 'commentarea' => 'page_comments', 282 'itemid' => 2, 283 'content' => 'Comment user 1 different component', 284 'format' => 0, 285 'userid' => $user1->id, 286 'timecreated' => time() 287 ]; 288 $DB->insert_record('comments', $record); 289 290 // Delete the comments for user 1. 291 $approvedcontextlist = new approved_contextlist($user1, 'block_comments', 292 [$coursecontext1->id, $coursecontext2->id]); 293 provider::delete_comments_for_user($approvedcontextlist, 'block_comments', 'page_comments', 0); 294 295 // No comments left in comments 1 as only user 1 commented there. 296 $this->assertCount(0, $comment1->get_comments()); 297 // Only user 2 comments left in comments 2. 298 $comment2comments = $comment2->get_comments(); 299 $this->assertCount(1, $comment2comments); 300 $data = array_shift($comment2comments); 301 $this->assertEquals($user2->id, $data->userid); 302 // Nothing changed here as user 1 did not leave a comment. 303 $comment3comments = $comment3->get_comments(); 304 $this->assertCount(1, $comment3comments); 305 $data = array_shift($comment3comments); 306 $this->assertEquals($user2->id, $data->userid); 307 // Check the other comment area. 308 $result = $DB->get_records('comments', ['commentarea' => 'other_comments']); 309 $this->assertCount(1, $result); 310 $data = array_shift($result); 311 $this->assertEquals('other_comments', $data->commentarea); 312 // Check the different component, same commentarea. 313 $result = $DB->get_records('comments', ['component' => 'tool_dataprivacy']); 314 $this->assertCount(1, $result); 315 $data = array_shift($result); 316 $this->assertEquals('tool_dataprivacy', $data->component); 317 } 318 319 /** 320 * Tests deletion of comments for a specified userlist and context. 321 */ 322 public function test_delete_comments_for_users() { 323 global $DB; 324 325 $course1 = $this->getDataGenerator()->create_course(); 326 $course2 = $this->getDataGenerator()->create_course(); 327 $course3 = $this->getDataGenerator()->create_course(); 328 329 $coursecontext1 = \context_course::instance($course1->id); 330 $coursecontext2 = \context_course::instance($course2->id); 331 $coursecontext3 = \context_course::instance($course3->id); 332 333 $user1 = $this->getDataGenerator()->create_user(); 334 $user2 = $this->getDataGenerator()->create_user(); 335 $user3 = $this->getDataGenerator()->create_user(); 336 337 $comment1 = $this->get_comment_object($coursecontext1, $course1); 338 $comment2 = $this->get_comment_object($coursecontext2, $course2); 339 $comment3 = $this->get_comment_object($coursecontext3, $course3); 340 341 $this->setUser($user1); 342 $comment1->add('First comment for user 1'); 343 $comment2->add('User 1 comment in second comment'); 344 345 $this->setUser($user2); 346 $comment2->add('User two replied in comment two'); 347 348 $this->setUser($user3); 349 $comment2->add('User 3 also writing on comment 2, but will not be deleted'); 350 $comment3->add('Only user 3 commenting in comment 3.'); 351 352 // Because of the way things are set up with validation, creating an entry with the same context in a different component 353 // or comment area is a huge pain. We're just going to jam entries into the table instead. 354 $record = (object) [ 355 'contextid' => $coursecontext1->id, 356 'component' => 'block_comments', 357 'commentarea' => 'other_comments', 358 'itemid' => 2, 359 'content' => 'Comment user 1 different comment area', 360 'format' => 0, 361 'userid' => $user1->id, 362 'timecreated' => time() 363 ]; 364 $DB->insert_record('comments', $record); 365 $record = (object) [ 366 'contextid' => $coursecontext1->id, 367 'component' => 'tool_dataprivacy', 368 'commentarea' => 'page_comments', 369 'itemid' => 2, 370 'content' => 'Comment user 1 different component', 371 'format' => 0, 372 'userid' => $user1->id, 373 'timecreated' => time() 374 ]; 375 $DB->insert_record('comments', $record); 376 377 // Delete the comments for users 1 and 2 in all 3 contexts. 378 $approvedusers = [$user1->id, $user2->id]; 379 380 $approveduserlist = new approved_userlist($coursecontext1, 'block_comments', $approvedusers); 381 provider::delete_comments_for_users($approveduserlist, 'block_comments', 'page_comments'); 382 383 $approveduserlist = new approved_userlist($coursecontext2, 'block_comments', $approvedusers); 384 provider::delete_comments_for_users($approveduserlist, 'block_comments', 'page_comments'); 385 386 $approveduserlist = new approved_userlist($coursecontext3, 'block_comments', $approvedusers); 387 provider::delete_comments_for_users($approveduserlist, 'block_comments', 'page_comments'); 388 389 // No comments left in comments 1 as only user 1 commented there. 390 $this->assertCount(0, $comment1->get_comments()); 391 392 // Only user 3's comment left in comments 2 as user 1 and 2 were approved for deletion. 393 $comment2comments = $comment2->get_comments(); 394 $this->assertCount(1, $comment2comments); 395 $comment2comment = array_shift($comment2comments); 396 $this->assertEquals($user3->id, $comment2comment->userid); 397 398 // Nothing changed here as user 1 and 2 did not leave a comment. 399 $comment3comments = $comment3->get_comments(); 400 $this->assertCount(1, $comment3comments); 401 $data = array_shift($comment3comments); 402 $this->assertEquals($user3->id, $data->userid); 403 404 // Check the other comment area. 405 $result = $DB->get_records('comments', ['commentarea' => 'other_comments']); 406 $this->assertCount(1, $result); 407 $data = array_shift($result); 408 $this->assertEquals('other_comments', $data->commentarea); 409 410 // Check the different component, same commentarea. 411 $result = $DB->get_records('comments', ['component' => 'tool_dataprivacy']); 412 $this->assertCount(1, $result); 413 $data = array_shift($result); 414 $this->assertEquals('tool_dataprivacy', $data->component); 415 } 416 417 /** 418 * Creates a comment object 419 * 420 * @param context $context A context object. 421 * @param stdClass $course A course object. 422 * @return comment The comment object. 423 */ 424 protected function get_comment_object($context, $course) { 425 // Comment on course page. 426 $args = new \stdClass; 427 $args->context = $context; 428 $args->course = $course; 429 $args->area = 'page_comments'; 430 $args->itemid = 0; 431 $args->component = 'block_comments'; 432 $comment = new \comment($args); 433 $comment->set_post_permission(true); 434 return $comment; 435 } 436 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body