Commit | Line | Data |
---|---|---|
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 | 28 | define('UPGRADE_LOG_NORMAL', 0); |
72fb21b6 | 29 | /** UPGRADE_LOG_NOTICE = 1 */ |
db9d4a3d | 30 | define('UPGRADE_LOG_NOTICE', 1); |
72fb21b6 | 31 | /** UPGRADE_LOG_ERROR = 2 */ |
795a08ad | 32 | define('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 | */ |
42 | class 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 | */ |
58 | class 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 | 73 | class 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 | 91 | class 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 | */ | |
110 | function 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 | */ | |
143 | function 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 | */ | |
179 | function 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 | 219 | function 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 | 259 | function 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 | 289 | function 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 | ||
9b683d13 | 325 | // try to recover from interrupted install.php if needed |
326 | if (file_exists($fullplug.'/db/install.php')) { | |
327 | if (get_config($plugin->fullname, 'installrunning')) { | |
328 | require_once($fullplug.'/db/install.php'); | |
329 | $recover_install_function = 'xmldb_'.$plugin->fullname.'_install_recovery'; | |
330 | if (function_exists($recover_install_function)) { | |
331 | $startcallback($component, true, $verbose); | |
332 | $recover_install_function(); | |
333 | unset_config('installrunning', 'block_'.$plugin->fullname); | |
334 | update_capabilities($component); | |
c976e271 | 335 | external_update_descriptions($component); |
9b683d13 | 336 | events_update_definition($component); |
337 | message_update_providers($component); | |
338 | $endcallback($component, true, $verbose); | |
339 | } | |
340 | } | |
341 | } | |
db9d4a3d | 342 | |
9b683d13 | 343 | $installedversion = get_config($plugin->fullname, 'version'); |
795a08ad | 344 | if (empty($installedversion)) { // new installation |
194cdca8 | 345 | $startcallback($component, true, $verbose); |
db9d4a3d | 346 | |
795a08ad | 347 | /// Install tables if defined |
348 | if (file_exists($fullplug.'/db/install.xml')) { | |
349 | $DB->get_manager()->install_from_xmldb_file($fullplug.'/db/install.xml'); | |
db9d4a3d | 350 | } |
9b683d13 | 351 | |
352 | /// store version | |
353 | upgrade_plugin_savepoint(true, $plugin->version, $type, $plug, false); | |
354 | ||
795a08ad | 355 | /// execute post install file |
356 | if (file_exists($fullplug.'/db/install.php')) { | |
357 | require_once($fullplug.'/db/install.php'); | |
9b683d13 | 358 | set_config('installrunning', 1, 'block_'.$plugin->fullname); |
795a08ad | 359 | $post_install_function = 'xmldb_'.$plugin->fullname.'_install';; |
360 | $post_install_function(); | |
9b683d13 | 361 | unset_config('installrunning', 'block_'.$plugin->fullname); |
795a08ad | 362 | } |
363 | ||
795a08ad | 364 | /// Install various components |
365 | update_capabilities($component); | |
c976e271 | 366 | external_update_descriptions($component); |
795a08ad | 367 | events_update_definition($component); |
368 | message_update_providers($component); | |
369 | ||
db4e1a3c | 370 | theme_reset_all_caches(); |
194cdca8 | 371 | $endcallback($component, true, $verbose); |
795a08ad | 372 | |
373 | } else if ($installedversion < $plugin->version) { // upgrade | |
374 | /// Run the upgrade function for the plugin. | |
194cdca8 | 375 | $startcallback($component, false, $verbose); |
795a08ad | 376 | |
377 | if (is_readable($fullplug.'/db/upgrade.php')) { | |
378 | require_once($fullplug.'/db/upgrade.php'); // defines upgrading function | |
379 | ||
380 | $newupgrade_function = 'xmldb_'.$plugin->fullname.'_upgrade'; | |
381 | $result = $newupgrade_function($installedversion); | |
382 | } else { | |
383 | $result = true; | |
384 | } | |
385 | ||
386 | $installedversion = get_config($plugin->fullname, 'version'); | |
387 | if ($installedversion < $plugin->version) { | |
388 | // store version if not already there | |
389 | upgrade_plugin_savepoint($result, $plugin->version, $type, $plug, false); | |
390 | } | |
391 | ||
392 | /// Upgrade various components | |
393 | update_capabilities($component); | |
c976e271 | 394 | external_update_descriptions($component); |
795a08ad | 395 | events_update_definition($component); |
396 | message_update_providers($component); | |
397 | ||
db4e1a3c | 398 | theme_reset_all_caches(); |
194cdca8 | 399 | $endcallback($component, false, $verbose); |
795a08ad | 400 | |
401 | } else if ($installedversion > $plugin->version) { | |
402 | throw new downgrade_exception($component, $installedversion, $plugin->version); | |
db9d4a3d | 403 | } |
404 | } | |
db9d4a3d | 405 | } |
406 | ||
407 | /** | |
408 | * Find and check all modules and load them up or upgrade them if necessary | |
72fb21b6 | 409 | * |
410 | * @global object | |
411 | * @global object | |
db9d4a3d | 412 | */ |
194cdca8 | 413 | function upgrade_plugins_modules($startcallback, $endcallback, $verbose) { |
db9d4a3d | 414 | global $CFG, $DB; |
415 | ||
17da2e6f | 416 | $mods = get_plugin_list('mod'); |
db9d4a3d | 417 | |
17da2e6f | 418 | foreach ($mods as $mod=>$fullmod) { |
db9d4a3d | 419 | |
420 | if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it | |
421 | continue; | |
422 | } | |
423 | ||
17da2e6f | 424 | $component = 'mod_'.$mod; |
db9d4a3d | 425 | |
795a08ad | 426 | if (!is_readable($fullmod.'/version.php')) { |
427 | throw new plugin_defective_exception($component, 'Missing version.php'); | |
db9d4a3d | 428 | } |
429 | ||
795a08ad | 430 | $module = new object(); |
431 | require($fullmod .'/version.php'); // defines $module with version etc | |
db9d4a3d | 432 | |
795a08ad | 433 | if (empty($module->version)) { |
c1fe2368 | 434 | if (isset($module->version)) { |
435 | // Version is empty but is set - it means its value is 0 or ''. Let us skip such module. | |
436 | // This is inteded for developers so they can work on the early stages of the module. | |
437 | continue; | |
438 | } | |
795a08ad | 439 | throw new plugin_defective_exception($component, 'Missing version value in version.php'); |
db9d4a3d | 440 | } |
441 | ||
442 | if (!empty($module->requires)) { | |
443 | if ($module->requires > $CFG->version) { | |
795a08ad | 444 | throw new upgrade_requires_exception($component, $module->version, $CFG->version, $module->requires); |
db9d4a3d | 445 | } |
446 | } | |
447 | ||
448 | $module->name = $mod; // The name MUST match the directory | |
449 | ||
795a08ad | 450 | $currmodule = $DB->get_record('modules', array('name'=>$module->name)); |
db9d4a3d | 451 | |
9b683d13 | 452 | if (file_exists($fullmod.'/db/install.php')) { |
453 | if (get_config($module->name, 'installrunning')) { | |
454 | require_once($fullmod.'/db/install.php'); | |
455 | $recover_install_function = 'xmldb_'.$module->name.'_install_recovery'; | |
456 | if (function_exists($recover_install_function)) { | |
457 | $startcallback($component, true, $verbose); | |
458 | $recover_install_function(); | |
459 | unset_config('installrunning', $module->name); | |
460 | // Install various components too | |
461 | update_capabilities($component); | |
c976e271 | 462 | external_update_descriptions($component); |
9b683d13 | 463 | events_update_definition($component); |
464 | message_update_providers($component); | |
465 | $endcallback($component, true, $verbose); | |
466 | } | |
467 | } | |
468 | } | |
469 | ||
795a08ad | 470 | if (empty($currmodule->version)) { |
194cdca8 | 471 | $startcallback($component, true, $verbose); |
db9d4a3d | 472 | |
795a08ad | 473 | /// Execute install.xml (XMLDB) - must be present in all modules |
474 | $DB->get_manager()->install_from_xmldb_file($fullmod.'/db/install.xml'); | |
db9d4a3d | 475 | |
2e3da297 | 476 | /// Add record into modules table - may be needed in install.php already |
477 | $module->id = $DB->insert_record('modules', $module); | |
478 | ||
db9d4a3d | 479 | /// Post installation hook - optional |
480 | if (file_exists("$fullmod/db/install.php")) { | |
481 | require_once("$fullmod/db/install.php"); | |
9b683d13 | 482 | // Set installation running flag, we need to recover after exception or error |
483 | set_config('installrunning', 1, $module->name); | |
db9d4a3d | 484 | $post_install_function = 'xmldb_'.$module->name.'_install';; |
485 | $post_install_function(); | |
9b683d13 | 486 | unset_config('installrunning', $module->name); |
db9d4a3d | 487 | } |
488 | ||
795a08ad | 489 | /// Install various components |
490 | update_capabilities($component); | |
c976e271 | 491 | external_update_descriptions($component); |
795a08ad | 492 | events_update_definition($component); |
493 | message_update_providers($component); | |
494 | ||
23fd6f83 | 495 | theme_reset_all_caches(); |
194cdca8 | 496 | $endcallback($component, true, $verbose); |
db9d4a3d | 497 | |
795a08ad | 498 | } else if ($currmodule->version < $module->version) { |
499 | /// If versions say that we need to upgrade but no upgrade files are available, notify and continue | |
194cdca8 | 500 | $startcallback($component, false, $verbose); |
795a08ad | 501 | |
502 | if (is_readable($fullmod.'/db/upgrade.php')) { | |
503 | require_once($fullmod.'/db/upgrade.php'); // defines new upgrading function | |
504 | $newupgrade_function = 'xmldb_'.$module->name.'_upgrade'; | |
505 | $result = $newupgrade_function($currmodule->version, $module); | |
506 | } else { | |
507 | $result = true; | |
508 | } | |
509 | ||
510 | $currmodule = $DB->get_record('modules', array('name'=>$module->name)); | |
511 | if ($currmodule->version < $module->version) { | |
512 | // store version if not already there | |
513 | upgrade_mod_savepoint($result, $module->version, $mod, false); | |
514 | } | |
515 | ||
516 | /// Upgrade various components | |
517 | update_capabilities($component); | |
c976e271 | 518 | external_update_descriptions($component); |
795a08ad | 519 | events_update_definition($component); |
520 | message_update_providers($component); | |
521 | ||
23fd6f83 | 522 | theme_reset_all_caches(); |
795a08ad | 523 | remove_dir($CFG->dataroot.'/cache', true); // flush cache |
524 | ||
194cdca8 | 525 | $endcallback($component, false, $verbose); |
795a08ad | 526 | |
527 | } else if ($currmodule->version > $module->version) { | |
528 | throw new downgrade_exception($component, $currmodule->version, $module->version); | |
529 | } | |
530 | } | |
531 | } | |
db9d4a3d | 532 | |
db9d4a3d | 533 | |
795a08ad | 534 | /** |
535 | * This function finds all available blocks and install them | |
536 | * into blocks table or do all the upgrade process if newer. | |
72fb21b6 | 537 | * |
538 | * @global object | |
539 | * @global object | |
795a08ad | 540 | */ |
194cdca8 | 541 | function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) { |
795a08ad | 542 | global $CFG, $DB; |
543 | ||
795a08ad | 544 | require_once($CFG->dirroot.'/blocks/moodleblock.class.php'); |
545 | ||
546 | $blocktitles = array(); // we do not want duplicate titles | |
547 | ||
548 | //Is this a first install | |
549 | $first_install = null; | |
550 | ||
17da2e6f | 551 | $blocks = get_plugin_list('block'); |
795a08ad | 552 | |
17da2e6f | 553 | foreach ($blocks as $blockname=>$fullblock) { |
795a08ad | 554 | |
555 | if (is_null($first_install)) { | |
556 | $first_install = ($DB->count_records('block') == 0); | |
557 | } | |
558 | ||
559 | if ($blockname == 'NEWBLOCK') { // Someone has unzipped the template, ignore it | |
560 | continue; | |
db9d4a3d | 561 | } |
562 | ||
17da2e6f | 563 | $component = 'block_'.$blockname; |
db9d4a3d | 564 | |
795a08ad | 565 | if (!is_readable($fullblock.'/block_'.$blockname.'.php')) { |
566 | throw new plugin_defective_exception('block/'.$blockname, 'Missing main block class file.'); | |
db9d4a3d | 567 | } |
795a08ad | 568 | require_once($fullblock.'/block_'.$blockname.'.php'); |
db9d4a3d | 569 | |
795a08ad | 570 | $classname = 'block_'.$blockname; |
571 | ||
572 | if (!class_exists($classname)) { | |
573 | throw new plugin_defective_exception($component, 'Can not load main class.'); | |
574 | } | |
575 | ||
576 | $blockobj = new $classname; // This is what we 'll be testing | |
577 | $blocktitle = $blockobj->get_title(); | |
578 | ||
579 | // OK, it's as we all hoped. For further tests, the object will do them itself. | |
580 | if (!$blockobj->_self_test()) { | |
581 | throw new plugin_defective_exception($component, 'Self test failed.'); | |
582 | } | |
583 | ||
584 | $block = new object(); // This may be used to update the db below | |
585 | $block->name = $blockname; // The name MUST match the directory | |
586 | $block->version = $blockobj->get_version(); | |
587 | $block->cron = !empty($blockobj->cron) ? $blockobj->cron : 0; | |
588 | $block->multiple = $blockobj->instance_allow_multiple() ? 1 : 0; | |
589 | ||
590 | if (empty($block->version)) { | |
591 | throw new plugin_defective_exception($component, 'Missing block version.'); | |
592 | } | |
593 | ||
594 | $currblock = $DB->get_record('block', array('name'=>$block->name)); | |
595 | ||
9b683d13 | 596 | if (file_exists($fullblock.'/db/install.php')) { |
597 | if (get_config('block_'.$blockname, 'installrunning')) { | |
598 | require_once($fullblock.'/db/install.php'); | |
599 | $recover_install_function = 'xmldb_block_'.$blockname.'_install_recovery'; | |
600 | if (function_exists($recover_install_function)) { | |
601 | $startcallback($component, true, $verbose); | |
602 | $recover_install_function(); | |
603 | unset_config('installrunning', 'block_'.$blockname); | |
604 | // Install various components | |
605 | update_capabilities($component); | |
c976e271 | 606 | external_update_descriptions($component); |
9b683d13 | 607 | events_update_definition($component); |
608 | message_update_providers($component); | |
609 | $endcallback($component, true, $verbose); | |
610 | } | |
611 | } | |
612 | } | |
613 | ||
795a08ad | 614 | if (empty($currblock->version)) { // block not installed yet, so install it |
615 | // If it allows multiples, start with it enabled | |
616 | ||
617 | $conflictblock = array_search($blocktitle, $blocktitles); | |
618 | if ($conflictblock !== false) { | |
619 | // Duplicate block titles are not allowed, they confuse people | |
620 | // AND PHP's associative arrays ;) | |
621 | throw new plugin_defective_exception($component, get_string('blocknameconflict', '', (object)array('name'=>$block->name, 'conflict'=>$conflictblock))); | |
622 | } | |
194cdca8 | 623 | $startcallback($component, true, $verbose); |
795a08ad | 624 | |
625 | if (file_exists($fullblock.'/db/install.xml')) { | |
626 | $DB->get_manager()->install_from_xmldb_file($fullblock.'/db/install.xml'); | |
627 | } | |
628 | $block->id = $DB->insert_record('block', $block); | |
629 | ||
630 | if (file_exists($fullblock.'/db/install.php')) { | |
631 | require_once($fullblock.'/db/install.php'); | |
9b683d13 | 632 | // Set installation running flag, we need to recover after exception or error |
633 | set_config('installrunning', 1, 'block_'.$blockname); | |
795a08ad | 634 | $post_install_function = 'xmldb_block_'.$blockname.'_install';; |
635 | $post_install_function(); | |
9b683d13 | 636 | unset_config('installrunning', 'block_'.$blockname); |
795a08ad | 637 | } |
638 | ||
639 | $blocktitles[$block->name] = $blocktitle; | |
640 | ||
641 | // Install various components | |
642 | update_capabilities($component); | |
c976e271 | 643 | external_update_descriptions($component); |
795a08ad | 644 | events_update_definition($component); |
645 | message_update_providers($component); | |
646 | ||
23fd6f83 | 647 | theme_reset_all_caches(); |
194cdca8 | 648 | $endcallback($component, true, $verbose); |
795a08ad | 649 | |
650 | } else if ($currblock->version < $block->version) { | |
194cdca8 | 651 | $startcallback($component, false, $verbose); |
795a08ad | 652 | |
653 | if (is_readable($fullblock.'/db/upgrade.php')) { | |
654 | require_once($fullblock.'/db/upgrade.php'); // defines new upgrading function | |
655 | $newupgrade_function = 'xmldb_block_'.$blockname.'_upgrade'; | |
656 | $result = $newupgrade_function($currblock->version, $block); | |
657 | } else { | |
658 | $result = true; | |
659 | } | |
660 | ||
661 | $currblock = $DB->get_record('block', array('name'=>$block->name)); | |
662 | if ($currblock->version < $block->version) { | |
663 | // store version if not already there | |
664 | upgrade_block_savepoint($result, $block->version, $block->name, false); | |
665 | } | |
666 | ||
667 | if ($currblock->cron != $block->cron) { | |
668 | // update cron flag if needed | |
669 | $currblock->cron = $block->cron; | |
670 | $DB->update_record('block', $currblock); | |
671 | } | |
672 | ||
673 | // Upgrade various componebts | |
795a08ad | 674 | update_capabilities($component); |
c976e271 | 675 | external_update_descriptions($component); |
17da2e6f | 676 | events_update_definition($component); |
795a08ad | 677 | message_update_providers($component); |
678 | ||
23fd6f83 | 679 | theme_reset_all_caches(); |
194cdca8 | 680 | $endcallback($component, false, $verbose); |
795a08ad | 681 | |
682 | } else if ($currblock->version > $block->version) { | |
683 | throw new downgrade_exception($component, $currblock->version, $block->version); | |
684 | } | |
685 | } | |
686 | ||
687 | ||
688 | // Finally, if we are in the first_install of BLOCKS setup frontpage and admin page blocks | |
689 | if ($first_install) { | |
795a08ad | 690 | //Iterate over each course - there should be only site course here now |
691 | if ($courses = $DB->get_records('course')) { | |
692 | foreach ($courses as $course) { | |
9d1d606e | 693 | blocks_add_default_course_blocks($course); |
db9d4a3d | 694 | } |
695 | } | |
795a08ad | 696 | |
9d1d606e | 697 | blocks_add_default_system_blocks(); |
795a08ad | 698 | } |
699 | } | |
700 | ||
c976e271 | 701 | /** |
702 | * Web service discovery function used during install and upgrade. | |
703 | * @param string $component name of component (moodle, mod_assignment, etc.) | |
704 | * @return void | |
705 | */ | |
706 | function external_update_descriptions($component) { | |
707 | global $DB; | |
708 | ||
709 | $defpath = get_component_directory($component).'/db/services.php'; | |
710 | ||
711 | if (!file_exists($defpath)) { | |
712 | external_delete_descriptions($component); | |
713 | return; | |
714 | } | |
715 | ||
716 | // load new info | |
717 | $functions = array(); | |
718 | $services = array(); | |
719 | include($defpath); | |
720 | ||
721 | // update all function fist | |
722 | $dbfunctions = $DB->get_records('external_functions', array('component'=>$component)); | |
723 | foreach ($dbfunctions as $dbfunction) { | |
724 | if (empty($functions[$dbfunction->name])) { | |
725 | $DB->delete_records('external_functions', array('id'=>$dbfunction->id)); | |
726 | // do not delete functions from external_services_functions, beacuse | |
727 | // we want to notify admins when functions used in custom services disappear | |
728 | continue; | |
729 | } | |
730 | ||
731 | $function = $functions[$dbfunction->name]; | |
732 | unset($functions[$dbfunction->name]); | |
733 | $function['classpath'] = empty($function['classpath']) ? null : $function['classpath']; | |
734 | ||
735 | $update = false; | |
736 | if ($dbfunction->classname != $function['classname']) { | |
737 | $dbfunction->classname = $function['classname']; | |
738 | $update = true; | |
739 | } | |
740 | if ($dbfunction->methodname != $function['methodname']) { | |
741 | $dbfunction->methodname = $function['methodname']; | |
742 | $update = true; | |
743 | } | |
744 | if ($dbfunction->classpath != $function['classpath']) { | |
745 | $dbfunction->classpath = $function['classpath']; | |
746 | $update = true; | |
747 | } | |
748 | if ($update) { | |
749 | $DB->update_record('external_functions', $dbfunction); | |
750 | } | |
751 | } | |
752 | foreach ($functions as $fname => $function) { | |
753 | $dbfunction = new object(); | |
754 | $dbfunction->name = $fname; | |
755 | $dbfunction->classname = $function['classname']; | |
756 | $dbfunction->methodname = $function['methodname']; | |
757 | $dbfunction->classpath = empty($function['classpath']) ? null : $function['classpath']; | |
758 | $dbfunction->component = $component; | |
759 | $dbfunction->id = $DB->insert_record('external_functions', $dbfunction); | |
760 | } | |
761 | unset($functions); | |
762 | ||
763 | // now deal with services | |
764 | $dbservices = $DB->get_records('external_services', array('component'=>$component)); | |
765 | foreach ($dbservices as $dbservice) { | |
766 | if (empty($services[$dbservice->name])) { | |
767 | $DB->delete_records('external_services_functions', array('externalserviceid'=>$dbservice->id)); | |
768 | $DB->delete_records('external_services_users', array('externalserviceid'=>$dbservice->id)); | |
769 | $DB->delete_records('external_services', array('id'=>$dbservice->id)); | |
770 | continue; | |
771 | } | |
772 | $service = $services[$dbservice->name]; | |
773 | unset($services[$dbservice->name]); | |
774 | $service['enabled'] = empty($service['enabled']) ? 0 : $service['enabled']; | |
775 | $service['requiredcapability'] = empty($service['requiredcapability']) ? null : $service['requiredcapability']; | |
776 | $service['restrictedusers'] = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers']; | |
777 | ||
778 | $update = false; | |
779 | if ($dbservice->enabled != $service['enabled']) { | |
780 | $dbservice->enabled = $service['enabled']; | |
781 | $update = true; | |
782 | } | |
783 | if ($dbservice->requiredcapability != $service['requiredcapability']) { | |
784 | $dbservice->requiredcapability = $service['requiredcapability']; | |
785 | $update = true; | |
786 | } | |
787 | if ($dbservice->restrictedusers != $service['restrictedusers']) { | |
788 | $dbservice->restrictedusers = $service['restrictedusers']; | |
789 | $update = true; | |
790 | } | |
791 | if ($update) { | |
792 | $DB->update_record('external_services', $dbservice); | |
793 | } | |
794 | ||
795 | $functions = $DB->get_records('external_services_functions', array('externalserviceid'=>$dbservice->id)); | |
796 | foreach ($functions as $function) { | |
797 | $key = array_search($function->functionname, $service['functions']); | |
798 | if ($key === false) { | |
799 | $DB->delete_records('external_services_functions', array('id'=>$function->id)); | |
800 | } else { | |
801 | unset($service['functions'][$key]); | |
802 | } | |
803 | } | |
804 | foreach ($service['functions'] as $fname) { | |
805 | $newf = new object(); | |
806 | $newf->externalserviceid = $dbservice->id; | |
807 | $newf->functionname = $fname; | |
808 | $DB->insert_record('external_services_functions', $newf); | |
809 | } | |
810 | unset($functions); | |
811 | } | |
812 | foreach ($services as $name => $service) { | |
813 | $dbservice = new object(); | |
814 | $dbservice->name = $name; | |
815 | $dbservice->enabled = empty($service['enabled']) ? 0 : $service['enabled']; | |
816 | $dbservice->requiredcapability = empty($service['requiredcapability']) ? null : $service['requiredcapability']; | |
817 | $dbservice->restrictedusers = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers']; | |
818 | $dbservice->component = $component; | |
e5180580 | 819 | $dbservice->timecreated = time(); |
c976e271 | 820 | $dbservice->id = $DB->insert_record('external_services', $dbservice); |
821 | foreach ($service['functions'] as $fname) { | |
822 | $newf = new object(); | |
823 | $newf->externalserviceid = $dbservice->id; | |
824 | $newf->functionname = $fname; | |
825 | $DB->insert_record('external_services_functions', $newf); | |
826 | } | |
827 | } | |
828 | } | |
829 | ||
830 | /** | |
831 | * Delete all service and external functions information defined in the specified compoment. | |
832 | * @param string $component name of component (moodle, mod_assignment, etc.) | |
833 | * @return void | |
834 | */ | |
835 | function external_delete_descriptions($component) { | |
836 | global $DB; | |
837 | ||
838 | $params = array($component); | |
839 | ||
840 | $DB->delete_records_select('external_services_users', "externalserviceid IN (SELECT id FROM {external_services} WHERE component = ?)", $params); | |
841 | $DB->delete_records_select('external_services_functions', "externalserviceid IN (SELECT id FROM {external_services} WHERE component = ?)", $params); | |
842 | $DB->delete_records('external_services', array('component'=>$component)); | |
843 | $DB->delete_records('external_functions', array('component'=>$component)); | |
844 | } | |
845 | ||
72fb21b6 | 846 | /** |
847 | * upgrade logging functions | |
72fb21b6 | 848 | */ |
fd1a792e | 849 | function upgrade_handle_exception($ex, $plugin = null) { |
a56c457e PS |
850 | // rollback everything, we need to log all upgrade problems |
851 | abort_all_db_transactions(); | |
852 | ||
c19bc39c PS |
853 | $info = get_exception_info($ex); |
854 | ||
855 | // First log upgrade error | |
856 | upgrade_log(UPGRADE_LOG_ERROR, $plugin, 'Exception: ' . get_class($ex), $info->message, $info->backtrace); | |
857 | ||
858 | // Always turn on debugging - admins need to know what is going on | |
859 | $CFG->debug = DEBUG_DEVELOPER; | |
860 | ||
fd1a792e | 861 | default_exception_handler($ex, true, $plugin); |
db9d4a3d | 862 | } |
863 | ||
864 | /** | |
865 | * Adds log entry into upgrade_log table | |
866 | * | |
72fb21b6 | 867 | * @global object |
868 | * @global object | |
869 | * @global object | |
db9d4a3d | 870 | * @param int $type UPGRADE_LOG_NORMAL, UPGRADE_LOG_NOTICE or UPGRADE_LOG_ERROR |
871 | * @param string $plugin plugin or null if main | |
872 | * @param string $info short description text of log entry | |
873 | * @param string $details long problem description | |
874 | * @param string $backtrace string used for errors only | |
875 | * @return void | |
876 | */ | |
877 | function upgrade_log($type, $plugin, $info, $details=null, $backtrace=null) { | |
878 | global $DB, $USER, $CFG; | |
879 | ||
795a08ad | 880 | $plugin = ($plugin==='moodle') ? null : $plugin; |
881 | ||
34a2777c | 882 | $backtrace = format_backtrace($backtrace, true); |
db9d4a3d | 883 | |
884 | $version = null; | |
885 | ||
886 | //first try to find out current version number | |
795a08ad | 887 | if (empty($plugin) or $plugin === 'moodle') { |
db9d4a3d | 888 | //main |
889 | $version = $CFG->version; | |
890 | ||
795a08ad | 891 | } else if ($plugin === 'local') { |
892 | //customisation | |
893 | $version = $CFG->local_version; | |
894 | ||
895 | } else if (strpos($plugin, 'mod/') === 0) { | |
db9d4a3d | 896 | try { |
897 | $modname = substr($plugin, strlen('mod/')); | |
898 | $version = $DB->get_field('modules', 'version', array('name'=>$modname)); | |
795a08ad | 899 | $version = ($version === false) ? null : $version; |
db9d4a3d | 900 | } catch (Exception $ignored) { |
901 | } | |
902 | ||
795a08ad | 903 | } else if (strpos($plugin, 'block/') === 0) { |
db9d4a3d | 904 | try { |
795a08ad | 905 | $blockname = substr($plugin, strlen('block/')); |
db9d4a3d | 906 | if ($block = $DB->get_record('block', array('name'=>$blockname))) { |
907 | $version = $block->version; | |
908 | } | |
909 | } catch (Exception $ignored) { | |
910 | } | |
795a08ad | 911 | |
912 | } else { | |
913 | $pluginversion = get_config(str_replace('/', '_', $plugin), 'version'); | |
914 | if (!empty($pluginversion)) { | |
915 | $version = $pluginversion; | |
916 | } | |
db9d4a3d | 917 | } |
918 | ||
919 | $log = new object(); | |
920 | $log->type = $type; | |
921 | $log->plugin = $plugin; | |
922 | $log->version = $version; | |
923 | $log->info = $info; | |
924 | $log->details = $details; | |
925 | $log->backtrace = $backtrace; | |
926 | $log->userid = $USER->id; | |
927 | $log->timemodified = time(); | |
db9d4a3d | 928 | try { |
929 | $DB->insert_record('upgrade_log', $log); | |
930 | } catch (Exception $ignored) { | |
795a08ad | 931 | // possible during install or 2.0 upgrade |
db9d4a3d | 932 | } |
933 | } | |
934 | ||
935 | /** | |
936 | * Marks start of upgrade, blocks any other access to site. | |
937 | * The upgrade is finished at the end of script or after timeout. | |
72fb21b6 | 938 | * |
939 | * @global object | |
940 | * @global object | |
941 | * @global object | |
db9d4a3d | 942 | */ |
943 | function upgrade_started($preinstall=false) { | |
de6d81e6 | 944 | global $CFG, $DB, $PAGE, $OUTPUT; |
db9d4a3d | 945 | |
946 | static $started = false; | |
947 | ||
948 | if ($preinstall) { | |
949 | ignore_user_abort(true); | |
950 | upgrade_setup_debug(true); | |
951 | ||
952 | } else if ($started) { | |
953 | upgrade_set_timeout(120); | |
954 | ||
955 | } else { | |
c13a5e71 | 956 | if (!CLI_SCRIPT and !$PAGE->headerprinted) { |
db9d4a3d | 957 | $strupgrade = get_string('upgradingversion', 'admin'); |
78946b9b | 958 | $PAGE->set_pagelayout('maintenance'); |
543f54d3 | 959 | upgrade_init_javascript(); |
de6d81e6 | 960 | $PAGE->set_title($strupgrade.' - Moodle '.$CFG->target_release); |
961 | $PAGE->set_heading($strupgrade); | |
962 | $PAGE->navbar->add($strupgrade); | |
963 | $PAGE->set_cacheable(false); | |
964 | echo $OUTPUT->header(); | |
db9d4a3d | 965 | } |
966 | ||
967 | ignore_user_abort(true); | |
968 | register_shutdown_function('upgrade_finished_handler'); | |
969 | upgrade_setup_debug(true); | |
970 | set_config('upgraderunning', time()+300); | |
971 | $started = true; | |
972 | } | |
973 | } | |
974 | ||
975 | /** | |
976 | * Internal function - executed if upgrade interruped. | |
977 | */ | |
978 | function upgrade_finished_handler() { | |
979 | upgrade_finished(); | |
980 | } | |
981 | ||
982 | /** | |
983 | * Indicates upgrade is finished. | |
984 | * | |
985 | * This function may be called repeatedly. | |
72fb21b6 | 986 | * |
987 | * @global object | |
988 | * @global object | |
db9d4a3d | 989 | */ |
990 | function upgrade_finished($continueurl=null) { | |
7e0d6675 | 991 | global $CFG, $DB, $OUTPUT; |
db9d4a3d | 992 | |
993 | if (!empty($CFG->upgraderunning)) { | |
994 | unset_config('upgraderunning'); | |
995 | upgrade_setup_debug(false); | |
996 | ignore_user_abort(false); | |
997 | if ($continueurl) { | |
aa9a6867 | 998 | echo $OUTPUT->continue_button($continueurl); |
7e0d6675 | 999 | echo $OUTPUT->footer(); |
db9d4a3d | 1000 | die; |
1001 | } | |
1002 | } | |
1003 | } | |
1004 | ||
72fb21b6 | 1005 | /** |
1006 | * @global object | |
1007 | * @global object | |
1008 | */ | |
db9d4a3d | 1009 | function upgrade_setup_debug($starting) { |
1010 | global $CFG, $DB; | |
1011 | ||
1012 | static $originaldebug = null; | |
1013 | ||
1014 | if ($starting) { | |
1015 | if ($originaldebug === null) { | |
1016 | $originaldebug = $DB->get_debug(); | |
1017 | } | |
1018 | if (!empty($CFG->upgradeshowsql)) { | |
1019 | $DB->set_debug(true); | |
1020 | } | |
1021 | } else { | |
1022 | $DB->set_debug($originaldebug); | |
1023 | } | |
1024 | } | |
1025 | ||
72fb21b6 | 1026 | /** |
1027 | * @global object | |
1028 | */ | |
90509582 | 1029 | function print_upgrade_reload($url) { |
f2a1963c | 1030 | global $OUTPUT; |
90509582 | 1031 | |
1032 | echo "<br />"; | |
1033 | echo '<div class="continuebutton">'; | |
b5d0cafc | 1034 | echo '<a href="'.$url.'" title="'.get_string('reload').'" ><img src="'.$OUTPUT->pix_url('i/reload') . '" alt="" /> '.get_string('reload').'</a>'; |
90509582 | 1035 | echo '</div><br />'; |
1036 | } | |
1037 | ||
db9d4a3d | 1038 | function print_upgrade_separator() { |
1039 | if (!CLI_SCRIPT) { | |
1040 | echo '<hr />'; | |
1041 | } | |
1042 | } | |
1043 | ||
795a08ad | 1044 | /** |
1045 | * Default start upgrade callback | |
1046 | * @param string $plugin | |
1047 | * @param bool $installation true if installation, false menas upgrade | |
1048 | */ | |
194cdca8 | 1049 | function print_upgrade_part_start($plugin, $installation, $verbose) { |
3c159385 | 1050 | global $OUTPUT; |
795a08ad | 1051 | if (empty($plugin) or $plugin == 'moodle') { |
1052 | upgrade_started($installation); // does not store upgrade running flag yet | |
194cdca8 | 1053 | if ($verbose) { |
3c159385 | 1054 | echo $OUTPUT->heading(get_string('coresystem')); |
194cdca8 | 1055 | } |
795a08ad | 1056 | } else { |
1057 | upgrade_started(); | |
194cdca8 | 1058 | if ($verbose) { |
3c159385 | 1059 | echo $OUTPUT->heading($plugin); |
194cdca8 | 1060 | } |
795a08ad | 1061 | } |
1062 | if ($installation) { | |
1063 | if (empty($plugin) or $plugin == 'moodle') { | |
1064 | // no need to log - log table not yet there ;-) | |
1065 | } else { | |
1066 | upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting plugin installation'); | |
1067 | } | |
1068 | } else { | |
1069 | if (empty($plugin) or $plugin == 'moodle') { | |
1070 | upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting core upgrade'); | |
1071 | } else { | |
1072 | upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting plugin upgrade'); | |
1073 | } | |
1074 | } | |
1075 | } | |
1076 | ||
1077 | /** | |
1078 | * Default end upgrade callback | |
1079 | * @param string $plugin | |
1080 | * @param bool $installation true if installation, false menas upgrade | |
1081 | */ | |
194cdca8 | 1082 | function print_upgrade_part_end($plugin, $installation, $verbose) { |
aa9a6867 | 1083 | global $OUTPUT; |
795a08ad | 1084 | upgrade_started(); |
1085 | if ($installation) { | |
1086 | if (empty($plugin) or $plugin == 'moodle') { | |
1087 | upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Core installed'); | |
1088 | } else { | |
1089 | upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Plugin installed'); | |
1090 | } | |
1091 | } else { | |
1092 | if (empty($plugin) or $plugin == 'moodle') { | |
1093 | upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Core upgraded'); | |
1094 | } else { | |
1095 | upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Plugin upgraded'); | |
1096 | } | |
1097 | } | |
194cdca8 | 1098 | if ($verbose) { |
aa9a6867 | 1099 | echo $OUTPUT->notification(get_string('success'), 'notifysuccess'); |
194cdca8 | 1100 | print_upgrade_separator(); |
96db14f9 | 1101 | } |
1102 | } | |
1103 | ||
72fb21b6 | 1104 | /** |
543f54d3 | 1105 | * Sets up JS code required for all ugprade scripts. |
72fb21b6 | 1106 | * @global object |
1107 | */ | |
543f54d3 | 1108 | function upgrade_init_javascript() { |
e29380f3 | 1109 | global $PAGE; |
543f54d3 PS |
1110 | // scroll to the end of each upgrade page so that ppl see either error or continue button, |
1111 | // no need to scroll continuously any more, it is enough to jump to end once the footer is printed ;-) | |
1112 | $js = "window.scrollTo(0, 5000000);"; | |
1113 | $PAGE->requires->js_init_code($js); | |
db9d4a3d | 1114 | } |
1115 | ||
1116 | ||
1117 | /** | |
1118 | * Try to upgrade the given language pack (or current language) | |
72fb21b6 | 1119 | * @global object |
db9d4a3d | 1120 | */ |
1121 | function upgrade_language_pack($lang='') { | |
3c159385 | 1122 | global $CFG, $OUTPUT; |
db9d4a3d | 1123 | |
1124 | if (empty($lang)) { | |
1125 | $lang = current_language(); | |
1126 | } | |
1127 | ||
1128 | if ($lang == 'en_utf8') { | |
1129 | return true; // Nothing to do | |
1130 | } | |
1131 | ||
551fe0e5 | 1132 | upgrade_started(false); |
3c159385 | 1133 | echo $OUTPUT->heading(get_string('langimport', 'admin').': '.$lang); |
db9d4a3d | 1134 | |
1135 | @mkdir ($CFG->dataroot.'/temp/'); //make it in case it's a fresh install, it might not be there | |
1136 | @mkdir ($CFG->dataroot.'/lang/'); | |
1137 | ||
1138 | require_once($CFG->libdir.'/componentlib.class.php'); | |
1139 | ||
1140 | if ($cd = new component_installer('http://download.moodle.org', 'lang16', $lang.'.zip', 'languages.md5', 'lang')) { | |
1141 | $status = $cd->install(); //returns COMPONENT_(ERROR | UPTODATE | INSTALLED) | |
1142 | ||
1143 | if ($status == COMPONENT_INSTALLED) { | |
db9d4a3d | 1144 | @unlink($CFG->dataroot.'/cache/languages'); |
551fe0e5 | 1145 | if ($parentlang = get_parent_language($lang)) { |
1146 | if ($cd = new component_installer('http://download.moodle.org', 'lang16', $parentlang.'.zip', 'languages.md5', 'lang')) { | |
1147 | $cd->install(); | |
1148 | } | |
1149 | } | |
aa9a6867 | 1150 | echo $OUTPUT->notification(get_string('success'), 'notifysuccess'); |
db9d4a3d | 1151 | } |
1152 | } | |
1153 | ||
551fe0e5 | 1154 | print_upgrade_separator(); |
db9d4a3d | 1155 | } |
8580535b | 1156 | |
1157 | /** | |
1158 | * Install core moodle tables and initialize | |
1159 | * @param float $version target version | |
1160 | * @param bool $verbose | |
1161 | * @return void, may throw exception | |
1162 | */ | |
1163 | function install_core($version, $verbose) { | |
1164 | global $CFG, $DB; | |
1165 | ||
1166 | try { | |
c3d0e149 | 1167 | set_time_limit(600); |
194cdca8 | 1168 | print_upgrade_part_start('moodle', true, $verbose); // does not store upgrade running flag |
8580535b | 1169 | |
1170 | $DB->get_manager()->install_from_xmldb_file("$CFG->libdir/db/install.xml"); | |
1171 | upgrade_started(); // we want the flag to be stored in config table ;-) | |
1172 | ||
1173 | // set all core default records and default settings | |
1174 | require_once("$CFG->libdir/db/install.php"); | |
1175 | xmldb_main_install(); | |
1176 | ||
1177 | // store version | |
1178 | upgrade_main_savepoint(true, $version, false); | |
1179 | ||
1180 | // Continue with the instalation | |
1181 | events_update_definition('moodle'); | |
1182 | message_update_providers('moodle'); | |
8580535b | 1183 | |
1184 | // Write default settings unconditionlly | |
1185 | admin_apply_default_settings(NULL, true); | |
1186 | ||
194cdca8 | 1187 | print_upgrade_part_end(null, true, $verbose); |
8580535b | 1188 | } catch (exception $ex) { |
1189 | upgrade_handle_exception($ex); | |
1190 | } | |
1191 | } | |
1192 | ||
1193 | /** | |
1194 | * Upgrade moodle core | |
1195 | * @param float $version target version | |
1196 | * @param bool $verbose | |
1197 | * @return void, may throw exception | |
1198 | */ | |
1199 | function upgrade_core($version, $verbose) { | |
1200 | global $CFG; | |
1201 | ||
3316fe24 | 1202 | require_once($CFG->libdir.'/db/upgrade.php'); // Defines upgrades |
3316fe24 | 1203 | |
8580535b | 1204 | try { |
1205 | // Upgrade current language pack if we can | |
1206 | if (empty($CFG->skiplangupgrade)) { | |
1207 | upgrade_language_pack(false); | |
1208 | } | |
1209 | ||
194cdca8 | 1210 | print_upgrade_part_start('moodle', false, $verbose); |
8580535b | 1211 | |
17da2e6f | 1212 | // one time special local migration pre 2.0 upgrade script |
1213 | if ($version < 2007101600) { | |
1214 | $pre20upgradefile = "$CFG->dirrot/local/upgrade_pre20.php"; | |
1215 | if (file_exists($pre20upgradefile)) { | |
1216 | set_time_limit(0); | |
1217 | require($pre20upgradefile); | |
1218 | // reset upgrade timeout to default | |
1219 | upgrade_set_timeout(); | |
1220 | } | |
1221 | } | |
1222 | ||
8580535b | 1223 | $result = xmldb_main_upgrade($CFG->version); |
1224 | if ($version > $CFG->version) { | |
1225 | // store version if not already there | |
1226 | upgrade_main_savepoint($result, $version, false); | |
1227 | } | |
1228 | ||
1229 | // perform all other component upgrade routines | |
1230 | update_capabilities('moodle'); | |
c976e271 | 1231 | external_update_descriptions('moodle'); |
8580535b | 1232 | events_update_definition('moodle'); |
1233 | message_update_providers('moodle'); | |
8580535b | 1234 | |
db4e1a3c | 1235 | theme_reset_all_caches(); |
8580535b | 1236 | remove_dir($CFG->dataroot . '/cache', true); // flush cache |
1237 | ||
194cdca8 | 1238 | print_upgrade_part_end('moodle', false, $verbose); |
8580535b | 1239 | } catch (Exception $ex) { |
1240 | upgrade_handle_exception($ex); | |
1241 | } | |
1242 | } | |
1243 | ||
1244 | /** | |
1245 | * Upgrade/install other parts of moodle | |
1246 | * @param bool $verbose | |
1247 | * @return void, may throw exception | |
1248 | */ | |
1249 | function upgrade_noncore($verbose) { | |
1250 | global $CFG; | |
1251 | ||
8580535b | 1252 | // upgrade all plugins types |
1253 | try { | |
1254 | $plugintypes = get_plugin_types(); | |
1255 | foreach ($plugintypes as $type=>$location) { | |
17da2e6f | 1256 | upgrade_plugins($type, 'print_upgrade_part_start', 'print_upgrade_part_end', $verbose); |
8580535b | 1257 | } |
1258 | } catch (Exception $ex) { | |
1259 | upgrade_handle_exception($ex); | |
1260 | } | |
1261 | ||
1262 | // Check for changes to RPC functions | |
1263 | if ($CFG->mnet_dispatcher_mode != 'off') { | |
1264 | try { | |
1265 | // this needs a full rewrite, sorry to mention that :-( | |
1266 | // we have to make it part of standard WS framework | |
1267 | require_once("$CFG->dirroot/$CFG->admin/mnet/adminlib.php"); | |
1268 | upgrade_RPC_functions(); // Return here afterwards | |
1269 | } catch (Exception $ex) { | |
1270 | upgrade_handle_exception($ex); | |
1271 | } | |
1272 | } | |
8580535b | 1273 | } |
3316fe24 | 1274 | |
1275 | /** | |
1276 | * Checks if the main tables have been installed yet or not. | |
1277 | * @return bool | |
1278 | */ | |
1279 | function core_tables_exist() { | |
1280 | global $DB; | |
1281 | ||
1282 | if (!$tables = $DB->get_tables() ) { // No tables yet at all. | |
1283 | return false; | |
9b683d13 | 1284 | |
3316fe24 | 1285 | } else { // Check for missing main tables |
1286 | $mtables = array('config', 'course', 'groupings'); // some tables used in 1.9 and 2.0, preferable something from the start and end of install.xml | |
1287 | foreach ($mtables as $mtable) { | |
1288 | if (!in_array($mtable, $tables)) { | |
1289 | return false; | |
1290 | } | |
1291 | } | |
1292 | return true; | |
9b683d13 | 1293 | } |
ba04999c | 1294 | } |