Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
defined('MOODLE_INTERNAL') || die();
18
 
19
use mod_questionnaire\generator\question_response,
20
    mod_questionnaire\generator\question_response_rank,
21
    mod_questionnaire\question\question;
22
 
23
global $CFG;
24
require_once($CFG->dirroot.'/mod/questionnaire/locallib.php');
25
require_once($CFG->dirroot . '/mod/questionnaire/classes/question/question.php');
26
 
27
/**
28
 * The mod_questionnaire data generator.
29
 *
30
 * @package    mod_questionnaire
31
 * @copyright  2015 Mike Churchward (mike@churchward.ca)
32
 * @author     Mike Churchward
33
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
class mod_questionnaire_generator extends testing_module_generator {
36
 
37
    /**
38
     * @var int Current position of assigned options.
39
     */
40
    protected $curpos = 0;
41
 
42
    /**
43
     * @var int keep track of how many questions have been created.
44
     */
45
    protected $questioncount = 0;
46
 
47
    /**
48
     * @var int
49
     */
50
    protected $responsecount = 0;
51
 
52
    /**
53
     * @var questionnaire[]
54
     */
55
    protected $questionnaires = [];
56
 
57
    /**
58
     * To be called from data reset code only, do not use in tests.
59
     * @return void
60
     */
61
    public function reset() {
62
        $this->questioncount = 0;
63
        $this->responsecount = 0;
64
        $this->questionnaires = [];
65
        parent::reset();
66
    }
67
 
68
    /**
69
     * Acessor for questionnaires.
70
     * @return array
71
     */
72
    public function questionnaires() {
73
        return $this->questionnaires;
74
    }
75
 
76
    /**
77
     * Create a questionnaire activity.
78
     * @param array $record Will be changed in this function.
79
     * @param array $options
80
     * @return questionnaire
81
     */
82
    public function create_instance($record = null, array $options = null) {
83
        $record = (object)(array)$record;
84
 
85
        $defaultquestionnairesettings = array(
86
            'qtype' => 0,
87
            'respondenttype' => 'fullname',
88
            'resp_eligible' => 'all',
89
            'resp_view' => 0,
90
            'opendate' => 0,
91
            'closedate' => 0,
92
            'resume' => 0,
93
            'navigate' => 0,
94
            'grade' => 0,
95
            'sid' => 0,
96
            'timemodified' => time(),
97
            'completionsubmit' => 0,
98
            'autonum' => 3,
99
            'create' => 'new-0', // Used in form only to indicate a new, empty instance.
100
        );
101
 
102
        foreach ($defaultquestionnairesettings as $name => $value) {
103
            if (!isset($record->{$name})) {
104
                $record->{$name} = $value;
105
            }
106
        }
107
 
108
        $instance = parent::create_instance($record, (array)$options);
109
        $cm = get_coursemodule_from_instance('questionnaire', $instance->id);
110
        $course = get_course($cm->course);
111
        $questionnaire = new questionnaire($course, $cm, 0, $instance, false);
112
 
113
        $this->questionnaires[$instance->id] = $questionnaire;
114
 
115
        return $questionnaire;
116
    }
117
 
118
    /**
119
     * Create a survey instance with data from an existing questionnaire object.
120
     * @param questionnaire $questionnaire
121
     * @param array $record
122
     * @return bool|int
123
     */
124
    public function create_content($questionnaire, $record = array()) {
125
        global $DB;
126
 
127
        $survey = $DB->get_record('questionnaire_survey', array('id' => $questionnaire->sid), '*', MUST_EXIST);
128
        foreach ($record as $name => $value) {
129
            $survey->{$name} = $value;
130
        }
131
        return $questionnaire->survey_update($survey);
132
    }
133
 
134
    /**
135
     * Function to create a question.
136
     *
137
     * @param questionnaire $questionnaire
138
     * @param array|stdClass $record
139
     * @param array|stdClass $data - accompanying data for question - e.g. choices
140
     * @return \mod_questionnaire\question\question the question object
141
     */
