fixed wrong error string
[moodle.git] / lib / upgradelib.php
CommitLineData
96db14f9 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/>.
db9d4a3d 17
18/**
8580535b 19 * Various upgrade/install related functions and classes.
db9d4a3d 20 *
96db14f9 21 * @package moodlecore
22 * @subpackage upgrade
23 * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
db9d4a3d 25 */
26
72fb21b6 27/** UPGRADE_LOG_NORMAL = 0 */
db9d4a3d 28define('UPGRADE_LOG_NORMAL', 0);
72fb21b6 29/** UPGRADE_LOG_NOTICE = 1 */
db9d4a3d 30define('UPGRADE_LOG_NOTICE', 1);
72fb21b6 31/** UPGRADE_LOG_ERROR = 2 */
795a08ad 32define('UPGRADE_LOG_ERROR', 2);
33
34/**
35 * Exception indicating unknown error during upgrade.
72fb21b6 36 *
37 * @package moodlecore
38 * @subpackage upgrade
39 * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
795a08ad 41 */
42class upgrade_exception extends moodle_exception {
43 function __construct($plugin, $version) {
44 global $CFG;
45 $a = (object)array('plugin'=>$plugin, 'version'=>$version);
45440ceb 46 parent::__construct('upgradeerror', 'admin', "$CFG->wwwroot/$CFG->admin/index.php", $a);
795a08ad 47 }
48}
49
50/**
51 * Exception indicating downgrade error during upgrade.
72fb21b6 52 *
53 * @package moodlecore
54 * @subpackage upgrade
55 * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
56 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
795a08ad 57 */
58class downgrade_exception extends moodle_exception {
59 function __construct($plugin, $oldversion, $newversion) {
60 global $CFG;
61 $plugin = is_null($plugin) ? 'moodle' : $plugin;
62 $a = (object)array('plugin'=>$plugin, 'oldversion'=>$oldversion, 'newversion'=>$newversion);
63 parent::__construct('cannotdowngrade', 'debug', "$CFG->wwwroot/$CFG->admin/index.php", $a);
64 }
65}
66
72fb21b6 67/**
68 * @package moodlecore
69 * @subpackage upgrade
70 * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
71 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
72 */
795a08ad 73class upgrade_requires_exception extends moodle_exception {
74 function __construct($plugin, $pluginversion, $currentmoodle, $requiremoodle) {
75 global $CFG;
76 $a = new object();
77 $a->pluginname = $plugin;
78 $a->pluginversion = $pluginversion;
79 $a->currentmoodle = $currentmoodle;
17da2e6f 80 $a->requiremoodle = $requiremoodle;
795a08ad 81 parent::__construct('pluginrequirementsnotmet', 'error', "$CFG->wwwroot/$CFG->admin/index.php", $a);
82 }
83}
84
72fb21b6 85/**
86 * @package moodlecore
87 * @subpackage upgrade
88 * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
89 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
90 */
795a08ad 91class plugin_defective_exception extends moodle_exception {
92 function __construct($plugin, $details) {
93 global $CFG;
94 parent::__construct('detectedbrokenplugin', 'error', "$CFG->wwwroot/$CFG->admin/index.php", $plugin, $details);
95 }
96}
db9d4a3d 97
98/**
99 * Insert or update log display entry. Entry may already exist.
100 * $module, $action must be unique
101 *
72fb21b6 102 * @global object
db9d4a3d 103 * @param string $module
104 * @param string $action
105 * @param string $mtable
106 * @param string $field
107 * @return void
108 *
109 */
110function update_log_display_entry($module, $action, $mtable, $field) {
111 global $DB;
112
113 if ($type = $DB->get_record('log_display', array('module'=>$module, 'action'=>$action))) {
114 $type->mtable = $mtable;
115 $type->field = $field;
116 $DB->update_record('log_display', $type);
117
118 } else {
119 $type = new object();
120 $type->module = $module;
121 $type->action = $action;
122 $type->mtable = $mtable;
123 $type->field = $field;
124
125 $DB->insert_record('log_display', $type, false);
126 }
127}
128
129/**
130 * Upgrade savepoint, marks end of each upgrade block.
131 * It stores new main version, resets upgrade timeout
132 * and abort upgrade if user cancels page loading.
133 *
134 * Please do not make large upgrade blocks with lots of operations,
135 * for example when adding tables keep only one table operation per block.
136 *
72fb21b6 137 * @global object
db9d4a3d 138 * @param bool $result false if upgrade step failed, true if completed
139 * @param string or float $version main version
140 * @param bool $allowabort allow user to abort script execution here
141 * @return void
142 */
143function upgrade_main_savepoint($result, $version, $allowabort=true) {
144 global $CFG;
145
795a08ad 146 if (!$result) {
520cea92 147 throw new upgrade_exception(null, $version);
795a08ad 148 }
149
150 if ($CFG->version >= $version) {
151 // something really wrong is going on in main upgrade script
152 throw new downgrade_exception(null, $CFG->version, $version);
db9d4a3d 153 }
154
795a08ad 155 set_config('version', $version);
156 upgrade_log(UPGRADE_LOG_NORMAL, null, 'Upgrade savepoint reached');
157
db9d4a3d 158 // reset upgrade timeout to default
159 upgrade_set_timeout();
160
161 // this is a safe place to stop upgrades if user aborts page loading
162 if ($allowabort and connection_aborted()) {
163 die;
164 }
165}
166
167/**
168 * Module upgrade savepoint, marks end of module upgrade blocks
169 * It stores module version, resets upgrade timeout
170 * and abort upgrade if user cancels page loading.
171 *
72fb21b6 172 * @global object
db9d4a3d 173 * @param bool $result false if upgrade step failed, true if completed
174 * @param string or float $version main version
175 * @param string $modname name of module
176 * @param bool $allowabort allow user to abort script execution here
177 * @return void
178 */
179function upgrade_mod_savepoint($result, $version, $modname, $allowabort=true) {
180 global $DB;
181
795a08ad 182 if (!$result) {
520cea92 183 throw new upgrade_exception("mod_$modname", $version);
795a08ad 184 }
185
db9d4a3d 186 if (!$module = $DB->get_record('modules', array('name'=>$modname))) {
187 print_error('modulenotexist', 'debug', '', $modname);
188 }
189
795a08ad 190 if ($module->version >= $version) {
191 // something really wrong is going on in upgrade script
520cea92 192 throw new downgrade_exception("mod_$modname", $module->version, $version);
db9d4a3d 193 }
795a08ad 194 $module->version = $version;
195 $DB->update_record('modules', $module);
520cea92 196 upgrade_log(UPGRADE_LOG_NORMAL, "mod_$modname", 'Upgrade savepoint reached');
db9d4a3d 197
198 // reset upgrade timeout to default
199 upgrade_set_timeout();
200
201 // this is a safe place to stop upgrades if user aborts page loading
202 if ($allowabort and connection_aborted()) {
203 die;
204 }
205}
206
207/**
208 * Blocks upgrade savepoint, marks end of blocks upgrade blocks
209 * It stores block version, resets upgrade timeout
210 * and abort upgrade if user cancels page loading.
211 *
72fb21b6 212 * @global object
db9d4a3d 213 * @param bool $result false if upgrade step failed, true if completed
214 * @param string or float $version main version
215 * @param string $blockname name of block
216 * @param bool $allowabort allow user to abort script execution here
217 * @return void
218 */
795a08ad 219function upgrade_block_savepoint($result, $version, $blockname, $allowabort=true) {
db9d4a3d 220 global $DB;
221
795a08ad 222 if (!$result) {
520cea92 223 throw new upgrade_exception("block_$blockname", $version);
795a08ad 224 }
225
db9d4a3d 226 if (!$block = $DB->get_record('block', array('name'=>$blockname))) {
227 print_error('blocknotexist', 'debug', '', $blockname);
228 }
229
795a08ad 230 if ($block->version >= $version) {
231 // something really wrong is going on in upgrade script
520cea92 232 throw new downgrade_exception("block_$blockname", $block->version, $version);
db9d4a3d 233 }
795a08ad 234 $block->version = $version;
235 $DB->update_record('block', $block);
520cea92 236 upgrade_log(UPGRADE_LOG_NORMAL, "block_$blockname", 'Upgrade savepoint reached');
db9d4a3d 237
238 // reset upgrade timeout to default
239 upgrade_set_timeout();
240
241 // this is a safe place to stop upgrades if user aborts page loading
242 if ($allowabort and connection_aborted()) {
243 die;
244 }
245}
246
247/**
248 * Plugins upgrade savepoint, marks end of blocks upgrade blocks
249 * It stores plugin version, resets upgrade timeout
250 * and abort upgrade if user cancels page loading.
251 *
252 * @param bool $result false if upgrade step failed, true if completed
253 * @param string or float $version main version
254 * @param string $type name of plugin
255 * @param string $dir location of plugin
256 * @param bool $allowabort allow user to abort script execution here
257 * @return void
258 */
17da2e6f 259function upgrade_plugin_savepoint($result, $version, $type, $plugin, $allowabort=true) {
260 $component = $type.'_'.$plugin;
261
795a08ad 262 if (!$result) {
17da2e6f 263 throw new upgrade_exception($component, $version);
db9d4a3d 264 }
265
17da2e6f 266 $installedversion = get_config($component, 'version');
795a08ad 267 if ($installedversion >= $version) {
268 // Something really wrong is going on in the upgrade script
269 throw new downgrade_exception($component, $installedversion, $version);
270 }
17da2e6f 271 set_config('version', $version, $component);
795a08ad 272 upgrade_log(UPGRADE_LOG_NORMAL, $component, 'Upgrade savepoint reached');
273
db9d4a3d 274 // Reset upgrade timeout to default
275 upgrade_set_timeout();
276
277 // This is a safe place to stop upgrades if user aborts page loading
278 if ($allowabort and connection_aborted()) {
279 die;
280 }
281}
282
283
284/**
285 * Upgrade plugins
db9d4a3d 286 * @param string $type The type of plugins that should be updated (e.g. 'enrol', 'qtype')
17da2e6f 287 * return void
db9d4a3d 288 */
17da2e6f 289function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
db9d4a3d 290 global $CFG, $DB;
291
292/// special cases
293 if ($type === 'mod') {
194cdca8 294 return upgrade_plugins_modules($startcallback, $endcallback, $verbose);
795a08ad 295 } else if ($type === 'block') {
194cdca8 296 return upgrade_plugins_blocks($startcallback, $endcallback, $verbose);
db9d4a3d 297 }
298
17da2e6f 299 $plugs = get_plugin_list($type);
db9d4a3d 300
17da2e6f 301 foreach ($plugs as $plug=>$fullplug) {
302 $component = $type.'_'.$plug; // standardised plugin name
db9d4a3d 303
795a08ad 304 if (!is_readable($fullplug.'/version.php')) {
305 continue;
db9d4a3d 306 }
307
795a08ad 308 $plugin = new object();
309 require($fullplug.'/version.php'); // defines $plugin with version etc
db9d4a3d 310
795a08ad 311 if (empty($plugin->version)) {
312 throw new plugin_defective_exception($component, 'Missing version value in version.php');
db9d4a3d 313 }
314
17da2e6f 315 $plugin->name = $plug;
316 $plugin->fullname = $component;
795a08ad 317
318
db9d4a3d 319 if (!empty($plugin->requires)) {
320 if ($plugin->requires > $CFG->version) {
795a08ad 321 throw new upgrade_requires_exception($component, $plugin->version, $CFG->version, $plugin->requires);
db9d4a3d 322 }
323 }
324
db9d4a3d 325 $installedversion = get_config($plugin->fullname, 'version');
326
795a08ad 327 if (empty($installedversion)) { // new installation
194cdca8 328 $startcallback($component, true, $verbose);
db9d4a3d 329
795a08ad 330 /// Install tables if defined
331 if (file_exists($fullplug.'/db/install.xml')) {
332 $DB->get_manager()->install_from_xmldb_file($fullplug.'/db/install.xml');
db9d4a3d 333 }
795a08ad 334 /// execute post install file
335 if (file_exists($fullplug.'/db/install.php')) {
336 require_once($fullplug.'/db/install.php');
337 $post_install_function = 'xmldb_'.$plugin->fullname.'_install';;
338 $post_install_function();
339 }
340
341 /// store version
342 upgrade_plugin_savepoint(true, $plugin->version, $type, $plug, false);
343
344 /// Install various components
345 update_capabilities($component);
346 events_update_definition($component);
347 message_update_providers($component);
348
194cdca8 349 $endcallback($component, true, $verbose);
795a08ad 350
351 } else if ($installedversion < $plugin->version) { // upgrade
352 /// Run the upgrade function for the plugin.
194cdca8 353 $startcallback($component, false, $verbose);
795a08ad 354
355 if (is_readable($fullplug.'/db/upgrade.php')) {
356 require_once($fullplug.'/db/upgrade.php'); // defines upgrading function
357
358 $newupgrade_function = 'xmldb_'.$plugin->fullname.'_upgrade';
359 $result = $newupgrade_function($installedversion);
360 } else {
361 $result = true;
362 }
363
364 $installedversion = get_config($plugin->fullname, 'version');
365 if ($installedversion < $plugin->version) {
366 // store version if not already there
367 upgrade_plugin_savepoint($result, $plugin->version, $type, $plug, false);
368 }
369
370 /// Upgrade various components
371 update_capabilities($component);
372 events_update_definition($component);
373 message_update_providers($component);
374
194cdca8 375 $endcallback($component, false, $verbose);
795a08ad 376
377 } else if ($installedversion > $plugin->version) {
378 throw new downgrade_exception($component, $installedversion, $plugin->version);
db9d4a3d 379 }
380 }
db9d4a3d 381}
382
383/**
384 * Find and check all modules and load them up or upgrade them if necessary
72fb21b6 385 *
386 * @global object
387 * @global object
db9d4a3d 388 */
194cdca8 389function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
db9d4a3d 390 global $CFG, $DB;
391
17da2e6f 392 $mods = get_plugin_list('mod');
db9d4a3d 393
17da2e6f 394 foreach ($mods as $mod=>$fullmod) {
db9d4a3d 395
396 if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it
397 continue;
398 }
399
17da2e6f 400 $component = 'mod_'.$mod;
db9d4a3d 401
795a08ad 402 if (!is_readable($fullmod.'/version.php')) {
403 throw new plugin_defective_exception($component, 'Missing version.php');
db9d4a3d 404 }
405
795a08ad 406 $module = new object();
407 require($fullmod .'/version.php'); // defines $module with version etc
db9d4a3d 408
795a08ad 409 if (empty($module->version)) {
c1fe2368 410 if (isset($module->version)) {
411 // Version is empty but is set - it means its value is 0 or ''. Let us skip such module.
412 // This is inteded for developers so they can work on the early stages of the module.
413 continue;
414 }
795a08ad 415 throw new plugin_defective_exception($component, 'Missing version value in version.php');
db9d4a3d 416 }
417
418 if (!empty($module->requires)) {
419 if ($module->requires > $CFG->version) {
795a08ad 420 throw new upgrade_requires_exception($component, $module->version, $CFG->version, $module->requires);
db9d4a3d 421 }
422 }
423
424 $module->name = $mod; // The name MUST match the directory
425
795a08ad 426 $currmodule = $DB->get_record('modules', array('name'=>$module->name));
db9d4a3d 427
795a08ad 428 if (empty($currmodule->version)) {
194cdca8 429 $startcallback($component, true, $verbose);
db9d4a3d 430
795a08ad 431 /// Execute install.xml (XMLDB) - must be present in all modules
432 $DB->get_manager()->install_from_xmldb_file($fullmod.'/db/install.xml');
db9d4a3d 433
2e3da297 434 /// Add record into modules table - may be needed in install.php already
435 $module->id = $DB->insert_record('modules', $module);
436
db9d4a3d 437 /// Post installation hook - optional
438 if (file_exists("$fullmod/db/install.php")) {
439 require_once("$fullmod/db/install.php");
440 $post_install_function = 'xmldb_'.$module->name.'_install';;
441 $post_install_function();
442 }
443
795a08ad 444 /// Install various components
445 update_capabilities($component);
446 events_update_definition($component);
447 message_update_providers($component);
448
194cdca8 449 $endcallback($component, true, $verbose);
db9d4a3d 450
795a08ad 451 } else if ($currmodule->version < $module->version) {
452 /// If versions say that we need to upgrade but no upgrade files are available, notify and continue
194cdca8 453 $startcallback($component, false, $verbose);
795a08ad 454
455 if (is_readable($fullmod.'/db/upgrade.php')) {
456 require_once($fullmod.'/db/upgrade.php'); // defines new upgrading function
457 $newupgrade_function = 'xmldb_'.$module->name.'_upgrade';
458 $result = $newupgrade_function($currmodule->version, $module);
459 } else {
460 $result = true;
461 }
462
463 $currmodule = $DB->get_record('modules', array('name'=>$module->name));
464 if ($currmodule->version < $module->version) {
465 // store version if not already there
466 upgrade_mod_savepoint($result, $module->version, $mod, false);
467 }
468
469 /// Upgrade various components
470 update_capabilities($component);
471 events_update_definition($component);
472 message_update_providers($component);
473
474 remove_dir($CFG->dataroot.'/cache', true); // flush cache
475
194cdca8 476 $endcallback($component, false, $verbose);
795a08ad 477
478 } else if ($currmodule->version > $module->version) {
479 throw new downgrade_exception($component, $currmodule->version, $module->version);
480 }
481 }
482}
db9d4a3d 483
db9d4a3d 484
795a08ad 485/**
486 * This function finds all available blocks and install them
487 * into blocks table or do all the upgrade process if newer.
72fb21b6 488 *
489 * @global object
490 * @global object
795a08ad 491 */
194cdca8 492function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
795a08ad 493 global $CFG, $DB;
494
795a08ad 495 require_once($CFG->dirroot.'/blocks/moodleblock.class.php');
496
497 $blocktitles = array(); // we do not want duplicate titles
498
499 //Is this a first install
500 $first_install = null;
501
17da2e6f 502 $blocks = get_plugin_list('block');
795a08ad 503
17da2e6f 504 foreach ($blocks as $blockname=>$fullblock) {
795a08ad 505
506 if (is_null($first_install)) {
507 $first_install = ($DB->count_records('block') == 0);
508 }
509
510 if ($blockname == 'NEWBLOCK') { // Someone has unzipped the template, ignore it
511 continue;
db9d4a3d 512 }
513
17da2e6f 514 $component = 'block_'.$blockname;
db9d4a3d 515
795a08ad 516 if (!is_readable($fullblock.'/block_'.$blockname.'.php')) {
517 throw new plugin_defective_exception('block/'.$blockname, 'Missing main block class file.');
db9d4a3d 518 }
795a08ad 519 require_once($fullblock.'/block_'.$blockname.'.php');
db9d4a3d 520
795a08ad 521 $classname = 'block_'.$blockname;
522
523 if (!class_exists($classname)) {
524 throw new plugin_defective_exception($component, 'Can not load main class.');
525 }
526
527 $blockobj = new $classname; // This is what we 'll be testing
528 $blocktitle = $blockobj->get_title();
529
530 // OK, it's as we all hoped. For further tests, the object will do them itself.
531 if (!$blockobj->_self_test()) {
532 throw new plugin_defective_exception($component, 'Self test failed.');
533 }
534
535 $block = new object(); // This may be used to update the db below
536 $block->name = $blockname; // The name MUST match the directory
537 $block->version = $blockobj->get_version();
538 $block->cron = !empty($blockobj->cron) ? $blockobj->cron : 0;
539 $block->multiple = $blockobj->instance_allow_multiple() ? 1 : 0;
540
541 if (empty($block->version)) {
542 throw new plugin_defective_exception($component, 'Missing block version.');
543 }
544
545 $currblock = $DB->get_record('block', array('name'=>$block->name));
546
547 if (empty($currblock->version)) { // block not installed yet, so install it
548 // If it allows multiples, start with it enabled
549
550 $conflictblock = array_search($blocktitle, $blocktitles);
551 if ($conflictblock !== false) {
552 // Duplicate block titles are not allowed, they confuse people
553 // AND PHP's associative arrays ;)
554 throw new plugin_defective_exception($component, get_string('blocknameconflict', '', (object)array('name'=>$block->name, 'conflict'=>$conflictblock)));
555 }
194cdca8 556 $startcallback($component, true, $verbose);
795a08ad 557
558 if (file_exists($fullblock.'/db/install.xml')) {
559 $DB->get_manager()->install_from_xmldb_file($fullblock.'/db/install.xml');
560 }
561 $block->id = $DB->insert_record('block', $block);
562
563 if (file_exists($fullblock.'/db/install.php')) {
564 require_once($fullblock.'/db/install.php');
565 $post_install_function = 'xmldb_block_'.$blockname.'_install';;
566 $post_install_function();
567 }
568
569 $blocktitles[$block->name] = $blocktitle;
570
571 // Install various components
572 update_capabilities($component);
573 events_update_definition($component);
574 message_update_providers($component);
575
194cdca8 576 $endcallback($component, true, $verbose);
795a08ad 577
578 } else if ($currblock->version < $block->version) {
194cdca8 579 $startcallback($component, false, $verbose);
795a08ad 580
581 if (is_readable($fullblock.'/db/upgrade.php')) {
582 require_once($fullblock.'/db/upgrade.php'); // defines new upgrading function
583 $newupgrade_function = 'xmldb_block_'.$blockname.'_upgrade';
584 $result = $newupgrade_function($currblock->version, $block);
585 } else {
586 $result = true;
587 }
588
589 $currblock = $DB->get_record('block', array('name'=>$block->name));
590 if ($currblock->version < $block->version) {
591 // store version if not already there
592 upgrade_block_savepoint($result, $block->version, $block->name, false);
593 }
594
595 if ($currblock->cron != $block->cron) {
596 // update cron flag if needed
597 $currblock->cron = $block->cron;
598 $DB->update_record('block', $currblock);
599 }
600
601 // Upgrade various componebts
795a08ad 602 update_capabilities($component);
17da2e6f 603 events_update_definition($component);
795a08ad 604 message_update_providers($component);
605
194cdca8 606 $endcallback($component, false, $verbose);
795a08ad 607
608 } else if ($currblock->version > $block->version) {
609 throw new downgrade_exception($component, $currblock->version, $block->version);
610 }
611 }
612
613
614 // Finally, if we are in the first_install of BLOCKS setup frontpage and admin page blocks
615 if ($first_install) {
795a08ad 616 //Iterate over each course - there should be only site course here now
617 if ($courses = $DB->get_records('course')) {
618 foreach ($courses as $course) {
9d1d606e 619 blocks_add_default_course_blocks($course);
db9d4a3d 620 }
621 }
795a08ad 622
9d1d606e 623 blocks_add_default_system_blocks();
795a08ad 624 }
625}
626
72fb21b6 627/**
628 * upgrade logging functions
72fb21b6 629 */
fd1a792e 630function upgrade_handle_exception($ex, $plugin = null) {
631 default_exception_handler($ex, true, $plugin);
db9d4a3d 632}
633
634/**
635 * Adds log entry into upgrade_log table
636 *
72fb21b6 637 * @global object
638 * @global object
639 * @global object
db9d4a3d 640 * @param int $type UPGRADE_LOG_NORMAL, UPGRADE_LOG_NOTICE or UPGRADE_LOG_ERROR
641 * @param string $plugin plugin or null if main
642 * @param string $info short description text of log entry
643 * @param string $details long problem description
644 * @param string $backtrace string used for errors only
645 * @return void
646 */
647function upgrade_log($type, $plugin, $info, $details=null, $backtrace=null) {
648 global $DB, $USER, $CFG;
649
795a08ad 650 $plugin = ($plugin==='moodle') ? null : $plugin;
651
34a2777c 652 $backtrace = format_backtrace($backtrace, true);
db9d4a3d 653
654 $version = null;
655
656 //first try to find out current version number
795a08ad 657 if (empty($plugin) or $plugin === 'moodle') {
db9d4a3d 658 //main
659 $version = $CFG->version;
660
795a08ad 661 } else if ($plugin === 'local') {
662 //customisation
663 $version = $CFG->local_version;
664
665 } else if (strpos($plugin, 'mod/') === 0) {
db9d4a3d 666 try {
667 $modname = substr($plugin, strlen('mod/'));
668 $version = $DB->get_field('modules', 'version', array('name'=>$modname));
795a08ad 669 $version = ($version === false) ? null : $version;
db9d4a3d 670 } catch (Exception $ignored) {
671 }
672
795a08ad 673 } else if (strpos($plugin, 'block/') === 0) {
db9d4a3d 674 try {
795a08ad 675 $blockname = substr($plugin, strlen('block/'));
db9d4a3d 676 if ($block = $DB->get_record('block', array('name'=>$blockname))) {
677 $version = $block->version;
678 }
679 } catch (Exception $ignored) {
680 }
795a08ad 681
682 } else {
683 $pluginversion = get_config(str_replace('/', '_', $plugin), 'version');
684 if (!empty($pluginversion)) {
685 $version = $pluginversion;
686 }
db9d4a3d 687 }
688
689 $log = new object();
690 $log->type = $type;
691 $log->plugin = $plugin;
692 $log->version = $version;
693 $log->info = $info;
694 $log->details = $details;
695 $log->backtrace = $backtrace;
696 $log->userid = $USER->id;
697 $log->timemodified = time();
db9d4a3d 698 try {
699 $DB->insert_record('upgrade_log', $log);
700 } catch (Exception $ignored) {
795a08ad 701 // possible during install or 2.0 upgrade
db9d4a3d 702 }
703}
704
705/**
706 * Marks start of upgrade, blocks any other access to site.
707 * The upgrade is finished at the end of script or after timeout.
72fb21b6 708 *
709 * @global object
710 * @global object
711 * @global object
db9d4a3d 712 */
713function upgrade_started($preinstall=false) {
c13a5e71 714 global $CFG, $DB, $PAGE;
db9d4a3d 715
716 static $started = false;
717
718 if ($preinstall) {
719 ignore_user_abort(true);
720 upgrade_setup_debug(true);
721
722 } else if ($started) {
723 upgrade_set_timeout(120);
724
725 } else {
c13a5e71 726 if (!CLI_SCRIPT and !$PAGE->headerprinted) {
db9d4a3d 727 $strupgrade = get_string('upgradingversion', 'admin');
d4a03c00 728 $PAGE->set_generaltype('maintenance');
e29380f3 729 upgrade_get_javascript();
9ace5094 730 print_header($strupgrade.' - Moodle '.$CFG->target_release, $strupgrade,
db9d4a3d 731 build_navigation(array(array('name' => $strupgrade, 'link' => null, 'type' => 'misc'))), '',
e29380f3 732 '', false, '&nbsp;', '&nbsp;');
db9d4a3d 733 }
734
735 ignore_user_abort(true);
736 register_shutdown_function('upgrade_finished_handler');
737 upgrade_setup_debug(true);
738 set_config('upgraderunning', time()+300);
739 $started = true;
740 }
741}
742
743/**
744 * Internal function - executed if upgrade interruped.
745 */
746function upgrade_finished_handler() {
747 upgrade_finished();
748}
749
750/**
751 * Indicates upgrade is finished.
752 *
753 * This function may be called repeatedly.
72fb21b6 754 *
755 * @global object
756 * @global object
db9d4a3d 757 */
758function upgrade_finished($continueurl=null) {
7e0d6675 759 global $CFG, $DB, $OUTPUT;
db9d4a3d 760
761 if (!empty($CFG->upgraderunning)) {
762 unset_config('upgraderunning');
763 upgrade_setup_debug(false);
764 ignore_user_abort(false);
765 if ($continueurl) {
766 print_continue($continueurl);
7e0d6675 767 echo $OUTPUT->footer();
db9d4a3d 768 die;
769 }
770 }
771}
772
72fb21b6 773/**
774 * @global object
775 * @global object
776 */
db9d4a3d 777function upgrade_setup_debug($starting) {
778 global $CFG, $DB;
779
780 static $originaldebug = null;
781
782 if ($starting) {
783 if ($originaldebug === null) {
784 $originaldebug = $DB->get_debug();
785 }
786 if (!empty($CFG->upgradeshowsql)) {
787 $DB->set_debug(true);
788 }
789 } else {
790 $DB->set_debug($originaldebug);
791 }
792}
793
72fb21b6 794/**
795 * @global object
796 */
90509582 797function print_upgrade_reload($url) {
f2a1963c 798 global $OUTPUT;
90509582 799
800 echo "<br />";
801 echo '<div class="continuebutton">';
f2a1963c 802 echo '<a href="'.$url.'" title="'.get_string('reload').'" ><img src="'.$OUTPUT->old_icon_url('i/reload') . '" alt="" /> '.get_string('reload').'</a>';
90509582 803 echo '</div><br />';
804}
805
db9d4a3d 806function print_upgrade_separator() {
807 if (!CLI_SCRIPT) {
808 echo '<hr />';
809 }
810}
811
795a08ad 812/**
813 * Default start upgrade callback
814 * @param string $plugin
815 * @param bool $installation true if installation, false menas upgrade
816 */
194cdca8 817function print_upgrade_part_start($plugin, $installation, $verbose) {
3c159385 818 global $OUTPUT;
795a08ad 819 if (empty($plugin) or $plugin == 'moodle') {
820 upgrade_started($installation); // does not store upgrade running flag yet
194cdca8 821 if ($verbose) {
3c159385 822 echo $OUTPUT->heading(get_string('coresystem'));
194cdca8 823 }
795a08ad 824 } else {
825 upgrade_started();
194cdca8 826 if ($verbose) {
3c159385 827 echo $OUTPUT->heading($plugin);
194cdca8 828 }
795a08ad 829 }
830 if ($installation) {
831 if (empty($plugin) or $plugin == 'moodle') {
832 // no need to log - log table not yet there ;-)
833 } else {
834 upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting plugin installation');
835 }
836 } else {
837 if (empty($plugin) or $plugin == 'moodle') {
838 upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting core upgrade');
839 } else {
840 upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting plugin upgrade');
841 }
842 }
843}
844
845/**
846 * Default end upgrade callback
847 * @param string $plugin
848 * @param bool $installation true if installation, false menas upgrade
849 */
194cdca8 850function print_upgrade_part_end($plugin, $installation, $verbose) {
795a08ad 851 upgrade_started();
852 if ($installation) {
853 if (empty($plugin) or $plugin == 'moodle') {
854 upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Core installed');
855 } else {
856 upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Plugin installed');
857 }
858 } else {
859 if (empty($plugin) or $plugin == 'moodle') {
860 upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Core upgraded');
861 } else {
862 upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Plugin upgraded');
863 }
864 }
194cdca8 865 if ($verbose) {
866 notify(get_string('success'), 'notifysuccess');
867 print_upgrade_separator();
96db14f9 868 }
869}
870
72fb21b6 871/**
872 * @global object
873 */
db9d4a3d 874function upgrade_get_javascript() {
e29380f3 875 global $PAGE;
876 $PAGE->requires->js('lib/javascript-static.js')->at_top_of_body();
877 $PAGE->requires->js_function_call('repeatedly_scroll_to_end')->at_top_of_body();
878 $PAGE->requires->js_function_call('cancel_scroll_to_end')->after_delay(1);
db9d4a3d 879}
880
881
882/**
883 * Try to upgrade the given language pack (or current language)
72fb21b6 884 * @global object
db9d4a3d 885 */
886function upgrade_language_pack($lang='') {
3c159385 887 global $CFG, $OUTPUT;
db9d4a3d 888
889 if (empty($lang)) {
890 $lang = current_language();
891 }
892
893 if ($lang == 'en_utf8') {
894 return true; // Nothing to do
895 }
896
551fe0e5 897 upgrade_started(false);
3c159385 898 echo $OUTPUT->heading(get_string('langimport', 'admin').': '.$lang);
db9d4a3d 899
900 @mkdir ($CFG->dataroot.'/temp/'); //make it in case it's a fresh install, it might not be there
901 @mkdir ($CFG->dataroot.'/lang/');
902
903 require_once($CFG->libdir.'/componentlib.class.php');
904
905 if ($cd = new component_installer('http://download.moodle.org', 'lang16', $lang.'.zip', 'languages.md5', 'lang')) {
906 $status = $cd->install(); //returns COMPONENT_(ERROR | UPTODATE | INSTALLED)
907
908 if ($status == COMPONENT_INSTALLED) {
db9d4a3d 909 @unlink($CFG->dataroot.'/cache/languages');
551fe0e5 910 if ($parentlang = get_parent_language($lang)) {
911 if ($cd = new component_installer('http://download.moodle.org', 'lang16', $parentlang.'.zip', 'languages.md5', 'lang')) {
912 $cd->install();
913 }
914 }
915 notify(get_string('success'), 'notifysuccess');
db9d4a3d 916 }
917 }
918
551fe0e5 919 print_upgrade_separator();
db9d4a3d 920}
8580535b 921
922/**
923 * Install core moodle tables and initialize
924 * @param float $version target version
925 * @param bool $verbose
926 * @return void, may throw exception
927 */
928function install_core($version, $verbose) {
929 global $CFG, $DB;
930
931 try {
c3d0e149 932 set_time_limit(600);
194cdca8 933 print_upgrade_part_start('moodle', true, $verbose); // does not store upgrade running flag
8580535b 934
935 $DB->get_manager()->install_from_xmldb_file("$CFG->libdir/db/install.xml");
936 upgrade_started(); // we want the flag to be stored in config table ;-)
937
938 // set all core default records and default settings
939 require_once("$CFG->libdir/db/install.php");
940 xmldb_main_install();
941
942 // store version
943 upgrade_main_savepoint(true, $version, false);
944
945 // Continue with the instalation
946 events_update_definition('moodle');
947 message_update_providers('moodle');
8580535b 948
949 // Write default settings unconditionlly
950 admin_apply_default_settings(NULL, true);
951
194cdca8 952 print_upgrade_part_end(null, true, $verbose);
8580535b 953 } catch (exception $ex) {
954 upgrade_handle_exception($ex);
955 }
956}
957
958/**
959 * Upgrade moodle core
960 * @param float $version target version
961 * @param bool $verbose
962 * @return void, may throw exception
963 */
964function upgrade_core($version, $verbose) {
965 global $CFG;
966
3316fe24 967 require_once($CFG->libdir.'/db/upgrade.php'); // Defines upgrades
3316fe24 968
8580535b 969 try {
970 // Upgrade current language pack if we can
971 if (empty($CFG->skiplangupgrade)) {
972 upgrade_language_pack(false);
973 }
974
194cdca8 975 print_upgrade_part_start('moodle', false, $verbose);
8580535b 976
17da2e6f 977 // one time special local migration pre 2.0 upgrade script
978 if ($version < 2007101600) {
979 $pre20upgradefile = "$CFG->dirrot/local/upgrade_pre20.php";
980 if (file_exists($pre20upgradefile)) {
981 set_time_limit(0);
982 require($pre20upgradefile);
983 // reset upgrade timeout to default
984 upgrade_set_timeout();
985 }
986 }
987
8580535b 988 $result = xmldb_main_upgrade($CFG->version);
989 if ($version > $CFG->version) {
990 // store version if not already there
991 upgrade_main_savepoint($result, $version, false);
992 }
993
994 // perform all other component upgrade routines
995 update_capabilities('moodle');
996 events_update_definition('moodle');
997 message_update_providers('moodle');
8580535b 998
999 remove_dir($CFG->dataroot . '/cache', true); // flush cache
1000
194cdca8 1001 print_upgrade_part_end('moodle', false, $verbose);
8580535b 1002 } catch (Exception $ex) {
1003 upgrade_handle_exception($ex);
1004 }
1005}
1006
1007/**
1008 * Upgrade/install other parts of moodle
1009 * @param bool $verbose
1010 * @return void, may throw exception
1011 */
1012function upgrade_noncore($verbose) {
1013 global $CFG;
1014
8580535b 1015 // upgrade all plugins types
1016 try {
1017 $plugintypes = get_plugin_types();
1018 foreach ($plugintypes as $type=>$location) {
17da2e6f 1019 upgrade_plugins($type, 'print_upgrade_part_start', 'print_upgrade_part_end', $verbose);
8580535b 1020 }
1021 } catch (Exception $ex) {
1022 upgrade_handle_exception($ex);
1023 }
1024
1025 // Check for changes to RPC functions
1026 if ($CFG->mnet_dispatcher_mode != 'off') {
1027 try {
1028 // this needs a full rewrite, sorry to mention that :-(
1029 // we have to make it part of standard WS framework
1030 require_once("$CFG->dirroot/$CFG->admin/mnet/adminlib.php");
1031 upgrade_RPC_functions(); // Return here afterwards
1032 } catch (Exception $ex) {
1033 upgrade_handle_exception($ex);
1034 }
1035 }
8580535b 1036}
3316fe24 1037
1038/**
1039 * Checks if the main tables have been installed yet or not.
1040 * @return bool
1041 */
1042function core_tables_exist() {
1043 global $DB;
1044
1045 if (!$tables = $DB->get_tables() ) { // No tables yet at all.
1046 return false;
1047
1048 } else { // Check for missing main tables
1049 $mtables = array('config', 'course', 'groupings'); // some tables used in 1.9 and 2.0, preferable something from the start and end of install.xml
1050 foreach ($mtables as $mtable) {
1051 if (!in_array($mtable, $tables)) {
1052 return false;
1053 }
1054 }
1055 return true;
1056 }
ba04999c 1057}