on-demand release 3.6dev+
[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
132 public function test_delete_data_for_user() {
133 global $DB;
134
135 $dg = $this->getDataGenerator();
136 $c1 = $dg->create_course();
137 $c2 = $dg->create_course();
138 $cm1a = $dg->create_module('page', ['course' => $c1]);
139 $cm1b = $dg->create_module('page', ['course' => $c1]);
140 $cm2a = $dg->create_module('page', ['course' => $c2]);
141 $u1 = $dg->create_user();
142 $u2 = $dg->create_user();
143 $u3 = $dg->create_user();
144
145 $c1ctx = context_course::instance($c1->id);
146 $c2ctx = context_course::instance($c2->id);
147 $cm1actx = context_module::instance($cm1a->cmid);
148 $cm1bctx = context_module::instance($cm1b->cmid);
149 $cm2actx = context_module::instance($cm2a->cmid);
150 $u1ctx = context_user::instance($u1->id);
151 $u2ctx = context_user::instance($u2->id);
152
153 // Blog share a table with notes, so throw data in there and make sure it doesn't get deleted.
154 $this->assertFalse($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
155 $dg->get_plugin_generator('core_notes')->create_instance(['userid' => $u1->id, 'courseid' => $c1->id]);
156 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
157
158 // Create two external blogs.
159 $extu1 = $this->create_external_blog(['userid' => $u1->id]);
160 $extu2 = $this->create_external_blog(['userid' => $u2->id]);
161
162 // Create a set of posts.
163 $entry = new blog_entry($this->create_post(['userid' => $u1->id])->id);
164 $commentedon = $entry;
165 $entry = new blog_entry($this->create_post(['userid' => $u2->id])->id);
166
167 // Two course associations for u1.
168 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
169 $entry->add_association($c1ctx->id);
170 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
171 $entry->add_association($c1ctx->id);
172
173 // Two module associations with cm1a, and 1 with cm1b for u1.
174 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
175 $entry->add_association($cm1actx->id);
176 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
177 $entry->add_association($cm1actx->id);
178 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
179 $entry->add_association($cm1bctx->id);
180
181 // One association for u2 in c1, cm1a and cm2a.
182 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id);
183 $entry->add_association($c1ctx->id);
184 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id);
185 $entry->add_association($cm1actx->id);
186 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c2->id])->id);
187 $entry->add_association($cm2actx->id);
188
189 // One association for u1 in c2 and cm2a.
190 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c2->id])->id);
191 $entry->add_association($c2ctx->id);
192 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c2->id])->id);
193 $entry->add_association($cm2actx->id);
194
195 // Add comments.
196 $comment = $this->get_comment_object($u1ctx, $commentedon->id);
197 $this->setUser($u1);
198 $comment->add('Hello, it\'s me!');
199 $comment->add('I was wondering...');
200 $this->setUser($u2);
201 $comment->add('If after all these years');
202 $this->setUser($u3);
203 $comment->add('You\'d like to meet');
204
205 // Assert current setup.
206 $this->assertCount(6, provider::get_contexts_for_userid($u1->id)->get_contextids());
207 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
208 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
209 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
210 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
211 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
212 $this->assertCount(2, $DB->get_records('comments', ['userid' => $u1->id]));
213 $this->assertCount(1, $DB->get_records('comments', ['userid' => $u2->id]));
214 $this->assertCount(1, $DB->get_records('comments', ['userid' => $u3->id]));
215
216 // Delete for u1 in cm1a.
217 $appctxs = new approved_contextlist($u1, 'core_blog', [$cm1actx->id]);
218 provider::delete_data_for_user($appctxs);
219 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
220 $this->assertCount(5, $contextids);
221 $this->assertFalse(in_array($cm1actx->id, $contextids));
222 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
223 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
224 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
225 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
226 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
227 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
228
229 // Delete for u1 in c1.
230 $appctxs = new approved_contextlist($u1, 'core_blog', [$c1ctx->id]);
231 provider::delete_data_for_user($appctxs);
232 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
233 $this->assertCount(4, $contextids);
234 $this->assertFalse(in_array($c1ctx->id, $contextids));
235 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
236 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
237 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
238 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
239 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
240 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
241
242 // Delete for u1 in c2.
243 $appctxs = new approved_contextlist($u1, 'core_blog', [$c2ctx->id]);
244 provider::delete_data_for_user($appctxs);
245 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
246 $this->assertCount(3, $contextids);
247 $this->assertFalse(in_array($c2ctx->id, $contextids));
248 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
249 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
250 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
251 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
252 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
253 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
254
255 // Delete for u1 in another user's context, shouldn't do anything.
256 provider::delete_data_for_user(new approved_contextlist($u1, 'core_blog', [$u2ctx->id]));
257 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
258 $this->assertCount(3, $contextids);
259 $this->assertFalse(in_array($c2ctx->id, $contextids));
260 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
261 $this->assertCount(5, provider::get_contexts_for_userid($u2->id)->get_contextids());
262 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
263 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
264 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
265 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
266 $this->assertCount(2, $DB->get_records('comments', ['userid' => $u1->id]));
267 $this->assertCount(1, $DB->get_records('comments', ['userid' => $u2->id]));
268
269 // Delete for u2 in u1 context.
270 provider::delete_data_for_user(new approved_contextlist($u2, 'core_blog', [$u1ctx->id]));
271 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
272 $this->assertCount(3, $contextids);
273 $this->assertFalse(in_array($c2ctx->id, $contextids));
274 $this->assertCount(9, $DB->get_records('post', ['userid' => $u1->id]));
275 $this->assertCount(4, provider::get_contexts_for_userid($u2->id)->get_contextids());
276 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
277 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
278 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
279 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
280 $this->assertCount(2, $DB->get_records('comments', ['userid' => $u1->id]));
281 $this->assertCount(0, $DB->get_records('comments', ['userid' => $u2->id]));
282 $this->assertCount(1, $DB->get_records('comments', ['userid' => $u3->id]));
283
284 // Delete for u1 in their context.
285 $appctxs = new approved_contextlist($u1, 'core_blog', [$u1ctx->id]);
286 provider::delete_data_for_user($appctxs);
287 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
288 $this->assertCount(0, $contextids);
289 $this->assertCount(1, $DB->get_records('post', ['userid' => $u1->id]));
290 $this->assertCount(4, provider::get_contexts_for_userid($u2->id)->get_contextids());
291 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
292 $this->assertCount(0, $DB->get_records('blog_external', ['userid' => $u1->id]));
293 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
294 $this->assertCount(0, $DB->get_records('comments', ['userid' => $u1->id]));
295 $this->assertCount(0, $DB->get_records('comments', ['userid' => $u2->id]));
296 $this->assertCount(0, $DB->get_records('comments', ['userid' => $u3->id]));
297 $this->assertTrue($DB->record_exists('post', ['courseid' => $c1->id, 'userid' => $u1->id, 'module' => 'notes']));
298 }
299
300 public function test_delete_data_for_all_users_in_context() {
301 global $DB;
302
303 $dg = $this->getDataGenerator();
304 $c1 = $dg->create_course();
305 $c2 = $dg->create_course();
306 $cm1a = $dg->create_module('page', ['course' => $c1]);
307 $cm1b = $dg->create_module('page', ['course' => $c1]);
308 $cm2a = $dg->create_module('page', ['course' => $c2]);
309 $u1 = $dg->create_user();
310 $u2 = $dg->create_user();
311
312 $c1ctx = context_course::instance($c1->id);
313 $c2ctx = context_course::instance($c2->id);
314 $cm1actx = context_module::instance($cm1a->cmid);
315 $cm1bctx = context_module::instance($cm1b->cmid);
316 $cm2actx = context_module::instance($cm2a->cmid);
317 $u1ctx = context_user::instance($u1->id);
318
319 // Create two external blogs.
320 $extu1 = $this->create_external_blog(['userid' => $u1->id]);
321 $extu2 = $this->create_external_blog(['userid' => $u2->id]);
322
323 // Create a set of posts.
324 $entry = new blog_entry($this->create_post(['userid' => $u1->id])->id);
325 $entry = new blog_entry($this->create_post(['userid' => $u2->id])->id);
326
327 // Course associations for u1 and u2.
328 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
329 $entry->add_association($c1ctx->id);
330 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
331 $entry->add_association($c1ctx->id);
332 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id);
333 $entry->add_association($c1ctx->id);
334
335 // Module associations for u1 and u2.
336 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
337 $entry->add_association($cm1actx->id);
338 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
339 $entry->add_association($cm1actx->id);
340 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id);
341 $entry->add_association($cm1bctx->id);
342 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id);
343 $entry->add_association($cm1actx->id);
344
345 // Foreign associations for u1, u2.
346 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c2->id])->id);
347 $entry->add_association($c2ctx->id);
348 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c2->id])->id);
349 $entry->add_association($c2ctx->id);
350 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $cm2a->id])->id);
351 $entry->add_association($cm2actx->id);
352
353 // Validate what we've got.
354 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
355 $this->assertCount(8, $DB->get_records('post', ['userid' => $u1->id]));
356 $this->assertCount(6, $contextids);
357 $this->assertTrue(in_array($c1ctx->id, $contextids));
358 $this->assertTrue(in_array($c2ctx->id, $contextids));
359 $this->assertTrue(in_array($cm1actx->id, $contextids));
360 $this->assertTrue(in_array($cm1bctx->id, $contextids));
361 $this->assertTrue(in_array($cm2actx->id, $contextids));
362 $this->assertTrue(in_array($u1ctx->id, $contextids));
363 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
364 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
365 $this->assertCount(4, $contextids);
366 $this->assertTrue(in_array($c1ctx->id, $contextids));
367 $this->assertTrue(in_array($c2ctx->id, $contextids));
368 $this->assertTrue(in_array($cm1actx->id, $contextids));
369
370 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
371 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
372
373 // Delete cm1a context.
374 provider::delete_data_for_all_users_in_context($cm1actx);
375 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
376 $this->assertCount(8, $DB->get_records('post', ['userid' => $u1->id]));
377 $this->assertCount(5, $contextids);
378 $this->assertTrue(in_array($c1ctx->id, $contextids));
379 $this->assertTrue(in_array($c2ctx->id, $contextids));
380 $this->assertFalse(in_array($cm1actx->id, $contextids));
381 $this->assertTrue(in_array($cm1bctx->id, $contextids));
382 $this->assertTrue(in_array($cm2actx->id, $contextids));
383 $this->assertTrue(in_array($u1ctx->id, $contextids));
384 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
385 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
386 $this->assertCount(3, $contextids);
387 $this->assertTrue(in_array($c1ctx->id, $contextids));
388 $this->assertTrue(in_array($c2ctx->id, $contextids));
389 $this->assertFalse(in_array($cm1actx->id, $contextids));
390
391 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
392 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
393
394 // Delete c1 context.
395 provider::delete_data_for_all_users_in_context($c1ctx);
396 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
397 $this->assertCount(8, $DB->get_records('post', ['userid' => $u1->id]));
398 $this->assertCount(4, $contextids);
399 $this->assertFalse(in_array($c1ctx->id, $contextids));
400 $this->assertTrue(in_array($c2ctx->id, $contextids));
401 $this->assertFalse(in_array($cm1actx->id, $contextids));
402 $this->assertTrue(in_array($cm1bctx->id, $contextids));
403 $this->assertTrue(in_array($cm2actx->id, $contextids));
404 $this->assertTrue(in_array($u1ctx->id, $contextids));
405 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
406 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
407 $this->assertCount(2, $contextids);
408 $this->assertFalse(in_array($c1ctx->id, $contextids));
409 $this->assertTrue(in_array($c2ctx->id, $contextids));
410 $this->assertFalse(in_array($cm1actx->id, $contextids));
411
412 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id]));
413 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
414
415 // Delete u1 context.
416 provider::delete_data_for_all_users_in_context($u1ctx);
417 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
418 $this->assertCount(0, $DB->get_records('post', ['userid' => $u1->id]));
419 $this->assertCount(0, $contextids);
420 $this->assertFalse(in_array($c1ctx->id, $contextids));
421 $this->assertFalse(in_array($c2ctx->id, $contextids));
422 $this->assertFalse(in_array($cm1actx->id, $contextids));
423 $this->assertFalse(in_array($cm1bctx->id, $contextids));
424 $this->assertFalse(in_array($cm2actx->id, $contextids));
425 $this->assertFalse(in_array($u1ctx->id, $contextids));
426 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
427 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id]));
428 $this->assertCount(2, $contextids);
429 $this->assertFalse(in_array($c1ctx->id, $contextids));
430 $this->assertTrue(in_array($c2ctx->id, $contextids));
431 $this->assertFalse(in_array($cm1actx->id, $contextids));
432
433 $this->assertCount(0, $DB->get_records('blog_external', ['userid' => $u1->id]));
434 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id]));
435 }
436
437 public function test_export_data_for_user() {
438 global $DB;
439 $dg = $this->getDataGenerator();
440
441 $c1 = $dg->create_course();
442 $cm1a = $dg->create_module('page', ['course' => $c1]);
443 $cm1b = $dg->create_module('page', ['course' => $c1]);
444 $u1 = $dg->create_user();
445 $u2 = $dg->create_user();
446 $c1ctx = context_course::instance($c1->id);
447 $cm1actx = context_module::instance($cm1a->cmid);
448 $cm1bctx = context_module::instance($cm1b->cmid);
449 $u1ctx = context_user::instance($u1->id);
450 $u2ctx = context_user::instance($u2->id);
451
452 // System entries.
453 $e1 = new blog_entry($this->create_post(['userid' => $u1->id, 'subject' => 'Hello world!',
454 'publishstate' => 'public'])->id);
455 $e2 = new blog_entry($this->create_post(['userid' => $u1->id, 'subject' => 'Hi planet!',
456 'publishstate' => 'draft'])->id);
457 $e3 = new blog_entry($this->create_post(['userid' => $u2->id, 'subject' => 'Ignore me'])->id);
458
459 // Create a blog entry associated with contexts.
460 $e4 = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'Course assoc'])->id);
461 $e4->add_association($c1ctx->id);
462 $e4b = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'Course assoc 2'])->id);
463 $e4b->add_association($c1ctx->id);
464 $e5 = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'Module assoc',
465 'publishstate' => 'public'])->id);
466 $e5->add_association($cm1actx->id);
467 $e5b = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'C/CM assoc'])->id);
468 $e5b->add_association($c1ctx->id);
469 $e5b->add_association($cm1actx->id);
470 $e6 = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id, 'subject' => 'Module assoc'])->id);
471 $e6->add_association($cm1actx->id);
472
473 // External blogs.
474 $ex1 = $this->create_external_blog(['userid' => $u1->id, 'url' => 'https://moodle.org', 'name' => 'Moodle RSS']);
475 $ex2 = $this->create_external_blog(['userid' => $u1->id, 'url' => 'https://example.com', 'name' => 'Example']);
476 $ex3 = $this->create_external_blog(['userid' => $u2->id, 'url' => 'https://example.com', 'name' => 'Ignore me']);
477
478 // Attach tags.
479 core_tag_tag::set_item_tags('core', 'post', $e1->id, $u1ctx, ['Beer', 'Golf']);
480 core_tag_tag::set_item_tags('core', 'blog_external', $ex1->id, $u1ctx, ['Car', 'Golf']);
481 core_tag_tag::set_item_tags('core', 'post', $e3->id, $u2ctx, ['ITG']);
482 core_tag_tag::set_item_tags('core', 'blog_external', $ex3->id, $u2ctx, ['DDR']);
483 core_tag_tag::set_item_tags('core', 'dontfindme', $e1->id, $u1ctx, ['Lone tag']);
484
485 // Attach comments.
486 $comment = $this->get_comment_object($u1ctx, $e1->id);
487 $this->setUser($u1);
488 $comment->add('Hello, it\'s me!');
489 $this->setUser($u2);
490 $comment->add('I was wondering if after');
491 $this->setUser($u1);
492 $comment = $this->get_comment_object($u2ctx, $e3->id);
493 $comment->add('All these years');
494
495 // Blog share a table with notes, so throw some data in there, it should not be exported.
496 $note = $dg->get_plugin_generator('core_notes')->create_instance(['userid' => $u1->id, 'courseid' => $c1->id,
497 'subject' => 'ABC']);
498
499 // Validate module associations.
500 $contextlist = new approved_contextlist($u1, 'core_blog', [$cm1actx->id]);
501 provider::export_user_data($contextlist);
502 $writer = writer::with_context($cm1actx);
503 $assocs = $writer->get_data([get_string('privacy:path:blogassociations', 'core_blog')]);
504 $this->assertCount(2, $assocs->associations);
505 $this->assertTrue(in_array('Module assoc', $assocs->associations));
506 $this->assertTrue(in_array('C/CM assoc', $assocs->associations));
507
508 // Validate course associations.
509 $contextlist = new approved_contextlist($u1, 'core_blog', [$c1ctx->id]);
510 provider::export_user_data($contextlist);
511 $writer = writer::with_context($c1ctx);
512 $assocs = $writer->get_data([get_string('privacy:path:blogassociations', 'core_blog')]);
513 $this->assertCount(3, $assocs->associations);
514 $this->assertTrue(in_array('Course assoc', $assocs->associations));
515 $this->assertTrue(in_array('Course assoc 2', $assocs->associations));
516 $this->assertTrue(in_array('C/CM assoc', $assocs->associations));
517
518 // Confirm we're not exporting for another user.
519 $contextlist = new approved_contextlist($u2, 'core_blog', [$u2ctx->id]);
520 $writer = writer::with_context($u1ctx);
521 $this->assertFalse($writer->has_any_data());
522
523 // Now export user context for u2.
524 $this->setUser($u2);
525 $contextlist = new approved_contextlist($u2, 'core_blog', [$u1ctx->id]);
526 provider::export_user_data($contextlist);
527 $writer = writer::with_context($u1ctx);
528 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('externalblogs', 'core_blog'),
529 $ex1->name . " ({$ex1->id})"]);
530 $this->assertEmpty($data);
531 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'),
532 $e2->subject . " ({$e2->id})"]);
533 $this->assertEmpty($data);
534 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'),
535 $e1->subject . " ({$e1->id})"]);
536 $this->assertEmpty($data);
537 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'),
538 $e1->subject . " ({$e1->id})", get_string('commentsubcontext', 'core_comment')]);
539 $this->assertNotEmpty($data);
540 $this->assertCount(1, $data->comments);
541 $comment = array_shift($data->comments);
542 $this->assertEquals('I was wondering if after', strip_tags($comment->content));
543
544 // Now export user context data.
545 $this->setUser($u1);
546 $contextlist = new approved_contextlist($u1, 'core_blog', [$u1ctx->id]);
547 writer::reset();
548 provider::export_user_data($contextlist);
549 $writer = writer::with_context($u1ctx);
550
551 // Check external blogs.
552 $externals = [$ex1, $ex2];
553 foreach ($externals as $ex) {
554 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('externalblogs', 'core_blog'),
555 $ex->name . " ({$ex->id})"]);
556 $this->assertNotEmpty($data);
557 $this->assertEquals($data->name, $ex->name);
558 $this->assertEquals($data->description, $ex->description);
559 $this->assertEquals($data->url, $ex->url);
560 $this->assertEquals($data->filtertags, $ex->filtertags);
561 $this->assertEquals($data->modified, transform::datetime($ex->timemodified));
562 $this->assertEquals($data->lastfetched, transform::datetime($ex->timefetched));
563 }
564
565 // Check entries.
566 $entries = [$e1, $e2, $e4, $e4b, $e5, $e5b];
567 $associations = [
568 $e1->id => null,
569 $e2->id => null,
570 $e4->id => $c1ctx->get_context_name(),
571 $e4b->id => $c1ctx->get_context_name(),
572 $e5->id => $cm1actx->get_context_name(),
573 $e5b->id => [$c1ctx->get_context_name(), $cm1actx->get_context_name()],
574 ];
575 foreach ($entries as $e) {
576 $path = [get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'), $e->subject . " ({$e->id})"];
577 $data = $writer->get_data($path);
578 $this->assertNotEmpty($data);
579 $this->assertEquals($data->subject, $e->subject);
580 $this->assertEquals($data->summary, $e->summary);
581 $this->assertEquals($data->publishstate, provider::transform_publishstate($e->publishstate));
582 $this->assertEquals($data->created, transform::datetime($e->created));
583 $this->assertEquals($data->lastmodified, transform::datetime($e->lastmodified));
584
585 // We attached comments and tags to this entry.
586 $commentpath = array_merge($path, [get_string('commentsubcontext', 'core_comment')]);
587 if ($e->id == $e1->id) {
588 $tagdata = $writer->get_related_data($path, 'tags');
2207b0fa 589 $this->assertEquals(['Beer', 'Golf'], $tagdata, '', 0, 10, true);
ce1ec9b4
FM
590
591 $comments = $writer->get_data($commentpath);
592 $this->assertCount(2, $comments->comments);
70720094
AN
593
594 $c0 = strip_tags($comments->comments[0]->content);
595 $c1 = strip_tags($comments->comments[1]->content);
596 $expectedcomments = [
597 'Hello, it\'s me!',
598 'I was wondering if after',
599 ];
600
601 $this->assertNotFalse(array_search($c0, $expectedcomments));
602 $this->assertNotFalse(array_search($c1, $expectedcomments));
603 $this->assertNotEquals($c0, $c1);
ce1ec9b4
FM
604
605 } else {
606 $tagdata = $writer->get_related_data($path, 'tags');
607 $this->assertEmpty($tagdata);
608 $comments = $writer->get_data($commentpath);
609 $this->assertEmpty($comments);
610 }
611
612 if (isset($associations[$e->id])) {
613 $assocs = $associations[$e->id];
614 if (is_array($assocs)) {
615 $this->assertCount(count($assocs), $data->associations);
616 foreach ($assocs as $v) {
617 $this->assertTrue(in_array($v, $data->associations));
618 }
619 } else {
620 $this->assertCount(1, $data->associations);
621 $this->assertTrue(in_array($assocs, $data->associations));
622 }
623 }
624 }
625
626 // The note was not exported.
627 $path = [get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'), "ABC ($note->id)"];
628 $this->assertEmpty($writer->get_data($path));
629
630 }
631
632 /**
633 * Create a blog post.
634 *
635 * @param array $params The params.
636 * @return stdClass
637 */
638 protected function create_post(array $params) {
639 global $DB;
640 $post = new stdClass();
641 $post->module = 'blog';
642 $post->courseid = 0;
643 $post->subject = 'the test post';
644 $post->summary = 'test post summary text';
645 $post->summaryformat = FORMAT_PLAIN;
646 $post->publishstate = 'site';
647 $post->created = time() - HOURSECS;
648 $post->lastmodified = time();
649 foreach ($params as $key => $value) {
650 $post->{$key} = $value;
651 }
652
653 $post->id = $DB->insert_record('post', $post);
654 return $post;
655 }
656
657 /**
658 * Create an extenral blog.
659 *
660 * @param array $params The params.
661 * @return stdClass
662 */
663 protected function create_external_blog(array $params) {
664 global $DB;
665 $post = new stdClass();
666 $post->name = 'test external';
667 $post->description = 'the description';
668 $post->url = 'http://example.com';
669 $post->filtertags = 'a, c, b';
670 $post->timefetched = time() - HOURSECS;
671 $post->timemodified = time();
672 foreach ($params as $key => $value) {
673 $post->{$key} = $value;
674 }
675 $post->id = $DB->insert_record('blog_external', $post);
676 return $post;
677 }
678
679 /**
680 * Get the comment area.
681 *
682 * @param context $context The context.
683 * @param int $itemid The item ID.
684 * @param string $component The component.
685 * @param string $area The area.
686 * @return comment
687 */
688 protected function get_comment_object(context $context, $itemid) {
689 $args = new stdClass();
690 $args->context = $context;
691 $args->course = get_course(SITEID);
692 $args->area = 'format_blog';
693 $args->itemid = $itemid;
694 $args->component = 'blog';
695 $comment = new comment($args);
696 $comment->set_post_permission(true);
697 return $comment;
698 }
699}