142
    public function create_question(questionnaire $questionnaire, $record = null, $data = null) {
143
        global $DB;
144
 
145
        // Increment the question count.
146
        $this->questioncount++;
147
 
148
        $record = (array)$record;
149
 
150
        $record['position'] = count($questionnaire->questions);
151
 
152
        if (!isset($record['surveyid'])) {
153
            throw new coding_exception('surveyid must be present in phpunit_util::create_question() $record');
154
        }
155
 
156
        if (!isset($record['name'])) {
157
            throw new coding_exception('name must be present in phpunit_util::create_question() $record');
158
        }
159
 
160
        if (!isset($record['type_id'])) {
161
            throw new coding_exception('typeid must be present in phpunit_util::create_question() $record');
162
        }
163
 
164
        if (!isset($record['content'])) {
165
            $record['content'] = 'Random '.$this->type_str($record['type_id']).' '.uniqid();
166
        }
167
 
168
        // Get question type.
169
        $typeid = $record['type_id'];
170
 
171
        if ($typeid === QUESRATE && !isset($record['length'])) {
172
            $record['length'] = 5;
173
        }
174
 
175
        if ($typeid !== QUESPAGEBREAK && $typeid !== QUESSECTIONTEXT) {
176
            $qtype = $DB->get_record('questionnaire_question_type', ['id' => $typeid]);
177
            if (!$qtype) {
178
                throw new coding_exception('Could not find question type with id ' . $typeid);
179
            }
180
            // Throw an error if this requires choices and it hasn't got them.
181
            $this->validate_question($qtype->typeid, $data);
182
        }
183
 
184
        $record = (object)$record;
185
 
186
        // Add the question.
187
        $record->id = $DB->insert_record('questionnaire_question', $record);
188
 
189
        $question = \mod_questionnaire\question\question::question_builder($record->type_id, $record->id, $record);
190
 
191
        // Add the question choices if required.
192
        if ($typeid !== QUESPAGEBREAK && $typeid !== QUESSECTIONTEXT) {
193
            if ($question->has_choices()) {
194
                $this->add_question_choices($question, $data);
195
                $record->opts = $data;
196
            }
197
        }
198
 
199
        // Update questionnaire.
200
        $questionnaire->add_questions();
201
 
202
        return $question;
203
    }
204
 
205
    /**
206
     * Create a questionnaire with questions and response data for use in other tests.
207
     * @param stdClass $course
208
     * @param null|int $qtype
209
     * @param array $questiondata
210
     * @param null|array|stdClass $choicedata
211
     * @return questionnaire
212
     */
213
    public function create_test_questionnaire($course, $qtype = null, $questiondata = array(), $choicedata = null) {
214
        $questionnaire = $this->create_instance(array('course' => $course->id));
215
        $cm = get_coursemodule_from_instance('questionnaire', $questionnaire->id);
216
        if ($qtype !== null) {
217
            $questiondata['type_id'] = $qtype;
218
            $questiondata['surveyid'] = $questionnaire->sid;
219
            $questiondata['name'] = isset($questiondata['name']) ? $questiondata['name'] : 'Q1';
220
            $questiondata['content'] = isset($questiondata['content']) ? $questiondata['content'] : 'Test content';
221
            $this->create_question($questionnaire, $questiondata, $choicedata);
222
        }
223
        $questionnaire = new questionnaire($course, $cm, $questionnaire->id, null, true);
224
        return $questionnaire;
225
    }
226
 
227
    /**
228
     * Create a reponse to the supplied question.
229
     * @param questionnaire $questionnaire
230
     * @param question $question
231
     * @param int|array $respval
232
     * @param int $userid
233
     * @param int $section
234
     * @return false|mixed|stdClass
235
     */
236
    public function create_question_response($questionnaire, $question, $respval, $userid = 1, $section = 1) {
237
        global $DB;
238
        $currentrid = 0;
239
        if (!is_array($respval)) {
240
            $respval = ['q'.$question->id => $respval];
241
        }
242
        $respdata = (object)(array_merge(['sec' => $section, 'rid' => $currentrid, 'a' => $questionnaire->id], $respval));
243
        $responseid = $questionnaire->response_insert($respdata, $userid);
244
        $this->response_commit($questionnaire, $responseid);
245
        return $DB->get_record('questionnaire_response', array('id' => $responseid));
246
    }
247
 
248
    /**
249
     * Need to create a method to access a private questionnaire method.
250
     * TO DO - may not need this with above "TO DO".
251
     * @param questionnaire $questionnaire
252
     * @param int $responseid
253
     * @return mixed
254
     */
255
    private function response_commit($questionnaire, $responseid) {
256
        $method = new ReflectionMethod('questionnaire', 'response_commit');
257
        $method->setAccessible(true);
258
        return $method->invoke($questionnaire, $responseid);
259
    }
260
 
261
    /**
262
     * Validate choice question type
263
     * @param array $data
264
     * @throws coding_exception
265
     */
