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
/**
18
 * mod_feedback data generator.
19
 *
20
 * @package    mod_feedback
21
 * @category   test
22
 * @copyright  2013 Ankit Agarwal
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
defined('MOODLE_INTERNAL') || die();
27
 
28
/**
29
 * mod_feedback data generator class.
30
 *
31
 * @package    mod_feedback
32
 * @category   test
33
 * @copyright  2013 Ankit Agarwal
34
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
class mod_feedback_generator extends testing_module_generator {
37
 
38
    public function create_instance($record = null, array $options = null) {
39
        global $CFG;
40
        require_once($CFG->dirroot.'/mod/feedback/lib.php');
41
        $record = (object)(array)$record;
42
 
43
        if (!isset($record->anonymous)) {
44
            $record->anonymous = FEEDBACK_ANONYMOUS_YES;
45
        }
46
        if (!isset($record->email_notification)) {
47
            $record->email_notification = 0;
48
        }
49
        if (!isset($record->multiple_submit)) {
50
            $record->multiple_submit = 0;
51
        }
52
        if (!isset($record->autonumbering)) {
53
            $record->autonumbering = 0;
54
        }
55
        if (!isset($record->site_after_submit)) {
56
            $record->site_after_submit = '';
57
        }
58
        if (!isset($record->page_after_submit)) {
59
            $record->page_after_submit = 'This is page after submit';
60
        }
61
        if (!isset($record->page_after_submitformat)) {
62
            $record->page_after_submitformat = FORMAT_MOODLE;
63
        }
64
        if (!isset($record->publish_stats)) {
65
            $record->publish_stats = 0;
66
        }
67
        if (!isset($record->timeopen)) {
68
            $record->timeopen = 0;
69
        }
70
        if (!isset($record->timeclose)) {
71
            $record->timeclose = 0;
72
        }
73
        if (!isset($record->timemodified)) {
74
            $record->timemodified = time();
75
        }
76
        if (!isset($record->completionsubmit)) {
77
            $record->completionsubmit = 0;
78
        }
79
 
80
        // Hack to bypass draft processing of feedback_add_instance.
81
        $record->page_after_submit_editor['itemid'] = false;
82
 
83
        return parent::create_instance($record, (array)$options);
84
    }
85
 
86
    /**
87
     * Create question.
88
     *
89
     * @param array $data Question data
90
     * @return mixed Question instance
91
     */
92
    public function create_question(array $data) {
93
        global $DB;
94
 
95
        $questiontype = $data['questiontype'] ?? 'textfield';
96
        $cm = get_coursemodule_from_id('feedback', $data['cmid']);
97
        $feedback = $DB->get_record('feedback', ['id' => $cm->instance]);
98
 
99
        unset($data['questiontype']);
100
        unset($data['cmid']);
101
 
102
        if (isset($data['values'])) {
103
            $data['values'] = $this->format_item_values($questiontype, $data['values']);
104
        }
105
 
106
        return call_user_func([$this, "create_item_{$questiontype}"], $feedback, $data);
107
    }
108
 
109
    /**
110
     * Create response.
111
     *
112
     * @param array $data Response data.
113
     * @return stdClass feedback_completed response instance.
114
     */
115
    public function create_response(array $data): stdClass {
116
        global $DB;
117
 
118
        $userid = $data['userid'];
119
        $responsenumber = null;
120
        $cm = get_coursemodule_from_id('feedback', $data['cmid']);
121
        $feedback = $DB->get_record('feedback', ['id' => $cm->instance]);
122
        $answers = [];
123
 
124
        if (isset($data['responsenumber']) && trim($data['responsenumber']) !== '') {
125
            $responsenumber = $data['responsenumber'];
126
        }
127
 
128
        if (isset($data['anonymous']) && trim($data['anonymous']) !== '') {
129
            $anonymous = filter_var(trim($data['anonymous']), FILTER_VALIDATE_BOOLEAN);
130
            $feedback->anonymous = $anonymous ? FEEDBACK_ANONYMOUS_YES : FEEDBACK_ANONYMOUS_NO;
131
        }
132
 
133
        unset($data['cmid']);
134
        unset($data['userid']);
135
        unset($data['anonymous']);
136
        unset($data['responsenumber']);
137
 
138
        foreach ($data as $question => $response) {
139
            $item = $DB->get_record('feedback_item', ['name' => trim($question)], '*', MUST_EXIST);
140
 
141
            $answers["{$item->typ}_{$item->id}"] = $this->get_item_response_value($item, $response);
142
        }
143
 
144
        $feedbackcompletion = new mod_feedback_completion(
145
            $feedback,
146
            $cm,
147
            $cm->course,
148
            false,
149
            null,
150
            $feedback->anonymous === FEEDBACK_ANONYMOUS_YES ? null : $userid,
151
            $userid
152
        );
153
 
154
        if (!$feedbackcompletion->can_complete()) {
155
            throw new coding_exception("User {$userid} cannot complete this feedback activity.");
156
        }
157
 
158
        if (!$feedbackcompletion->is_open()) {
159
            throw new coding_exception("This activity is not open.");
160
        }
161
 
162
        $feedbackcompletion->set_module_viewed();
163
        $feedbackcompletion->save_response_tmp((object) $answers);
164
        $feedbackcompletion->save_response();
165
        $completed = $feedbackcompletion->get_completed();
166
 
167
        if (!is_null($responsenumber)) {
168
            $DB->update_record('feedback_completed', [
169
                'id' => $completed->id,
170
                'random_response' => $responsenumber,
171
            ]);
172
        }
173
 
174
        return $completed;
175
    }
