2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Numerical question type upgrade code.
21 * @subpackage numerical
22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') ||
die();
31 * Upgrade code for the numerical question type.
32 * @param int $oldversion the version we are upgrading from.
34 function xmldb_qtype_numerical_upgrade($oldversion) {
37 $dbman = $DB->get_manager();
39 //===== 1.9.0 upgrade line ======//
40 if ($oldversion < 2009100100 ) { //New version in version.php
42 // Define table question_numerical_options to be created
43 $table = new xmldb_table('question_numerical_options');
45 // Adding fields to table question_numerical_options
46 $table->add_field('id', XMLDB_TYPE_INTEGER
, '10', XMLDB_UNSIGNED
,
47 XMLDB_NOTNULL
, XMLDB_SEQUENCE
, null);
48 $table->add_field('question', XMLDB_TYPE_INTEGER
, '10', XMLDB_UNSIGNED
,
49 XMLDB_NOTNULL
, null, '0');
50 $table->add_field('instructions', XMLDB_TYPE_TEXT
, 'small', null,
52 $table->add_field('showunits', XMLDB_TYPE_INTEGER
, '4', XMLDB_UNSIGNED
,
53 XMLDB_NOTNULL
, null, '0');
54 $table->add_field('unitsleft', XMLDB_TYPE_INTEGER
, '4', null,
55 XMLDB_NOTNULL
, null, '0');
56 $table->add_field('unitgradingtype', XMLDB_TYPE_INTEGER
, '4', XMLDB_UNSIGNED
,
57 XMLDB_NOTNULL
, null, '0');
58 $table->add_field('unitpenalty', XMLDB_TYPE_NUMBER
, '12, 7', XMLDB_UNSIGNED
,
59 XMLDB_NOTNULL
, null, '0.1');
61 // Adding keys to table question_numerical_options
62 $table->add_key('primary', XMLDB_KEY_PRIMARY
, array('id'));
63 $table->add_key('question', XMLDB_KEY_FOREIGN
, array('question'), 'question', array('id'));
64 // Conditionally launch create table for question_calculated_options
65 if (!$dbman->table_exists($table)) {
66 // $dbman->create_table doesnt return a result, we just have to trust it
67 $dbman->create_table($table);
69 upgrade_plugin_savepoint(true, 2009100100, 'qtype', 'numerical');
72 if ($oldversion < 2009100101) {
74 // Define field instructionsformat to be added to question_numerical_options
75 $table = new xmldb_table('question_numerical_options');
76 $field = new xmldb_field('instructionsformat', XMLDB_TYPE_INTEGER
, '2', null,
77 XMLDB_NOTNULL
, null, '0', 'instructions');
79 // Conditionally launch add field instructionsformat
80 if (!$dbman->field_exists($table, $field)) {
81 $dbman->add_field($table, $field);
84 // In the past, question_match_sub.questiontext assumed to contain
85 // content of the same form as question.questiontextformat. If we are
86 // using the HTML editor, then convert FORMAT_MOODLE content to FORMAT_HTML.
87 $rs = $DB->get_recordset_sql('
88 SELECT qno.*, q.oldquestiontextformat
89 FROM {question_numerical_options} qno
90 JOIN {question} q ON qno.question = q.id');
91 foreach ($rs as $record) {
92 if ($CFG->texteditors
!== 'textarea' &&
93 $record->oldquestiontextformat
== FORMAT_MOODLE
) {
94 $record->instructions
= text_to_html($record->instructions
, false, false, true);
95 $record->instructionsformat
= FORMAT_HTML
;
97 $record->instructionsformat
= $record->oldquestiontextformat
;
99 $DB->update_record('question_numerical_options', $record);
103 // numerical savepoint reached
104 upgrade_plugin_savepoint(true, 2009100101, 'qtype', 'numerical');
107 if ($oldversion < 2011042600) {
108 // Get rid of the instructions field by adding it to the qestion
109 // text. Also, if the unit was set to be displayed beside the input,
110 // deal with that within the question text too.
112 // The hard-coded constants used here are:
113 // 2 = the old qtype_numerical::UNITDISPLAY for ->showunits
114 // 3 = qtype_numerical::UNITNONE
116 $fs = get_file_storage();
118 $rs = $DB->get_recordset_sql('
119 SELECT q.id AS questionid,
121 q.questiontextformat,
125 qno.instructionsformat,
128 qnu.unit AS defaultunit
131 JOIN {question_categories} qc ON qc.id = q.category
132 JOIN {question_numerical_options} qno ON qno.question = q.id
133 JOIN {question_numerical_units} qnu ON qnu.id = (
135 FROM {question_numerical_units}
136 WHERE question = q.id AND ABS(multiplier - 1) < 0.0000000001)');
137 foreach ($rs as $numericaloptions) {
138 if ($numericaloptions->showunits
!= 2 && empty($numericaloptions->instructions
)) {
139 // Nothing to do for this question.
143 $ishtml = qtype_numerical_convert_text_format($numericaloptions);
145 $response = '_______________';
146 if ($numericaloptions->showunits
== 2) {
147 if ($numericaloptions->unitsleft
) {
148 $response = $numericaloptions->defaultunit
. ' _______________';
150 $response = '_______________ ' . $numericaloptions->defaultunit
;
153 $DB->set_field('question_numerical_options', 'showunits', 3,
154 array('id' => $numericaloptions->qnoid
));
158 $numericaloptions->questiontext
.= '<p>' . $response . '</p>';
160 $numericaloptions->questiontext
.= "\n\n" . $response;
163 if (!empty($numericaloptions->instructions
)) {
165 $numericaloptions->questiontext
.= $numericaloptions->instructions
;
167 $numericaloptions->questiontext
.= "\n\n" . $numericaloptions->instructions
;
170 $oldfiles = $fs->get_area_files($numericaloptions->contextid
,
171 'qtype_numerical', 'instruction', $numericaloptions->questionid
,
173 foreach ($oldfiles as $oldfile) {
174 $filerecord = new stdClass();
175 $filerecord->component
= 'question';
176 $filerecord->filearea
= 'questiontext';
177 $fs->create_file_from_storedfile($filerecord, $oldfile);
181 $fs->delete_area_files($numericaloptions->contextid
,
182 'qtype_numerical', 'instruction', $numericaloptions->questionid
);
186 $updaterecord = new stdClass();
187 $updaterecord->id
= $numericaloptions->questionid
;
188 $updaterecord->questiontext
= $numericaloptions->questiontext
;
189 $updaterecord->questiontextformat
= $numericaloptions->questiontextformat
;
190 $DB->update_record('question', $updaterecord);
194 // numerical savepoint reached
195 upgrade_plugin_savepoint(true, 2011042600, 'qtype', 'numerical');
198 if ($oldversion < 2011042601) {
199 // Define field instructions to be dropped from question_numerical_options
200 $table = new xmldb_table('question_numerical_options');
201 $field = new xmldb_field('instructions');
203 // Conditionally launch drop field instructions
204 if ($dbman->field_exists($table, $field)) {
205 $dbman->drop_field($table, $field);
208 // numerical savepoint reached
209 upgrade_plugin_savepoint(true, 2011042601, 'qtype', 'numerical');
212 if ($oldversion < 2011042602) {
213 // Define field instructionsformat to be dropped from question_numerical_options
214 $table = new xmldb_table('question_numerical_options');
215 $field = new xmldb_field('instructionsformat');
217 // Conditionally launch drop field instructionsformat
218 if ($dbman->field_exists($table, $field)) {
219 $dbman->drop_field($table, $field);
222 // numerical savepoint reached
223 upgrade_plugin_savepoint(true, 2011042602, 'qtype', 'numerical');
226 // Moodle v2.1.0 release upgrade line
227 // Put any upgrade step following this
233 * Convert the ->questiontext and ->instructions fields to have the same text format.
234 * If they are already the same, do nothing. Otherwise, this method works by
235 * converting both to HTML.
236 * @param $numericaloptions the data to convert.
237 * @return bool true if the resulting fields are in HTML, as opposed to one of
238 * the text-based formats.
240 function qtype_numerical_convert_text_format($numericaloptions) {
241 if ($numericaloptions->questiontextformat
== $numericaloptions->instructionsformat
) {
243 return $numericaloptions->questiontextformat
== FORMAT_HTML
;
246 if ($numericaloptions->questiontextformat
!= FORMAT_HTML
) {
247 $numericaloptions->questiontext
= qtype_numerical_convert_to_html(
248 $numericaloptions->questiontext
, $numericaloptions->questiontextformat
);
249 $numericaloptions->questiontextformat
= FORMAT_HTML
;
252 if ($numericaloptions->instructionsformat
!= FORMAT_HTML
) {
253 $numericaloptions->instructions
= qtype_numerical_convert_to_html(
254 $numericaloptions->instructions
, $numericaloptions->instructionsformat
);
255 $numericaloptions->instructionsformat
= FORMAT_HTML
;
261 // Add some helper functions that should be in upgradelib.php, but having there already
262 // the question attempts updater classes prevents us to do so :-(
265 * Convert some content to HTML.
266 * @param string $text the content to convert to HTML
267 * @param int $oldformat One of the FORMAT_... constants.
269 function qtype_numerical_convert_to_html($text, $oldformat) {
270 switch ($oldformat) {
271 // Similar to format_text.
275 $text = str_replace(' ', ' ', $text);
276 $text = nl2br($text);
279 case FORMAT_MARKDOWN
:
280 return markdown_to_html($text);
283 return text_to_html($text, null, $options['para'], $options['newlines']);
286 throw new coding_exception(
287 'Unexpected text format when upgrading numerical questions.');