266
    protected function validate_question_choice($data) {
267
        if (empty($data)) {
268
            throw new coding_exception('You must pass in an array of choices for the choice question type');
269
        }
270
    }
271
 
272
    /**
273
     * Validate radio question type
274
     * @param array $data
275
     * @throws coding_exception
276
     */
277
    protected function validate_question_radio($data) {
278
        if (empty($data)) {
279
            throw new coding_exception('You must pass in an array of choices for the radio question type');
280
        }
281
    }
282
 
283
    /**
284
     * Validate checkbox question type
285
     * @param array $data
286
     * @throws coding_exception
287
     */
288
    protected function validate_question_check($data) {
289
        if (empty($data)) {
290
            throw new coding_exception('You must pass in an array of choices for the checkbox question type');
291
        }
292
    }
293
 
294
    /**
295
     * Validate rating question type
296
     * @param array $data
297
     * @throws coding_exception
298
     */
299
    protected function validate_question_rate($data) {
300
        if (empty($data)) {
301
            throw new coding_exception('You must pass in an array of choices for the rate question type');
302
        }
303
    }
304
 
305
    /**
306
     * Thrown an error if the question isn't receiving the data it should receive.
307
     * @param string $typeid
308
     * @param array $data
309
     */
310
    protected function validate_question($typeid, $data) {
311
        if ($typeid == QUESCHOOSE) {
312
            $this->validate_question_choice($data);
313
        } else if ($typeid === QUESRADIO) {
314
            $this->validate_question_radio($data);
315
        } else if ($typeid === QUESCHECK) {
316
            $this->validate_question_check($data);
317
        } else if ($typeid === QUESRATE) {
318
            $this->validate_question_rate($data);
319
        }
320
    }
321
 
322
    /**
323
     * Add choices to question.
324
     *
325
     * @param \mod_questionnaire\question\question $question
326
     * @param array $data
327
     */
328
    protected function add_question_choices($question, $data) {
329
        foreach ($data as $content) {
330
            if (!is_object($content)) {
331
                $content = (object)[
332
                    'content' => $content,
333
                    'value' => $content
334
                ];
335
            }
336
            $record = (object)[
337
                'question_id' => $question->id,
338
                'content' => $content->content,
339
                'value' => $content->value
340
            ];
341
            $question->add_choice($record);
342
        }
343
    }
344
 
345
    /**
346
     * Does this question have choices.
347
     * TODO - use question object
348
     * @param int $typeid
349
     * @return bool
350
     */
351
    public function question_has_choices($typeid) {
352
        $choicequestions = [QUESCHOOSE, QUESRADIO, QUESCHECK, QUESDROP, QUESRATE];
353
        return in_array($typeid, $choicequestions);
354
    }
355
 
356
    /**
357
     * Return a string value for the int id.
358
     * @param int $qtypeid
359
     * @return string
360
     */
361
    public function type_str($qtypeid) {
362
        switch ($qtypeid) {
363
            case QUESYESNO:
364
                $qtype = 'yesno';
365
                break;
366
            case QUESTEXT:
367
                $qtype = 'textbox';
368
                break;
369
            case QUESESSAY:
370
                $qtype = 'essaybox';
371
                break;
372
            case QUESRADIO:
373
                $qtype = 'radiobuttons';
374
                break;
375
            case QUESCHECK:
376
                $qtype = 'checkboxes';
377
                break;
378
            case QUESDROP:
379
                $qtype = 'dropdown';
380
                break;
381
            case QUESRATE:
382
                $qtype = 'ratescale';
383
                break;
384
            case QUESDATE:
385
                $qtype = 'date';
386
                break;
387
            case QUESNUMERIC:
388
                $qtype = 'numeric';
389
                break;
390
            case QUESSECTIONTEXT:
391
                $qtype = 'sectiontext';
392
                break;
393
            case QUESPAGEBREAK:
394
                $qtype = 'sectionbreak';
395
                break;
396
            case QUESSLIDER:
397
                $qtype = 'Slider';
398
                break;
399
        }
400
        return $qtype;
401
    }
402
 
403
    /**
404
     * Return a display string for the int id.
405
     * @param int $qtypeid
406
     * @return string
407
     */