176
 
177
    /**
178
     * Create info question item.
179
     *
180
     * @param object $feedback feedback record
181
     * @param array $record (optional) to override default values
182
     * @return stdClass
183
     */
184
    public function create_item_info($feedback, $record = array()) {
185
        global $DB, $CFG;
186
 
187
        require_once($CFG->dirroot.'/mod/feedback/lib.php');
188
 
189
        $itemobj = feedback_get_item_class('info');
190
        $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1;
191
 
192
        $record = (array)$record + array(
193
            'id' => 0,
194
            'feedback' => $feedback->id,
195
            'template' => 0,
196
            'name' => 'Feedback question item ' . $position,
197
            'label' => 'Feedback label ' . $position,
198
            'presentation' => \feedback_item_info::MODE_COURSE,
199
            'typ' => 'info',
200
            'hasvalue' => 0,
201
            'position' => $position,
202
            'required' => 0,
203
            'dependitem' => 0,
204
            'dependvalue' => '',
205
            'options' => '',
206
        );
207
 
208
        $itemobj->set_data((object) $record);
209
        return $itemobj->save_item();
210
    }
211
 
212
    /**
213
     * Create label question item.
214
     *
215
     * @param object $feedback feedback record
216
     * @param array $record (optional) to override default values
217
     * @return stdClass
218
     */
219
    public function create_item_label($feedback, $record = array()) {
220
        global $DB, $CFG;
221
 
222
        require_once($CFG->dirroot.'/mod/feedback/lib.php');
223
 
224
        $itemobj = feedback_get_item_class('label');
225
        $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1;
226
 
227
        $record = (array)$record + array(
228
            'id' => 0,
229
            'feedback' => $feedback->id,
230
            'template' => 0,
231
            'name' => 'label',
232
            'label' => '',
233
            'presentation' => '',
234
            'typ' => 'label',
235
            'hasvalue' => 0,
236
            'position' => $position,
237
            'required' => 0,
238
            'dependitem' => 0,
239
            'dependvalue' => '',
240
            'options' => '',
241
        );
242
 
243
        if (!isset($record['presentation_editor'])) {
244
            $record['presentation_editor'] = array(
245
                'text' => "The label $position text goes here",
246
                'format' => FORMAT_HTML,
247
                'itemid' => 0
248
            );
249
        }
250
 
251
        $itemobj->set_data((object) $record);
252
        return $itemobj->save_item();
253
    }
254
 
255
    /**
256
     * Create multichoice question item.
257
     *
258
     * @param object $feedback feedback record
259
     * @param array $record (optional) to override default values
260
     * @return stdClass
261
     */
262
    public function create_item_multichoice($feedback, $record = array()) {
263
        global $DB, $CFG;
264
 
265
        require_once($CFG->dirroot.'/mod/feedback/lib.php');
266
 
267
        $itemobj = feedback_get_item_class('multichoice');
268
        $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1;
269
 
270
        $record = (array)$record + array(
271
            'id' => 0,
272
            'feedback' => $feedback->id,
273
            'template' => 0,
274
            'name' => 'Feedback question item ' . $position,
275
            'label' => 'Feedback label ' . $position,
276
            'presentation' => '',
277
            'typ' => 'multichoice',
278
            'hasvalue' => 0,
279
            'position' => $position,
280
            'required' => 0,
281
            'dependitem' => 0,
282
            'dependvalue' => '',
283
            'options' => '',
284
            'subtype' => 'r',
285
            'horizontal' => 0,
286
            'hidenoselect' => 1,
287
            'ignoreempty' => 0,
288
            'values' => "a\nb\nc\nd\ne"
289
        );
290
 
291
        $presentation = str_replace("\n", FEEDBACK_MULTICHOICE_LINE_SEP, trim($record['values']));
292
 
293
        if ($record['horizontal'] == 1 AND $record['subtype'] != 'd') {
294
            $presentation .= FEEDBACK_MULTICHOICE_ADJUST_SEP.'1';
295
        }
296
        $record['presentation'] = $record['subtype'].FEEDBACK_MULTICHOICE_TYPE_SEP.$presentation;
297
 
298
        $itemobj->set_data((object) $record);
299
        return $itemobj->save_item();
300
    }
