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