408
    public function type_name($qtypeid) {
409
        switch ($qtypeid) {
410
            case QUESYESNO:
411
                $qtype = 'Yes / No';
412
                break;
413
            case QUESTEXT:
414
                $qtype = 'Text Box';
415
                break;
416
            case QUESESSAY:
417
                $qtype = 'Essay Box';
418
                break;
419
            case QUESRADIO:
420
                $qtype = 'Radio Buttons';
421
                break;
422
            case QUESCHECK:
423
                $qtype = 'Check Boxes';
424
                break;
425
            case QUESDROP:
426
                $qtype = 'Drop Down';
427
                break;
428
            case QUESRATE:
429
                $qtype = 'Rate Scale';
430
                break;
431
            case QUESDATE:
432
                $qtype = 'Date';
433
                break;
434
            case QUESNUMERIC:
435
                $qtype = 'Numeric';
436
                break;
437
            case QUESSECTIONTEXT:
438
                $qtype = 'Section Text';
439
                break;
440
            case QUESPAGEBREAK:
441
                $qtype = 'Section Break';
442
                break;
443
            case QUESSLIDER:
444
                $qtype = 'Slider';
445
                break;
446
        }
447
        return $qtype;
448
    }
449
 
450
    /**
451
     * Add the response choice.
452
     * @param \mod_questionnaire\responsetype\response\response $questionresponse
453
     * @param int $responseid
454
     */
455
    protected function add_response_choice($questionresponse, $responseid) {
456
        global $DB;
457
 
458
        $question = $DB->get_record('questionnaire_question', ['id' => $questionresponse->questionid]);
459
        $qtype = intval($question->type_id);
460
 
461
        if (is_array($questionresponse->response)) {
462
            foreach ($questionresponse->response as $choice) {
463
                $newresponse = clone($questionresponse);
464
                $newresponse->response = $choice;
465
                $this->add_response_choice($newresponse, $responseid);
466
            }
467
            return;
468
        }
469
 
470
        if ($qtype === QUESCHOOSE || $qtype === QUESRADIO || $qtype === QUESDROP || $qtype === QUESCHECK || $qtype === QUESRATE) {
471
            if (is_int($questionresponse->response)) {
472
                $choiceid = $questionresponse->response;
473
            } else {
474
                if ($qtype === QUESRATE) {
475
                    if (!$questionresponse->response instanceof question_response_rank) {
476
                        throw new coding_exception('Question response for ranked choice should be of type question_response_rank');
477
                    }
478
                    $choiceval = $questionresponse->response->choice->content;
479
                } else {
480
                    if (!is_object($questionresponse->response)) {
481
                        $choiceval = $questionresponse->response;
482
                    } else {
483
                        if ($questionresponse->response->content.'' === '') {
484
                            throw new coding_exception('Question response cannot be null for question type '.$qtype);
485
                        }
486
                        $choiceval = $questionresponse->response->content;
487
                    }
488
 
489
                }
490
 
491
                // Lookup the choice id.
492
                $comptext = $DB->sql_compare_text('content');
493
                $select = 'WHERE question_id = ? AND '.$comptext.' = ?';
494
 
495
                $params = [intval($question->id), $choiceval];
496
                $rs = $DB->get_records_sql("SELECT * FROM {questionnaire_quest_choice} $select", $params, 0, 1);
497
                $choice = reset($rs);
498
                if (!$choice) {
499
                    throw new coding_exception('Could not find choice for "'.$choiceval.
500
                        '" (question_id = '.$question->id.')', var_export($choiceval, true));
501
                }
502
                $choiceid = $choice->id;
503
 
504
            }
505
            if ($qtype == QUESRATE) {
506
                $DB->insert_record('questionnaire_response_rank', [
507
                        'response_id' => $responseid,
508
                        'question_id' => $questionresponse->questionid,
509
                        'choice_id' => $choiceid,
510
                        'rankvalue' => $questionresponse->response->rankvalue
511
                    ]
512
                );
513
            } else {
514
                if ($qtype === QUESCHOOSE || $qtype === QUESRADIO || $qtype === QUESDROP) {
515
                    $instable = 'questionnaire_resp_single';
516
                } else if ($qtype === QUESCHECK) {
517
                    $instable = 'questionnaire_resp_multiple';
518
                }
519
                $DB->insert_record($instable, [
520
                        'response_id' => $responseid,
521
                        'question_id' => $questionresponse->questionid,
522
                        'choice_id' => $choiceid
523
                    ]
524
                );
525
            }
526
        } else {
527
            $DB->insert_record('questionnaire_response_text', [
528
                    'response_id' => $responseid,
529
                    'question_id' => $questionresponse->questionid,
530
                    'response' => $questionresponse->response
531
                ]
532
            );
533
        }
534
    }
