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