Differences Between: [Versions 39 and 310]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * 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 27 defined('MOODLE_INTERNAL') || die(); 28 global $CFG; 29 30 use core_privacy\tests\provider_testcase; 31 use core_privacy\local\request\approved_contextlist; 32 use core_privacy\local\request\transform; 33 use core_privacy\local\request\writer; 34 use core_blog\privacy\provider; 35 36 require_once($CFG->dirroot . '/blog/locallib.php'); 37 require_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 */ 48 class core_blog_privacy_testcase extends provider_testcase { 49 50 public function setUp(): void { 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 /** 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 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 /** 374 * Test provider delete_data_for_user with a context that contains no entries 375 * 376 * @return void 377 */ 378 public function test_delete_data_for_user_empty_context() { 379 global $DB; 380 381 $user = $this->getDataGenerator()->create_user(); 382 $course = $this->getDataGenerator()->create_course(); 383 $context = context_course::instance($course->id); 384 385 // Create a blog entry for user, associated with course. 386 $entry = new blog_entry($this->create_post(['userid' => $user->id, 'courseid' => $course->id])->id); 387 $entry->add_association($context->id); 388 389 // Generate list of contexts for user. 390 $contexts = provider::get_contexts_for_userid($user->id); 391 $this->assertContains($context->id, $contexts->get_contextids()); 392 393 // Now delete the blog entry. 394 $entry->delete(); 395 396 // Try to delete user data using contexts obtained prior to entry deletion. 397 $contextlist = new approved_contextlist($user, 'core_blog', $contexts->get_contextids()); 398 provider::delete_data_for_user($contextlist); 399 400 // Sanity check to ensure blog_associations is really empty. 401 $this->assertEmpty($DB->get_records('blog_association', ['contextid' => $context->id])); 402 } 403 404 public function test_delete_data_for_all_users_in_context() { 405 global $DB; 406 407 $dg = $this->getDataGenerator(); 408 $c1 = $dg->create_course(); 409 $c2 = $dg->create_course(); 410 $cm1a = $dg->create_module('page', ['course' => $c1]); 411 $cm1b = $dg->create_module('page', ['course' => $c1]); 412 $cm2a = $dg->create_module('page', ['course' => $c2]); 413 $u1 = $dg->create_user(); 414 $u2 = $dg->create_user(); 415 416 $c1ctx = context_course::instance($c1->id); 417 $c2ctx = context_course::instance($c2->id); 418 $cm1actx = context_module::instance($cm1a->cmid); 419 $cm1bctx = context_module::instance($cm1b->cmid); 420 $cm2actx = context_module::instance($cm2a->cmid); 421 $u1ctx = context_user::instance($u1->id); 422 423 // Create two external blogs. 424 $extu1 = $this->create_external_blog(['userid' => $u1->id]); 425 $extu2 = $this->create_external_blog(['userid' => $u2->id]); 426 427 // Create a set of posts. 428 $entry = new blog_entry($this->create_post(['userid' => $u1->id])->id); 429 $entry = new blog_entry($this->create_post(['userid' => $u2->id])->id); 430 431 // Course associations for u1 and u2. 432 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id); 433 $entry->add_association($c1ctx->id); 434 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id); 435 $entry->add_association($c1ctx->id); 436 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id); 437 $entry->add_association($c1ctx->id); 438 439 // Module associations for u1 and u2. 440 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id); 441 $entry->add_association($cm1actx->id); 442 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id); 443 $entry->add_association($cm1actx->id); 444 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id])->id); 445 $entry->add_association($cm1bctx->id); 446 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id])->id); 447 $entry->add_association($cm1actx->id); 448 449 // Foreign associations for u1, u2. 450 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c2->id])->id); 451 $entry->add_association($c2ctx->id); 452 $entry = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c2->id])->id); 453 $entry->add_association($c2ctx->id); 454 $entry = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $cm2a->id])->id); 455 $entry->add_association($cm2actx->id); 456 457 // Validate what we've got. 458 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids(); 459 $this->assertCount(8, $DB->get_records('post', ['userid' => $u1->id])); 460 $this->assertCount(6, $contextids); 461 $this->assertTrue(in_array($c1ctx->id, $contextids)); 462 $this->assertTrue(in_array($c2ctx->id, $contextids)); 463 $this->assertTrue(in_array($cm1actx->id, $contextids)); 464 $this->assertTrue(in_array($cm1bctx->id, $contextids)); 465 $this->assertTrue(in_array($cm2actx->id, $contextids)); 466 $this->assertTrue(in_array($u1ctx->id, $contextids)); 467 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids(); 468 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id])); 469 $this->assertCount(4, $contextids); 470 $this->assertTrue(in_array($c1ctx->id, $contextids)); 471 $this->assertTrue(in_array($c2ctx->id, $contextids)); 472 $this->assertTrue(in_array($cm1actx->id, $contextids)); 473 474 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id])); 475 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id])); 476 477 // Delete cm1a context. 478 provider::delete_data_for_all_users_in_context($cm1actx); 479 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids(); 480 $this->assertCount(8, $DB->get_records('post', ['userid' => $u1->id])); 481 $this->assertCount(5, $contextids); 482 $this->assertTrue(in_array($c1ctx->id, $contextids)); 483 $this->assertTrue(in_array($c2ctx->id, $contextids)); 484 $this->assertFalse(in_array($cm1actx->id, $contextids)); 485 $this->assertTrue(in_array($cm1bctx->id, $contextids)); 486 $this->assertTrue(in_array($cm2actx->id, $contextids)); 487 $this->assertTrue(in_array($u1ctx->id, $contextids)); 488 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids(); 489 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id])); 490 $this->assertCount(3, $contextids); 491 $this->assertTrue(in_array($c1ctx->id, $contextids)); 492 $this->assertTrue(in_array($c2ctx->id, $contextids)); 493 $this->assertFalse(in_array($cm1actx->id, $contextids)); 494 495 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id])); 496 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id])); 497 498 // Delete c1 context. 499 provider::delete_data_for_all_users_in_context($c1ctx); 500 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids(); 501 $this->assertCount(8, $DB->get_records('post', ['userid' => $u1->id])); 502 $this->assertCount(4, $contextids); 503 $this->assertFalse(in_array($c1ctx->id, $contextids)); 504 $this->assertTrue(in_array($c2ctx->id, $contextids)); 505 $this->assertFalse(in_array($cm1actx->id, $contextids)); 506 $this->assertTrue(in_array($cm1bctx->id, $contextids)); 507 $this->assertTrue(in_array($cm2actx->id, $contextids)); 508 $this->assertTrue(in_array($u1ctx->id, $contextids)); 509 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids(); 510 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id])); 511 $this->assertCount(2, $contextids); 512 $this->assertFalse(in_array($c1ctx->id, $contextids)); 513 $this->assertTrue(in_array($c2ctx->id, $contextids)); 514 $this->assertFalse(in_array($cm1actx->id, $contextids)); 515 516 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u1->id])); 517 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id])); 518 519 // Delete u1 context. 520 provider::delete_data_for_all_users_in_context($u1ctx); 521 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids(); 522 $this->assertCount(0, $DB->get_records('post', ['userid' => $u1->id])); 523 $this->assertCount(0, $contextids); 524 $this->assertFalse(in_array($c1ctx->id, $contextids)); 525 $this->assertFalse(in_array($c2ctx->id, $contextids)); 526 $this->assertFalse(in_array($cm1actx->id, $contextids)); 527 $this->assertFalse(in_array($cm1bctx->id, $contextids)); 528 $this->assertFalse(in_array($cm2actx->id, $contextids)); 529 $this->assertFalse(in_array($u1ctx->id, $contextids)); 530 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids(); 531 $this->assertCount(4, $DB->get_records('post', ['userid' => $u2->id])); 532 $this->assertCount(2, $contextids); 533 $this->assertFalse(in_array($c1ctx->id, $contextids)); 534 $this->assertTrue(in_array($c2ctx->id, $contextids)); 535 $this->assertFalse(in_array($cm1actx->id, $contextids)); 536 537 $this->assertCount(0, $DB->get_records('blog_external', ['userid' => $u1->id])); 538 $this->assertCount(1, $DB->get_records('blog_external', ['userid' => $u2->id])); 539 } 540 541 public function test_export_data_for_user() { 542 global $DB; 543 $dg = $this->getDataGenerator(); 544 545 $c1 = $dg->create_course(); 546 $cm1a = $dg->create_module('page', ['course' => $c1]); 547 $cm1b = $dg->create_module('page', ['course' => $c1]); 548 $u1 = $dg->create_user(); 549 $u2 = $dg->create_user(); 550 $c1ctx = context_course::instance($c1->id); 551 $cm1actx = context_module::instance($cm1a->cmid); 552 $cm1bctx = context_module::instance($cm1b->cmid); 553 $u1ctx = context_user::instance($u1->id); 554 $u2ctx = context_user::instance($u2->id); 555 556 // System entries. 557 $e1 = new blog_entry($this->create_post(['userid' => $u1->id, 'subject' => 'Hello world!', 558 'publishstate' => 'public'])->id); 559 $e2 = new blog_entry($this->create_post(['userid' => $u1->id, 'subject' => 'Hi planet!', 560 'publishstate' => 'draft'])->id); 561 $e3 = new blog_entry($this->create_post(['userid' => $u2->id, 'subject' => 'Ignore me'])->id); 562 563 // Create a blog entry associated with contexts. 564 $e4 = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'Course assoc'])->id); 565 $e4->add_association($c1ctx->id); 566 $e4b = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'Course assoc 2'])->id); 567 $e4b->add_association($c1ctx->id); 568 $e5 = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'Module assoc', 569 'publishstate' => 'public'])->id); 570 $e5->add_association($cm1actx->id); 571 $e5b = new blog_entry($this->create_post(['userid' => $u1->id, 'courseid' => $c1->id, 'subject' => 'C/CM assoc'])->id); 572 $e5b->add_association($c1ctx->id); 573 $e5b->add_association($cm1actx->id); 574 $e6 = new blog_entry($this->create_post(['userid' => $u2->id, 'courseid' => $c1->id, 'subject' => 'Module assoc'])->id); 575 $e6->add_association($cm1actx->id); 576 577 // External blogs. 578 $ex1 = $this->create_external_blog(['userid' => $u1->id, 'url' => 'https://moodle.org', 'name' => 'Moodle RSS']); 579 $ex2 = $this->create_external_blog(['userid' => $u1->id, 'url' => 'https://example.com', 'name' => 'Example']); 580 $ex3 = $this->create_external_blog(['userid' => $u2->id, 'url' => 'https://example.com', 'name' => 'Ignore me']); 581 582 // Attach tags. 583 core_tag_tag::set_item_tags('core', 'post', $e1->id, $u1ctx, ['Beer', 'Golf']); 584 core_tag_tag::set_item_tags('core', 'blog_external', $ex1->id, $u1ctx, ['Car', 'Golf']); 585 core_tag_tag::set_item_tags('core', 'post', $e3->id, $u2ctx, ['ITG']); 586 core_tag_tag::set_item_tags('core', 'blog_external', $ex3->id, $u2ctx, ['DDR']); 587 core_tag_tag::set_item_tags('core', 'dontfindme', $e1->id, $u1ctx, ['Lone tag']); 588 589 // Attach comments. 590 $comment = $this->get_comment_object($u1ctx, $e1->id); 591 $this->setUser($u1); 592 $comment->add('Hello, it\'s me!'); 593 $this->setUser($u2); 594 $comment->add('I was wondering if after'); 595 $this->setUser($u1); 596 $comment = $this->get_comment_object($u2ctx, $e3->id); 597 $comment->add('All these years'); 598 599 // Blog share a table with notes, so throw some data in there, it should not be exported. 600 $note = $dg->get_plugin_generator('core_notes')->create_instance(['userid' => $u1->id, 'courseid' => $c1->id, 601 'subject' => 'ABC']); 602 603 // Validate module associations. 604 $contextlist = new approved_contextlist($u1, 'core_blog', [$cm1actx->id]); 605 provider::export_user_data($contextlist); 606 $writer = writer::with_context($cm1actx); 607 $assocs = $writer->get_data([get_string('privacy:path:blogassociations', 'core_blog')]); 608 $this->assertCount(2, $assocs->associations); 609 $this->assertTrue(in_array('Module assoc', $assocs->associations)); 610 $this->assertTrue(in_array('C/CM assoc', $assocs->associations)); 611 612 // Validate course associations. 613 $contextlist = new approved_contextlist($u1, 'core_blog', [$c1ctx->id]); 614 provider::export_user_data($contextlist); 615 $writer = writer::with_context($c1ctx); 616 $assocs = $writer->get_data([get_string('privacy:path:blogassociations', 'core_blog')]); 617 $this->assertCount(3, $assocs->associations); 618 $this->assertTrue(in_array('Course assoc', $assocs->associations)); 619 $this->assertTrue(in_array('Course assoc 2', $assocs->associations)); 620 $this->assertTrue(in_array('C/CM assoc', $assocs->associations)); 621 622 // Confirm we're not exporting for another user. 623 $contextlist = new approved_contextlist($u2, 'core_blog', [$u2ctx->id]); 624 $writer = writer::with_context($u1ctx); 625 $this->assertFalse($writer->has_any_data()); 626 627 // Now export user context for u2. 628 $this->setUser($u2); 629 $contextlist = new approved_contextlist($u2, 'core_blog', [$u1ctx->id]); 630 provider::export_user_data($contextlist); 631 $writer = writer::with_context($u1ctx); 632 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('externalblogs', 'core_blog'), 633 $ex1->name . " ({$ex1->id})"]); 634 $this->assertEmpty($data); 635 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'), 636 $e2->subject . " ({$e2->id})"]); 637 $this->assertEmpty($data); 638 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'), 639 $e1->subject . " ({$e1->id})"]); 640 $this->assertEmpty($data); 641 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'), 642 $e1->subject . " ({$e1->id})", get_string('commentsubcontext', 'core_comment')]); 643 $this->assertNotEmpty($data); 644 $this->assertCount(1, $data->comments); 645 $comment = array_shift($data->comments); 646 $this->assertEquals('I was wondering if after', strip_tags($comment->content)); 647 648 // Now export user context data. 649 $this->setUser($u1); 650 $contextlist = new approved_contextlist($u1, 'core_blog', [$u1ctx->id]); 651 writer::reset(); 652 provider::export_user_data($contextlist); 653 $writer = writer::with_context($u1ctx); 654 655 // Check external blogs. 656 $externals = [$ex1, $ex2]; 657 foreach ($externals as $ex) { 658 $data = $writer->get_data([get_string('blog', 'core_blog'), get_string('externalblogs', 'core_blog'), 659 $ex->name . " ({$ex->id})"]); 660 $this->assertNotEmpty($data); 661 $this->assertEquals($data->name, $ex->name); 662 $this->assertEquals($data->description, $ex->description); 663 $this->assertEquals($data->url, $ex->url); 664 $this->assertEquals($data->filtertags, $ex->filtertags); 665 $this->assertEquals($data->modified, transform::datetime($ex->timemodified)); 666 $this->assertEquals($data->lastfetched, transform::datetime($ex->timefetched)); 667 } 668 669 // Check entries. 670 $entries = [$e1, $e2, $e4, $e4b, $e5, $e5b]; 671 $associations = [ 672 $e1->id => null, 673 $e2->id => null, 674 $e4->id => $c1ctx->get_context_name(), 675 $e4b->id => $c1ctx->get_context_name(), 676 $e5->id => $cm1actx->get_context_name(), 677 $e5b->id => [$c1ctx->get_context_name(), $cm1actx->get_context_name()], 678 ]; 679 foreach ($entries as $e) { 680 $path = [get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'), $e->subject . " ({$e->id})"]; 681 $data = $writer->get_data($path); 682 $this->assertNotEmpty($data); 683 $this->assertEquals($data->subject, $e->subject); 684 $this->assertEquals($data->summary, $e->summary); 685 $this->assertEquals($data->publishstate, provider::transform_publishstate($e->publishstate)); 686 $this->assertEquals($data->created, transform::datetime($e->created)); 687 $this->assertEquals($data->lastmodified, transform::datetime($e->lastmodified)); 688 689 // We attached comments and tags to this entry. 690 $commentpath = array_merge($path, [get_string('commentsubcontext', 'core_comment')]); 691 if ($e->id == $e1->id) { 692 $tagdata = $writer->get_related_data($path, 'tags'); 693 $this->assertEqualsCanonicalizing(['Beer', 'Golf'], $tagdata); 694 695 $comments = $writer->get_data($commentpath); 696 $this->assertCount(2, $comments->comments); 697 698 $c0 = strip_tags($comments->comments[0]->content); 699 $c1 = strip_tags($comments->comments[1]->content); 700 $expectedcomments = [ 701 'Hello, it\'s me!', 702 'I was wondering if after', 703 ]; 704 705 $this->assertNotFalse(array_search($c0, $expectedcomments)); 706 $this->assertNotFalse(array_search($c1, $expectedcomments)); 707 $this->assertNotEquals($c0, $c1); 708 709 } else { 710 $tagdata = $writer->get_related_data($path, 'tags'); 711 $this->assertEmpty($tagdata); 712 $comments = $writer->get_data($commentpath); 713 $this->assertEmpty($comments); 714 } 715 716 if (isset($associations[$e->id])) { 717 $assocs = $associations[$e->id]; 718 if (is_array($assocs)) { 719 $this->assertCount(count($assocs), $data->associations); 720 foreach ($assocs as $v) { 721 $this->assertTrue(in_array($v, $data->associations)); 722 } 723 } else { 724 $this->assertCount(1, $data->associations); 725 $this->assertTrue(in_array($assocs, $data->associations)); 726 } 727 } 728 } 729 730 // The note was not exported. 731 $path = [get_string('blog', 'core_blog'), get_string('blogentries', 'core_blog'), "ABC ($note->id)"]; 732 $this->assertEmpty($writer->get_data($path)); 733 734 } 735 736 /** 737 * Test that deleting of blog information in a user context works as desired. 738 */ 739 public function test_delete_data_for_users_user_context() { 740 global $DB; 741 742 $u1 = $this->getDataGenerator()->create_user(); 743 $u2 = $this->getDataGenerator()->create_user(); 744 $u3 = $this->getDataGenerator()->create_user(); 745 $u4 = $this->getDataGenerator()->create_user(); 746 $u5 = $this->getDataGenerator()->create_user(); 747 748 $u1ctx = context_user::instance($u1->id); 749 750 $post = $this->create_post(['userid' => $u1->id]); 751 $entry = new blog_entry($post->id); 752 753 $comment = $this->get_comment_object($u1ctx, $entry->id); 754 $this->setUser($u1); 755 $comment->add('Hello, I created the blog'); 756 $this->setUser($u2); 757 $comment->add('User 2 making a comment.'); 758 $this->setUser($u3); 759 $comment->add('User 3 here.'); 760 $this->setUser($u4); 761 $comment->add('User 4 is nice.'); 762 $this->setUser($u5); 763 $comment->add('User 5 for the win.'); 764 765 // This will only delete the comments made by user 4 and 5. 766 $this->assertCount(5, $DB->get_records('comments', ['contextid' => $u1ctx->id])); 767 $userlist = new \core_privacy\local\request\approved_userlist($u1ctx, 'core_blog', [$u4->id, $u5->id]); 768 provider::delete_data_for_users($userlist); 769 $this->assertCount(3, $DB->get_records('comments', ['contextid' => $u1ctx->id])); 770 $this->assertCount(1, $DB->get_records('post', ['userid' => $u1->id])); 771 772 // As the owner of the post is here everything will be deleted. 773 $userlist = new \core_privacy\local\request\approved_userlist($u1ctx, 'core_blog', [$u1->id, $u2->id]); 774 provider::delete_data_for_users($userlist); 775 $this->assertEmpty($DB->get_records('comments', ['contextid' => $u1ctx->id])); 776 $this->assertEmpty($DB->get_records('post', ['userid' => $u1->id])); 777 } 778 779 /** 780 * Test that deleting of an external blog in a user context works as desired. 781 */ 782 public function test_delete_data_for_users_external_blog() { 783 global $DB; 784 785 $u1 = $this->getDataGenerator()->create_user(); 786 $u2 = $this->getDataGenerator()->create_user(); 787 788 $u1ctx = context_user::instance($u1->id); 789 $u2ctx = context_user::instance($u2->id); 790 791 $post = $this->create_external_blog(['userid' => $u1->id, 'url' => 'https://moodle.org', 'name' => 'Moodle RSS']); 792 $post2 = $this->create_external_blog(['userid' => $u2->id, 'url' => 'https://moodle.com', 'name' => 'Some other thing']); 793 794 // Check that we have two external blogs created. 795 $this->assertCount(2, $DB->get_records('blog_external')); 796 // This will only delete the external blog for user 1. 797 $userlist = new \core_privacy\local\request\approved_userlist($u1ctx, 'core_blog', [$u1->id, $u2->id]); 798 provider::delete_data_for_users($userlist); 799 $this->assertCount(1, $DB->get_records('blog_external')); 800 } 801 802 public function test_delete_data_for_users_course_and_module_context() { 803 global $DB; 804 805 $u1 = $this->getDataGenerator()->create_user(); 806 $u2 = $this->getDataGenerator()->create_user(); 807 $u3 = $this->getDataGenerator()->create_user(); 808 $u4 = $this->getDataGenerator()->create_user(); 809 $u5 = $this->getDataGenerator()->create_user(); 810 811 $course = $this->getDataGenerator()->create_course(); 812 $module = $this->getDataGenerator()->create_module('page', ['course' => $course]); 813 814 $u1ctx = context_user::instance($u1->id); 815 $u3ctx = context_user::instance($u3->id); 816 $c1ctx = context_course::instance($course->id); 817 $cm1ctx = context_module::instance($module->cmid); 818 819 // Blog with course association. 820 $post1 = $this->create_post(['userid' => $u1->id, 'courseid' => $course->id]); 821 $entry1 = new blog_entry($post1->id); 822 $entry1->add_association($c1ctx->id); 823 824 // Blog with module association. 825 $post2 = $this->create_post(['userid' => $u3->id, 'courseid' => $course->id]); 826 $entry2 = new blog_entry($post2->id); 827 $entry2->add_association($cm1ctx->id); 828 829 $comment = $this->get_comment_object($u1ctx, $entry1->id); 830 $this->setUser($u1); 831 $comment->add('Hello, I created the blog'); 832 $this->setUser($u2); 833 $comment->add('comment on first course blog'); 834 $this->setUser($u4); 835 $comment->add('user 4 on course blog'); 836 837 $comment = $this->get_comment_object($u3ctx, $entry2->id); 838 $this->setUser($u3); 839 $comment->add('Hello, I created the module blog'); 840 $this->setUser($u2); 841 $comment->add('I am commenting on both'); 842 $this->setUser($u5); 843 $comment->add('User 5 for modules'); 844 845 $this->assertCount(6, $DB->get_records('comments', ['component' => 'blog'])); 846 $this->assertCount(2, $DB->get_records('post', ['courseid' => $course->id])); 847 $this->assertCount(2, $DB->get_records('blog_association')); 848 849 // When using the course or module context we are only removing the blog associations and the comments. 850 $userlist = new \core_privacy\local\request\approved_userlist($c1ctx, 'core_blog', [$u2->id, $u1->id, $u5->id]); 851 provider::delete_data_for_users($userlist); 852 // Only one of the blog_associations should be removed. Everything else should be as before. 853 $this->assertCount(6, $DB->get_records('comments', ['component' => 'blog'])); 854 $this->assertCount(2, $DB->get_records('post', ['courseid' => $course->id])); 855 $this->assertCount(1, $DB->get_records('blog_association')); 856 857 $userlist = new \core_privacy\local\request\approved_userlist($cm1ctx, 'core_blog', [$u2->id, $u1->id, $u3->id]); 858 provider::delete_data_for_users($userlist); 859 // Now we've removed the other association. 860 $this->assertCount(6, $DB->get_records('comments', ['component' => 'blog'])); 861 $this->assertCount(2, $DB->get_records('post', ['courseid' => $course->id])); 862 $this->assertEmpty($DB->get_records('blog_association')); 863 } 864 865 /** 866 * Create a blog post. 867 * 868 * @param array $params The params. 869 * @return stdClass 870 */ 871 protected function create_post(array $params) { 872 global $DB; 873 $post = new stdClass(); 874 $post->module = 'blog'; 875 $post->courseid = 0; 876 $post->subject = 'the test post'; 877 $post->summary = 'test post summary text'; 878 $post->summaryformat = FORMAT_PLAIN; 879 $post->publishstate = 'site'; 880 $post->created = time() - HOURSECS; 881 $post->lastmodified = time(); 882 foreach ($params as $key => $value) { 883 $post->{$key} = $value; 884 } 885 886 $post->id = $DB->insert_record('post', $post); 887 return $post; 888 } 889 890 /** 891 * Create an extenral blog. 892 * 893 * @param array $params The params. 894 * @return stdClass 895 */ 896 protected function create_external_blog(array $params) { 897 global $DB; 898 $post = new stdClass(); 899 $post->name = 'test external'; 900 $post->description = 'the description'; 901 $post->url = 'http://example.com'; 902 $post->filtertags = 'a, c, b'; 903 $post->timefetched = time() - HOURSECS; 904 $post->timemodified = time(); 905 foreach ($params as $key => $value) { 906 $post->{$key} = $value; 907 } 908 $post->id = $DB->insert_record('blog_external', $post); 909 return $post; 910 } 911 912 /** 913 * Get the comment area. 914 * 915 * @param context $context The context. 916 * @param int $itemid The item ID. 917 * @param string $component The component. 918 * @param string $area The area. 919 * @return comment 920 */ 921 protected function get_comment_object(context $context, $itemid) { 922 $args = new stdClass(); 923 $args->context = $context; 924 $args->course = get_course(SITEID); 925 $args->area = 'format_blog'; 926 $args->itemid = $itemid; 927 $args->component = 'blog'; 928 $comment = new comment($args); 929 $comment->set_post_permission(true); 930 return $comment; 931 } 932 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body