535
 
536
    /**
537
     * Create response to questionnaire.
538
     *
539
     * @param array $questionresponses
540
     * @param array|stdClass $record
541
     * @param boolean $complete Whether the response is complete or not.
542
     * @return stdClass the discussion object
543
     */
544
    public function create_response($questionresponses, $record = null, $complete = true) {
545
        global $DB;
546
 
547
        // Increment the response count.
548
        $this->responsecount++;
549
 
550
        $record = (array)$record;
551
 
552
        if (!isset($record['questionnaireid'])) {
553
            throw new coding_exception('questionnaireid must be present in phpunit_util::create_response() $record');
554
        }
555
 
556
        if (!isset($record['userid'])) {
557
            throw new coding_exception('userid must be present in phpunit_util::create_response() $record');
558
        }
559
 
560
        $record['submitted'] = time() + $this->responsecount;
561
 
562
        // Add the response.
563
        $record['id'] = $DB->insert_record('questionnaire_response', $record);
564
        $responseid = $record['id'];
565
 
566
        foreach ($questionresponses as $questionresponse) {
567
            if (!$questionresponse instanceof question_response) {
568
                throw new coding_exception('Question responses must have an instance of question_response'.
569
                    var_export($questionresponse, true));
570
            }
571
            $this->add_response_choice($questionresponse, $responseid);
572
        }
573
 
574
        // Mark response as complete.
575
        $record['complete'] = ($complete) ? 'y' : 'n';
576
        $DB->update_record('questionnaire_response', $record);
577
 
578
        return $record;
579
    }
580
 
581
 
582
    /**
583
     * Generate an array of assigned options;
584
     * @param int $number
585
     */
586
    public function assign_opts($number = 5) {
587
        $opts = 'blue, red, yellow, orange, green, purple, white, black, earth, wind, fire, space, car, truck, train' .
588
            ', van, tram, one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve, thirteen' .
589
            ', fourteen, fifteen, sixteen, seventeen, eighteen, nineteen, twenty, happy, sad, jealous, angry';
590
        $opts = explode (', ', $opts);
591
        $numopts = count($opts);
592
 
593
        if ($number > (count($opts) / 2)) {
594
            throw new coding_exception('Maxiumum number of options is '.(count($opts) / 2));
595
        }
596
 
597
        $retopts = [];
598
        while (count($retopts) < $number) {
599
            $retopts[] = $opts[$this->curpos];
600
            $retopts = array_unique($retopts);
601
            if (++$this->curpos == $numopts) {
602
                $this->curpos = 0;
603
            }
604
        }
605
        // Return re-indexed version of array (otherwise you can get a weird index of 1,2,5,9, etc).
606
        return array_values($retopts);
607
    }
608
 
609
    /**
610
     * Generate a response.
611
     * @param questionnaire $questionnaire
612
     * @param \mod_questionnaire\question\question[] $questions
613
     * @param int $userid
614
     * @param bool $complete
615
     * @return stdClass
616
     */
617
    public function generate_response($questionnaire, $questions, $userid, $complete = true) {
618
        $responses = [];
619
        foreach ($questions as $question) {
620
 
621
            $choices = [];
622
            if ($question->has_choices()) {
623
                $choices = array_values($question->choices);
624
            }
625
 
626
            switch ($question->type_id) {
627
                case QUESTEXT :
628
                    $responses[] = new question_response($question->id, 'Test answer');
629
                    break;
630
                case QUESESSAY :
631
                    $resptext = '<h1>Some header text</h1><p>Some paragraph text</p>';
632
                    $responses[] = new question_response($question->id, $resptext);
633
                    break;
634
                case QUESNUMERIC :
635
                    $responses[] = new question_response($question->id, 83);
636
                    break;
637
                case QUESDATE :
638
                    $date = mktime(0, 0, 0, 12, 28, 2017);
639
                    $dateformat = get_string('strfdate', 'questionnaire');
640
                    $datestr = userdate ($date, $dateformat, '1', false);
641
                    $responses[] = new question_response($question->id, $datestr);
642
                    break;
643
                case QUESRADIO :
644
                case QUESDROP :
645
                    $optidx = count($choices) - 1;
646
                    $responses[] = new question_response($question->id, $choices[$optidx]);
647
                    break;
648
                case QUESCHECK :
649
                    $answers = [];
650
                    for ($a = 0; $a < count($choices) - 1; $a++) {
651
                        $optidx = count($choices) - 1;
652
                        $answers[] = $choices[$optidx]->content;
653
                    }
654
 
655
                    $answers = array_unique($answers);
656
 
657
                    $responses[] = new question_response($question->id, $answers);
658
                    break;
659
                case QUESRATE :
660
                    $answers = [];
661
                    for ($a = 0; $a < count($choices) - 1; $a++) {
662
                        $answers[] = new question_response_rank($choices[$a], (($a % 5) + 1));
663
                    }
664
                    $responses[] = new question_response($question->id, $answers);
665
                    break;
666
                case QUESSLIDER :
667
                    $responses[] = new question_response($question->id, 5);
668
                    break;
669
            }
670
 
671
        }
672
        return $this->create_response($responses, ['questionnaireid' => $questionnaire->id, 'userid' => $userid], $complete);
673
    }
