weekly release 2.3dev
[moodle.git] / lib / db / upgrade.php
1 <?php
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/>.
18 /**
19  * This file keeps track of upgrades to Moodle.
20  *
21  * Sometimes, changes between versions involve
22  * alterations to database structures and other
23  * major things that may break installations.
24  *
25  * The upgrade function in this file will attempt
26  * to perform all the necessary actions to upgrade
27  * your older installation to the current version.
28  *
29  * If there's something it cannot do itself, it
30  * will tell you what you need to do.
31  *
32  * The commands in here will all be database-neutral,
33  * using the methods of database_manager class
34  *
35  * Please do not forget to use upgrade_set_timeout()
36  * before any action that may take longer time to finish.
37  *
38  * @package    core
39  * @subpackage admin
40  * @copyright  2006 onwards Martin Dougiamas  http://dougiamas.com
41  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42  */
44 defined('MOODLE_INTERNAL') || die();
46 /**
47  *
48  * @global stdClass $CFG
49  * @global stdClass $USER
50  * @global moodle_database $DB
51  * @global core_renderer $OUTPUT
52  * @param int $oldversion
53  * @return bool always true
54  */
55 function xmldb_main_upgrade($oldversion) {
56     global $CFG, $USER, $DB, $OUTPUT;
58     require_once($CFG->libdir.'/db/upgradelib.php'); // Core Upgrade-related functions
60     $dbman = $DB->get_manager(); // loads ddl manager and xmldb classes
62     if ($oldversion < 2011120500) {
63         // just in case somebody hacks upgrade scripts or env, we really can not continue
64         echo("You need to upgrade to 2.2.x first!\n");
65         exit(1);
66         // Note this savepoint is 100% unreachable, but needed to pass the upgrade checks
67         upgrade_main_savepoint(true, 2011120500);
68     }
70     ////////////////////////////////////////
71     ///upgrade supported only from 2.2.x ///
72     ////////////////////////////////////////
74     if ($oldversion < 2011120500.02) {
76         upgrade_set_timeout(60*20); // This may take a while
77         // MDL-28180. Some missing restrictions in certain backup & restore operations
78         // were causing incorrect duplicates in the course_completion_aggr_methd table.
79         // This upgrade step takes rid of them.
80         $sql = 'SELECT course, criteriatype, MIN(id) AS minid
81                   FROM {course_completion_aggr_methd}
82               GROUP BY course, criteriatype
83                 HAVING COUNT(*) > 1';
84         $duprs = $DB->get_recordset_sql($sql);
85         foreach ($duprs as $duprec) {
86             // We need to handle NULLs in criteriatype diferently
87             if (is_null($duprec->criteriatype)) {
88                 $where = 'course = ? AND criteriatype IS NULL AND id > ?';
89                 $params = array($duprec->course, $duprec->minid);
90             } else {
91                 $where = 'course = ? AND criteriatype = ? AND id > ?';
92                 $params = array($duprec->course, $duprec->criteriatype, $duprec->minid);
93             }
94             $DB->delete_records_select('course_completion_aggr_methd', $where, $params);
95         }
96         $duprs->close();
98         // Main savepoint reached
99         upgrade_main_savepoint(true, 2011120500.02);
100     }
102     if ($oldversion < 2011120500.03) {
104         // Changing precision of field value on table user_preferences to (1333)
105         $table = new xmldb_table('user_preferences');
106         $field = new xmldb_field('value', XMLDB_TYPE_CHAR, '1333', null, XMLDB_NOTNULL, null, null, 'name');
108         // Launch change of precision for field value
109         $dbman->change_field_precision($table, $field);
111         // Main savepoint reached
112         upgrade_main_savepoint(true, 2011120500.03);
113     }
115     if ($oldversion < 2012020200.03) {
117         // Define index rolecontext (not unique) to be added to role_assignments
118         $table = new xmldb_table('role_assignments');
119         $index = new xmldb_index('rolecontext', XMLDB_INDEX_NOTUNIQUE, array('roleid', 'contextid'));
121         // Conditionally launch add index rolecontext
122         if (!$dbman->index_exists($table, $index)) {
123             $dbman->add_index($table, $index);
124         }
126         // Define index usercontextrole (not unique) to be added to role_assignments
127         $index = new xmldb_index('usercontextrole', XMLDB_INDEX_NOTUNIQUE, array('userid', 'contextid', 'roleid'));
129         // Conditionally launch add index usercontextrole
130         if (!$dbman->index_exists($table, $index)) {
131             $dbman->add_index($table, $index);
132         }
134         // Main savepoint reached
135         upgrade_main_savepoint(true, 2012020200.03);
136     }
138     if ($oldversion < 2012020200.06) {
139         // Previously we always allowed users to override their email address via the messaging system
140         // We have now added a setting to allow admins to turn this this ability on and off
141         // While this setting defaults to 0 (off) we're setting it to 1 (on) to maintain the behaviour for upgrading sites
142         set_config('messagingallowemailoverride', 1);
144         // Main savepoint reached
145         upgrade_main_savepoint(true, 2012020200.06);
146     }
148     if ($oldversion < 2012021700.01) {
149         // Changing precision of field uniquehash on table post to 255
150         $table = new xmldb_table('post');
151         $field = new xmldb_field('uniquehash', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'content');
153         // Launch change of precision for field uniquehash
154         $dbman->change_field_precision($table, $field);
156         // Main savepoint reached
157         upgrade_main_savepoint(true, 2012021700.01);
158     }
160     if ($oldversion < 2012021700.02) {
161         // Somewhere before 1.9 summary and content column in post table were not null. In 1.9+
162         // not null became false.
163         $columns = $DB->get_columns('post');
165         // Fix discrepancies in summary field after upgrade from 1.9
166         if (array_key_exists('summary', $columns) && $columns['summary']->not_null != false) {
167             $table = new xmldb_table('post');
168             $summaryfield = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'big', null, null, null, null, 'subject');
170             if ($dbman->field_exists($table, $summaryfield)) {
171                 $dbman->change_field_notnull($table, $summaryfield);
172             }
174         }
176         // Fix discrepancies in content field after upgrade from 1.9
177         if (array_key_exists('content', $columns) && $columns['content']->not_null != false) {
178             $table = new xmldb_table('post');
179             $contentfield = new xmldb_field('content', XMLDB_TYPE_TEXT, 'big', null, null, null, null, 'summary');
181             if ($dbman->field_exists($table, $contentfield)) {
182                 $dbman->change_field_notnull($table, $contentfield);
183             }
185         }
187         upgrade_main_savepoint(true, 2012021700.02);
188     }
190     // The ability to backup user (private) files is out completely - MDL-29248
191     if ($oldversion < 2012030100.01) {
192         unset_config('backup_general_user_files', 'backup');
193         unset_config('backup_general_user_files_locked', 'backup');
194         unset_config('backup_auto_user_files', 'backup');
196         upgrade_main_savepoint(true, 2012030100.01);
197     }
199     if ($oldversion < 2012030100.02) {
200         // migrate all numbers to signed - it should be safe to interrupt this and continue later
201         upgrade_mysql_fix_unsigned_columns();
203         // Main savepoint reached
204         upgrade_main_savepoint(true, 2012030100.02);
205     }
207     if ($oldversion < 2012030900.01) {
208         // migrate all texts and binaries to big size - it should be safe to interrupt this and continue later
209         upgrade_mysql_fix_lob_columns();
211         // Main savepoint reached
212         upgrade_main_savepoint(true, 2012030900.01);
213     }
215     if ($oldversion < 2012031500.01) {
216         // Upgrade old course_allowed_modules data to be permission overrides.
217         if ($CFG->restrictmodulesfor === 'all') {
218             $courses = $DB->get_records_menu('course', array(), 'id', 'id, 1');
219         } else if ($CFG->restrictmodulesfor === 'requested') {
220             $courses = $DB->get_records_menu('course', array('retrictmodules' => 1), 'id', 'id, 1');
221         } else {
222             $courses = array();
223         }
225         if (!$dbman->table_exists('course_allowed_modules')) {
226             // Upgrade must already have been run on this server. This might happen,
227             // for example, during development of these changes.
228             $courses = array();
229         }
231         $modidtoname = $DB->get_records_menu('modules', array(), 'id', 'id, name');
233         $coursecount = count($courses);
234         if ($coursecount) {
235             $pbar = new progress_bar('allowedmods', 500, true);
236             $transaction = $DB->start_delegated_transaction();
237         }
239         $i = 0;
240         foreach ($courses as $courseid => $notused) {
241             $i += 1;
242             upgrade_set_timeout(60); // 1 minute per course should be fine.
244             $allowedmoduleids = $DB->get_records_menu('course_allowed_modules',
245             array('course' => $courseid), 'module', 'module, 1');
246             if (empty($allowedmoduleids)) {
247                 // This seems to be the best match for backwards compatibility,
248                 // not necessarily with the old code in course_allowed_module function,
249                 // but with the code that used to be in the coures settings form.
250                 $allowedmoduleids = explode(',', $CFG->defaultallowedmodules);
251                 $allowedmoduleids = array_combine($allowedmoduleids, $allowedmoduleids);
252             }
254             $context = context_course::instance($courseid);
256             list($roleids) = get_roles_with_cap_in_context($context, 'moodle/course:manageactivities');
257             list($managerroleids) = get_roles_with_cap_in_context($context, 'moodle/site:config');
258             foreach ($managerroleids as $roleid) {
259                 unset($roleids[$roleid]);
260             }
262             foreach ($modidtoname as $modid => $modname) {
263                 if (isset($allowedmoduleids[$modid])) {
264                     // Module is allowed, no worries.
265                     continue;
266                 }
268                 $capability = 'mod/' . $modname . ':addinstance';
269                 foreach ($roleids as $roleid) {
270                     assign_capability($capability, CAP_PREVENT, $roleid, $context);
271                 }
272             }
274             $pbar->update($i, $coursecount, "Upgrading legacy course_allowed_modules data - $i/$coursecount.");
275         }
277         if ($coursecount) {
278             $transaction->allow_commit();
279         }
281         upgrade_main_savepoint(true, 2012031500.01);
282     }
284     if ($oldversion < 2012031500.02) {
286         // Define field retrictmodules to be dropped from course
287         $table = new xmldb_table('course');
288         $field = new xmldb_field('restrictmodules');
290         // Conditionally launch drop field requested
291         if ($dbman->field_exists($table, $field)) {
292             $dbman->drop_field($table, $field);
293         }
295         upgrade_main_savepoint(true, 2012031500.02);
296     }
298     if ($oldversion < 2012031500.03) {
300         // Define table course_allowed_modules to be dropped
301         $table = new xmldb_table('course_allowed_modules');
303         // Conditionally launch drop table for course_allowed_modules
304         if ($dbman->table_exists($table)) {
305             $dbman->drop_table($table);
306         }
308         upgrade_main_savepoint(true, 2012031500.03);
309     }
311     if ($oldversion < 2012031500.04) {
312         // Clean up the old admin settings.
313         unset_config('restrictmodulesfor');
314         unset_config('restrictbydefault');
315         unset_config('defaultallowedmodules');
317         upgrade_main_savepoint(true, 2012031500.04);
318     }
320     if ($oldversion < 2012032300.02) {
321         // Migrate the old admin debug setting.
322         if ($CFG->debug == 38911) {
323             set_config('debug', DEBUG_DEVELOPER);
324         } else if ($CFG->debug == 6143) {
325             set_config('debug', DEBUG_ALL);
326         }
327         upgrade_main_savepoint(true, 2012032300.02);
328     }
331     return true;