301
 
302
    /**
303
     * Create multichoicerated question item.
304
     *
305
     * @param object $feedback feedback record
306
     * @param array $record (optional) to override default values
307
     * @return stdClass
308
     */
309
    public function create_item_multichoicerated($feedback, $record = array()) {
310
        global $DB, $CFG;
311
 
312
        require_once($CFG->dirroot.'/mod/feedback/lib.php');
313
 
314
        $itemobj = feedback_get_item_class('multichoicerated');
315
        $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1;
316
 
317
        $record = (array)$record + array(
318
            'id' => 0,
319
            'feedback' => $feedback->id,
320
            'template' => 0,
321
            'name' => 'Feedback question item ' . $position,
322
            'label' => 'Feedback label ' . $position,
323
            'presentation' => '',
324
            'typ' => 'multichoicerated',
325
            'hasvalue' => 0,
326
            'position' => $position,
327
            'required' => 0,
328
            'dependitem' => 0,
329
            'dependvalue' => '',
330
            'options' => '',
331
            'subtype' => 'r',
332
            'horizontal' => 0,
333
            'hidenoselect' => 1,
334
            'ignoreempty' => 0,
335
            'values' => "0/a\n1/b\n2/c\n3/d\n4/e"
336
        );
337
 
338
        $itemobj = new feedback_item_multichoicerated();
339
        $presentation = $itemobj->prepare_presentation_values_save(trim($record['values']),
340
            FEEDBACK_MULTICHOICERATED_VALUE_SEP2, FEEDBACK_MULTICHOICERATED_VALUE_SEP);
341
 
342
        if ($record['horizontal'] == 1 AND $record['subtype'] != 'd') {
343
            $presentation .= FEEDBACK_MULTICHOICERATED_ADJUST_SEP.'1';
344
        }
345
        $record['presentation'] = $record['subtype'].FEEDBACK_MULTICHOICERATED_TYPE_SEP.$presentation;
346
 
347
        $itemobj->set_data((object) $record);
348
        return $itemobj->save_item();
349
    }
350
 
351
    /**
352
     * Create numeric question item.
353
     *
354
     * @param object $feedback feedback record
355
     * @param array $record (optional) to override default values
356
     * @return stdClass
357
     */
358
    public function create_item_numeric($feedback, $record = array()) {
359
        global $DB, $CFG;
360
 
361
        require_once($CFG->dirroot.'/mod/feedback/lib.php');
362
 
363
        $itemobj = feedback_get_item_class('numeric');
364
        $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1;
365
 
366
        $record = (array)$record + array(
367
            'id' => 0,
368
            'feedback' => $feedback->id,
369
            'template' => 0,
370
            'name' => 'Feedback question item ' . $position,
371
            'label' => 'Feedback label ' . $position,
372
            'presentation' => '',
373
            'typ' => 'numeric',
374
            'hasvalue' => 0,
375
            'position' => $position,
376
            'required' => 0,
377
            'dependitem' => 0,
378
            'dependvalue' => '',
379
            'options' => '',
380
            'rangefrom' => '-',
381
            'rangeto' => '-',
382
        );
383
 
384
        if ($record['rangefrom'] === '-' OR $record['rangeto'] === '-') {
385
            $record['presentation'] = $record['rangefrom'] . '|'. $record['rangeto'];
386
        } else if ($record['rangefrom'] > $record['rangeto']) {
387
            $record['presentation'] = $record['rangeto'] . '|'. $record['rangefrom'];
388
        } else {
389
            $record['presentation'] = $record['rangefrom'] . '|'. $record['rangeto'];
390
        }
391
 
392
        $itemobj->set_data((object) $record);
393
        return $itemobj->save_item();
394
    }
395
 
396
    /**
397
     * Create textarea question item.
398
     *
399
     * @param object $feedback feedback record
400
     * @param array $record (optional) to override default values
401
     * @return stdClass
402
     */
