Differences Between: [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 /** 17 * Privacy tests for core_course. 18 * 19 * @package core_course 20 * @category test 21 * @copyright 2018 Adrian Greeve <adrian@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 namespace core_course\privacy; 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 require_once($CFG->dirroot . '/completion/tests/fixtures/completion_creation.php'); 30 31 use core_privacy\local\request\transform; 32 33 /** 34 * Unit tests for course/classes/privacy/policy 35 * 36 * @copyright 2018 Adrian Greeve <adrian@moodle.com> 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 */ 39 class provider_test extends \core_privacy\tests\provider_testcase { 40 41 use \completion_creation; 42 43 /** 44 * Test getting the appropriate context for the userid. This should only ever 45 * return the user context for the user id supplied. 46 */ 47 public function test_get_contexts_for_userid() { 48 $this->resetAfterTest(); 49 50 $user1 = $this->getDataGenerator()->create_user(); 51 $user2 = $this->getDataGenerator()->create_user(); 52 53 // Make sure contexts are not being returned for user1. 54 $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user1->id); 55 $this->assertCount(0, $contextlist->get_contextids()); 56 57 // Make sure contexts are not being returned for user2. 58 $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user2->id); 59 $this->assertCount(0, $contextlist->get_contextids()); 60 61 // Create course completion data for user1. 62 $this->create_course_completion(); 63 $this->complete_course($user1); 64 65 // Make sure the course context is being returned for user1. 66 $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user1->id); 67 $expected = [$this->coursecontext->id]; 68 $actual = $contextlist->get_contextids(); 69 $this->assertCount(1, $actual); 70 $this->assertEquals($expected, $actual); 71 72 // Make sure contexts are still not being returned for user2. 73 $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user2->id); 74 $this->assertCount(0, $contextlist->get_contextids()); 75 76 // User2 has a favourite course. 77 $user2context = \context_user::instance($user2->id); 78 $ufservice = \core_favourites\service_factory::get_service_for_user_context($user2context); 79 $ufservice->create_favourite('core_course', 'courses', $this->coursecontext->instanceid, 80 $this->coursecontext); 81 82 // Make sure the course context is being returned for user2. 83 $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user2->id); 84 $expected = [$this->coursecontext->id]; 85 $actual = $contextlist->get_contextids(); 86 $this->assertCount(1, $actual); 87 $this->assertEquals($expected, $actual); 88 } 89 90 /** 91 * Test fetching users within a context. 92 */ 93 public function test_get_users_in_context() { 94 $this->resetAfterTest(); 95 $component = 'core_course'; 96 97 $user1 = $this->getDataGenerator()->create_user(); 98 $user2 = $this->getDataGenerator()->create_user(); 99 $user3 = $this->getDataGenerator()->create_user(); 100 $user4 = $this->getDataGenerator()->create_user(); 101 102 // User1 and user2 complete course. 103 $this->create_course_completion(); 104 $this->complete_course($user1); 105 $this->complete_course($user2); 106 107 // User3 is enrolled but has not completed course. 108 $this->getDataGenerator()->enrol_user($user3->id, $this->course->id, 'student'); 109 110 // User4 has a favourited course. 111 $systemcontext = \context_system::instance(); 112 $user4ctx = \context_user::instance($user4->id); 113 $ufservice = \core_favourites\service_factory::get_service_for_user_context($user4ctx); 114 $ufservice->create_favourite('core_course', 'courses', $this->coursecontext->instanceid, 115 $this->coursecontext); 116 117 // Ensure only users that have course completion or favourites are returned. 118 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, $component); 119 \core_course\privacy\provider::get_users_in_context($userlist); 120 $expected = [ 121 $user1->id, 122 $user2->id, 123 $user4->id 124 ]; 125 $actual = $userlist->get_userids(); 126 sort($expected); 127 sort($actual); 128 $this->assertCount(3, $actual); 129 $this->assertEquals($expected, $actual); 130 131 // Ensure that users are not being returned in other contexts than the course context. 132 $userlist = new \core_privacy\local\request\userlist($systemcontext, $component); 133 \core_course\privacy\provider::get_users_in_context($userlist); 134 $actual = $userlist->get_userids(); 135 $this->assertCount(0, $actual); 136 } 137 138 /** 139 * Test that user data is exported. 140 */ 141 public function test_export_user_data() { 142 $this->resetAfterTest(); 143 144 $user = $this->getDataGenerator()->create_user(); 145 $this->create_course_completion(); 146 $this->complete_course($user); 147 $approvedlist = new \core_privacy\local\request\approved_contextlist($user, 'core_course', 148 [$this->coursecontext->id]); 149 $writer = \core_privacy\local\request\writer::with_context($this->coursecontext); 150 \core_course\privacy\provider::export_user_data($approvedlist); 151 $completiondata = $writer->get_data([get_string('privacy:completionpath', 'course')]); 152 $this->assertEquals('In progress', $completiondata->status); 153 $this->assertCount(2, $completiondata->criteria); 154 155 // User has a favourite course. 156 $usercontext = \context_user::instance($user->id); 157 $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext); 158 $favourite = $ufservice->create_favourite('core_course', 'courses', 159 $this->coursecontext->instanceid, $this->coursecontext); 160 161 // Ensure that user's favourites data in the course context is being exported. 162 $writer = \core_privacy\local\request\writer::with_context($this->coursecontext); 163 \core_course\privacy\provider::export_user_data($approvedlist); 164 $favouritedata = $writer->get_data([get_string('privacy:favouritespath', 'course')]); 165 166 $this->assertEquals(transform::yesno(true), $favouritedata->starred); 167 $this->assertEquals('', $favouritedata->ordering); 168 $this->assertEquals(transform::datetime($favourite->timecreated), $favouritedata->timecreated); 169 $this->assertEquals(transform::datetime($favourite->timemodified), $favouritedata->timemodified); 170 } 171 172 /** 173 * Verify that if a module context is included in the contextlist_collection and its parent course is not, the 174 * export_context_data() call picks this up, and that the contextual course information is included. 175 */ 176 public function test_export_context_data_module_context_only() { 177 $this->resetAfterTest(); 178 179 // Create a course and a single module. 180 $course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course 1', 'shortname' => 'C1']); 181 $context1 = \context_course::instance($course1->id); 182 $modassign = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id, 'name' => 'assign test 1']); 183 $assigncontext = \context_module::instance($modassign->cmid); 184 185 // Now, let's assume during user info export, only the coursemodule context is returned in the contextlist_collection. 186 $user = $this->getDataGenerator()->create_user(); 187 $collection = new \core_privacy\local\request\contextlist_collection($user->id); 188 $approvedlist = new \core_privacy\local\request\approved_contextlist($user, 'mod_assign', [$assigncontext->id]); 189 $collection->add_contextlist($approvedlist); 190 191 // Now, verify that core_course will detect this, and add relevant contextual information. 192 \core_course\privacy\provider::export_context_data($collection); 193 $writer = \core_privacy\local\request\writer::with_context($context1); 194 $this->assertTrue($writer->has_any_data()); 195 $writerdata = $writer->get_data(); 196 $this->assertObjectHasAttribute('fullname', $writerdata); 197 $this->assertObjectHasAttribute('shortname', $writerdata); 198 $this->assertObjectHasAttribute('idnumber', $writerdata); 199 $this->assertObjectHasAttribute('summary', $writerdata); 200 } 201 202 /** 203 * Verify that if a module context and its parent course context are both included in the contextlist_collection, that course 204 * contextual information is present in the export. 205 */ 206 public function test_export_context_data_course_and_module_contexts() { 207 $this->resetAfterTest(); 208 209 // Create a course and a single module. 210 $course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course 1', 'shortname' => 'C1', 'format' => 'site']); 211 $context1 = \context_course::instance($course1->id); 212 $modassign = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id, 'name' => 'assign test 1']); 213 $assigncontext = \context_module::instance($modassign->cmid); 214 215 // Now, assume during user info export, that both module and course contexts are returned in the contextlist_collection. 216 $user = $this->getDataGenerator()->create_user(); 217 $collection = new \core_privacy\local\request\contextlist_collection($user->id); 218 $approvedlist = new \core_privacy\local\request\approved_contextlist($user, 'mod_assign', [$assigncontext->id]); 219 $approvedlist2 = new \core_privacy\local\request\approved_contextlist($user, 'core_course', [$context1->id]); 220 $collection->add_contextlist($approvedlist); 221 $collection->add_contextlist($approvedlist2); 222 223 // Now, verify that core_course still adds relevant contextual information, even for courses which are explicitly listed in 224 // the contextlist_collection. 225 \core_course\privacy\provider::export_context_data($collection); 226 $writer = \core_privacy\local\request\writer::with_context($context1); 227 $this->assertTrue($writer->has_any_data()); 228 $writerdata = $writer->get_data(); 229 $this->assertObjectHasAttribute('fullname', $writerdata); 230 $this->assertObjectHasAttribute('shortname', $writerdata); 231 $this->assertObjectHasAttribute('idnumber', $writerdata); 232 $this->assertObjectHasAttribute('summary', $writerdata); 233 } 234 235 /** 236 * Test deleting all user data for one context. 237 */ 238 public function test_delete_data_for_all_users_in_context() { 239 global $DB; 240 241 $this->resetAfterTest(); 242 243 $user1 = $this->getDataGenerator()->create_user(); 244 $user2 = $this->getDataGenerator()->create_user(); 245 $this->create_course_completion(); 246 247 $systemcontext = \context_system::instance(); 248 $user1ctx = \context_user::instance($user1->id); 249 $user2ctx = \context_user::instance($user2->id); 250 // User1 and user2 have a favourite course. 251 $ufservice1 = \core_favourites\service_factory::get_service_for_user_context($user1ctx); 252 $ufservice1->create_favourite('core_course', 'courses', $this->coursecontext->instanceid, 253 $this->coursecontext); 254 $ufservice2 = \core_favourites\service_factory::get_service_for_user_context($user2ctx); 255 $ufservice2->create_favourite('core_course', 'courses', $this->coursecontext->instanceid, 256 $this->coursecontext); 257 258 // Ensure only users that have course favourites are returned in the course context (user1 and user2). 259 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 260 \core_course\privacy\provider::get_users_in_context($userlist); 261 $actual = $userlist->get_userids(); 262 $this->assertCount(2, $actual); 263 264 // Ensure the users does not have a course completion data. 265 $records = $DB->get_records('course_modules_completion'); 266 $this->assertCount(0, $records); 267 $records = $DB->get_records('course_completion_crit_compl'); 268 $this->assertCount(0, $records); 269 270 // Create course completions for user1 and users. 271 $this->complete_course($user1); 272 $this->complete_course($user2); 273 $records = $DB->get_records('course_modules_completion'); 274 $this->assertCount(2, $records); 275 $records = $DB->get_records('course_completion_crit_compl'); 276 $this->assertCount(2, $records); 277 278 // Delete data for all users in a context different than the course context (system context). 279 \core_course\privacy\provider::delete_data_for_all_users_in_context($systemcontext); 280 281 // Ensure the data in the course context has not been deleted. 282 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 283 \core_course\privacy\provider::get_users_in_context($userlist); 284 $actual = $userlist->get_userids(); 285 $this->assertCount(2, $actual); 286 287 // Delete data for all users in the course context. 288 \core_course\privacy\provider::delete_data_for_all_users_in_context($this->coursecontext); 289 290 // Ensure the completion data has been removed in the course context. 291 $records = $DB->get_records('course_modules_completion'); 292 $this->assertCount(0, $records); 293 $records = $DB->get_records('course_completion_crit_compl'); 294 $this->assertCount(0, $records); 295 296 // Ensure that users are not returned after the deletion in the course context. 297 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 298 \core_course\privacy\provider::get_users_in_context($userlist); 299 $actual = $userlist->get_userids(); 300 $this->assertCount(0, $actual); 301 } 302 303 /** 304 * Test deleting data for only one user. 305 */ 306 public function test_delete_data_for_user() { 307 $this->resetAfterTest(); 308 309 $user1 = $this->getDataGenerator()->create_user(); 310 $user2 = $this->getDataGenerator()->create_user(); 311 $user3 = $this->getDataGenerator()->create_user(); 312 313 // Create course completion for user1. 314 $this->create_course_completion(); 315 $this->complete_course($user1); 316 317 // Ensure user1 is returned in the course context. 318 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 319 \core_course\privacy\provider::get_users_in_context($userlist); 320 $actual = $userlist->get_userids(); 321 $expected = [$user1->id]; 322 $this->assertCount(1, $actual); 323 $this->assertEquals($expected, $actual); 324 325 // User2 and user3 have a favourite course. 326 $systemcontext = \context_system::instance(); 327 $user2ctx = \context_user::instance($user2->id); 328 $user3ctx = \context_user::instance($user3->id); 329 $ufservice2 = \core_favourites\service_factory::get_service_for_user_context($user2ctx); 330 $ufservice2->create_favourite('core_course', 'courses', $this->coursecontext->instanceid, 331 $this->coursecontext); 332 $ufservice3 = \core_favourites\service_factory::get_service_for_user_context($user3ctx); 333 $ufservice3->create_favourite('core_course', 'courses', $this->coursecontext->instanceid, 334 $this->coursecontext); 335 336 // Ensure user1, user2 and user3 are returned in the course context. 337 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 338 \core_course\privacy\provider::get_users_in_context($userlist); 339 $actual = $userlist->get_userids(); 340 $expected = [ 341 $user1->id, 342 $user2->id, 343 $user3->id 344 ]; 345 sort($expected); 346 sort($actual); 347 $this->assertCount(3, $actual); 348 $this->assertEquals($expected, $actual); 349 350 // Delete user1's data in the course context. 351 $approvedlist = new \core_privacy\local\request\approved_contextlist($user1, 'core_course', 352 [$this->coursecontext->id]); 353 \core_course\privacy\provider::delete_data_for_user($approvedlist); 354 355 // Ensure user1's data is deleted and only user2 and user3 are returned in the course context. 356 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 357 \core_course\privacy\provider::get_users_in_context($userlist); 358 $actual = $userlist->get_userids(); 359 $expected = [ 360 $user2->id, 361 $user3->id 362 ]; 363 sort($expected); 364 sort($actual); 365 $this->assertEquals($expected, $actual); 366 367 // Delete user2's data in a context different than the course context (system context). 368 $approvedlist = new \core_privacy\local\request\approved_contextlist($user2, 'core_course', 369 [$systemcontext->id]); 370 \core_course\privacy\provider::delete_data_for_user($approvedlist); 371 372 // Ensure user2 and user3 are still returned in the course context. 373 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 374 \core_course\privacy\provider::get_users_in_context($userlist); 375 $actual = $userlist->get_userids(); 376 $expected = [ 377 $user2->id, 378 $user3->id 379 ]; 380 sort($expected); 381 sort($actual); 382 $this->assertEquals($expected, $actual); 383 384 // Delete user2's data in the course context. 385 $approvedlist = new \core_privacy\local\request\approved_contextlist($user2, 'core_course', 386 [$this->coursecontext->id]); 387 \core_course\privacy\provider::delete_data_for_user($approvedlist); 388 389 // Ensure user2's is deleted and user3 is still returned in the course context. 390 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 391 \core_course\privacy\provider::get_users_in_context($userlist); 392 $actual = $userlist->get_userids(); 393 $expected = [ 394 $user3->id 395 ]; 396 $this->assertEquals($expected, $actual); 397 } 398 399 /** 400 * Test deleting data within a context for an approved userlist. 401 */ 402 public function test_delete_data_for_users() { 403 $this->resetAfterTest(); 404 405 $component = 'core_course'; 406 $user1 = $this->getDataGenerator()->create_user(); 407 $user2 = $this->getDataGenerator()->create_user(); 408 $user3 = $this->getDataGenerator()->create_user(); 409 410 $this->create_course_completion(); 411 $this->complete_course($user1); 412 $this->complete_course($user2); 413 414 // Ensure user1, user2 are returned in the course context. 415 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 416 \core_course\privacy\provider::get_users_in_context($userlist); 417 $actual = $userlist->get_userids(); 418 $expected = [ 419 $user1->id, 420 $user2->id 421 ]; 422 sort($expected); 423 sort($actual); 424 $this->assertCount(2, $actual); 425 $this->assertEquals($expected, $actual); 426 427 $systemcontext = \context_system::instance(); 428 // User3 has a favourite course. 429 $user3ctx = \context_user::instance($user3->id); 430 $ufservice = \core_favourites\service_factory::get_service_for_user_context($user3ctx); 431 $ufservice->create_favourite('core_course', 'courses', $this->coursecontext->instanceid, 432 $this->coursecontext); 433 434 // Ensure user1, user2 and user3 are now returned in the course context. 435 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 436 \core_course\privacy\provider::get_users_in_context($userlist); 437 $actual = $userlist->get_userids(); 438 $expected = [ 439 $user1->id, 440 $user2->id, 441 $user3->id 442 ]; 443 sort($expected); 444 sort($actual); 445 $this->assertCount(3, $actual); 446 $this->assertEquals($expected, $actual); 447 448 // Delete data for user1 and user3 in the course context. 449 $approveduserids = [$user1->id, $user3->id]; 450 $approvedlist = new \core_privacy\local\request\approved_userlist($this->coursecontext, $component, $approveduserids); 451 \core_course\privacy\provider::delete_data_for_users($approvedlist); 452 453 // Ensure user1 and user3 are deleted and user2 is still returned in the course context. 454 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 455 \core_course\privacy\provider::get_users_in_context($userlist); 456 $actual = $userlist->get_userids(); 457 $expected = [$user2->id]; 458 $this->assertCount(1, $actual); 459 $this->assertEquals($expected, $actual); 460 461 // Try to delete user2's data in a context different than course (system context). 462 $approveduserids = [$user2->id]; 463 $approvedlist = new \core_privacy\local\request\approved_userlist($systemcontext, $component, $approveduserids); 464 \core_course\privacy\provider::delete_data_for_users($approvedlist); 465 466 // Ensure user2 is still returned in the course context. 467 $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course'); 468 \core_course\privacy\provider::get_users_in_context($userlist); 469 $actual = $userlist->get_userids(); 470 $expected = [ 471 $user2->id 472 ]; 473 $this->assertCount(1, $actual); 474 $this->assertEquals($expected, $actual); 475 } 476 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body