Merge branch 'MDL-29058' of git://github.com/timhunt/moodle
[moodle.git] / question / type / numerical / db / upgrade.php
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/>.
17 /**
18  * Numerical question type upgrade code.
19  *
20  * @package    qtype
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
24  */
27 defined('MOODLE_INTERNAL') || die();
30 /**
31  * Upgrade code for the numerical question type.
32  * @param int $oldversion the version we are upgrading from.
33  */
34 function xmldb_qtype_numerical_upgrade($oldversion) {
35     global $CFG, $DB;
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,
51                 null, null, 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);
68         }
69         upgrade_plugin_savepoint(true, 2009100100, 'qtype', 'numerical');
70     }
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);
82         }
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;
96             } else {
97                 $record->instructionsformat = $record->oldquestiontextformat;
98             }
99             $DB->update_record('question_numerical_options', $record);
100         }
101         $rs->close();
103         // numerical savepoint reached
104         upgrade_plugin_savepoint(true, 2009100101, 'qtype', 'numerical');
105     }
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,
120                        q.questiontext,
121                        q.questiontextformat,
122                        qc.contextid,
123                        qno.id AS qnoid,
124                        qno.instructions,
125                        qno.instructionsformat,
126                        qno.showunits,
127                        qno.unitsleft,
128                        qnu.unit AS defaultunit
130                   FROM {question} q
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 = (
134                             SELECT min(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.
140                 continue;
141             }
143             $ishtml = qtype_numerical_convert_text_format($numericaloptions);
145             $response = '_______________';
146             if ($numericaloptions->showunits == 2) {
147                 if ($numericaloptions->unitsleft) {
148                     $response = $numericaloptions->defaultunit . ' _______________';
149                 } else {
150                     $response = '_______________ ' . $numericaloptions->defaultunit;
151                 }
153                 $DB->set_field('question_numerical_options', 'showunits', 3,
154                         array('id' => $numericaloptions->qnoid));
155             }
157             if ($ishtml) {
158                 $numericaloptions->questiontext .= '<p>' . $response . '</p>';
159             } else {
160                 $numericaloptions->questiontext .= "\n\n" . $response;
161             }
163             if (!empty($numericaloptions->instructions)) {
164                 if ($ishtml) {
165                     $numericaloptions->questiontext .= $numericaloptions->instructions;
166                 } else {
167                     $numericaloptions->questiontext .= "\n\n" . $numericaloptions->instructions;
168                 }
170                 $oldfiles = $fs->get_area_files($numericaloptions->contextid,
171                         'qtype_numerical', 'instruction', $numericaloptions->questionid,
172                         'id', false);
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);
178                 }
180                 if ($oldfiles) {
181                     $fs->delete_area_files($numericaloptions->contextid,
182                         'qtype_numerical', 'instruction', $numericaloptions->questionid);
183                 }
184             }
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);
191         }
192         $rs->close();
194         // numerical savepoint reached
195         upgrade_plugin_savepoint(true, 2011042600, 'qtype', 'numerical');
196     }
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);
206         }
208         // numerical savepoint reached
209         upgrade_plugin_savepoint(true, 2011042601, 'qtype', 'numerical');
210     }
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);
220         }
222         // numerical savepoint reached
223         upgrade_plugin_savepoint(true, 2011042602, 'qtype', 'numerical');
224     }
226     // Moodle v2.1.0 release upgrade line
227     // Put any upgrade step following this
229     return true;
232 /**
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.
239  */
240 function qtype_numerical_convert_text_format($numericaloptions) {
241     if ($numericaloptions->questiontextformat == $numericaloptions->instructionsformat) {
242         // Nothing to do:
243         return $numericaloptions->questiontextformat == FORMAT_HTML;
244     }
246     if ($numericaloptions->questiontextformat != FORMAT_HTML) {
247         $numericaloptions->questiontext = qtype_numerical_convert_to_html(
248                 $numericaloptions->questiontext, $numericaloptions->questiontextformat);
249         $numericaloptions->questiontextformat = FORMAT_HTML;
250     }
252     if ($numericaloptions->instructionsformat != FORMAT_HTML) {
253         $numericaloptions->instructions = qtype_numerical_convert_to_html(
254                 $numericaloptions->instructions, $numericaloptions->instructionsformat);
255         $numericaloptions->instructionsformat = FORMAT_HTML;
256     }
258     return true;
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 :-(
264 /**
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.
268  */
269 function qtype_numerical_convert_to_html($text, $oldformat) {
270     switch ($oldformat) {
271         // Similar to format_text.
273         case FORMAT_PLAIN:
274             $text = s($text);
275             $text = str_replace('  ', '&nbsp; ', $text);
276             $text = nl2br($text);
277             return $text;
279         case FORMAT_MARKDOWN:
280             return markdown_to_html($text);
282         case FORMAT_MOODLE:
283             return text_to_html($text, null, $options['para'], $options['newlines']);
285         default:
286             throw new coding_exception(
287                     'Unexpected text format when upgrading numerical questions.');
288     }