403
    public function create_item_textarea($feedback, $record = array()) {
404
        global $DB, $CFG;
405
 
406
        require_once($CFG->dirroot.'/mod/feedback/lib.php');
407
 
408
        $itemobj = feedback_get_item_class('textarea');
409
        $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1;
410
 
411
        $record = (array)$record + array(
412
            'id' => 0,
413
            'feedback' => $feedback->id,
414
            'template' => 0,
415
            'name' => 'Feedback question item ' . $position,
416
            'label' => 'Feedback label ' . $position,
417
            'presentation' => '',
418
            'typ' => 'textarea',
419
            'hasvalue' => 0,
420
            'position' => $position,
421
            'required' => 0,
422
            'dependitem' => 0,
423
            'dependvalue' => '',
424
            'options' => '',
425
            'itemwidth' => '40',
426
            'itemheight' => '20',
427
        );
428
 
429
        $record['presentation'] = $record['itemwidth'] . '|'. $record['itemheight'];
430
 
431
        $itemobj->set_data((object) $record);
432
        return $itemobj->save_item();
433
    }
434
 
435
    /**
436
     * Create textfield question item.
437
     *
438
     * @param object $feedback feedback record
439
     * @param array $record (optional) to override default values
440
     * @return stdClass
441
     */
442
    public function create_item_textfield($feedback, $record = array()) {
443
        global $DB, $CFG;
444
 
445
        require_once($CFG->dirroot.'/mod/feedback/lib.php');
446
 
447
        $itemobj = feedback_get_item_class('textfield');
448
        $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1;
449
 
450
        $record = (array)$record + array(
451
            'id' => 0,
452
            'feedback' => $feedback->id,
453
            'template' => 0,
454
            'name' => 'Feedback question item ' . $position,
455
            'label' => 'Feedback label ' . $position,
456
            'presentation' => '',
457
            'typ' => 'textfield',
458
            'hasvalue' => 0,
459
            'position' => $position,
460
            'required' => 0,
461
            'dependitem' => 0,
462
            'dependvalue' => '',
463
            'options' => '',
464
            'itemsize' => '20',
465
            'itemmaxlength' => '30',
466
        );
467
 
468
        $record['presentation'] = $record['itemsize'] . '|'. $record['itemmaxlength'];
469
 
470
        $itemobj->set_data((object) $record);
471
        return $itemobj->save_item();
472
    }
473
 
474
    /**
475
     * Create pagebreak.
476
     *
477
     * @param object $feedback feedback record
478
     * @return int|false false if there already is a pagebreak on last position or the id of the pagebreak-item
479
     */
480
    public function create_item_pagebreak($feedback) {
481
        global $CFG;
482
        require_once($CFG->dirroot.'/mod/feedback/lib.php');
483
 
484
        return feedback_create_pagebreak($feedback->id);
485
    }
486
 
487
    /**
488
     * Format feedback item values.
489
     *
490
     * This method will replace newline characters with the proper line separator for each question type.
491
     *
492
     * @param string $questiontype Question types
493
     * @param string $values Values
494
     * @return string Formatted values
495
     */
496
    protected function format_item_values(string $questiontype, string $values): string {
497
        global $CFG;
498
 
499
        if (!file_exists($CFG->dirroot.'/mod/feedback/item/'.$questiontype.'/lib.php')) {
500
            throw new coding_exception("Question type '$questiontype' not found");
501
        }
502
 
503
        require_once($CFG->dirroot.'/mod/feedback/item/'.$questiontype.'/lib.php');
504
 
505
        $questiontype = strtoupper($questiontype);
506
 
507
        if (defined("FEEDBACK_{$questiontype}_LINE_SEP")) {
508
            return implode(constant("FEEDBACK_{$questiontype}_LINE_SEP"), explode('\n', $values));
509
        }
510
 
511
        return $values;
512
    }
513
 
514
    /**
515
     * Given a response to a feedback item, return its corresponding value.
516
     *
517
     * @param mixed $record Item record
518
     * @param string $response Response name
519
     * @return int|string Response value
520
     */
521
    protected function get_item_response_value($record, string $response) {
522
        if (strpos($record->typ, 'multichoice') === 0) {
523
            $item = feedback_get_item_class($record->typ);
524
 
525
            return $this->get_choice_item_response_value($item, $record, $response);
526
        }
527
 
528
        return $response;
529
    }
530
 
531
    /**
532
     * Given a response to a feedback choice item, return its corresponding value.
533
     *
534
     * @param feedback_item_base $item Feedback item
535
     * @param mixed $record Item record
536
     * @param string $response Response
537
     * @param int $offset Choice to start looking from
538
     * @return int Response choice index
539
     */
540
    protected function get_choice_item_response_value(feedback_item_base $item, $record, string $response, int $offset = 1): int {
541
        $printval = $item->get_printval($record, (object) ['value' => $offset]);
542
 
543
        if (empty($printval)) {
544
            throw new coding_exception("Value '$offset' not found");
545
        }
546
 
547
        if ($printval === $response) {
548
            return $offset;
549
        }
550
 
551
        return $this->get_choice_item_response_value($item, $record, $response, $offset + 1);
552
    }
553
}