Differences Between: [Versions 311 and 402] [Versions 400 and 402] [Versions 401 and 402]
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 * mod_h5pactivity privacy tests 19 * 20 * @package mod_h5pactivity 21 * @category test 22 * @copyright 2020 Ferran Recio <ferran@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 namespace mod_h5pactivity\privacy; 27 28 use \core_privacy\local\request\approved_contextlist; 29 use \core_privacy\local\request\approved_userlist; 30 use \core_privacy\local\request\writer; 31 use \core_privacy\tests\provider_testcase; 32 use core_xapi\local\statement\item_activity; 33 use core_xapi\test_helper; 34 use stdClass; 35 36 /** 37 * Privacy tests class for mod_h5pactivity. 38 * 39 * @package mod_h5pactivity 40 * @category test 41 * @copyright 2020 Ferran Recio <ferran@moodle.com> 42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 43 * @covers \mod_h5pactivity\privacy\provider 44 */ 45 class provider_test extends provider_testcase { 46 47 /** @var stdClass User without any attempt. */ 48 protected $student0; 49 50 /** @var stdClass User with some attempt. */ 51 protected $student1; 52 53 /** @var stdClass User with some attempt. */ 54 protected $student2; 55 56 /** @var stdClass User with some attempt. */ 57 protected $student3; 58 59 /** @var \context context_module of the H5P activity. */ 60 protected $context; 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 $this->resetAfterTest(true); 67 $this->setAdminUser(); 68 $this->h5pactivity_setup_test_scenario_data(); 69 70 // The student0 hasn't any attempt. 71 $contextlist = provider::get_contexts_for_userid($this->student0->id); 72 $this->assertCount(0, (array) $contextlist->get_contextids()); 73 74 // The student1 has data in the mod_h5pactivity context. 75 $contextlist = provider::get_contexts_for_userid($this->student1->id); 76 $this->assertCount(1, (array) $contextlist->get_contextids()); 77 $this->assertContainsEquals($this->context->id, $contextlist->get_contextids()); 78 } 79 80 /** 81 * Test getting the user IDs for the context related to this plugin. 82 */ 83 public function test_get_users_in_context() { 84 $this->resetAfterTest(true); 85 $this->setAdminUser(); 86 $this->h5pactivity_setup_test_scenario_data(); 87 $component = 'mod_h5pactivity'; 88 89 $userlist = new \core_privacy\local\request\userlist($this->context, $component); 90 provider::get_users_in_context($userlist); 91 92 // Students 1 and 2 have attempts in the H5P context, student 0 does not. 93 $this->assertCount(2, $userlist); 94 95 $expected = [$this->student1->id, $this->student2->id]; 96 $actual = $userlist->get_userids(); 97 sort($expected); 98 sort($actual); 99 $this->assertEquals($expected, $actual); 100 } 101 102 /** 103 * Test that data is exported correctly for this plugin. 104 */ 105 public function test_export_user_data() { 106 $this->resetAfterTest(true); 107 $this->setAdminUser(); 108 $this->h5pactivity_setup_test_scenario_data(); 109 $component = 'mod_h5pactivity'; 110 111 // Validate exported data for student0 (without any attempt). 112 $this->setUser($this->student0); 113 $writer = writer::with_context($this->context); 114 115 $this->export_context_data_for_user($this->student0->id, $this->context, $component); 116 $subcontextattempt1 = [ 117 get_string('myattempts', 'mod_h5pactivity'), 118 get_string('attempt', 'mod_h5pactivity'). " 1" 119 ]; 120 $data = $writer->get_data($subcontextattempt1); 121 $this->assertEmpty($data); 122 123 // Validate exported data for student1. 124 writer::reset(); 125 $this->setUser($this->student1); 126 $writer = writer::with_context($this->context); 127 $this->assertFalse($writer->has_any_data()); 128 $this->export_context_data_for_user($this->student1->id, $this->context, $component); 129 130 $data = $writer->get_data([]); 131 $this->assertEquals('H5P 1', $data->name); 132 133 $data = (array)$writer->get_data($subcontextattempt1); 134 $this->assertCount(1, $data); 135 $this->assertCount(3, (array) reset($data)); 136 $subcontextattempt2 = [ 137 get_string('myattempts', 'mod_h5pactivity'), 138 get_string('attempt', 'mod_h5pactivity'). " 2" 139 ]; 140 $data = (array)$writer->get_data($subcontextattempt2); 141 $this->assertCount(3, (array) reset($data)); 142 // The student1 has only 1 tracked attempts. 143 $subcontextattempt3 = [ 144 get_string('myattempts', 'mod_h5pactivity'), 145 get_string('attempt', 'mod_h5pactivity'). " 3" 146 ]; 147 $data = (array)$writer->get_data($subcontextattempt3); 148 $this->assertEmpty($data); 149 } 150 151 /** 152 * Test for provider::delete_data_for_all_users_in_context(). 153 */ 154 public function test_delete_data_for_all_users_in_context() { 155 global $DB; 156 157 $this->resetAfterTest(true); 158 $this->setAdminUser(); 159 $this->h5pactivity_setup_test_scenario_data(true); 160 161 // Check data before deletion. 162 $this->assertEquals(6, $DB->count_records('h5pactivity_attempts')); 163 $this->assertEquals(18, $DB->count_records('h5pactivity_attempts_results')); 164 $this->assertEquals(2, $DB->count_records('xapi_states')); 165 166 // Delete data based on the context. 167 provider::delete_data_for_all_users_in_context($this->context); 168 169 // After deletion, the attempts entries should have been deleted. 170 $this->assertEquals(0, $DB->count_records('h5pactivity_attempts')); 171 // After deletion, the results entries should have been deleted. 172 $this->assertEquals(0, $DB->count_records('h5pactivity_attempts_results')); 173 // After deletion, the xapi states should have been deleted. 174 $this->assertEquals(0, $DB->count_records('xapi_states')); 175 } 176 177 /** 178 * Test for provider::delete_data_for_user(). 179 */ 180 public function test_delete_data_for_user() { 181 global $DB; 182 183 $this->resetAfterTest(true); 184 $this->setAdminUser(); 185 $this->h5pactivity_setup_test_scenario_data(true); 186 187 $params = ['userid' => $this->student1->id]; 188 189 // Check data before deletion. 190 $this->assertEquals(6, $DB->count_records('h5pactivity_attempts')); 191 $this->assertEquals(18, $DB->count_records('h5pactivity_attempts_results')); 192 $this->assertEquals(2, $DB->count_records('xapi_states')); 193 194 // Save student1 attempts ids. 195 $attemptsids = $DB->get_records_menu('h5pactivity_attempts', $params, '', 'attempt, id'); 196 list($resultselect, $attemptids) = $DB->get_in_or_equal($attemptsids); 197 $resultselect = 'id ' . $resultselect; 198 199 $approvedcontextlist = new approved_contextlist($this->student1, 'h5pactivity', [$this->context->id]); 200 provider::delete_data_for_user($approvedcontextlist); 201 202 // After deletion, the h5pactivity_attempts entries for the first student should have been deleted. 203 $this->assertEquals(0, $DB->count_records('h5pactivity_attempts', $params)); 204 $this->assertEquals(4, $DB->count_records('h5pactivity_attempts')); 205 // After deletion, the results entries for the first student should have been deleted. 206 $count = $DB->count_records_select('h5pactivity_attempts_results', $resultselect, $attemptids); 207 $this->assertEquals(0, $count); 208 $this->assertEquals(12, $DB->count_records('h5pactivity_attempts_results')); 209 // After deletion, the results entries for the first student should have been deleted. 210 $this->assertEquals(0, $DB->count_records('xapi_states', $params)); 211 $this->assertEquals(1, $DB->count_records('xapi_states')); 212 213 // Confirm that the h5pactivity hasn't been removed. 214 $h5pactivitycount = $DB->get_records('h5pactivity'); 215 $this->assertCount(1, (array) $h5pactivitycount); 216 217 // Delete track for student0 (nothing has to be removed). 218 $approvedcontextlist = new approved_contextlist($this->student0, 'h5pactivity', [$this->context->id]); 219 provider::delete_data_for_user($approvedcontextlist); 220 221 $this->assertEquals(4, $DB->count_records('h5pactivity_attempts')); 222 $this->assertEquals(12, $DB->count_records('h5pactivity_attempts_results')); 223 $this->assertEquals(1, $DB->count_records('xapi_states')); 224 } 225 226 /** 227 * Test for provider::delete_data_for_users(). 228 */ 229 public function test_delete_data_for_users() { 230 global $DB; 231 $component = 'mod_h5pactivity'; 232 233 $this->resetAfterTest(true); 234 $this->setAdminUser(); 235 // In this scenario we need a 3rd user to test batch deletion. 236 // Create student2 with 2 attempts. 237 $this->h5pactivity_setup_test_scenario_data(true); 238 239 // Check data before deletion. 240 $this->assertEquals(6, $DB->count_records('h5pactivity_attempts')); 241 $this->assertEquals(18, $DB->count_records('h5pactivity_attempts_results')); 242 $this->assertEquals(2, $DB->count_records('xapi_states')); 243 244 // Save student1 and student2 attempts ids. 245 $params1 = ['userid' => $this->student1->id]; 246 $attempts1ids = $DB->get_records_menu('h5pactivity_attempts', $params1, '', 'attempt, id'); 247 $params2 = ['userid' => $this->student2->id]; 248 $attempts2ids = $DB->get_records_menu('h5pactivity_attempts', $params2, '', 'attempt, id'); 249 list($resultselect, $attemptids) = $DB->get_in_or_equal(array_merge($attempts1ids, $attempts2ids)); 250 $resultselect = 'id ' . $resultselect; 251 252 // Delete student 1 ans 2 data, retain student 3 data. 253 $approveduserids = [$this->student1->id, $this->student2->id]; 254 $approvedlist = new approved_userlist($this->context, $component, $approveduserids); 255 provider::delete_data_for_users($approvedlist); 256 257 // After deletion, the h5pactivity_attempts entries for student1 and student2 should have been deleted. 258 $this->assertEquals(0, $DB->count_records('h5pactivity_attempts', $params1)); 259 $this->assertEquals(0, $DB->count_records('h5pactivity_attempts', $params2)); 260 $this->assertEquals(0, $DB->count_records('xapi_states', $params1)); 261 $this->assertEquals(0, $DB->count_records('xapi_states', $params2)); 262 263 $this->assertEquals(2, $DB->count_records('h5pactivity_attempts')); 264 // After deletion, the results entries for the first and second student should have been deleted. 265 $count = $DB->count_records_select('h5pactivity_attempts_results', $resultselect, $attemptids); 266 $this->assertEquals(0, $count); 267 $this->assertEquals(6, $DB->count_records('h5pactivity_attempts_results')); 268 $this->assertEquals(1, $DB->count_records('xapi_states')); 269 270 // Confirm that the h5pactivity hasn't been removed. 271 $h5pactivitycount = $DB->get_records('h5pactivity'); 272 $this->assertCount(1, (array) $h5pactivitycount); 273 274 // Delete results track for student0 (nothing has to be removed). 275 $approveduserids = [$this->student0->id]; 276 $approvedlist = new approved_userlist($this->context, $component, $approveduserids); 277 provider::delete_data_for_users($approvedlist); 278 279 $this->assertEquals(2, $DB->count_records('h5pactivity_attempts')); 280 $this->assertEquals(6, $DB->count_records('h5pactivity_attempts_results')); 281 $this->assertEquals(1, $DB->count_records('xapi_states')); 282 } 283 284 /** 285 * Helper function to setup 3 users and 2 H5P attempts for student1 and student2. 286 * $this->student0 is always created without any attempt. 287 * 288 * @param bool $extrauser generate a 3rd user (default false). 289 */ 290 protected function h5pactivity_setup_test_scenario_data(bool $extrauser = false): void { 291 global $CFG, $USER; 292 require_once($CFG->dirroot.'/lib/xapi/tests/helper.php'); 293 294 $generator = $this->getDataGenerator(); 295 296 $course = $this->getDataGenerator()->create_course(); 297 $params = ['course' => $course]; 298 $activity = $this->getDataGenerator()->create_module('h5pactivity', $params); 299 $cm = get_coursemodule_from_id('h5pactivity', $activity->cmid, 0, false, MUST_EXIST); 300 $this->context = \context_module::instance($activity->cmid); 301 302 /** @var \mod_h5pactivity_generator $generator */ 303 $generator = $this->getDataGenerator()->get_plugin_generator('mod_h5pactivity'); 304 305 // Create student0 without any attempt. 306 $this->student0 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 307 308 // Create student1 with 2 attempts and 1 xapi state. 309 $this->student1 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 310 $params = ['cmid' => $cm->id, 'userid' => $this->student1->id]; 311 $generator->create_content($activity, $params); 312 $generator->create_content($activity, $params); 313 $currentuser = $USER; 314 $this->setUser($this->student1); 315 test_helper::create_state([ 316 'activity' => item_activity::create_from_id($this->context->id), 317 'component' => 'mod_h5pactivity', 318 ], true); 319 $this->setUser($currentuser); 320 321 // Create student2 with 2 attempts. 322 $this->student2 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 323 $params = ['cmid' => $cm->id, 'userid' => $this->student2->id]; 324 $generator->create_content($activity, $params); 325 $generator->create_content($activity, $params); 326 327 if ($extrauser) { 328 $this->student3 = $this->getDataGenerator()->create_and_enrol($course, 'student'); 329 $params = ['cmid' => $cm->id, 'userid' => $this->student3->id]; 330 $generator->create_content($activity, $params); 331 $generator->create_content($activity, $params); 332 // Add 1 xapi state. 333 $currentuser = $USER; 334 $this->setUser($this->student3); 335 test_helper::create_state([ 336 'activity' => item_activity::create_from_id($this->context->id), 337 'component' => 'mod_h5pactivity', 338 ], true); 339 $this->setUser($currentuser); 340 } 341 } 342 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body