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