MDL-31065 qtype shortanswer: refactor the unit tests to use a proper helper.
[moodle.git] / question / type / shortanswer / questiontype.php
CommitLineData
aeb15530 1<?php
fe6ce234
DC
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
41a89a07 17/**
068b4594
TH
18 * Question type class for the short answer question type.
19 *
7764183a
TH
20 * @package qtype
21 * @subpackage shortanswer
22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
53a4d39f 24 */
516cf3eb 25
516cf3eb 26
a17b297d
TH
27defined('MOODLE_INTERNAL') || die();
28
068b4594
TH
29require_once($CFG->libdir . '/questionlib.php');
30require_once($CFG->dirroot . '/question/engine/lib.php');
31require_once($CFG->dirroot . '/question/type/shortanswer/question.php');
516cf3eb 32
869309b8 33
068b4594
TH
34/**
35 * The short answer question type.
36 *
7764183a
TH
37 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
068b4594
TH
39 */
40class qtype_shortanswer extends question_type {
41 public function extra_question_fields() {
fe6ce234 42 return array('question_shortanswer', 'answers', 'usecase');
d001dac7 43 }
516cf3eb 44
56565037 45 public function questionid_column_name() {
d001dac7 46 return 'question';
516cf3eb 47 }
48
c7df5006 49 public function move_files($questionid, $oldcontextid, $newcontextid) {
5d548d3e
TH
50 parent::move_files($questionid, $oldcontextid, $newcontextid);
51 $this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
fe6ce234
DC
52 }
53
9203b705
TH
54 protected function delete_files($questionid, $contextid) {
55 parent::delete_files($questionid, $contextid);
56 $this->delete_files_in_answers($questionid, $contextid);
57 }
58
068b4594 59 public function save_question_options($question) {
f34488b2 60 global $DB;
0ff4bd08 61 $result = new stdClass();
90a36f8c 62
fe6ce234
DC
63 $context = $question->context;
64
69988ed4
TH
65 $oldanswers = $DB->get_records('question_answers',
66 array('question' => $question->id), 'id ASC');
516cf3eb 67
68 $answers = array();
69 $maxfraction = -1;
068b4594
TH
70
71 // Insert all the new answers
69988ed4
TH
72 foreach ($question->answer as $key => $answerdata) {
73 // Check for, and ignore, completely blank answer from the form.
74 if (trim($answerdata) == '' && $question->fraction[$key] == 0 &&
fe6ce234 75 html_is_blank($question->feedback[$key]['text'])) {
94a6d656 76 continue;
77 }
78
69988ed4
TH
79 // Update an existing answer if possible.
80 $answer = array_shift($oldanswers);
81 if (!$answer) {
82 $answer = new stdClass();
83 $answer->question = $question->id;
84 $answer->answer = '';
85 $answer->feedback = '';
86 $answer->id = $DB->insert_record('question_answers', $answer);
cde2709a 87 }
fe6ce234 88
69988ed4
TH
89 $answer->answer = trim($answerdata);
90 $answer->fraction = $question->fraction[$key];
91 $answer->feedback = $this->import_or_save_files($question->feedback[$key],
92 $context, 'question', 'answerfeedback', $answer->id);
93 $answer->feedbackformat = $question->feedback[$key]['format'];
94 $DB->update_record('question_answers', $answer);
fe6ce234 95
94a6d656 96 $answers[] = $answer->id;
97 if ($question->fraction[$key] > $maxfraction) {
98 $maxfraction = $question->fraction[$key];
99 }
516cf3eb 100 }
101
068b4594
TH
102 $question->answers = implode(',', $answers);
103 $parentresult = parent::save_question_options($question);
104 if ($parentresult !== null) {
105 // Parent function returns null if all is OK
106 return $parentresult;
107 }
108
69988ed4
TH
109 // Delete any left over old answer records.
110 $fs = get_file_storage();
8cfc4fbd 111 foreach ($oldanswers as $oldanswer) {
69988ed4
TH
112 $fs->delete_area_files($context->id, 'question', 'answerfeedback', $oldanswer->id);
113 $DB->delete_records('question_answers', array('id' => $oldanswer->id));
114 }
115
068b4594 116 $this->save_hints($question);
516cf3eb 117
69988ed4 118 // Perform sanity checks on fractional grades
516cf3eb 119 if ($maxfraction != 1) {
5e8a85aa 120 $result->noticeyesno = get_string('fractionsnomax', 'question', $maxfraction * 100);
516cf3eb 121 return $result;
516cf3eb 122 }
516cf3eb 123 }
124
068b4594
TH
125 protected function initialise_question_instance(question_definition $question, $questiondata) {
126 parent::initialise_question_instance($question, $questiondata);
068b4594 127 $this->initialise_question_answers($question, $questiondata);
516cf3eb 128 }
1a1293ed 129
068b4594
TH
130 public function get_random_guess_score($questiondata) {
131 foreach ($questiondata->options->answers as $aid => $answer) {
132 if ('*' == trim($answer->answer)) {
6f51ed72 133 return $answer->fraction;
134 }
135 }
136 return 0;
137 }
516cf3eb 138
068b4594
TH
139 public function get_possible_responses($questiondata) {
140 $responses = array();
90a36f8c 141
068b4594
TH
142 foreach ($questiondata->options->answers as $aid => $answer) {
143 $responses[$aid] = new question_possible_response($answer->answer,
144 $answer->fraction);
93a501c1 145 }
068b4594 146 $responses[null] = question_possible_response::no_response();
b9bd6da4 147
068b4594 148 return array($questiondata->id => $responses);
b9bd6da4 149 }
516cf3eb 150}