Merge branch 'MDL-66374-master' of git://github.com/jleyva/moodle
[moodle.git] / blog / tests / privacy_test.php
CommitLineData
ce1ec9b4
FM
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 * Data provider tests.
19 *
20 * @package core_blog
21 * @category test
22 * @copyright 2018 Frédéric Massart
23 * @author Frédéric Massart <fred@branchup.tech>
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27defined('MOODLE_INTERNAL') || die();
28global $CFG;
29
30use core_privacy\tests\provider_testcase;
31use core_privacy\local\request\approved_contextlist;
32use core_privacy\local\request\transform;
33use core_privacy\local\request\writer;
34use core_blog\privacy\provider;
35
36require_once($CFG->dirroot . '/blog/locallib.php');
37require_once($CFG->dirroot . '/comment/lib.php');
38
39/**
40 * Data provider testcase class.
41 *
42 * @package core_blog
43 * @category test
44 * @copyright 2018 Frédéric Massart
45 * @author Frédéric Massart <fred@branchup.tech>
46 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
47 */
48class core_blog_privacy_testcase extends provider_testcase {
49
50 public function setUp() {
51 $this->resetAfterTest();
52 }
53
54 public function test_get_contexts_for_userid() {
55 $dg = $this->getDataGenerator();
56 $c1 = $dg->create_course();
57 $c2 = $dg->create_course();
58 $c3 = $dg->create_course();
59 $cm1a = $dg->create_module('page', ['course' => $c1]);
60 $cm1b = $dg->create_module('page', ['course' => $c1]);
61 $cm2a = $dg->create_module('page', ['course' => $c2]);
62 $u1 = $dg->create_user();
63 $u2 = $dg->create_user();
64 $u1ctx = context_user::instance($u1->id);
65
66 // Blog share a table with notes, so throw data in there and make sure it doesn't get reported.
67 $dg->get_plugin_generator('core_notes')->create_instance(['userid' => $u1->id, 'courseid' => $c3->id]);
68
69 $this->assertEmpty(provider::get_contexts_for_userid($u1->id)->get_contextids());
70 $this->assertEmpty(provider::get_contexts_for_userid($u2->id)->get_contextids());
71
72 // Gradually create blog posts for user 1. First system one.
73 $this->create_post(['userid' => $u1->id]);
74 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
75 $this->assertCount(1, $contextids);
76 $this->assertEquals($u1ctx->id, $contextids[0]);
77 $this->assertEmpty(provider::get_contexts_for_userid($u2->id)->get_contextids());
78
79 // Create a blog post associated with c1.
80 $post = $this->create_post(['userid' => $u1->id, 'courseid' => $c1->id]);
81 $entry = new blog_entry($post->id);
82 $entry->add_association(context_course::instance($c1->id)->id);
83 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
84 $this->assertCount(2, $contextids);
85 $this->assertTrue(in_array($u1ctx->id, $contextids));
86 $this->assertTrue(in_array(context_course::instance($c1->id)->id, $contextids));
87 $this->assertEmpty(provider::get_contexts_for_userid($u2->id)->get_contextids());
88
89 // Create a blog post associated with cm2a.
90 $post = $this->create_post(['userid' => $u1->id, 'courseid' => $c2->id]);
91 $entry = new blog_entry($post->id);
92 $entry->add_association(context_module::instance($cm2a->cmid)->id);
93 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
94 $this->assertCount(3, $contextids);
95 $this->assertTrue(in_array($u1ctx->id, $contextids));
96 $this->assertTrue(in_array(context_course::instance($c1->id)->id, $contextids));
97 $this->assertTrue(in_array(context_module::instance($cm2a->cmid)->id, $contextids));
98 $this->assertEmpty(provider::get_contexts_for_userid($u2->id)->get_contextids());
99
100 // User 2 comments on u1's post.
101 $comment = $this->get_comment_object($u1ctx, $post->id);
102 $this->setUser($u2);
103 $comment->add('Hello, it\'s me!');
104 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
105 $this->assertCount(3, $contextids);
106 $this->assertTrue(in_array($u1ctx->id, $contextids));
107 $this->assertTrue(in_array(context_course::instance($c1->id)->id, $contextids));
108 $this->assertTrue(in_array(context_module::instance($cm2a->cmid)->id, $contextids));
109 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
110 $this->assertCount(1, $contextids);
111 $this->assertTrue(in_array($u1ctx->id, $contextids));
112 }
113
114 public function test_get_contexts_for_userid_with_one_associated_post_only() {
115 $dg = $this->getDataGenerator();
116 $c1 = $dg->create_course();
117 $u1 = $dg->create_user();
118 $u1ctx = context_user::instance($u1->id);
119
120 $this->assertEmpty(provider::get_contexts_for_userid($u1->id)->get_contextids());
121
122 // Create a blog post associated with c1. It should always return both the course and user context.
123 $post = $this->create_post(['userid' => $u1->id, 'courseid' => $c1->id]);
124 $entry = new blog_entry($post->id);
125 $entry->add_association(context_course::instance($c1->id)->id);
126 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
127 $this->assertCount(2, $contextids);
128 $this->assertTrue(in_array($u1ctx->id, $contextids));
129 $this->assertTrue(in_array(context_course::instance($c1->id)->id, $contextids));
130 }
131
799d32fd
AG
132 /**
133 * Test that user IDs are returned for a specificed course or module context.
134 */
135 public function test_get_users_in_context_course_and_module() {
136 $user1 = $this->getDataGenerator()->create_user();
137 $user2 = $this->getDataGenerator()->create_user();
138 $course = $this->getDataGenerator()->create_course();
139 $c1ctx = context_course::instance($course->id);
140
141 $post = $this->create_post(['userid' => $user1->id, 'courseid' => $course->id]);
142 $entry = new blog_entry($post->id);
143 $entry->add_association($c1ctx->id);
144
145 // Add a comment from user 2.
146 $comment = $this->get_comment_object(context_user::instance($user1->id), $entry->id);
147 $this->setUser($user2);
148 $comment->add('Nice blog post');
149
150 $userlist = new \core_privacy\local\request\userlist($c1ctx, 'core_blog');
151 provider::get_users_in_context($userlist);
152 $userids = $userlist->get_userids();
153 $this->assertCount(2, $userids);
154
155 // Add an association for a module.
156 $cm1a = $this->getDataGenerator()->create_module('page', ['course' => $course]);
157 $cm1ctx = context_module::instance($cm1a->cmid);
158
159 $post2 = $this->create_post(['userid' => $user2->id, 'courseid' => $course->id]);
160 $entry2 = new blog_entry($post2->id);
161 $entry2->add_association($cm1ctx->id);
162
163 $userlist = new \core_privacy\local\request\userlist($cm1ctx, 'core_blog');
164 provider::get_users_in_context($userlist);
165 $userids = $userlist->get_userids();
166 $this->assertCount(1, $userids);
167 }
168
169 /**
170 * Test that user IDs are returned for a specificed user context.
171 */
172 public function test_get_users_in_context_user_context() {
173 $user1 = $this->getDataGenerator()->create_user();
174 $user2 = $this->getDataGenerator()->create_user();
175 $u1ctx = context_user::instance($user1->id);
176
177 $post = $this->create_post(['userid' => $user1->id]);
178 $entry = new blog_entry($post->id);
179
180 // Add a comment from user 2.
181 $comment = $this->get_comment_object($u1ctx, $entry->id);
182 $this->setUser($user2);
183 $comment->add('Another nice blog post');
184
185 $userlist = new \core_privacy\local\request\userlist($u1ctx, 'core_blog');
186 provider::get_users_in_context($userlist);
187 $userids = $userlist->get_userids();
188 $this->assertCount(2, $userids);
189 }
190
191 /**
192 * Test that user IDs are returned for a specificed user context for an external blog.
193 */
194 public function test_get_users_in_context_external_blog() {
195 $user1 = $this->getDataGenerator()->create_user();
196 $u1ctx = context_user::instance($user1->id);
197 $extu1 = $this->create_external_blog(['userid' => $user1->id]);
198
199 $userlist = new \core_privacy\local\request\userlist($u1ctx, 'core_blog');
200 provider::get_users_in_context($userlist);
201 $userids = $userlist->get_userids();
202 $this->assertCount(1, $userids);
203 }
204
ce1ec9b4
FM
205 public function test_delete_data_for_user() {
206 global $DB;
207
208 $dg = $this->getDataGenerator();
209 $c1 = $dg->create_course();
210 $c2 = $dg->create_course();
211 $cm1a = $dg->create_module('page', ['course' => $c1]);
212 $cm1b = $dg->create_module('page', ['course' => $c1]);
213 $cm2a = $dg->create_module('page', ['course' => $c2]);
214 $u1 = $dg->create_user();
215 $u2 = $dg->create_user();
216 $u3 = $dg->create_user();
217
218 $c1ctx = context_course::instance($c1->id);
219 $c2ctx = context_course::instance($c2->id);
220 $cm1actx = context_module::instance($cm1a->cmid);
221 $cm1bctx = context_module::instance($cm1b->cmid);
222 $cm2actx = context_module::instance($cm2a->cmid);
223 $u1ctx = context_user::instance($u1->id);
224 $u2ctx = context_user::instance($u2->id);
225
226 // Blog share a table with notes, so throw data in there and make sure it doesn't get deleted.
227 $this->assertFalse($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
228 $dg->get_plugin_generator('core_notes')->create_instance(['userid' => $u1->id, 'courseid' => $c1->id]);
229 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
230
231 // Create two external blogs.
232 $extu1 = $this->create_external_blog(['userid' => $u1->id]);
233 $extu2 = $this->create_external_blog(['userid' => $u2->id]);
234
235 // Create a set of posts.
236 $entry = new blog_entry($this->create_post(['userid' => $u1->id])->id);
237 $commentedon = $entry;
238 $entry = new blog_entry($this->create_post(['userid' => $u2->id])->id);
239
240 // Two course associations for u1.
241 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
242 $entry->add_association($c1ctx->id);
243 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
244 $entry->add_association($c1ctx->id);
245
246 // Two module associations with cm1a, and 1 with cm1b for u1.
247 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
248 $entry->add_association($cm1actx->id);
249 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
250 $entry->add_association($cm1actx->id);
251 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
252 $entry->add_association($cm1bctx->id);
253
254 // One association for u2 in c1, cm1a and cm2a.
255 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id);
256 $entry->add_association($c1ctx->id);
257 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id);
258 $entry->add_association($cm1actx->id);
259 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c2->id])->id);
260 $entry->add_association($cm2actx->id);
261
262 // One association for u1 in c2 and cm2a.
263 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c2->id])->id);
264 $entry->add_association($c2ctx->id);
265 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c2->id])->id);
266 $entry->add_association($cm2actx->id);
267
268 // Add comments.
269 $comment = $this->get_comment_object($u1ctx, $commentedon->id);
270 $this->setUser($u1);
271 $comment->add('Hello, it\'s me!');
272 $comment->add('I was wondering...');
273 $this->setUser($u2);
274 $comment->add('If after all these years');
275 $this->setUser($u3);
276 $comment->add('You\'d like to meet');
277
278 // Assert current setup.
279 $this->assertCount(6, provider::get_contexts_for_userid($u1->id)->get_contextids());
280 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
281 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
282 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
283 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
284 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
285 $this->assertCount(2, $DB->get_records('comments', ['userid' => $u1->id]));
286 $this->assertCount(1, $DB->get_records('comments', ['userid' => $u2->id]));
287 $this->assertCount(1, $DB->get_records('comments', ['userid' => $u3->id]));
288
289 // Delete for u1 in cm1a.
290 $appctxs = new approved_contextlist($u1, 'core_blog', [$cm1actx->id]);
291 provider::delete_data_for_user($appctxs);
292 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
293 $this->assertCount(5, $contextids);
294 $this->assertFalse(in_array($cm1actx->id, $contextids));
295 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
296 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
297 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
298 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
299 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
300 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
301
302 // Delete for u1 in c1.
303 $appctxs = new approved_contextlist($u1, 'core_blog', [$c1ctx->id]);
304 provider::delete_data_for_user($appctxs);
305 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
306 $this->assertCount(4, $contextids);
307 $this->assertFalse(in_array($c1ctx->id, $contextids));
308 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
309 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
310 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
311 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
312 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
313 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
314
315 // Delete for u1 in c2.
316 $appctxs = new approved_contextlist($u1, 'core_blog', [$c2ctx->id]);
317 provider::delete_data_for_user($appctxs);
318 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
319 $this->assertCount(3, $contextids);
320 $this->assertFalse(in_array($c2ctx->id, $contextids));
321 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
322 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
323 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
324 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
325 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
326 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
327
328 // Delete for u1 in another user's context, shouldn't do anything.
329 provider::delete_data_for_user(new approved_contextlist($u1, 'core_blog', [$u2ctx->id]));
330 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
331 $this->assertCount(3, $contextids);
332 $this->assertFalse(in_array($c2ctx->id, $contextids));
333 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
334 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
335 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
336 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
337 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
338 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
339 $this->assertCount(2, $DB->get_records('comments', ['userid' => $u1->id]));
340 $this->assertCount(1, $DB->get_records('comments', ['userid' => $u2->id]));
341
342 // Delete for u2 in u1 context.
343 provider::delete_data_for_user(new approved_contextlist($u2, 'core_blog', [$u1ctx->id]));
344 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
345 $this->assertCount(3, $contextids);
346 $this->assertFalse(in_array($c2ctx->id, $contextids));
347 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
348 $this->assertCount(4, provider::get_contexts_for_userid($u2->id)->get_contextids());
349 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
350 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
351 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
352 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
353 $this->assertCount(2, $DB->get_records('comments', ['userid' => $u1->id]));
354 $this->assertCount(0, $DB->get_records('comments', ['userid' => $u2->id]));
355 $this->assertCount(1, $DB->get_records('comments', ['userid' => $u3->id]));
356
357 // Delete for u1 in their context.
358 $appctxs = new approved_contextlist($u1, 'core_blog', [$u1ctx->id]);
359 provider::delete_data_for_user($appctxs);
360 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
361 $this->assertCount(0, $contextids);
362 $this->assertCount(1, $DB->get_records('post', ['userid' => $u1->id]));
363 $this->assertCount(4, provider::get_contexts_for_userid($u2->id)->get_contextids());
364 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
365 $this->assertCount(0, $DB->get_records('blog_external', ['userid' => $u1->id]));
366 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
367 $this->assertCount(0, $DB->get_records('comments', ['userid' => $u1->id]));
368 $this->assertCount(0, $DB->get_records('comments', ['userid' => $u2->id]));
369 $this->assertCount(0, $DB->get_records('comments', ['userid' => $u3->id]));
370 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
371 }
372
373 public function test_delete_data_for_all_users_in_context() {
374 global $DB;
375
376 $dg = $this->getDataGenerator();
377 $c1 = $dg->create_course();
378 $c2 = $dg->create_course();
379 $cm1a = $dg->create_module('page', ['course' => $c1]);
380 $cm1b = $dg->create_module('page', ['course' => $c1]);
381 $cm2a = $dg->create_module('page', ['course' => $c2]);
382 $u1 = $dg->create_user();
383 $u2 = $dg->create_user();
384
385 $c1ctx = context_course::instance($c1->id);
386 $c2ctx = context_course::instance($c2->id);
387 $cm1actx = context_module::instance($cm1a->cmid);
388 $cm1bctx = context_module::instance($cm1b->cmid);
389 $cm2actx = context_module::instance($cm2a->cmid);
390 $u1ctx = context_user::instance($u1->id);
391
392 // Create two external blogs.
393 $extu1 = $this->create_external_blog(['userid' => $u1->id]);
394 $extu2 = $this->create_external_blog(['userid' => $u2->id]);
395
396 // Create a set of posts.
397 $entry = new blog_entry($this->create_post(['userid' => $u1->id])->id);
398 $entry = new blog_entry($this->create_post(['userid' => $u2->id])->id);
399
400 // Course associations for u1 and u2.
401 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
402 $entry->add_association($c1ctx->id);
403 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
404 $entry->add_association($c1ctx->id);
405 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id);
406 $entry->add_association($c1ctx->id);
407
408 // Module associations for u1 and u2.
409 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
410 $entry->add_association($cm1actx->id);
411 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
412 $entry->add_association($cm1actx->id);
413 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
414 $entry->add_association($cm1bctx->id);
415 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id);
416 $entry->add_association($cm1actx->id);
417
418 // Foreign associations for u1, u2.
419 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c2->id])->id);
420 $entry->add_association($c2ctx->id);
421 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c2->id])->id);
422 $entry->add_association($c2ctx->id);
423 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $cm2a->id])->id);
424 $entry->add_association($cm2actx->id);
425
426 // Validate what we've got.
427 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
428 $this->assertCount(8, $DB->get_records('post', ['userid' => $u1->id]));
429 $this->assertCount(6, $contextids);
430 $this->assertTrue(in_array($c1ctx->id, $contextids));
431 $this->assertTrue(in_array($c2ctx->id, $contextids));
432 $this->assertTrue(in_array($cm1actx->id, $contextids));
433 $this->assertTrue(in_array($cm1bctx->id, $contextids));
434 $this->assertTrue(in_array($cm2actx->id, $contextids));
435 $this->assertTrue(in_array($u1ctx->id, $contextids));
436 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
437 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
438 $this->assertCount(4, $contextids);
439 $this->assertTrue(in_array($c1ctx->id, $contextids));
440 $this->assertTrue(in_array($c2ctx->id, $contextids));
441 $this->assertTrue(in_array($cm1actx->id, $contextids));
442
443 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
444 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
445
446 // Delete cm1a context.
447 provider::delete_data_for_all_users_in_context($cm1actx);
448 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
449 $this->assertCount(8, $DB->get_records('post', ['userid' => $u1->id]));
450 $this->assertCount(5, $contextids);
451 $this->assertTrue(in_array($c1ctx->id, $contextids));
452 $this->assertTrue(in_array($c2ctx->id, $contextids));
453 $this->assertFalse(in_array($cm1actx->id, $contextids));
454 $this->assertTrue(in_array($cm1bctx->id, $contextids));
455 $this->assertTrue(in_array($cm2actx->id, $contextids));
456 $this->assertTrue(in_array($u1ctx->id, $contextids));
457 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
458 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
459 $this->assertCount(3, $contextids);
460 $this->assertTrue(in_array($c1ctx->id, $contextids));
461 $this->assertTrue(in_array($c2ctx->id, $contextids));
462 $this->assertFalse(in_array($cm1actx->id, $contextids));
463
464 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
465 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
466
467 // Delete c1 context.
468 provider::delete_data_for_all_users_in_context($c1ctx);
469 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
470 $this->assertCount(8, $DB->get_records('post', ['userid' => $u1->id]));
471 $this->assertCount(4, $contextids);
472 $this->assertFalse(in_array($c1ctx->id, $contextids));
473 $this->assertTrue(in_array($c2ctx->id, $contextids));
474 $this->assertFalse(in_array($cm1actx->id, $contextids));
475 $this->assertTrue(in_array($cm1bctx->id, $contextids));
476 $this->assertTrue(in_array($cm2actx->id, $contextids));
477 $this->assertTrue(in_array($u1ctx->id, $contextids));
478 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
479 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
480 $this->assertCount(2, $contextids);
481 $this->assertFalse(in_array($c1ctx->id, $contextids));
482 $this->assertTrue(in_array($c2ctx->id, $contextids));
483 $this->assertFalse(in_array($cm1actx->id, $contextids));
484
485 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
486 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
487
488 // Delete u1 context.
489 provider::delete_data_for_all_users_in_context($u1ctx);
490 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
491 $this->assertCount(0, $DB->get_records('post', ['userid' => $u1->id]));
492 $this->assertCount(0, $contextids);
493 $this->assertFalse(in_array($c1ctx->id, $contextids));
494 $this->assertFalse(in_array($c2ctx->id, $contextids));
495 $this->assertFalse(in_array($cm1actx->id, $contextids));
496 $this->assertFalse(in_array($cm1bctx->id, $contextids));
497 $this->assertFalse(in_array($cm2actx->id, $contextids));
498 $this->assertFalse(in_array($u1ctx->id, $contextids));
499 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
500 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
501 $this->assertCount(2, $contextids);
502 $this->assertFalse(in_array($c1ctx->id, $contextids));
503 $this->assertTrue(in_array($c2ctx->id, $contextids));
504 $this->assertFalse(in_array($cm1actx->id, $contextids));
505
506 $this->assertCount(0, $DB->get_records('blog_external', ['userid' => $u1->id]));
507 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
508 }
509
510 public function test_export_data_for_user() {
511 global $DB;
512 $dg = $this->getDataGenerator();
513
514 $c1 = $dg->create_course();
515 $cm1a = $dg->create_module('page', ['course' => $c1]);
516 $cm1b = $dg->create_module('page', ['course' => $c1]);
517 $u1 = $dg->create_user();
518 $u2 = $dg->create_user();
519 $c1ctx = context_course::instance($c1->id);
520 $cm1actx = context_module::instance($cm1a->cmid);
521 $cm1bctx = context_module::instance($cm1b->cmid);
522 $u1ctx = context_user::instance($u1->id);
523 $u2ctx = context_user::instance($u2->id);
524
525 // System entries.
526 $e1 = new blog_entry($this->create_post(['userid' => $u1->id, 'subject' => 'Hello world!',
527 'publishstate' => 'public'])->id);
528 $e2 = new blog_entry($this->create_post(['userid' => $u1->id, 'subject' => 'Hi planet!',
529 'publishstate' => 'draft'])->id);
530 $e3 = new blog_entry($this->create_post(['userid' => $u2->id, 'subject' => 'Ignore me'])->id);
531
532 // Create a blog entry associated with contexts.
533 $e4 = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'Course assoc'])->id);
534 $e4->add_association($c1ctx->id);
535 $e4b = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'Course assoc 2'])->id);
536 $e4b->add_association($c1ctx->id);
537 $e5 = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'Module assoc',
538 'publishstate' => 'public'])->id);
539 $e5->add_association($cm1actx->id);
540 $e5b = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'C/CM assoc'])->id);
541 $e5b->add_association($c1ctx->id);
542 $e5b->add_association($cm1actx->id);
543 $e6 = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id, 'subject' => 'Module assoc'])->id);
544 $e6->add_association($cm1actx->id);
545
546 // External blogs.
547 $ex1 = $this->create_external_blog(['userid' => $u1->id, 'url' => 'https://moodle.org', 'name' => 'Moodle RSS']);
548 $ex2 = $this->create_external_blog(['userid' => $u1->id, 'url' => 'https://example.com', 'name' => 'Example']);
549 $ex3 = $this->create_external_blog(['userid' => $u2->id, 'url' => 'https://example.com', 'name' => 'Ignore me']);
550
551 // Attach tags.
552 core_tag_tag::set_item_tags('core', 'post', $e1->id, $u1ctx, ['Beer', 'Golf']);
553 core_tag_tag::set_item_tags('core', 'blog_external', $ex1->id, $u1ctx, ['Car', 'Golf']);
554 core_tag_tag::set_item_tags('core', 'post', $e3->id, $u2ctx, ['ITG']);
555 core_tag_tag::set_item_tags('core', 'blog_external', $ex3->id, $u2ctx, ['DDR']);
556 core_tag_tag::set_item_tags('core', 'dontfindme', $e1->id, $u1ctx, ['Lone tag']);
557
558 // Attach comments.
559 $comment = $this->get_comment_object($u1ctx, $e1->id);
560 $this->setUser($u1);
561 $comment->add('Hello, it\'s me!');
562 $this->setUser($u2);
563 $comment->add('I was wondering if after');
564 $this->setUser($u1);
565 $comment = $this->get_comment_object($u2ctx, $e3->id);
566 $comment->add('All these years');
567
568 // Blog share a table with notes, so throw some data in there, it should not be exported.
569 $note = $dg->get_plugin_generator('core_notes')->create_instance(['userid' => $u1->id, 'courseid' => $c1->id,
570 'subject' => 'ABC']);
571
572 // Validate module associations.
573 $contextlist = new approved_contextlist($u1, 'core_blog', [$cm1actx->id]);
574 provider::export_user_data($contextlist);
575 $writer = writer::with_context($cm1actx);
576 $assocs = $writer->get_data([get_string('privacy:path:blogassociations', 'core_blog')]);
577 $this->assertCount(2, $assocs->associations);
578 $this->assertTrue(in_array('Module assoc', $assocs->associations));
579 $this->assertTrue(in_array('C/CM assoc', $assocs->associations));
580
581 // Validate course associations.
582 $contextlist = new approved_contextlist($u1, 'core_blog', [$c1ctx->id]);
583 provider::export_user_data($contextlist);
584 $writer = writer::with_context($c1ctx);
585 $assocs = $writer->get_data([get_string('privacy:path:blogassociations', 'core_blog')]);
586 $this->assertCount(3, $assocs->associations);
587 $this->assertTrue(in_array('Course assoc', $assocs->associations));
588 $this->assertTrue(in_array('Course assoc 2', $assocs->associations));
589 $this->assertTrue(in_array('C/CM assoc', $assocs->associations));
590
591 // Confirm we're not exporting for another user.
592 $contextlist = new approved_contextlist($u2, 'core_blog', [$u2ctx->id]);
593 $writer = writer::with_context($u1ctx);
594 $this->assertFalse($writer->has_any_data());
595
596 // Now export user context for u2.
597 $this->setUser($u2);
598 $contextlist = new approved_contextlist($u2, 'core_blog', [$u1ctx->id]);
599 provider::export_user_data($contextlist);
600 $writer = writer::with_context($u1ctx);
601 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('externalblogs', 'core_blog'),
602 $ex1->name . " ({$ex1->id})"]);
603 $this->assertEmpty($data);
604 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'),
605 $e2->subject . " ({$e2->id})"]);
606 $this->assertEmpty($data);
607 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'),
608 $e1->subject . " ({$e1->id})"]);
609 $this->assertEmpty($data);
610 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'),
611 $e1->subject . " ({$e1->id})", get_string('commentsubcontext', 'core_comment')]);
612 $this->assertNotEmpty($data);
613 $this->assertCount(1, $data->comments);
614 $comment = array_shift($data->comments);
615 $this->assertEquals('I was wondering if after', strip_tags($comment->content));
616
617 // Now export user context data.
618 $this->setUser($u1);
619 $contextlist = new approved_contextlist($u1, 'core_blog', [$u1ctx->id]);
620 writer::reset();
621 provider::export_user_data($contextlist);
622 $writer = writer::with_context($u1ctx);
623
624 // Check external blogs.
625 $externals = [$ex1, $ex2];
626 foreach ($externals as $ex) {
627 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('externalblogs', 'core_blog'),
628 $ex->name . " ({$ex->id})"]);
629 $this->assertNotEmpty($data);
630 $this->assertEquals($data->name, $ex->name);
631 $this->assertEquals($data->description, $ex->description);
632 $this->assertEquals($data->url, $ex->url);
633 $this->assertEquals($data->filtertags, $ex->filtertags);
634 $this->assertEquals($data->modified, transform::datetime($ex->timemodified));
635 $this->assertEquals($data->lastfetched, transform::datetime($ex->timefetched));
636 }
637
638 // Check entries.
639 $entries = [$e1, $e2, $e4, $e4b, $e5, $e5b];
640 $associations = [
641 $e1->id => null,
642 $e2->id => null,
643 $e4->id => $c1ctx->get_context_name(),
644 $e4b->id => $c1ctx->get_context_name(),
645 $e5->id => $cm1actx->get_context_name(),
646 $e5b->id => [$c1ctx->get_context_name(), $cm1actx->get_context_name()],
647 ];
648 foreach ($entries as $e) {
649 $path = [get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'), $e->subject . " ({$e->id})"];
650 $data = $writer->get_data($path);
651 $this->assertNotEmpty($data);
652 $this->assertEquals($data->subject, $e->subject);
653 $this->assertEquals($data->summary, $e->summary);
654 $this->assertEquals($data->publishstate, provider::transform_publishstate($e->publishstate));
655 $this->assertEquals($data->created, transform::datetime($e->created));
656 $this->assertEquals($data->lastmodified, transform::datetime($e->lastmodified));
657
658 // We attached comments and tags to this entry.
659 $commentpath = array_merge($path, [get_string('commentsubcontext', 'core_comment')]);
660 if ($e->id == $e1->id) {
661 $tagdata = $writer->get_related_data($path, 'tags');
2207b0fa 662 $this->assertEquals(['Beer', 'Golf'], $tagdata, '', 0, 10, true);
ce1ec9b4
FM
663
664 $comments = $writer->get_data($commentpath);
665 $this->assertCount(2, $comments->comments);
70720094
AN
666
667 $c0 = strip_tags($comments->comments[0]->content);
668 $c1 = strip_tags($comments->comments[1]->content);
669 $expectedcomments = [
670 'Hello, it\'s me!',
671 'I was wondering if after',
672 ];
673
674 $this->assertNotFalse(array_search($c0, $expectedcomments));
675 $this->assertNotFalse(array_search($c1, $expectedcomments));
676 $this->assertNotEquals($c0, $c1);
ce1ec9b4
FM
677
678 } else {
679 $tagdata = $writer->get_related_data($path, 'tags');
680 $this->assertEmpty($tagdata);
681 $comments = $writer->get_data($commentpath);
682 $this->assertEmpty($comments);
683 }
684
685 if (isset($associations[$e->id])) {
686 $assocs = $associations[$e->id];
687 if (is_array($assocs)) {
688 $this->assertCount(count($assocs), $data->associations);
689 foreach ($assocs as $v) {
690 $this->assertTrue(in_array($v, $data->associations));
691 }
692 } else {
693 $this->assertCount(1, $data->associations);
694 $this->assertTrue(in_array($assocs, $data->associations));
695 }
696 }
697 }
698
699 // The note was not exported.
700 $path = [get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'), "ABC ($note->id)"];
701 $this->assertEmpty($writer->get_data($path));
702
703 }
704
799d32fd
AG
705 /**
706 * Test that deleting of blog information in a user context works as desired.
707 */
708 public function test_delete_data_for_users_user_context() {
709 global $DB;
710
711 $u1 = $this->getDataGenerator()->create_user();
712 $u2 = $this->getDataGenerator()->create_user();
713 $u3 = $this->getDataGenerator()->create_user();
714 $u4 = $this->getDataGenerator()->create_user();
715 $u5 = $this->getDataGenerator()->create_user();
716
717 $u1ctx = context_user::instance($u1->id);
718
719 $post = $this->create_post(['userid' => $u1->id]);
720 $entry = new blog_entry($post->id);
721
722 $comment = $this->get_comment_object($u1ctx, $entry->id);
723 $this->setUser($u1);
724 $comment->add('Hello, I created the blog');
725 $this->setUser($u2);
726 $comment->add('User 2 making a comment.');
727 $this->setUser($u3);
728 $comment->add('User 3 here.');
729 $this->setUser($u4);
730 $comment->add('User 4 is nice.');
731 $this->setUser($u5);
732 $comment->add('User 5 for the win.');
733
734 // This will only delete the comments made by user 4 and 5.
735 $this->assertCount(5, $DB->get_records('comments', ['contextid' => $u1ctx->id]));
736 $userlist = new \core_privacy\local\request\approved_userlist($u1ctx, 'core_blog', [$u4->id, $u5->id]);
737 provider::delete_data_for_users($userlist);
738 $this->assertCount(3, $DB->get_records('comments', ['contextid' => $u1ctx->id]));
739 $this->assertCount(1, $DB->get_records('post', ['userid' => $u1->id]));
740
741 // As the owner of the post is here everything will be deleted.
742 $userlist = new \core_privacy\local\request\approved_userlist($u1ctx, 'core_blog', [$u1->id, $u2->id]);
743 provider::delete_data_for_users($userlist);
744 $this->assertEmpty($DB->get_records('comments', ['contextid' => $u1ctx->id]));
745 $this->assertEmpty($DB->get_records('post', ['userid' => $u1->id]));
746 }
747
748 /**
749 * Test that deleting of an external blog in a user context works as desired.
750 */
751 public function test_delete_data_for_users_external_blog() {
752 global $DB;
753
754 $u1 = $this->getDataGenerator()->create_user();
755 $u2 = $this->getDataGenerator()->create_user();
756
757 $u1ctx = context_user::instance($u1->id);
758 $u2ctx = context_user::instance($u2->id);
759
760 $post = $this->create_external_blog(['userid' => $u1->id, 'url' => 'https://moodle.org', 'name' => 'Moodle RSS']);
761 $post2 = $this->create_external_blog(['userid' => $u2->id, 'url' => 'https://moodle.com', 'name' => 'Some other thing']);
762
763 // Check that we have two external blogs created.
764 $this->assertCount(2, $DB->get_records('blog_external'));
765 // This will only delete the external blog for user 1.
766 $userlist = new \core_privacy\local\request\approved_userlist($u1ctx, 'core_blog', [$u1->id, $u2->id]);
767 provider::delete_data_for_users($userlist);
768 $this->assertCount(1, $DB->get_records('blog_external'));
769 }
770
771 public function test_delete_data_for_users_course_and_module_context() {
772 global $DB;
773
774 $u1 = $this->getDataGenerator()->create_user();
775 $u2 = $this->getDataGenerator()->create_user();
776 $u3 = $this->getDataGenerator()->create_user();
777 $u4 = $this->getDataGenerator()->create_user();
778 $u5 = $this->getDataGenerator()->create_user();
779
780 $course = $this->getDataGenerator()->create_course();
781 $module = $this->getDataGenerator()->create_module('page', ['course' => $course]);
782
783 $u1ctx = context_user::instance($u1->id);
784 $u3ctx = context_user::instance($u3->id);
785 $c1ctx = context_course::instance($course->id);
786 $cm1ctx = context_module::instance($module->cmid);
787
788 // Blog with course association.
789 $post1 = $this->create_post(['userid' => $u1->id, 'courseid' => $course->id]);
790 $entry1 = new blog_entry($post1->id);
791 $entry1->add_association($c1ctx->id);
792
793 // Blog with module association.
794 $post2 = $this->create_post(['userid' => $u3->id, 'courseid' => $course->id]);
795 $entry2 = new blog_entry($post2->id);
796 $entry2->add_association($cm1ctx->id);
797
798 $comment = $this->get_comment_object($u1ctx, $entry1->id);
799 $this->setUser($u1);
800 $comment->add('Hello, I created the blog');
801 $this->setUser($u2);
802 $comment->add('comment on first course blog');
803 $this->setUser($u4);
804 $comment->add('user 4 on course blog');
805
806 $comment = $this->get_comment_object($u3ctx, $entry2->id);
807 $this->setUser($u3);
808 $comment->add('Hello, I created the module blog');
809 $this->setUser($u2);
810 $comment->add('I am commenting on both');
811 $this->setUser($u5);
812 $comment->add('User 5 for modules');
813
814 $this->assertCount(6, $DB->get_records('comments', ['component' => 'blog']));
815 $this->assertCount(2, $DB->get_records('post', ['courseid' => $course->id]));
816 $this->assertCount(2, $DB->get_records('blog_association'));
817
818 // When using the course or module context we are only removing the blog associations and the comments.
819 $userlist = new \core_privacy\local\request\approved_userlist($c1ctx, 'core_blog', [$u2->id, $u1->id, $u5->id]);
820 provider::delete_data_for_users($userlist);
821 // Only one of the blog_associations should be removed. Everything else should be as before.
822 $this->assertCount(6, $DB->get_records('comments', ['component' => 'blog']));
823 $this->assertCount(2, $DB->get_records('post', ['courseid' => $course->id]));
824 $this->assertCount(1, $DB->get_records('blog_association'));
825
826 $userlist = new \core_privacy\local\request\approved_userlist($cm1ctx, 'core_blog', [$u2->id, $u1->id, $u3->id]);
827 provider::delete_data_for_users($userlist);
828 // Now we've removed the other association.
829 $this->assertCount(6, $DB->get_records('comments', ['component' => 'blog']));
830 $this->assertCount(2, $DB->get_records('post', ['courseid' => $course->id]));
831 $this->assertEmpty($DB->get_records('blog_association'));
832 }
833
ce1ec9b4
FM
834 /**
835 * Create a blog post.
836 *
837 * @param array $params The params.
838 * @return stdClass
839 */
840 protected function create_post(array $params) {
841 global $DB;
842 $post = new stdClass();
843 $post->module = 'blog';
844 $post->courseid = 0;
845 $post->subject = 'the test post';
846 $post->summary = 'test post summary text';
847 $post->summaryformat = FORMAT_PLAIN;
848 $post->publishstate = 'site';
849 $post->created = time() - HOURSECS;
850 $post->lastmodified = time();
851 foreach ($params as $key => $value) {
852 $post->{$key} = $value;
853 }
854
855 $post->id = $DB->insert_record('post', $post);
856 return $post;
857 }
858
859 /**
860 * Create an extenral blog.
861 *
862 * @param array $params The params.
863 * @return stdClass
864 */
865 protected function create_external_blog(array $params) {
866 global $DB;
867 $post = new stdClass();
868 $post->name = 'test external';
869 $post->description = 'the description';
870 $post->url = 'http://example.com';
871 $post->filtertags = 'a, c, b';
872 $post->timefetched = time() - HOURSECS;
873 $post->timemodified = time();
874 foreach ($params as $key => $value) {
875 $post->{$key} = $value;
876 }
877 $post->id = $DB->insert_record('blog_external', $post);
878 return $post;
879 }
880
881 /**
882 * Get the comment area.
883 *
884 * @param context $context The context.
885 * @param int $itemid The item ID.
886 * @param string $component The component.
887 * @param string $area The area.
888 * @return comment
889 */
890 protected function get_comment_object(context $context, $itemid) {
891 $args = new stdClass();
892 $args->context = $context;
893 $args->course = get_course(SITEID);
894 $args->area = 'format_blog';
895 $args->itemid = $itemid;
896 $args->component = 'blog';
897 $comment = new comment($args);
898 $comment->set_post_permission(true);
899 return $comment;
900 }
901}