MDL-26312 Workshop: unset temporary arrays in upgrade code
[moodle.git] / mod / workshop / db / upgrade.php
CommitLineData
b876ab80
DM
1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Keeps track of upgrades to the workshop module
20 *
65601f04
DM
21 * @package mod
22 * @subpackage workshop
23 * @copyright 2009 David Mudrak <david.mudrak@gmail.com>
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
b876ab80
DM
25 */
26
27/**
28 * Performs upgrade of the database structure and data
29 *
30 * Workshop supports upgrades from version 1.9.0 and higher only. During 1.9 > 2.0 upgrade,
31 * there are significant database changes.
32 *
33 * @param int $oldversion the version we are upgrading from
34 * @return bool result
35 */
36function xmldb_workshop_upgrade($oldversion) {
37 global $CFG, $DB, $OUTPUT;
38
39 $dbman = $DB->get_manager();
b876ab80 40
a2d57f96
DM
41 //===== 1.9.0 upgrade line ======//
42
43 /**
44 * the following blocks contain all the db/upgrade.php logic from MOODLE_19_STABLE branch
45 * so that it does not matter if we are upgrading from 1.9.0, 1.9.3 or 1.9.whatever
46 */
47
a4cdd6d2 48 if ($oldversion < 2007101510) {
a2d57f96
DM
49 $orphans = $DB->get_records_sql('SELECT wa.id
50 FROM {workshop_assessments} wa
51 LEFT JOIN {workshop_submissions} ws ON wa.submissionid = ws.id
52 WHERE ws.id IS NULL');
53 if (!empty($orphans)) {
54 echo $OUTPUT->notification('Orphaned assessment records found - cleaning...');
5452309a 55 $DB->delete_records_list('workshop_assessments', 'id', array_keys($orphans));
a2d57f96 56 }
a4cdd6d2 57 upgrade_mod_savepoint(true, 2007101510, 'workshop');
a2d57f96
DM
58 }
59
60 //===== end of 1.9.0 upgrade line ======//
61
b876ab80
DM
62 /**
63 * Upgrading from workshop 1.9.x - big things going to happen now...
64 * The migration procedure is divided into smaller chunks using incremental
65 * versions 2009102900, 2009102901, 2009102902 etc. The day zero of the new
66 * workshop 2.0 is version 2009103000 since when the upgrade code is maintained.
67 */
68
69 /**
70 * Migration from 1.9 - step 1 - rename old tables
71 */
a4cdd6d2 72 if ($oldversion < 2009102901) {
b876ab80
DM
73 echo $OUTPUT->notification('Renaming old workshop module tables', 'notifysuccess');
74 foreach (array('workshop', 'workshop_elements', 'workshop_rubrics', 'workshop_submissions', 'workshop_assessments',
75 'workshop_grades', 'workshop_comments', 'workshop_stockcomments') as $tableorig) {
76 $tablearchive = $tableorig . '_old';
77 if ($dbman->table_exists($tableorig)) {
ffe50258 78 $dbman->rename_table(new xmldb_table($tableorig), $tablearchive);
b876ab80 79 }
067f63c5
DM
80 // append a new field 'newplugin' into every archived table. In this field, the name of the subplugin
81 // who adopted the record during the migration is stored. null value means the record is not migrated yet
82 $table = new xmldb_table($tablearchive);
83 $field = new xmldb_field('newplugin', XMLDB_TYPE_CHAR, '28', null, null, null, null);
84 if (!$dbman->field_exists($table, $field)) {
85 $dbman->add_field($table, $field);
86 }
87 // append a new field 'newid' in every archived table. null value means the record was not migrated yet.
88 // the field will hold the new id of the migrated record
b876ab80
DM
89 $table = new xmldb_table($tablearchive);
90 $field = new xmldb_field('newid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null);
91 if (!$dbman->field_exists($table, $field)) {
92 $dbman->add_field($table, $field);
93 }
94 }
a4cdd6d2 95 upgrade_mod_savepoint(true, 2009102901, 'workshop');
b876ab80
DM
96 }
97
98 /**
99 * Migration from 1.9 - step 2 - create new workshop core tables
100 */
a4cdd6d2 101 if ($oldversion < 2009102902) {
b876ab80
DM
102 require_once(dirname(__FILE__) . '/upgradelib.php');
103 echo $OUTPUT->notification('Preparing new workshop module tables', 'notifysuccess');
104 workshop_upgrade_prepare_20_tables();
a4cdd6d2 105 upgrade_mod_savepoint(true, 2009102902, 'workshop');
b876ab80
DM
106 }
107
108 /**
109 * Migration from 1.9 - step 3 - migrate workshop instances
110 */
a4cdd6d2 111 if ($oldversion < 2009102903) {
b876ab80
DM
112 require_once(dirname(__FILE__) . '/upgradelib.php');
113 echo $OUTPUT->notification('Copying workshop core data', 'notifysuccess');
067f63c5 114 workshop_upgrade_module_instances();
a4cdd6d2 115 upgrade_mod_savepoint(true, 2009102903, 'workshop');
b876ab80
DM
116 }
117
067f63c5
DM
118 /**
119 * Migration from 1.9 - step 4 - migrate submissions
120 */
a4cdd6d2 121 if ($oldversion < 2009102904) {
067f63c5
DM
122 require_once(dirname(__FILE__) . '/upgradelib.php');
123 echo $OUTPUT->notification('Copying submissions', 'notifysuccess');
124 workshop_upgrade_submissions();
a4cdd6d2 125 upgrade_mod_savepoint(true, 2009102904, 'workshop');
067f63c5
DM
126 }
127
128 /**
129 * Migration from 1.9 - step 5 - migrate submission attachment to new file storage
130 */
a4cdd6d2 131 if ($oldversion < 2009102905) {
067f63c5
DM
132 // $filearea = "$workshop->course/$CFG->moddata/workshop/$submission->id";
133 $fs = get_file_storage();
134 $from = 'FROM {workshop_submissions} s
135 JOIN {workshop} w ON (w.id = s.workshopid)
136 JOIN {modules} m ON (m.name = :modulename)
137 JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = w.id)
138 WHERE s.attachment <> 1';
139 $params = array('modulename' => 'workshop');
140 $count = $DB->count_records_sql('SELECT COUNT(s.id) ' . $from, $params);
141 $rs = $DB->get_recordset_sql('SELECT s.id, s.authorid, s.workshopid, cm.course, cm.id AS cmid ' .
142 $from . ' ORDER BY cm.course, w.id', $params);
143 $pbar = new progress_bar('migrateworkshopsubmissions', 500, true);
144 $i = 0;
145 foreach ($rs as $submission) {
146 $i++;
147 upgrade_set_timeout(60); // set up timeout, may also abort execution
148 $pbar->update($i, $count, "Migrating workshop submissions - $i/$count");
149
150 $filedir = "$CFG->dataroot/$submission->course/$CFG->moddata/workshop/$submission->id";
151 if ($files = get_directory_list($filedir, '', false)) {
152 $context = get_context_instance(CONTEXT_MODULE, $submission->cmid);
153 foreach ($files as $filename) {
154 $filepath = $filedir . '/' . $filename;
155 if (!is_readable($filepath)) {
156 echo $OUTPUT->notification('File not readable: ' . $filepath);
157 continue;
158 }
159 $filename = clean_param($filename, PARAM_FILE);
160 if ($filename === '') {
161 echo $OUTPUT->notification('Unsupported submission filename: ' . $filepath);
162 continue;
163 }
64f93798 164 if (! $fs->file_exists($context->id, 'mod_workshop', 'submission_attachment', $submission->id, '/', $filename)) {
067f63c5 165 $filerecord = array('contextid' => $context->id,
64f93798
PS
166 'component' => 'mod_workshop',
167 'filearea' => 'submission_attachment',
067f63c5
DM
168 'itemid' => $submission->id,
169 'filepath' => '/',
170 'filename' => $filename,
171 'userid' => $submission->authorid);
172 if ($fs->create_file_from_pathname($filerecord, $filepath)) {
173 $submission->attachment = 1;
dd88de0e
PS
174 $DB->update_record('workshop_submissions', $submission);
175 unlink($filepath);
067f63c5
DM
176 }
177 }
178 }
179 }
180 // remove dirs if empty
181 @rmdir("$CFG->dataroot/$submission->course/$CFG->moddata/workshop/$submission->id");
182 @rmdir("$CFG->dataroot/$submission->course/$CFG->moddata/workshop");
183 @rmdir("$CFG->dataroot/$submission->course/$CFG->moddata");
184 @rmdir("$CFG->dataroot/$submission->course");
185 }
186 $rs->close();
a4cdd6d2 187 upgrade_mod_savepoint(true, 2009102905, 'workshop');
067f63c5
DM
188 }
189
3d8649b1
DM
190 /**
191 * Migration from 1.9 - step 6 - migrate assessments
192 */
a4cdd6d2 193 if ($oldversion < 2009102906) {
3d8649b1
DM
194 require_once(dirname(__FILE__) . '/upgradelib.php');
195 echo $OUTPUT->notification('Copying assessments', 'notifysuccess');
196 workshop_upgrade_assessments();
a4cdd6d2 197 upgrade_mod_savepoint(true, 2009102906, 'workshop');
3d8649b1
DM
198 }
199
f2443a42
DM
200 /**
201 * End of migration from 1.9
202 */
203
204 /**
205 * Add 'published' field into workshop_submissions
206 */
a4cdd6d2 207 if ($oldversion < 2009121800) {
f2443a42
DM
208 $table = new xmldb_table('workshop_submissions');
209 $field = new xmldb_field('published', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, null, null, '0', 'timegraded');
210 if (!$dbman->field_exists($table, $field)) {
211 $dbman->add_field($table, $field);
212 }
a4cdd6d2 213 upgrade_mod_savepoint(true, 2009121800, 'workshop');
f2443a42
DM
214 }
215
c2d2eb6e
DM
216 /**
217 * Add 'evaluation' field into workshop
218 */
219 if ($oldversion < 2010070700) {
220 $table = new xmldb_table('workshop');
221 $field = new xmldb_field('evaluation', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null, 'strategy');
222 if (!$dbman->field_exists($table, $field)) {
223 $dbman->add_field($table, $field);
224 }
225 upgrade_mod_savepoint(true, 2010070700, 'workshop');
226 }
227
228 /**
229 * Set the value of the new 'evaluation' field to 'best', there is no alternative at the moment
230 */
231 if ($oldversion < 2010070701) {
232 $DB->set_field('workshop', 'evaluation', 'best');
233 upgrade_mod_savepoint(true, 2010070701, 'workshop');
234 }
235
c0ce5658
DM
236 /**
237 * Add 'late' field into workshop_submissions
238 */
239 if ($oldversion < 2010072300) {
240 $table = new xmldb_table('workshop_submissions');
241 $field = new xmldb_field('late', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'published');
242 if (!$dbman->field_exists($table, $field)) {
243 $dbman->add_field($table, $field);
244 }
245 upgrade_mod_savepoint(true, 2010072300, 'workshop');
246 }
247
4588b17b
DM
248 /**
249 * Create legacy _old tables to sync install.xml and real database
250 *
251 * In most cases these tables already exists because they were created during 1.9->2.0 migration
252 * This step is just for those site that were installed from vanilla 2.0 and these _old tables
253 * were not created.
254 * Note that these tables will be dropped again later in 2.x
255 */
256 if ($oldversion < 2010111200) {
257 foreach (array('workshop', 'workshop_elements', 'workshop_rubrics', 'workshop_submissions', 'workshop_assessments',
258 'workshop_grades', 'workshop_comments', 'workshop_stockcomments') as $tableorig) {
259 $tablearchive = $tableorig . '_old';
260 if (!$dbman->table_exists($tablearchive)) {
261 $dbman->install_one_table_from_xmldb_file($CFG->dirroot.'/mod/workshop/db/install.xml', $tablearchive);
262 }
263 }
264 upgrade_mod_savepoint(true, 2010111200, 'workshop');
265 }
266
f593111b
DM
267 /**
268 * Check the course_module integrity - see MDL-26312 for details
269 *
270 * Because of a bug in Workshop upgrade code, multiple workshop course_modules can
271 * potentially point to a single workshop instance. The chance is pretty low as in most cases,
272 * the upgrade failed. But under certain circumstances, workshop could be upgraded with
273 * this data integrity issue. We want to detect it now and let the admin know.
274 */
275 if ($oldversion < 2011021100) {
276 $sql = "SELECT cm.id, cm.course, cm.instance
277 FROM {course_modules} cm
278 WHERE cm.module IN (SELECT id
279 FROM {modules}
280 WHERE name = ?)";
281 $rs = $DB->get_recordset_sql($sql, array('workshop'));
282 $map = array(); // returned stdClasses by instance id
283 foreach ($rs as $cm) {
284 $map[$cm->instance][$cm->id] = $cm;
285 }
286 $rs->close();
287
288 $problems = array();
289 foreach ($map as $instanceid => $cms) {
290 if (count($cms) > 1) {
291 $problems[] = 'workshop instance ' . $instanceid . ' referenced by course_modules ' . implode(', ', array_keys($cms));
292 }
293 }
294 if ($problems) {
295 echo $OUTPUT->notification('¬°Ay, caramba! Data integrity corruption has been detected in your workshop ' . PHP_EOL .
296 'module database tables. This might be caused by a bug in workshop upgrade code. ' . PHP_EOL .
297 'Please report this issue immediately in workshop module support forum at ' . PHP_EOL .
298 'http://moodle.org so that we can help to fix this problem. Please copy and keep ' . PHP_EOL .
299 'following information for future reference:');
300 foreach ($problems as $problem) {
301 echo $OUTPUT->notification($problem);
302 upgrade_log(UPGRADE_LOG_NOTICE, 'mod_workshop', 'course_modules integrity problem', $problem);
303 }
304 }
305
0c3c0de1
DM
306 unset($problems);
307 unset($map);
f593111b
DM
308 upgrade_mod_savepoint(true, 2011021100, 'workshop');
309 }
310
a4cdd6d2 311 return true;
b876ab80 312}