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 * Privacy tests for core_grading. 19 * 20 * @package core_grading 21 * @category test 22 * @copyright 2018 Sara Arjona <sara@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 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_grading\privacy\provider; 35 36 /** 37 * Privacy tests for core_grading. 38 * 39 * @copyright 2018 Sara Arjona <sara@moodle.com> 40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 41 */ 42 class core_grading_privacy_testcase extends provider_testcase { 43 44 /** @var stdClass User without data. */ 45 protected $user0; 46 47 /** @var stdClass User with data. */ 48 protected $user1; 49 50 /** @var stdClass User with data. */ 51 protected $user2; 52 53 /** @var context context_module of an activity without grading definitions. */ 54 protected $instancecontext0; 55 56 /** @var context context_module of the activity where the grading definitions are. */ 57 protected $instancecontext1; 58 59 /** @var context context_module of the activity where the grading definitions are. */ 60 protected $instancecontext2; 61 62 /** 63 * Test getting the context for the user ID related to this plugin. 64 */ 65 public function test_get_contexts_for_userid() { 66 global $DB; 67 68 $this->resetAfterTest(); 69 $this->grading_setup_test_scenario_data(); 70 $this->assertCount(2, $DB->get_records('grading_definitions')); 71 72 // User1 has created grading definitions for instance1 and instance2. 73 $contextlist = provider::get_contexts_for_userid($this->user1->id); 74 $this->assertCount(2, $contextlist); 75 $this->assertContains($this->instancecontext1->id, $contextlist->get_contextids()); 76 $this->assertContains($this->instancecontext2->id, $contextlist->get_contextids()); 77 $this->assertNotContains($this->instancecontext0->id, $contextlist->get_contextids()); 78 79 // User2 has only modified grading definitions for instance2. 80 $contextlist = provider::get_contexts_for_userid($this->user2->id); 81 $this->assertCount(1, $contextlist); 82 $this->assertContains($this->instancecontext2->id, $contextlist->get_contextids()); 83 84 // User0 hasn't created or modified any grading definition. 85 $contextlist = provider::get_contexts_for_userid($this->user0->id); 86 $this->assertCount(0, $contextlist); 87 } 88 89 /** 90 * Test retrieval of user ids in a given context. 91 */ 92 public function test_get_users_in_context() { 93 $this->resetAfterTest(); 94 $this->grading_setup_test_scenario_data(); 95 // Instance two has one user who created the definitions and another who modified it. 96 $userlist = new \core_privacy\local\request\userlist($this->instancecontext2, 'core_grading'); 97 provider::get_users_in_context($userlist); 98 // Check that we get both. 99 $this->assertCount(2, $userlist->get_userids()); 100 } 101 102 /** 103 * Export for a user with no grading definitions created or modified will not have any data exported. 104 */ 105 public function test_export_user_data_no_content() { 106 $this->resetAfterTest(); 107 108 $user = $this->getDataGenerator()->create_user(); 109 $this->setUser($user); 110 $context = \context_system::instance(); 111 112 $writer = writer::with_context($context); 113 $this->assertFalse($writer->has_any_data()); 114 $this->export_context_data_for_user($user->id, $context, 'core_grading'); 115 $this->assertFalse(writer::with_context($context)->has_any_data()); 116 } 117 118 /** 119 * Test that data is exported correctly for this plugin. 120 */ 121 public function test_export_user_data() { 122 global $DB; 123 124 $this->resetAfterTest(); 125 $now = time(); 126 $defnameprefix = 'fakename'; 127 $this->grading_setup_test_scenario_data($defnameprefix, $now); 128 $this->assertCount(2, $DB->get_records('grading_definitions')); 129 130 // Validate exported data: instance1 - user0 has NO data. 131 $this->setUser($this->user0); 132 writer::reset(); 133 $writer = writer::with_context($this->instancecontext1); 134 $this->assertFalse($writer->has_any_data()); 135 $this->export_context_data_for_user($this->user0->id, $this->instancecontext1, 'core_grading'); 136 $data = $writer->get_data([get_string('gradingmethod', 'grading')]); 137 $this->assertEmpty($data); 138 139 // Validate exported data: instance0 - user1 has NO data. 140 $this->setUser($this->user1); 141 writer::reset(); 142 $writer = writer::with_context($this->instancecontext0); 143 $this->assertFalse($writer->has_any_data()); 144 $this->export_context_data_for_user($this->user1->id, $this->instancecontext0, 'core_grading'); 145 $data = $writer->get_data([get_string('gradingmethod', 'grading')]); 146 $this->assertEmpty($data); 147 148 // Validate exported data: instance1 - user1 has data (user has created and modified it). 149 writer::reset(); 150 $writer = writer::with_context($this->instancecontext1); 151 $this->assertFalse($writer->has_any_data()); 152 $this->export_context_data_for_user($this->user1->id, $this->instancecontext1, 'core_grading'); 153 $data = $writer->get_data([get_string('gradingmethod', 'grading')]); 154 $this->assertCount(1, $data->definitions); 155 156 $firstkey = reset($data->definitions); 157 $this->assertNotEmpty($firstkey->name); 158 $this->assertEquals('test_method', $firstkey->method); 159 $this->assertEquals(transform::datetime($now), $firstkey->timecreated); 160 $this->assertEquals($this->user1->id, $firstkey->usercreated); 161 $this->assertEquals($defnameprefix.'1', $firstkey->name); 162 163 // Validate exported data: instance2 - user1 has data (user has created it). 164 writer::reset(); 165 $writer = writer::with_context($this->instancecontext2); 166 $this->assertFalse($writer->has_any_data()); 167 $this->export_context_data_for_user($this->user1->id, $this->instancecontext2, 'core_grading'); 168 $data = $writer->get_data([get_string('gradingmethod', 'grading')]); 169 $this->assertCount(1, $data->definitions); 170 171 $firstkey = reset($data->definitions); 172 $this->assertNotEmpty($firstkey->name); 173 $this->assertEquals('test_method', $firstkey->method); 174 $this->assertEquals(transform::datetime($now), $firstkey->timecreated); 175 $this->assertEquals($this->user1->id, $firstkey->usercreated); 176 $this->assertEquals($defnameprefix.'2', $firstkey->name); 177 178 // Validate exported data: instance1 - user2 has NO data. 179 $this->setUser($this->user2); 180 writer::reset(); 181 $writer = writer::with_context($this->instancecontext1); 182 $this->assertFalse($writer->has_any_data()); 183 $this->export_context_data_for_user($this->user2->id, $this->instancecontext1, 'core_grading'); 184 $data = $writer->get_data([get_string('gradingmethod', 'grading')]); 185 $this->assertEmpty($data); 186 187 // Validate exported data: instance2 - user2 has data (user has modified it). 188 $this->setUser($this->user2); 189 writer::reset(); 190 $writer = writer::with_context($this->instancecontext2); 191 $this->assertFalse($writer->has_any_data()); 192 $this->export_context_data_for_user($this->user2->id, $this->instancecontext2, 'core_grading'); 193 $data = $writer->get_data([get_string('gradingmethod', 'grading')]); 194 $this->assertCount(1, $data->definitions); 195 } 196 197 /** 198 * Test for provider::delete_data_for_all_users_in_context(). 199 */ 200 public function test_delete_data_for_all_users_in_context() { 201 global $DB; 202 203 $this->resetAfterTest(); 204 $this->grading_setup_test_scenario_data(); 205 206 // Before deletion, we should have 2 grading_definitions. 207 $this->assertCount(2, $DB->get_records('grading_definitions')); 208 209 // Delete data. 210 provider::delete_data_for_all_users_in_context($this->instancecontext0); 211 provider::delete_data_for_all_users_in_context($this->instancecontext1); 212 provider::delete_data_for_all_users_in_context($this->instancecontext2); 213 214 // Before deletion, we should have same grading_definitions (nothing was deleted). 215 $this->assertCount(2, $DB->get_records('grading_definitions')); 216 } 217 218 /** 219 * Test for provider::delete_data_for_user(). 220 */ 221 public function test_delete_data_for_user() { 222 global $DB; 223 224 $this->resetAfterTest(); 225 $this->grading_setup_test_scenario_data(); 226 227 // Before deletion, we should have 2 grading_definitions. 228 $this->assertCount(2, $DB->get_records('grading_definitions')); 229 230 // Delete data for $user0. 231 $contextlist = provider::get_contexts_for_userid($this->user0->id); 232 $approvedcontextlist = new approved_contextlist( 233 $this->user0, 234 'core_grading', 235 $contextlist->get_contextids() 236 ); 237 provider::delete_data_for_user($approvedcontextlist); 238 239 // Delete data for $user1. 240 $contextlist = provider::get_contexts_for_userid($this->user1->id); 241 $approvedcontextlist = new approved_contextlist( 242 $this->user1, 243 'core_grading', 244 $contextlist->get_contextids() 245 ); 246 provider::delete_data_for_user($approvedcontextlist); 247 248 // Delete data for $user2. 249 $contextlist = provider::get_contexts_for_userid($this->user2->id); 250 $approvedcontextlist = new approved_contextlist( 251 $this->user2, 252 'core_grading', 253 $contextlist->get_contextids() 254 ); 255 provider::delete_data_for_user($approvedcontextlist); 256 257 // Before deletion, we should have same grading_definitions (nothing was deleted). 258 $this->assertCount(2, $DB->get_records('grading_definitions')); 259 } 260 261 /** 262 * Test exporting user data relating to an item ID. 263 */ 264 public function test_export_item_data() { 265 global $DB; 266 $this->resetAfterTest(); 267 $course = $this->getDataGenerator()->create_course(); 268 $module = $this->getDataGenerator()->create_module('assign', ['course' => $course]); 269 $user = $this->getDataGenerator()->create_user(); 270 $guidegenerator = \testing_util::get_data_generator()->get_plugin_generator('gradingform_guide'); 271 272 $this->setUser($user); 273 274 $modulecontext = context_module::instance($module->cmid); 275 $controller = $guidegenerator->get_test_guide($modulecontext); 276 277 // In the situation of mod_assign this would be the id from assign_grades. 278 $itemid = 1; 279 $instance = $controller->create_instance($user->id, $itemid); 280 $data = $guidegenerator->get_test_form_data( 281 $controller, 282 $itemid, 283 5, 'This user made several mistakes.', 284 10, 'This user has two pictures.' 285 ); 286 287 $instance->update($data); 288 $instanceid = $instance->get_data('id'); 289 290 provider::export_item_data($modulecontext, $itemid, ['Test']); 291 $data = (array) writer::with_context($modulecontext)->get_data(['Test', 'Marking guide', $instance->get_data('id')]); 292 $this->assertCount(2, $data); 293 $this->assertEquals('This user made several mistakes.', $data['Spelling mistakes']->remark); 294 $this->assertEquals(5, $data['Spelling mistakes']->score); 295 $this->assertEquals('This user has two pictures.', $data['Pictures']->remark); 296 $this->assertEquals(10, $data['Pictures']->score); 297 } 298 299 /** 300 * Test deleting user data related to a context and item ID. 301 */ 302 public function test_delete_instance_data() { 303 global $DB; 304 $this->resetAfterTest(); 305 $course = $this->getDataGenerator()->create_course(); 306 $module = $this->getDataGenerator()->create_module('assign', ['course' => $course]); 307 $user = $this->getDataGenerator()->create_user(); 308 $guidegenerator = \testing_util::get_data_generator()->get_plugin_generator('gradingform_guide'); 309 310 $this->setUser($user); 311 312 $modulecontext = context_module::instance($module->cmid); 313 $controller = $guidegenerator->get_test_guide($modulecontext); 314 315 // In the situation of mod_assign this would be the id from assign_grades. 316 $itemid = 1; 317 $instance = $controller->create_instance($user->id, $itemid); 318 $data = $guidegenerator->get_test_form_data( 319 $controller, 320 $itemid, 321 5, 'This user made several mistakes.', 322 10, 'This user has two pictures.' 323 ); 324 $instance->update($data); 325 326 $itemid = 2; 327 $instance = $controller->create_instance($user->id, $itemid); 328 $data = $guidegenerator->get_test_form_data( 329 $controller, 330 $itemid, 331 25, 'This user made no mistakes.', 332 5, 'This user has one picture.' 333 ); 334 $instance->update($data); 335 336 // Check how many records we have in the fillings table. 337 $records = $DB->get_records('gradingform_guide_fillings'); 338 $this->assertCount(4, $records); 339 // Let's delete one of the instances (the last one would be the easiest). 340 provider::delete_instance_data($modulecontext, $itemid); 341 $records = $DB->get_records('gradingform_guide_fillings'); 342 $this->assertCount(2, $records); 343 foreach ($records as $record) { 344 $this->assertNotEquals($instance->get_id(), $record->instanceid); 345 } 346 // This will delete all the rest of the instances for this context. 347 provider::delete_instance_data($modulecontext); 348 $records = $DB->get_records('gradingform_guide_fillings'); 349 $this->assertEmpty($records); 350 } 351 352 /** 353 * Test the deletion of multiple instances at once. 354 */ 355 public function test_delete_data_for_instances() { 356 global $DB; 357 $this->resetAfterTest(); 358 $course = $this->getDataGenerator()->create_course(); 359 $module = $this->getDataGenerator()->create_module('assign', ['course' => $course]); 360 $user1 = $this->getDataGenerator()->create_user(); 361 $user2 = $this->getDataGenerator()->create_user(); 362 $user3 = $this->getDataGenerator()->create_user(); 363 $guidegenerator = \testing_util::get_data_generator()->get_plugin_generator('gradingform_guide'); 364 365 $this->setUser($user1); 366 367 $modulecontext = context_module::instance($module->cmid); 368 $controller = $guidegenerator->get_test_guide($modulecontext); 369 370 // In the situation of mod_assign this would be the id from assign_grades. 371 $itemid1 = 1; 372 $instance1 = $controller->create_instance($user1->id, $itemid1); 373 $data = $guidegenerator->get_test_form_data( 374 $controller, 375 $itemid1, 376 5, 'This user made several mistakes.', 377 10, 'This user has two pictures.' 378 ); 379 $instance1->update($data); 380 381 $itemid2 = 2; 382 $instance2 = $controller->create_instance($user2->id, $itemid2); 383 $data = $guidegenerator->get_test_form_data( 384 $controller, 385 $itemid2, 386 15, 'This user made a couple of mistakes.', 387 10, 'This user has one picture.' 388 ); 389 $instance2->update($data); 390 391 $itemid3 = 3; 392 $instance3 = $controller->create_instance($user3->id, $itemid3); 393 $data = $guidegenerator->get_test_form_data( 394 $controller, 395 $itemid3, 396 20, 'This user made one mistakes.', 397 10, 'This user has one picture.' 398 ); 399 $instance3->update($data); 400 401 $records = $DB->get_records('gradingform_guide_fillings'); 402 $this->assertCount(6, $records); 403 404 // Delete all user data for items 1 and 3. 405 provider::delete_data_for_instances($modulecontext, [$itemid1, $itemid3]); 406 407 $records = $DB->get_records('gradingform_guide_fillings'); 408 $this->assertCount(2, $records); 409 $instanceid = $instance2->get_data('id'); 410 // The instance id should match for all remaining records. 411 foreach ($records as $record) { 412 $this->assertEquals($instanceid, $record->instanceid); 413 } 414 } 415 416 /** 417 * Helper function to setup the environment. 418 * 419 * course 420 * | 421 * +--instance0 (assignment) 422 * | | 423 * +--instance1 (assignment) 424 * | | 425 * | +--grading_definition1 (created and modified by user1) 426 * | | 427 * +--instance2 (assignment) 428 * | | 429 * | +--grading_definition2 (created by user1 and modified by user2) 430 * 431 * 432 * user0 hasn't any data. 433 * 434 * @param string $defnameprefix 435 * @param timestamp $now 436 */ 437 protected function grading_setup_test_scenario_data($defnameprefix = null, $now = null) { 438 global $DB; 439 440 $this->user0 = $this->getDataGenerator()->create_user(); 441 $this->user1 = $this->getDataGenerator()->create_user(); 442 $this->user2 = $this->getDataGenerator()->create_user(); 443 444 // Create a course. 445 $course = $this->getDataGenerator()->create_course(); 446 $coursecontext = context_course::instance($course->id); 447 448 // Create some assignment instances. 449 $params = (object)array( 450 'course' => $course->id, 451 'name' => 'Testing instance' 452 ); 453 $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); 454 $instance0 = $generator->create_instance($params); 455 $cm0 = get_coursemodule_from_instance('assign', $instance0->id); 456 $this->instancecontext0 = context_module::instance($cm0->id); 457 $instance1 = $generator->create_instance($params); 458 $cm1 = get_coursemodule_from_instance('assign', $instance1->id); 459 $this->instancecontext1 = context_module::instance($cm1->id); 460 $instance2 = $generator->create_instance($params); 461 $cm2 = get_coursemodule_from_instance('assign', $instance2->id); 462 $this->instancecontext2 = context_module::instance($cm2->id); 463 464 // Create fake grading areas. 465 $fakearea1 = (object)array( 466 'contextid' => $this->instancecontext1->id, 467 'component' => 'mod_assign', 468 'areaname' => 'submissions', 469 'activemethod' => 'test_method' 470 ); 471 $fakeareaid1 = $DB->insert_record('grading_areas', $fakearea1); 472 $fakearea2 = clone($fakearea1); 473 $fakearea2->contextid = $this->instancecontext2->id; 474 $fakeareaid2 = $DB->insert_record('grading_areas', $fakearea2); 475 476 // Create fake grading definitions. 477 if (empty($now)) { 478 $now = time(); 479 } 480 if (empty($defnameprefix)) { 481 $defnameprefix = 'fakename'; 482 } 483 $fakedefinition1 = (object)array( 484 'areaid' => $fakeareaid1, 485 'method' => 'test_method', 486 'name' => $defnameprefix.'1', 487 'status' => 0, 488 'timecreated' => $now, 489 'usercreated' => $this->user1->id, 490 'timemodified' => $now + 1, 491 'usermodified' => $this->user1->id, 492 ); 493 $fakedefid1 = $DB->insert_record('grading_definitions', $fakedefinition1); 494 $fakedefinition2 = clone($fakedefinition1); 495 $fakedefinition2->areaid = $fakeareaid2; 496 $fakedefinition2->name = $defnameprefix.'2'; 497 $fakedefinition2->usermodified = $this->user2->id; 498 $fakedefid2 = $DB->insert_record('grading_definitions', $fakedefinition2); 499 } 500 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body