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_survey
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
27defined('MOODLE_INTERNAL') || die();
28global $CFG;
29
30use core_privacy\tests\provider_testcase;
31use core_privacy\local\request\approved_contextlist;
32use core_privacy\local\request\approved_userlist;
33use core_privacy\local\request\transform;
34use core_privacy\local\request\writer;
35use mod_survey\privacy\provider;
36
37require_once($CFG->dirroot . '/mod/survey/lib.php');
38
39/**
40 * Data provider testcase class.
41 *
42 * @package    mod_survey
43 * @category   test
44 * @copyright  2018 Frédéric Massart
45 * @author     Frédéric Massart <fred@branchup.tech>
46 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
47 */
48class mod_survey_privacy_testcase extends provider_testcase {
49
50    public function setUp(): void {
51        global $PAGE;
52        $this->resetAfterTest();
53        $PAGE->get_renderer('core');
54    }
55
56    public function test_get_contexts_for_userid() {
57        $dg = $this->getDataGenerator();
58
59        $c1 = $dg->create_course();
60        $c2 = $dg->create_course();
61        $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]);
62        $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]);
63        $cm1c = $dg->create_module('survey', ['template' => 2, 'course' => $c1]);
64        $cm2a = $dg->create_module('survey', ['template' => 1, 'course' => $c2]);
65        $cm2b = $dg->create_module('survey', ['template' => 1, 'course' => $c2]);
66        $u1 = $dg->create_user();
67        $u2 = $dg->create_user();
68
69        $this->create_answer($cm1a->id, 1, $u1->id);
70        $this->create_answer($cm1a->id, 1, $u2->id);
71        $this->create_answer($cm1b->id, 1, $u2->id);
72        $this->create_answer($cm2a->id, 1, $u1->id);
73        $this->create_analysis($cm2b->id, $u1->id);
74        $this->create_analysis($cm1c->id, $u2->id);
75
76        $contextids = provider::get_contexts_for_userid($u1->id)->get_contextids();
77        $this->assertCount(3, $contextids);
78        $this->assertTrue(in_array(context_module::instance($cm1a->cmid)->id, $contextids));
79        $this->assertTrue(in_array(context_module::instance($cm2a->cmid)->id, $contextids));
80        $this->assertTrue(in_array(context_module::instance($cm2b->cmid)->id, $contextids));
81
82        $contextids = provider::get_contexts_for_userid($u2->id)->get_contextids();
83        $this->assertCount(3, $contextids);
84        $this->assertTrue(in_array(context_module::instance($cm1a->cmid)->id, $contextids));
85        $this->assertTrue(in_array(context_module::instance($cm1b->cmid)->id, $contextids));
86        $this->assertTrue(in_array(context_module::instance($cm1c->cmid)->id, $contextids));
87    }
88
89    /**
90     * Test for provider::test_get_users_in_context().
91     */
92    public function test_get_users_in_context() {
93        $dg = $this->getDataGenerator();
94        $component = 'mod_survey';
95
96        $c1 = $dg->create_course();
97        $c2 = $dg->create_course();
98        $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]);
99        $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]);
100        $cm2 = $dg->create_module('survey', ['template' => 1, 'course' => $c2]);
101        $cm1acontext = context_module::instance($cm1a->cmid);
102        $cm1bcontext = context_module::instance($cm1b->cmid);
103        $cm2context = context_module::instance($cm2->cmid);
104
105        $u1 = $dg->create_user();
106        $u2 = $dg->create_user();
107        $bothusers = [$u1->id, $u2->id];
108        sort($bothusers);
109
110        $this->create_answer($cm1a->id, 1, $u1->id);
111        $this->create_answer($cm1b->id, 1, $u1->id);
112        $this->create_answer($cm1b->id, 1, $u2->id);
113        $this->create_answer($cm2->id, 1, $u2->id);
114        $this->create_analysis($cm2->id, $u1->id);
115
116        // Cm1a should only contain u1.
117        $userlist = new \core_privacy\local\request\userlist($cm1acontext, $component);
118        provider::get_users_in_context($userlist);
119
120        $this->assertCount(1, $userlist);
121        $this->assertEquals([$u1->id], $userlist->get_userids());
122
123        // Cm1b should contain u1 and u2 (both have answers).
124        $userlist = new \core_privacy\local\request\userlist($cm1bcontext, $component);
125        provider::get_users_in_context($userlist);
126
127        $this->assertCount(2, $userlist);
128        $actual = $userlist->get_userids();
129        sort($actual);
130        $this->assertEquals($bothusers, $actual);
131
132        // Cm2 should contain u1 (analysis) and u2 (answer).
133        $userlist = new \core_privacy\local\request\userlist($cm2context, $component);
134        provider::get_users_in_context($userlist);
135
136        $this->assertCount(2, $userlist);
137        $actual = $userlist->get_userids();
138        sort($actual);
139        $this->assertEquals($bothusers, $actual);
140    }
141
142    public function test_delete_data_for_all_users_in_context() {
143        global $DB;
144        $dg = $this->getDataGenerator();
145
146        $c1 = $dg->create_course();
147        $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]);
148        $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]);
149        $cm1c = $dg->create_module('survey', ['template' => 2, 'course' => $c1]);
150        $u1 = $dg->create_user();
151        $u2 = $dg->create_user();
152
153        $this->create_answer($cm1a->id, 1, $u1->id);
154        $this->create_answer($cm1a->id, 1, $u2->id);
155        $this->create_answer($cm1b->id, 1, $u2->id);
156        $this->create_answer($cm1c->id, 1, $u1->id);
157        $this->create_analysis($cm1a->id, $u1->id);
158        $this->create_analysis($cm1b->id, $u1->id);
159        $this->create_analysis($cm1a->id, $u2->id);
160        $this->create_analysis($cm1c->id, $u2->id);
161
162        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id]));
163        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id]));
164        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id]));
165        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id]));
166        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id]));
167        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id]));
168        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id]));
169        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id]));
170
171        // Deleting the course does nothing.
172        provider::delete_data_for_all_users_in_context(context_course::instance($c1->id));
173        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id]));
174        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id]));
175        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id]));
176        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id]));
177        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id]));
178        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id]));
179        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id]));
180        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id]));
181
182        provider::delete_data_for_all_users_in_context(context_module::instance($cm1c->cmid));
183        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id]));
184        $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id]));
185        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id]));
186        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id]));
187        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id]));
188        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id]));
189        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id]));
190        $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id]));
191
192        provider::delete_data_for_all_users_in_context(context_module::instance($cm1a->cmid));
193        $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id]));
194        $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id]));
195        $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id]));
196        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id]));
197        $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id]));
198        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id]));
199        $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id]));
200        $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id]));
201    }
202
203    public function test_delete_data_for_user() {
204        global $DB;
205        $dg = $this->getDataGenerator();
206
207        $c1 = $dg->create_course();
208        $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]);
209        $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]);
210        $cm1c = $dg->create_module('survey', ['template' => 2, 'course' => $c1]);
211        $u1 = $dg->create_user();
212        $u2 = $dg->create_user();
213
214        $this->create_answer($cm1a->id, 1, $u1->id);
215        $this->create_answer($cm1a->id, 1, $u2->id);
216        $this->create_answer($cm1b->id, 1, $u2->id);
217        $this->create_answer($cm1c->id, 1, $u1->id);
218        $this->create_analysis($cm1a->id, $u1->id);
219        $this->create_analysis($cm1b->id, $u1->id);
220        $this->create_analysis($cm1a->id, $u2->id);
221        $this->create_analysis($cm1c->id, $u2->id);
222
223        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id]));
224        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id]));
225        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id]));
226        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id]));
227        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id]));
228        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id]));
229        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id]));
230        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id]));
231
232        provider::delete_data_for_user(new approved_contextlist($u1, 'mod_survey', [
233            context_course::instance($c1->id)->id,
234            context_module::instance($cm1a->cmid)->id,
235            context_module::instance($cm1b->cmid)->id,
236        ]));
237        $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id]));
238        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id]));
239        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id]));
240        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id]));
241        $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id]));
242        $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id]));
243        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id]));
244        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id]));
245    }
246
247    /**
248     * Test for provider::delete_data_for_users().
249     */
250    public function test_delete_data_for_users() {
251        global $DB;
252        $dg = $this->getDataGenerator();
253        $component = 'mod_survey';
254
255        $c1 = $dg->create_course();
256        $cm1a = $dg->create_module('survey', ['template' => 1, 'course' => $c1]);
257        $cm1b = $dg->create_module('survey', ['template' => 2, 'course' => $c1]);
258        $cm1c = $dg->create_module('survey', ['template' => 2, 'course' => $c1]);
259        $cm1acontext = context_module::instance($cm1a->cmid);
260        $cm1bcontext = context_module::instance($cm1b->cmid);
261
262        $u1 = $dg->create_user();
263        $u2 = $dg->create_user();
264
265        $this->create_answer($cm1a->id, 1, $u1->id);
266        $this->create_answer($cm1a->id, 1, $u2->id);
267        $this->create_analysis($cm1a->id, $u1->id);
268        $this->create_analysis($cm1a->id, $u2->id);
269        $this->create_answer($cm1b->id, 1, $u2->id);
270        $this->create_analysis($cm1b->id, $u1->id);
271        $this->create_answer($cm1c->id, 1, $u1->id);
272        $this->create_analysis($cm1c->id, $u2->id);
273
274        // Confirm data exists before deletion.
275        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id]));
276        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id]));
277        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id]));
278        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1b->id]));
279        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id]));
280        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1b->id]));
281        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id]));
282        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id]));
283
284        // Ensure only approved user data is deleted.
285        $approveduserids = [$u1->id];
286        $approvedlist = new approved_userlist($cm1acontext, $component, $approveduserids);
287        provider::delete_data_for_users($approvedlist);
288
289        $this->assertFalse($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1a->id]));
290        $this->assertFalse($DB->record_exists('survey_analysis', ['userid' => $u1->id, 'survey' => $cm1a->id]));
291        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u2->id, 'survey' => $cm1a->id]));
292        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1a->id]));
293
294        $approveduserids = [$u1->id, $u2->id];
295        $approvedlist = new approved_userlist($cm1bcontext, $component, $approveduserids);
296        provider::delete_data_for_users($approvedlist);
297
298        $this->assertFalse($DB->record_exists('survey_answers', ['survey' => $cm1b->id]));
299        $this->assertFalse($DB->record_exists('survey_analysis', ['survey' => $cm1b->id]));
300
301        $this->assertTrue($DB->record_exists('survey_answers', ['userid' => $u1->id, 'survey' => $cm1c->id]));
302        $this->assertTrue($DB->record_exists('survey_analysis', ['userid' => $u2->id, 'survey' => $cm1c->id]));
303    }
304
305    public function test_export_data_for_user() {
306        global $DB;
307        $dg = $this->getDataGenerator();
308
309        $templates = $DB->get_records_menu('survey', array('template' => 0), 'name', 'name, id');
310
311        $c1 = $dg->create_course();
312        $s1a = $dg->create_module('survey', ['template' => $templates['attlsname'], 'course' => $c1]);
313        $s1b = $dg->create_module('survey', ['template' => $templates['ciqname'], 'course' => $c1]);
314        $s1c = $dg->create_module('survey', ['template' => $templates['collesapname'], 'course' => $c1]);
315        $u1 = $dg->create_user();
316        $u2 = $dg->create_user();
317
318        $s1actx = context_module::instance($s1a->cmid);
319        $s1bctx = context_module::instance($s1b->cmid);
320        $s1cctx = context_module::instance($s1c->cmid);
321
322        $this->answer_survey($s1a, $u1, $c1, $s1actx);
323        $this->answer_survey($s1b, $u1, $c1, $s1bctx);
324        $this->create_analysis($s1a->id, $u1->id, 'Hello,');
325
326        $this->answer_survey($s1a, $u2, $c1, $s1actx);
327        $this->answer_survey($s1c, $u2, $c1, $s1cctx);
328        $this->create_analysis($s1b->id, $u2->id, 'World!');
329
330        provider::export_user_data(new approved_contextlist($u1, 'mod_survey', [$s1actx->id, $s1bctx->id, $s1cctx->id]));
331
332        $data = writer::with_context($s1actx)->get_data([]);
333        $this->assertNotEmpty($data);
334        $this->assert_exported_answers($data->answers, $u1, $s1a);
335        $data = writer::with_context($s1actx)->get_related_data([], 'survey_analysis');
336        $this->assertEquals('Hello,', $data->notes);
337
338        $data = writer::with_context($s1bctx)->get_data([]);
339        $this->assertNotEmpty($data);
340        $this->assert_exported_answers($data->answers, $u1, $s1b);
341        $data = writer::with_context($s1bctx)->get_related_data([], 'survey_analysis');
342        $this->assertEmpty($data);
343
344        $data = writer::with_context($s1cctx)->get_data([]);
345        $this->assertEmpty($data);
346        $data = writer::with_context($s1cctx)->get_related_data([], 'survey_analysis');
347        $this->assertEmpty($data);
348
349        writer::reset();
350        provider::export_user_data(new approved_contextlist($u2, 'mod_survey', [$s1actx->id, $s1bctx->id, $s1cctx->id]));
351
352        $data = writer::with_context($s1actx)->get_data([]);
353        $this->assertNotEmpty($data);
354        $this->assert_exported_answers($data->answers, $u2, $s1a);
355        $data = writer::with_context($s1actx)->get_related_data([], 'survey_analysis');
356        $this->assertEmpty($data);
357
358        $data = writer::with_context($s1bctx)->get_data([]);
359        $this->assertEmpty($data);
360        $data = writer::with_context($s1bctx)->get_related_data([], 'survey_analysis');
361        $this->assertEquals('World!', $data->notes);
362
363        $data = writer::with_context($s1cctx)->get_data([]);
364        $this->assertNotEmpty($data);
365        $this->assert_exported_answers($data->answers, $u2, $s1c);
366        $data = writer::with_context($s1cctx)->get_related_data([], 'survey_analysis');
367        $this->assertEmpty($data);
368    }
369
370    /**
371     * Answer a survey in a predictable manner.
372     *
373     * @param stdClass $survey The survey.
374     * @param stdClass $user The user.
375     * @param stdClass $course The course.
376     * @param context_module $context The module context.
377     * @return void
378     */
379    protected function answer_survey($survey, $user, $course, context_module $context) {
380        global $USER;
381
382        $userid = $user->id;
383        $questions = survey_get_questions($survey);
384        $answer = function(&$answers, $q) use ($userid) {
385            $key = 'q' . ($q->type == 2 ? 'P' : '') . $q->id;
386
387            if ($q->type < 1) {
388                $a = "A:{$q->id}:{$userid}";
389                $answers[$key] = $a;
390
391            } else if ($q->type < 3) {
392                $options = explode(',', get_string($q->options, 'mod_survey'));
393                $answers[$key] = ($q->id + $userid) % count($options) + 1;
394
395            } else {
396                $options = explode(',', get_string($q->options, 'mod_survey'));
397                $answers["q{$q->id}"] = ($q->id + $userid) % count($options) + 1;
398                $answers["qP{$q->id}"] = ($q->id + $userid + 1) % count($options) + 1;
399            }
400
401        };
402
403        foreach ($questions as $q) {
404            if ($q->type < 0) {
405                continue;
406            } else if ($q->type > 0 && $q->multi) {
407                $subquestions = survey_get_subquestions($q);
408                foreach ($subquestions as $sq) {
409                    $answer($answers, $sq);
410                }
411            } else {
412                $answer($answers, $q);
413            }
414        }
415
416        $origuser = $USER;
417        $this->setUser($user);
418        survey_save_answers($survey, $answers, $course, $context);
419        $this->setUser($origuser);
420    }
421
422    /**
423     * Assert the answers provided to a survey.
424     *
425     * @param array $answers The answers.
426     * @param object $user The user.
427     * @param object $survey The survey.
428     * @return void
429     */
430    protected function assert_exported_answers($answers, $user, $survey) {
431        global $DB;
432
433        $userid = $user->id;
434        $questionids = explode(',', $survey->questions);
435        $topquestions = $DB->get_records_list('survey_questions', 'id', $questionids, 'id');
436        $questions = [];
437
438        foreach ($topquestions as $q) {
439            if ($q->type < 0) {
440                continue;
441            } else if ($q->type > 0 && $q->multi) {
442                $questionids = explode(',', $q->multi);
443                $subqs = $DB->get_records_list('survey_questions', 'id', $questionids, 'id');
444            } else {
445                $subqs = [$q];
446            }
447            foreach ($subqs as $sq) {
448                $questions[] = $sq;
449            }
450        }
451
452        $this->assertCount(count($questions), $answers);
453
454        $answer = reset($answers);
455        foreach ($questions as $question) {
456            $qtype = $question->type;
457            $question = survey_translate_question($question);
458            $options = $qtype > 0 ? explode(',', $question->options) : '-';
459            $this->assertEquals($question->text, $answer['question']['text']);
460            $this->assertEquals($question->shorttext, $answer['question']['shorttext']);
461            $this->assertEquals($question->intro, $answer['question']['intro']);
462            $this->assertEquals($options, $answer['question']['options']);
463
464            if ($qtype < 1) {
465                $this->assertEquals("A:{$question->id}:{$userid}", $answer['answer']['actual']);
466
467            } else if ($qtype == 1 || $qtype == 2) {
468                $chosen = ($question->id + $userid) % count($options);
469                $key = $qtype == 1 ? 'actual' : 'preferred';
470                $this->assertEquals($options[$chosen], $answer['answer'][$key]);
471
472            } else {
473                $chosen = ($question->id + $userid) % count($options);
474                $this->assertEquals($options[$chosen], $answer['answer']['actual']);
475                $chosen = ($question->id + $userid + 1) % count($options);
476                $this->assertEquals($options[$chosen], $answer['answer']['preferred']);
477            }
478
479            // Grab next answer, if any.
480            $answer = next($answers);
481        }
482
483    }
484
485    /**
486     * Create analysis.
487     *
488     * @param int $surveyid The survey ID.
489     * @param int $userid The user ID.
490     * @param string $notes The nodes.
491     * @return stdClass
492     */
493    protected function create_analysis($surveyid, $userid, $notes = '') {
494        global $DB;
495        $record = (object) [
496            'survey' => $surveyid,
497            'userid' => $userid,
498            'notes' => $notes
499        ];
500        $record->id = $DB->insert_record('survey_analysis', $record);
501        return $record;
502    }
503
504    /**
505     * Create answer.
506     *
507     * @param int $surveyid The survey ID.
508     * @param int $questionid The question ID.
509     * @param int $userid The user ID.
510     * @param string $answer1 The first answer field.
511     * @param string $answer2 The second answer field.
512     * @return stdClass
513     */
514    protected function create_answer($surveyid, $questionid, $userid, $answer1 = '', $answer2 = '') {
515        global $DB;
516        $record = (object) [
517            'survey' => $surveyid,
518            'question' => $questionid,
519            'userid' => $userid,
520            'answer1' => $answer1,
521            'answer2' => $answer2,
522            'time' => time()
523        ];
524        $record->id = $DB->insert_record('survey_answers', $record);
525        return $record;
526    }
527
528}
529