674
 
675
    /**
676
     * Create fully defined questionnaires into the test database.
677
     * @param int $coursecount
678
     * @param int $studentcount
679
     * @param int $questionnairecount
680
     * @param int $questionspertype
681
     */
682
    public function create_and_fully_populate($coursecount = 4, $studentcount = 20, $questionnairecount = 2,
683
                                              $questionspertype = 5) {
684
        global $DB;
685
 
686
        $dg = $this->datagenerator;
687
        $qdg = $this;
688
 
689
        $this->curpos = 0;
690
        $questiontypes = [QUESTEXT, QUESESSAY, QUESNUMERIC, QUESDATE, QUESRADIO, QUESDROP, QUESCHECK, QUESRATE, QUESSLIDER];
691
        $students = [];
692
        $courses = [];
693
        $questionnaires = [];
694
 
695
        for ($u = 0; $u < $studentcount; $u++) {
696
            $students[] = $dg->create_user(['firstname' => 'Testy']);
697
        }
698
 
699
        $manplugin = enrol_get_plugin('manual');
700
 
701
        // Create courses.
702
        for ($c = 0; $c < $coursecount; $c++) {
703
            $course = $dg->create_course();
704
            $courses[] = $course;
705
 
706
            // Enrol students on course.
707
            $manualenrol = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'));
708
            foreach ($students as $student) {
709
                $studentrole = $DB->get_record('role', array('shortname' => 'student'));
710
                $manplugin->enrol_user($manualenrol, $student->id, $studentrole->id);
711
            }
712
        }
713
 
714
        // Create questionnaires in each course.
715
        $qname = 1000;
716
        for ($q = 0; $q < $questionnairecount; $q++) {
717
            foreach ($courses as $course) {
718
                $questionnaire = $qdg->create_instance(['course' => $course->id]);
719
                $questionnaires[] = $questionnaire;
720
                $questions = [];
721
                foreach ($questiontypes as $questiontype) {
722
                    // Add section text for this question.
723
                    $qdg->create_question(
724
                        $questionnaire,
725
                        [
726
                            'surveyid' => $questionnaire->sid,
727
                            'name' => $qdg->type_name($questiontype),
728
                            'type_id' => QUESSECTIONTEXT
729
                        ]
730
                    );
731
                    // Create questions.
732
                    for ($qpt = 0; $qpt < $questionspertype; $qpt++) {
733
                        $opts = null;
734
                        if ($qdg->question_has_choices($questiontype)) {
735
                            $opts = $qdg->assign_opts(10);
736
                        }
737
                        $questions[] = $qdg->create_question(
738
                            $questionnaire,
739
                            [
740
                                'surveyid' => $questionnaire->sid,
741
                                'name' => $qdg->type_name($questiontype).' '.$qname++,
742
                                'type_id' => $questiontype
743
                            ],
744
                            $opts
745
                        );
746
                    }
747
                    // Add page break.
748
                    $qdg->create_question(
749
                        $questionnaire,
750
                        [
751
                            'surveyid' => $questionnaire->sid,
752
                            'name' => 'pagebreak '.$qname++,
753
                            'type_id' => QUESPAGEBREAK
754
                        ]
755
                    );
756
                }
757
 
758
                // Create responses.
759
                $count = 1;
760
                foreach ($students as $student) {
761
                    // Make the last response an "incomplete" response.
762
                    if ($count < $studentcount) {
763
                        $qdg->generate_response($questionnaire, $questions, $student->id);
764
                    } else {
765
                        $qdg->generate_response($questionnaire, $questions, $student->id, false);
766
                    }
767
                    $count++;
768
                }
769
            }
770
        }
771
    }
772
}