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 mod_feedback 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 mod_feedback\privacy\provider; 35 36 require_once($CFG->dirroot . '/mod/feedback/lib.php'); 37 38 /** 39 * Data provider testcase class. 40 * 41 * @package mod_feedback 42 * @category test 43 * @copyright 2018 Frédéric Massart 44 * @author Frédéric Massart <fred@branchup.tech> 45 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 46 */ 47 class mod_feedback_privacy_testcase extends provider_testcase { 48 49 public function setUp(): void { 50 $this->resetAfterTest(); 51 } 52 53 /** 54 * Test getting the contexts for a user. 55 */ 56 public function test_get_contexts_for_userid() { 57 global $DB; 58 $dg = $this->getDataGenerator(); 59 $fg = $dg->get_plugin_generator('mod_feedback'); 60 61 $c1 = $dg->create_course(); 62 $c2 = $dg->create_course(); 63 $cm0a = $dg->create_module('feedback', ['course' => SITEID]); 64 $cm1a = $dg->create_module('feedback', ['course' => $c1, 'anonymous' => FEEDBACK_ANONYMOUS_NO]); 65 $cm1b = $dg->create_module('feedback', ['course' => $c1]); 66 $cm2a = $dg->create_module('feedback', ['course' => $c2]); 67 $cm2b = $dg->create_module('feedback', ['course' => $c2]); 68 $cm2c = $dg->create_module('feedback', ['course' => $c2]); 69 70 $u1 = $dg->create_user(); 71 $u2 = $dg->create_user(); 72 73 foreach ([$cm0a, $cm1a, $cm1b, $cm2a] as $feedback) { 74 $i1 = $fg->create_item_numeric($feedback); 75 $i2 = $fg->create_item_multichoice($feedback); 76 $answers = ['numeric_' . $i1->id => '1', 'multichoice_' . $i2->id => [1]]; 77 78 if ($feedback == $cm1b) { 79 $this->create_submission_with_answers($feedback, $u2, $answers); 80 } else { 81 $this->create_submission_with_answers($feedback, $u1, $answers); 82 } 83 } 84 85 // Unsaved submission for u1 in cm2b. 86 $feedback = $cm2b; 87 $i1 = $fg->create_item_numeric($feedback); 88 $i2 = $fg->create_item_multichoice($feedback); 89 $answers = ['numeric_' . $i1->id => '1', 'multichoice_' . $i2->id => [1]]; 90 $this->create_tmp_submission_with_answers($feedback, $u1, $answers); 91 92 // Unsaved submission for u2 in cm2c. 93 $feedback = $cm2c; 94 $i1 = $fg->create_item_numeric($feedback); 95 $i2 = $fg->create_item_multichoice($feedback); 96 $answers = ['numeric_' . $i1->id => '1', 'multichoice_' . $i2->id => [1]]; 97 $this->create_tmp_submission_with_answers($feedback, $u2, $answers); 98 99 $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids(); 100 $this->assertCount(4, $contextids); 101 $this->assertTrue(in_array(context_module::instance($cm0a->cmid)->id, $contextids)); 102 $this->assertTrue(in_array(context_module::instance($cm1a->cmid)->id, $contextids)); 103 $this->assertTrue(in_array(context_module::instance($cm2a->cmid)->id, $contextids)); 104 $this->assertFalse(in_array(context_module::instance($cm1b->cmid)->id, $contextids)); 105 $this->assertTrue(in_array(context_module::instance($cm2b->cmid)->id, $contextids)); 106 $this->assertFalse(in_array(context_module::instance($cm2c->cmid)->id, $contextids)); 107 108 $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids(); 109 $this->assertCount(2, $contextids); 110 $this->assertFalse(in_array(context_module::instance($cm0a->cmid)->id, $contextids)); 111 $this->assertFalse(in_array(context_module::instance($cm1a->cmid)->id, $contextids)); 112 $this->assertFalse(in_array(context_module::instance($cm2a->cmid)->id, $contextids)); 113 $this->assertTrue(in_array(context_module::instance($cm1b->cmid)->id, $contextids)); 114 $this->assertFalse(in_array(context_module::instance($cm2b->cmid)->id, $contextids)); 115 $this->assertTrue(in_array(context_module::instance($cm2c->cmid)->id, $contextids)); 116 } 117 118 /** 119 * Test getting the users in a context. 120 */ 121 public function test_get_users_in_context() { 122 global $DB; 123 $dg = $this->getDataGenerator(); 124 $fg = $dg->get_plugin_generator('mod_feedback'); 125 $component = 'mod_feedback'; 126 127 $c1 = $dg->create_course(); 128 $c2 = $dg->create_course(); 129 $cm0 = $dg->create_module('feedback', ['course' => SITEID]); 130 $cm1a = $dg->create_module('feedback', ['course' => $c1, 'anonymous' => FEEDBACK_ANONYMOUS_NO]); 131 $cm1b = $dg->create_module('feedback', ['course' => $c1]); 132 $cm2 = $dg->create_module('feedback', ['course' => $c2]); 133 134 $u1 = $dg->create_user(); 135 $u2 = $dg->create_user(); 136 137 foreach ([$cm0, $cm1a, $cm1b, $cm2] as $feedback) { 138 $i1 = $fg->create_item_numeric($feedback); 139 $i2 = $fg->create_item_multichoice($feedback); 140 $answers = ['numeric_' . $i1->id => '1', 'multichoice_' . $i2->id => [1]]; 141 142 if ($feedback == $cm1b) { 143 $this->create_submission_with_answers($feedback, $u2, $answers); 144 } else { 145 $this->create_submission_with_answers($feedback, $u1, $answers); 146 } 147 } 148 149 // Unsaved submission for u2 in cm1a. 150 $feedback = $cm1a; 151 $i1 = $fg->create_item_numeric($feedback); 152 $i2 = $fg->create_item_multichoice($feedback); 153 $answers = ['numeric_' . $i1->id => '1', 'multichoice_' . $i2->id => [1]]; 154 $this->create_tmp_submission_with_answers($feedback, $u2, $answers); 155 156 // Only u1 in cm0. 157 $context = context_module::instance($cm0->cmid); 158 $userlist = new \core_privacy\local\request\userlist($context, $component); 159 provider::get_users_in_context($userlist); 160 161 $this->assertCount(1, $userlist); 162 $this->assertEquals([$u1->id], $userlist->get_userids()); 163 164 $context = context_module::instance($cm1a->cmid); 165 $userlist = new \core_privacy\local\request\userlist($context, $component); 166 provider::get_users_in_context($userlist); 167 168 // Two submissions in cm1a: saved for u1, unsaved for u2. 169 $this->assertCount(2, $userlist); 170 171 $expected = [$u1->id, $u2->id]; 172 $actual = $userlist->get_userids(); 173 sort($expected); 174 sort($actual); 175 176 $this->assertEquals($expected, $actual); 177 178 // Only u2 in cm1b. 179 $context = context_module::instance($cm1b->cmid); 180 $userlist = new \core_privacy\local\request\userlist($context, $component); 181 provider::get_users_in_context($userlist); 182 183 $this->assertCount(1, $userlist); 184 $this->assertEquals([$u2->id], $userlist->get_userids()); 185 186 // Only u1 in cm2. 187 $context = context_module::instance($cm2->cmid); 188 $userlist = new \core_privacy\local\request\userlist($context, $component); 189 provider::get_users_in_context($userlist); 190 191 $this->assertCount(1, $userlist); 192 $this->assertEquals([$u1->id], $userlist->get_userids()); 193 } 194 195 /** 196 * Test deleting user data. 197 */ 198 public function test_delete_data_for_user() { 199 global $DB; 200 $dg = $this->getDataGenerator(); 201 $fg = $dg->get_plugin_generator('mod_feedback'); 202 203 $c1 = $dg->create_course(); 204 $c2 = $dg->create_course(); 205 $cm0a = $dg->create_module('feedback', ['course' => SITEID]); 206 $cm1a = $dg->create_module('feedback', ['course' => $c1, 'anonymous' => FEEDBACK_ANONYMOUS_NO]); 207 $cm2a = $dg->create_module('feedback', ['course' => $c2]); 208 209 $u1 = $dg->create_user(); 210 $u2 = $dg->create_user(); 211 212 // Create a bunch of data. 213 foreach ([$cm1a, $cm0a, $cm2a] as $feedback) { 214 $i1 = $fg->create_item_numeric($feedback); 215 $i2 = $fg->create_item_multichoice($feedback); 216 $answers = ['numeric_' . $i1->id => '1', 'multichoice_' . $i2->id => [1]]; 217 218 // Create u2 user data for this module. 219 if ($feedback == $cm1a) { 220 $this->create_submission_with_answers($feedback, $u2, $answers); 221 $this->create_tmp_submission_with_answers($feedback, $u2, $answers); 222 } 223 224 $this->create_submission_with_answers($feedback, $u1, $answers); 225 $this->create_tmp_submission_with_answers($feedback, $u1, $answers); 226 } 227 228 $appctx = new approved_contextlist($u1, 'mod_feedback', [ 229 context_module::instance($cm0a->cmid)->id, 230 context_module::instance($cm1a->cmid)->id 231 ]); 232 provider::delete_data_for_user($appctx); 233 234 // Confirm all data is gone in those, except for u2. 235 foreach ([$cm0a, $cm1a] as $feedback) { 236 $this->assert_no_feedback_data_for_user($feedback, $u1); 237 if ($feedback == $cm1a) { 238 $this->assert_feedback_data_for_user($feedback, $u2); 239 $this->assert_feedback_tmp_data_for_user($feedback, $u2); 240 } 241 } 242 243 // Confirm cm2a wasn't affected. 244 $this->assert_feedback_data_for_user($cm2a, $u1); 245 $this->assert_feedback_tmp_data_for_user($cm2a, $u1); 246 247 } 248 249 /** 250 * Test deleting data within a context for an approved userlist. 251 */ 252 public function test_delete_data_for_users() { 253 global $DB; 254 $dg = $this->getDataGenerator(); 255 $fg = $dg->get_plugin_generator('mod_feedback'); 256 257 $c1 = $dg->create_course(); 258 $c2 = $dg->create_course(); 259 $cm0 = $dg->create_module('feedback', ['course' => SITEID]); 260 $cm1 = $dg->create_module('feedback', ['course' => $c1, 'anonymous' => FEEDBACK_ANONYMOUS_NO]); 261 $cm2 = $dg->create_module('feedback', ['course' => $c2]); 262 $context0 = context_module::instance($cm0->cmid); 263 $context1 = context_module::instance($cm1->cmid); 264 265 $u1 = $dg->create_user(); 266 $u2 = $dg->create_user(); 267 268 // Create a bunch of data. 269 foreach ([$cm0, $cm1, $cm2] as $feedback) { 270 $i1 = $fg->create_item_numeric($feedback); 271 $i2 = $fg->create_item_multichoice($feedback); 272 $answers = ['numeric_' . $i1->id => '1', 'multichoice_' . $i2->id => [1]]; 273 274 $this->create_submission_with_answers($feedback, $u1, $answers); 275 $this->create_tmp_submission_with_answers($feedback, $u1, $answers); 276 277 $this->create_submission_with_answers($feedback, $u2, $answers); 278 $this->create_tmp_submission_with_answers($feedback, $u2, $answers); 279 } 280 281 // Delete u1 from cm0, ensure u2 data is retained. 282 $approveduserlist = new core_privacy\local\request\approved_userlist($context0, 'mod_feedback', [$u1->id]); 283 provider::delete_data_for_users($approveduserlist); 284 285 $this->assert_no_feedback_data_for_user($cm0, $u1); 286 $this->assert_feedback_data_for_user($cm0, $u2); 287 $this->assert_feedback_tmp_data_for_user($cm0, $u2); 288 289 // Ensure cm1 unaffected by cm1 deletes. 290 $this->assert_feedback_data_for_user($cm1, $u1); 291 $this->assert_feedback_tmp_data_for_user($cm1, $u1); 292 $this->assert_feedback_data_for_user($cm1, $u2); 293 $this->assert_feedback_tmp_data_for_user($cm1, $u2); 294 295 // Delete u1 and u2 from cm1, ensure no data is retained. 296 $approveduserlist = new core_privacy\local\request\approved_userlist($context1, 'mod_feedback', [$u1->id, $u2->id]); 297 provider::delete_data_for_users($approveduserlist); 298 299 $this->assert_no_feedback_data_for_user($cm1, $u1); 300 $this->assert_no_feedback_data_for_user($cm1, $u2); 301 302 // Ensure cm2 is unaffected by any of the deletes. 303 $this->assert_feedback_data_for_user($cm2, $u1); 304 $this->assert_feedback_tmp_data_for_user($cm2, $u1); 305 $this->assert_feedback_data_for_user($cm2, $u2); 306 $this->assert_feedback_tmp_data_for_user($cm2, $u2); 307 } 308 309 /** 310 * Test deleting a whole context. 311 */ 312 public function test_delete_data_for_all_users_in_context() { 313 global $DB; 314 $dg = $this->getDataGenerator(); 315 $fg = $dg->get_plugin_generator('mod_feedback'); 316 317 $c1 = $dg->create_course(); 318 $c2 = $dg->create_course(); 319 $cm0a = $dg->create_module('feedback', ['course' => SITEID]); 320 $cm1a = $dg->create_module('feedback', ['course' => $c1, 'anonymous' => FEEDBACK_ANONYMOUS_NO]); 321 322 $u1 = $dg->create_user(); 323 $u2 = $dg->create_user(); 324 325 // Create a bunch of data. 326 foreach ([$cm1a, $cm0a] as $feedback) { 327 $i1 = $fg->create_item_numeric($feedback); 328 $i2 = $fg->create_item_multichoice($feedback); 329 $answers = ['numeric_' . $i1->id => '1', 'multichoice_' . $i2->id => [1]]; 330 331 $this->create_submission_with_answers($feedback, $u1, $answers); 332 $this->create_tmp_submission_with_answers($feedback, $u1, $answers); 333 334 $this->create_submission_with_answers($feedback, $u2, $answers); 335 $this->create_tmp_submission_with_answers($feedback, $u2, $answers); 336 } 337 338 provider::delete_data_for_all_users_in_context(context_module::instance($cm1a->cmid)); 339 340 $this->assert_no_feedback_data_for_user($cm1a, $u1); 341 $this->assert_no_feedback_data_for_user($cm1a, $u2); 342 $this->assert_feedback_data_for_user($cm0a, $u1); 343 $this->assert_feedback_data_for_user($cm0a, $u2); 344 $this->assert_feedback_tmp_data_for_user($cm0a, $u1); 345 $this->assert_feedback_tmp_data_for_user($cm0a, $u2); 346 } 347 348 /** 349 * Test exporting data. 350 */ 351 public function test_export_user_data() { 352 global $DB; 353 $dg = $this->getDataGenerator(); 354 $fg = $dg->get_plugin_generator('mod_feedback'); 355 356 $c1 = $dg->create_course(); 357 $c2 = $dg->create_course(); 358 $cm0a = $dg->create_module('feedback', ['course' => SITEID]); 359 $cm1a = $dg->create_module('feedback', ['course' => $c1, 'anonymous' => FEEDBACK_ANONYMOUS_NO]); 360 $cm2a = $dg->create_module('feedback', ['course' => $c2, 'anonymous' => FEEDBACK_ANONYMOUS_YES, 'multiple_submit' => 1]); 361 $cm2b = $dg->create_module('feedback', ['course' => $c2]); 362 $cm2c = $dg->create_module('feedback', ['course' => $c2]); 363 364 $u1 = $dg->create_user(); 365 $u2 = $dg->create_user(); 366 367 // Create a bunch of data. 368 foreach ([$cm0a, $cm1a, $cm2a, $cm2b] as $feedback) { 369 $i1 = $fg->create_item_numeric($feedback, ['name' => 'Q1', 'label' => 'L1']); 370 $i2 = $fg->create_item_multichoice($feedback, ['name' => 'Q2', 'label' => 'L2']); 371 $answersu1 = ['numeric_' . $i1->id => '1', 'multichoice_' . $i2->id => [1]]; 372 $answersu2 = ['numeric_' . $i1->id => '2', 'multichoice_' . $i2->id => [2]]; 373 374 if ($cm0a == $feedback) { 375 $this->create_submission_with_answers($feedback, $u1, $answersu1); 376 $this->create_tmp_submission_with_answers($feedback, $u1, $answersu1); 377 } else if ($cm1a == $feedback) { 378 $this->create_tmp_submission_with_answers($feedback, $u1, $answersu1); 379 } else if ($cm2a == $feedback) { 380 $this->create_submission_with_answers($feedback, $u1, $answersu1); 381 $this->create_submission_with_answers($feedback, $u1, ['numeric_' . $i1->id => '1337'], 2); 382 } else if ($cm2c == $feedback) { 383 $this->create_submission_with_answers($feedback, $u1, $answersu1); 384 $this->create_tmp_submission_with_answers($feedback, $u1, $answersu1); 385 } 386 387 $this->create_submission_with_answers($feedback, $u2, $answersu2); 388 $this->create_tmp_submission_with_answers($feedback, $u2, $answersu2); 389 } 390 391 $appctx = new approved_contextlist($u1, 'mod_feedback', [ 392 context_module::instance($cm0a->cmid)->id, 393 context_module::instance($cm1a->cmid)->id, 394 context_module::instance($cm2a->cmid)->id, 395 context_module::instance($cm2b->cmid)->id, 396 ]); 397 provider::export_user_data($appctx); 398 399 // CM0A. 400 $data = writer::with_context(context_module::instance($cm0a->cmid))->get_data(); 401 $this->assertCount(2, $data->submissions); 402 $submission = $data->submissions[0]; 403 $this->assertEquals(transform::yesno(false), $submission['inprogress']); 404 $this->assertEquals(transform::yesno(true), $submission['anonymousresponse']); 405 $this->assertCount(2, $submission['answers']); 406 $this->assertEquals('Q1', $submission['answers'][0]['question']); 407 $this->assertEquals('1', $submission['answers'][0]['answer']); 408 $this->assertEquals('Q2', $submission['answers'][1]['question']); 409 $this->assertEquals('a', $submission['answers'][1]['answer']); 410 $submission = $data->submissions[1]; 411 $this->assertEquals(transform::yesno(true), $submission['inprogress']); 412 $this->assertEquals(transform::yesno(true), $submission['anonymousresponse']); 413 $this->assertCount(2, $submission['answers']); 414 $this->assertEquals('Q1', $submission['answers'][0]['question']); 415 $this->assertEquals('1', $submission['answers'][0]['answer']); 416 $this->assertEquals('Q2', $submission['answers'][1]['question']); 417 $this->assertEquals('a', $submission['answers'][1]['answer']); 418 419 // CM1A. 420 $data = writer::with_context(context_module::instance($cm1a->cmid))->get_data(); 421 $this->assertCount(1, $data->submissions); 422 $submission = $data->submissions[0]; 423 $this->assertEquals(transform::yesno(true), $submission['inprogress']); 424 $this->assertEquals(transform::yesno(false), $submission['anonymousresponse']); 425 $this->assertCount(2, $submission['answers']); 426 $this->assertEquals('Q1', $submission['answers'][0]['question']); 427 $this->assertEquals('1', $submission['answers'][0]['answer']); 428 $this->assertEquals('Q2', $submission['answers'][1]['question']); 429 $this->assertEquals('a', $submission['answers'][1]['answer']); 430 431 // CM2A. 432 $data = writer::with_context(context_module::instance($cm2a->cmid))->get_data(); 433 $this->assertCount(2, $data->submissions); 434 $submission = $data->submissions[0]; 435 $this->assertEquals(transform::yesno(false), $submission['inprogress']); 436 $this->assertEquals(transform::yesno(true), $submission['anonymousresponse']); 437 $this->assertCount(2, $submission['answers']); 438 $this->assertEquals('Q1', $submission['answers'][0]['question']); 439 $this->assertEquals('1', $submission['answers'][0]['answer']); 440 $this->assertEquals('Q2', $submission['answers'][1]['question']); 441 $this->assertEquals('a', $submission['answers'][1]['answer']); 442 $submission = $data->submissions[1]; 443 $this->assertEquals(transform::yesno(false), $submission['inprogress']); 444 $this->assertEquals(transform::yesno(true), $submission['anonymousresponse']); 445 $this->assertCount(1, $submission['answers']); 446 $this->assertEquals('Q1', $submission['answers'][0]['question']); 447 $this->assertEquals('1337', $submission['answers'][0]['answer']); 448 449 // CM2B (no data). 450 $data = writer::with_context(context_module::instance($cm2b->cmid))->get_data(); 451 $this->assertEmpty($data); 452 453 // CM2C (not exported). 454 $data = writer::with_context(context_module::instance($cm2b->cmid))->get_data(); 455 $this->assertEmpty($data); 456 } 457 458 /** 459 * Assert there is no feedback data for a user. 460 * 461 * @param object $feedback The feedback. 462 * @param object $user The user. 463 * @return void 464 */ 465 protected function assert_no_feedback_data_for_user($feedback, $user) { 466 global $DB; 467 $this->assertFalse($DB->record_exists('feedback_completed', ['feedback' => $feedback->id, 'userid' => $user->id])); 468 $this->assertFalse($DB->record_exists('feedback_completedtmp', ['feedback' => $feedback->id, 'userid' => $user->id])); 469 470 // Check that there aren't orphan values because we can't check by userid. 471 $sql = " 472 SELECT fv.id 473 FROM {%s} fv 474 LEFT JOIN {%s} fc 475 ON fc.id = fv.completed 476 WHERE fc.id IS NULL"; 477 $this->assertFalse($DB->record_exists_sql(sprintf($sql, 'feedback_value', 'feedback_completed'), [])); 478 $this->assertFalse($DB->record_exists_sql(sprintf($sql, 'feedback_valuetmp', 'feedback_completedtmp'), [])); 479 } 480 481 /** 482 * Assert there are submissions and answers for user. 483 * 484 * @param object $feedback The feedback. 485 * @param object $user The user. 486 * @param int $submissioncount The number of submissions. 487 * @param int $valuecount The number of values per submission. 488 * @return void 489 */ 490 protected function assert_feedback_data_for_user($feedback, $user, $submissioncount = 1, $valuecount = 2) { 491 global $DB; 492 $completeds = $DB->get_records('feedback_completed', ['feedback' => $feedback->id, 'userid' => $user->id]); 493 $this->assertCount($submissioncount, $completeds); 494 foreach ($completeds as $record) { 495 $this->assertEquals($valuecount, $DB->count_records('feedback_value', ['completed' => $record->id])); 496 } 497 } 498 499 /** 500 * Assert there are temporary submissions and answers for user. 501 * 502 * @param object $feedback The feedback. 503 * @param object $user The user. 504 * @param int $submissioncount The number of submissions. 505 * @param int $valuecount The number of values per submission. 506 * @return void 507 */ 508 protected function assert_feedback_tmp_data_for_user($feedback, $user, $submissioncount = 1, $valuecount = 2) { 509 global $DB; 510 $completedtmps = $DB->get_records('feedback_completedtmp', ['feedback' => $feedback->id, 'userid' => $user->id]); 511 $this->assertCount($submissioncount, $completedtmps); 512 foreach ($completedtmps as $record) { 513 $this->assertEquals($valuecount, $DB->count_records('feedback_valuetmp', ['completed' => $record->id])); 514 } 515 } 516 517 /** 518 * Create an submission with answers. 519 * 520 * @param object $feedback The feedback. 521 * @param object $user The user. 522 * @param array $answers Answers. 523 * @param int $submissioncount The number of submissions expected after this entry. 524 * @return void 525 */ 526 protected function create_submission_with_answers($feedback, $user, $answers, $submissioncount = 1) { 527 global $DB; 528 529 $modinfo = get_fast_modinfo($feedback->course); 530 $cm = $modinfo->get_cm($feedback->cmid); 531 532 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $feedback->course, false, null, null, $user->id); 533 $feedbackcompletion->save_response_tmp((object) $answers); 534 $feedbackcompletion->save_response(); 535 $this->assertEquals($submissioncount, $DB->count_records('feedback_completed', ['feedback' => $feedback->id, 536 'userid' => $user->id])); 537 $this->assertEquals(count($answers), $DB->count_records('feedback_value', [ 538 'completed' => $feedbackcompletion->get_completed()->id])); 539 } 540 541 /** 542 * Create a temporary submission with answers. 543 * 544 * @param object $feedback The feedback. 545 * @param object $user The user. 546 * @param array $answers Answers. 547 * @return void 548 */ 549 protected function create_tmp_submission_with_answers($feedback, $user, $answers) { 550 global $DB; 551 552 $modinfo = get_fast_modinfo($feedback->course); 553 $cm = $modinfo->get_cm($feedback->cmid); 554 555 $feedbackcompletion = new mod_feedback_completion($feedback, $cm, $feedback->course, false, null, null, $user->id); 556 $feedbackcompletion->save_response_tmp((object) $answers); 557 $this->assertEquals(1, $DB->count_records('feedback_completedtmp', ['feedback' => $feedback->id, 'userid' => $user->id])); 558 $this->assertEquals(2, $DB->count_records('feedback_valuetmp', [ 559 'completed' => $feedbackcompletion->get_current_completed_tmp()->id])); 560 } 561 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body