PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/upgradelib.php

https://github.com/mylescarrick/moodle
PHP | 1667 lines | 1113 code | 236 blank | 318 comment | 221 complexity | 651be7d47e31ea1e7df2ddf4588f8fea MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Various upgrade/install related functions and classes.
  18. *
  19. * @package core
  20. * @subpackage upgrade
  21. * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. defined('MOODLE_INTERNAL') || die();
  25. /** UPGRADE_LOG_NORMAL = 0 */
  26. define('UPGRADE_LOG_NORMAL', 0);
  27. /** UPGRADE_LOG_NOTICE = 1 */
  28. define('UPGRADE_LOG_NOTICE', 1);
  29. /** UPGRADE_LOG_ERROR = 2 */
  30. define('UPGRADE_LOG_ERROR', 2);
  31. /**
  32. * Exception indicating unknown error during upgrade.
  33. *
  34. * @package core
  35. * @subpackage upgrade
  36. * @copyright 2009 Petr Skoda {@link http://skodak.org}
  37. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38. */
  39. class upgrade_exception extends moodle_exception {
  40. function __construct($plugin, $version, $debuginfo=NULL) {
  41. global $CFG;
  42. $a = (object)array('plugin'=>$plugin, 'version'=>$version);
  43. parent::__construct('upgradeerror', 'admin', "$CFG->wwwroot/$CFG->admin/index.php", $a, $debuginfo);
  44. }
  45. }
  46. /**
  47. * Exception indicating downgrade error during upgrade.
  48. *
  49. * @package core
  50. * @subpackage upgrade
  51. * @copyright 2009 Petr Skoda {@link http://skodak.org}
  52. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  53. */
  54. class downgrade_exception extends moodle_exception {
  55. function __construct($plugin, $oldversion, $newversion) {
  56. global $CFG;
  57. $plugin = is_null($plugin) ? 'moodle' : $plugin;
  58. $a = (object)array('plugin'=>$plugin, 'oldversion'=>$oldversion, 'newversion'=>$newversion);
  59. parent::__construct('cannotdowngrade', 'debug', "$CFG->wwwroot/$CFG->admin/index.php", $a);
  60. }
  61. }
  62. /**
  63. * @package core
  64. * @subpackage upgrade
  65. * @copyright 2009 Petr Skoda {@link http://skodak.org}
  66. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  67. */
  68. class upgrade_requires_exception extends moodle_exception {
  69. function __construct($plugin, $pluginversion, $currentmoodle, $requiremoodle) {
  70. global $CFG;
  71. $a = new stdClass();
  72. $a->pluginname = $plugin;
  73. $a->pluginversion = $pluginversion;
  74. $a->currentmoodle = $currentmoodle;
  75. $a->requiremoodle = $requiremoodle;
  76. parent::__construct('pluginrequirementsnotmet', 'error', "$CFG->wwwroot/$CFG->admin/index.php", $a);
  77. }
  78. }
  79. /**
  80. * @package core
  81. * @subpackage upgrade
  82. * @copyright 2009 Petr Skoda {@link http://skodak.org}
  83. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  84. */
  85. class plugin_defective_exception extends moodle_exception {
  86. function __construct($plugin, $details) {
  87. global $CFG;
  88. parent::__construct('detectedbrokenplugin', 'error', "$CFG->wwwroot/$CFG->admin/index.php", $plugin, $details);
  89. }
  90. }
  91. /**
  92. * Upgrade savepoint, marks end of each upgrade block.
  93. * It stores new main version, resets upgrade timeout
  94. * and abort upgrade if user cancels page loading.
  95. *
  96. * Please do not make large upgrade blocks with lots of operations,
  97. * for example when adding tables keep only one table operation per block.
  98. *
  99. * @global object
  100. * @param bool $result false if upgrade step failed, true if completed
  101. * @param string or float $version main version
  102. * @param bool $allowabort allow user to abort script execution here
  103. * @return void
  104. */
  105. function upgrade_main_savepoint($result, $version, $allowabort=true) {
  106. global $CFG;
  107. if (!$result) {
  108. throw new upgrade_exception(null, $version);
  109. }
  110. if ($CFG->version >= $version) {
  111. // something really wrong is going on in main upgrade script
  112. throw new downgrade_exception(null, $CFG->version, $version);
  113. }
  114. set_config('version', $version);
  115. upgrade_log(UPGRADE_LOG_NORMAL, null, 'Upgrade savepoint reached');
  116. // reset upgrade timeout to default
  117. upgrade_set_timeout();
  118. // this is a safe place to stop upgrades if user aborts page loading
  119. if ($allowabort and connection_aborted()) {
  120. die;
  121. }
  122. }
  123. /**
  124. * Module upgrade savepoint, marks end of module upgrade blocks
  125. * It stores module version, resets upgrade timeout
  126. * and abort upgrade if user cancels page loading.
  127. *
  128. * @global object
  129. * @param bool $result false if upgrade step failed, true if completed
  130. * @param string or float $version main version
  131. * @param string $modname name of module
  132. * @param bool $allowabort allow user to abort script execution here
  133. * @return void
  134. */
  135. function upgrade_mod_savepoint($result, $version, $modname, $allowabort=true) {
  136. global $DB;
  137. if (!$result) {
  138. throw new upgrade_exception("mod_$modname", $version);
  139. }
  140. if (!$module = $DB->get_record('modules', array('name'=>$modname))) {
  141. print_error('modulenotexist', 'debug', '', $modname);
  142. }
  143. if ($module->version >= $version) {
  144. // something really wrong is going on in upgrade script
  145. throw new downgrade_exception("mod_$modname", $module->version, $version);
  146. }
  147. $module->version = $version;
  148. $DB->update_record('modules', $module);
  149. upgrade_log(UPGRADE_LOG_NORMAL, "mod_$modname", 'Upgrade savepoint reached');
  150. // reset upgrade timeout to default
  151. upgrade_set_timeout();
  152. // this is a safe place to stop upgrades if user aborts page loading
  153. if ($allowabort and connection_aborted()) {
  154. die;
  155. }
  156. }
  157. /**
  158. * Blocks upgrade savepoint, marks end of blocks upgrade blocks
  159. * It stores block version, resets upgrade timeout
  160. * and abort upgrade if user cancels page loading.
  161. *
  162. * @global object
  163. * @param bool $result false if upgrade step failed, true if completed
  164. * @param string or float $version main version
  165. * @param string $blockname name of block
  166. * @param bool $allowabort allow user to abort script execution here
  167. * @return void
  168. */
  169. function upgrade_block_savepoint($result, $version, $blockname, $allowabort=true) {
  170. global $DB;
  171. if (!$result) {
  172. throw new upgrade_exception("block_$blockname", $version);
  173. }
  174. if (!$block = $DB->get_record('block', array('name'=>$blockname))) {
  175. print_error('blocknotexist', 'debug', '', $blockname);
  176. }
  177. if ($block->version >= $version) {
  178. // something really wrong is going on in upgrade script
  179. throw new downgrade_exception("block_$blockname", $block->version, $version);
  180. }
  181. $block->version = $version;
  182. $DB->update_record('block', $block);
  183. upgrade_log(UPGRADE_LOG_NORMAL, "block_$blockname", 'Upgrade savepoint reached');
  184. // reset upgrade timeout to default
  185. upgrade_set_timeout();
  186. // this is a safe place to stop upgrades if user aborts page loading
  187. if ($allowabort and connection_aborted()) {
  188. die;
  189. }
  190. }
  191. /**
  192. * Plugins upgrade savepoint, marks end of blocks upgrade blocks
  193. * It stores plugin version, resets upgrade timeout
  194. * and abort upgrade if user cancels page loading.
  195. *
  196. * @param bool $result false if upgrade step failed, true if completed
  197. * @param string or float $version main version
  198. * @param string $type name of plugin
  199. * @param string $dir location of plugin
  200. * @param bool $allowabort allow user to abort script execution here
  201. * @return void
  202. */
  203. function upgrade_plugin_savepoint($result, $version, $type, $plugin, $allowabort=true) {
  204. $component = $type.'_'.$plugin;
  205. if (!$result) {
  206. throw new upgrade_exception($component, $version);
  207. }
  208. $installedversion = get_config($component, 'version');
  209. if ($installedversion >= $version) {
  210. // Something really wrong is going on in the upgrade script
  211. throw new downgrade_exception($component, $installedversion, $version);
  212. }
  213. set_config('version', $version, $component);
  214. upgrade_log(UPGRADE_LOG_NORMAL, $component, 'Upgrade savepoint reached');
  215. // Reset upgrade timeout to default
  216. upgrade_set_timeout();
  217. // This is a safe place to stop upgrades if user aborts page loading
  218. if ($allowabort and connection_aborted()) {
  219. die;
  220. }
  221. }
  222. /**
  223. * Upgrade plugins
  224. * @param string $type The type of plugins that should be updated (e.g. 'enrol', 'qtype')
  225. * return void
  226. */
  227. function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
  228. global $CFG, $DB;
  229. /// special cases
  230. if ($type === 'mod') {
  231. return upgrade_plugins_modules($startcallback, $endcallback, $verbose);
  232. } else if ($type === 'block') {
  233. return upgrade_plugins_blocks($startcallback, $endcallback, $verbose);
  234. }
  235. $plugs = get_plugin_list($type);
  236. foreach ($plugs as $plug=>$fullplug) {
  237. $component = $type.'_'.$plug; // standardised plugin name
  238. // check plugin dir is valid name
  239. $cplug = strtolower($plug);
  240. $cplug = clean_param($cplug, PARAM_SAFEDIR);
  241. $cplug = str_replace('-', '', $cplug);
  242. if ($plug !== $cplug) {
  243. throw new plugin_defective_exception($component, 'Invalid plugin directory name.');
  244. }
  245. if (!is_readable($fullplug.'/version.php')) {
  246. continue;
  247. }
  248. $plugin = new stdClass();
  249. require($fullplug.'/version.php'); // defines $plugin with version etc
  250. // if plugin tells us it's full name we may check the location
  251. if (isset($plugin->component)) {
  252. if ($plugin->component !== $component) {
  253. throw new plugin_defective_exception($component, 'Plugin installed in wrong folder.');
  254. }
  255. }
  256. if (empty($plugin->version)) {
  257. throw new plugin_defective_exception($component, 'Missing version value in version.php');
  258. }
  259. $plugin->name = $plug;
  260. $plugin->fullname = $component;
  261. if (!empty($plugin->requires)) {
  262. if ($plugin->requires > $CFG->version) {
  263. throw new upgrade_requires_exception($component, $plugin->version, $CFG->version, $plugin->requires);
  264. } else if ($plugin->requires < 2010000000) {
  265. throw new plugin_defective_exception($component, 'Plugin is not compatible with Moodle 2.x or later.');
  266. }
  267. }
  268. // try to recover from interrupted install.php if needed
  269. if (file_exists($fullplug.'/db/install.php')) {
  270. if (get_config($plugin->fullname, 'installrunning')) {
  271. require_once($fullplug.'/db/install.php');
  272. $recover_install_function = 'xmldb_'.$plugin->fullname.'_install_recovery';
  273. if (function_exists($recover_install_function)) {
  274. $startcallback($component, true, $verbose);
  275. $recover_install_function();
  276. unset_config('installrunning', $plugin->fullname);
  277. update_capabilities($component);
  278. log_update_descriptions($component);
  279. external_update_descriptions($component);
  280. events_update_definition($component);
  281. message_update_providers($component);
  282. upgrade_plugin_mnet_functions($component);
  283. $endcallback($component, true, $verbose);
  284. }
  285. }
  286. }
  287. $installedversion = get_config($plugin->fullname, 'version');
  288. if (empty($installedversion)) { // new installation
  289. $startcallback($component, true, $verbose);
  290. /// Install tables if defined
  291. if (file_exists($fullplug.'/db/install.xml')) {
  292. $DB->get_manager()->install_from_xmldb_file($fullplug.'/db/install.xml');
  293. }
  294. /// store version
  295. upgrade_plugin_savepoint(true, $plugin->version, $type, $plug, false);
  296. /// execute post install file
  297. if (file_exists($fullplug.'/db/install.php')) {
  298. require_once($fullplug.'/db/install.php');
  299. set_config('installrunning', 1, $plugin->fullname);
  300. $post_install_function = 'xmldb_'.$plugin->fullname.'_install';
  301. $post_install_function();
  302. unset_config('installrunning', $plugin->fullname);
  303. }
  304. /// Install various components
  305. update_capabilities($component);
  306. log_update_descriptions($component);
  307. external_update_descriptions($component);
  308. events_update_definition($component);
  309. message_update_providers($component);
  310. upgrade_plugin_mnet_functions($component);
  311. purge_all_caches();
  312. $endcallback($component, true, $verbose);
  313. } else if ($installedversion < $plugin->version) { // upgrade
  314. /// Run the upgrade function for the plugin.
  315. $startcallback($component, false, $verbose);
  316. if (is_readable($fullplug.'/db/upgrade.php')) {
  317. require_once($fullplug.'/db/upgrade.php'); // defines upgrading function
  318. $newupgrade_function = 'xmldb_'.$plugin->fullname.'_upgrade';
  319. $result = $newupgrade_function($installedversion);
  320. } else {
  321. $result = true;
  322. }
  323. $installedversion = get_config($plugin->fullname, 'version');
  324. if ($installedversion < $plugin->version) {
  325. // store version if not already there
  326. upgrade_plugin_savepoint($result, $plugin->version, $type, $plug, false);
  327. }
  328. /// Upgrade various components
  329. update_capabilities($component);
  330. log_update_descriptions($component);
  331. external_update_descriptions($component);
  332. events_update_definition($component);
  333. message_update_providers($component);
  334. upgrade_plugin_mnet_functions($component);
  335. purge_all_caches();
  336. $endcallback($component, false, $verbose);
  337. } else if ($installedversion > $plugin->version) {
  338. throw new downgrade_exception($component, $installedversion, $plugin->version);
  339. }
  340. }
  341. }
  342. /**
  343. * Find and check all modules and load them up or upgrade them if necessary
  344. *
  345. * @global object
  346. * @global object
  347. */
  348. function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
  349. global $CFG, $DB;
  350. $mods = get_plugin_list('mod');
  351. foreach ($mods as $mod=>$fullmod) {
  352. if ($mod === 'NEWMODULE') { // Someone has unzipped the template, ignore it
  353. continue;
  354. }
  355. $component = 'mod_'.$mod;
  356. // check module dir is valid name
  357. $cmod = strtolower($mod);
  358. $cmod = clean_param($cmod, PARAM_SAFEDIR);
  359. $cmod = str_replace('-', '', $cmod);
  360. $cmod = str_replace('_', '', $cmod); // modules MUST not have '_' in name and never will, sorry
  361. if ($mod !== $cmod) {
  362. throw new plugin_defective_exception($component, 'Invalid plugin directory name.');
  363. }
  364. if (!is_readable($fullmod.'/version.php')) {
  365. throw new plugin_defective_exception($component, 'Missing version.php');
  366. }
  367. $module = new stdClass();
  368. require($fullmod .'/version.php'); // defines $module with version etc
  369. // if plugin tells us it's full name we may check the location
  370. if (isset($module->component)) {
  371. if ($module->component !== $component) {
  372. throw new plugin_defective_exception($component, 'Plugin installed in wrong folder.');
  373. }
  374. }
  375. if (empty($module->version)) {
  376. if (isset($module->version)) {
  377. // Version is empty but is set - it means its value is 0 or ''. Let us skip such module.
  378. // This is intended for developers so they can work on the early stages of the module.
  379. continue;
  380. }
  381. throw new plugin_defective_exception($component, 'Missing version value in version.php');
  382. }
  383. if (!empty($module->requires)) {
  384. if ($module->requires > $CFG->version) {
  385. throw new upgrade_requires_exception($component, $module->version, $CFG->version, $module->requires);
  386. } else if ($module->requires < 2010000000) {
  387. throw new plugin_defective_exception($component, 'Plugin is not compatible with Moodle 2.x or later.');
  388. }
  389. }
  390. // all modules must have en lang pack
  391. if (!is_readable("$fullmod/lang/en/$mod.php")) {
  392. throw new plugin_defective_exception($component, 'Missing mandatory en language pack.');
  393. }
  394. $module->name = $mod; // The name MUST match the directory
  395. $currmodule = $DB->get_record('modules', array('name'=>$module->name));
  396. if (file_exists($fullmod.'/db/install.php')) {
  397. if (get_config($module->name, 'installrunning')) {
  398. require_once($fullmod.'/db/install.php');
  399. $recover_install_function = 'xmldb_'.$module->name.'_install_recovery';
  400. if (function_exists($recover_install_function)) {
  401. $startcallback($component, true, $verbose);
  402. $recover_install_function();
  403. unset_config('installrunning', $module->name);
  404. // Install various components too
  405. update_capabilities($component);
  406. log_update_descriptions($component);
  407. external_update_descriptions($component);
  408. events_update_definition($component);
  409. message_update_providers($component);
  410. upgrade_plugin_mnet_functions($component);
  411. $endcallback($component, true, $verbose);
  412. }
  413. }
  414. }
  415. if (empty($currmodule->version)) {
  416. $startcallback($component, true, $verbose);
  417. /// Execute install.xml (XMLDB) - must be present in all modules
  418. $DB->get_manager()->install_from_xmldb_file($fullmod.'/db/install.xml');
  419. /// Add record into modules table - may be needed in install.php already
  420. $module->id = $DB->insert_record('modules', $module);
  421. /// Post installation hook - optional
  422. if (file_exists("$fullmod/db/install.php")) {
  423. require_once("$fullmod/db/install.php");
  424. // Set installation running flag, we need to recover after exception or error
  425. set_config('installrunning', 1, $module->name);
  426. $post_install_function = 'xmldb_'.$module->name.'_install';;
  427. $post_install_function();
  428. unset_config('installrunning', $module->name);
  429. }
  430. /// Install various components
  431. update_capabilities($component);
  432. log_update_descriptions($component);
  433. external_update_descriptions($component);
  434. events_update_definition($component);
  435. message_update_providers($component);
  436. upgrade_plugin_mnet_functions($component);
  437. purge_all_caches();
  438. $endcallback($component, true, $verbose);
  439. } else if ($currmodule->version < $module->version) {
  440. /// If versions say that we need to upgrade but no upgrade files are available, notify and continue
  441. $startcallback($component, false, $verbose);
  442. if (is_readable($fullmod.'/db/upgrade.php')) {
  443. require_once($fullmod.'/db/upgrade.php'); // defines new upgrading function
  444. $newupgrade_function = 'xmldb_'.$module->name.'_upgrade';
  445. $result = $newupgrade_function($currmodule->version, $module);
  446. } else {
  447. $result = true;
  448. }
  449. $currmodule = $DB->get_record('modules', array('name'=>$module->name));
  450. if ($currmodule->version < $module->version) {
  451. // store version if not already there
  452. upgrade_mod_savepoint($result, $module->version, $mod, false);
  453. }
  454. /// Upgrade various components
  455. update_capabilities($component);
  456. log_update_descriptions($component);
  457. external_update_descriptions($component);
  458. events_update_definition($component);
  459. message_update_providers($component);
  460. upgrade_plugin_mnet_functions($component);
  461. purge_all_caches();
  462. $endcallback($component, false, $verbose);
  463. } else if ($currmodule->version > $module->version) {
  464. throw new downgrade_exception($component, $currmodule->version, $module->version);
  465. }
  466. }
  467. }
  468. /**
  469. * This function finds all available blocks and install them
  470. * into blocks table or do all the upgrade process if newer.
  471. *
  472. * @global object
  473. * @global object
  474. */
  475. function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
  476. global $CFG, $DB;
  477. require_once($CFG->dirroot.'/blocks/moodleblock.class.php');
  478. $blocktitles = array(); // we do not want duplicate titles
  479. //Is this a first install
  480. $first_install = null;
  481. $blocks = get_plugin_list('block');
  482. foreach ($blocks as $blockname=>$fullblock) {
  483. if (is_null($first_install)) {
  484. $first_install = ($DB->count_records('block_instances') == 0);
  485. }
  486. if ($blockname == 'NEWBLOCK') { // Someone has unzipped the template, ignore it
  487. continue;
  488. }
  489. $component = 'block_'.$blockname;
  490. // check block dir is valid name
  491. $cblockname = strtolower($blockname);
  492. $cblockname = clean_param($cblockname, PARAM_SAFEDIR);
  493. $cblockname = str_replace('-', '', $cblockname);
  494. if ($blockname !== $cblockname) {
  495. throw new plugin_defective_exception($component, 'Invalid plugin directory name.');
  496. }
  497. if (!is_readable($fullblock.'/version.php')) {
  498. throw new plugin_defective_exception('block/'.$blockname, 'Missing version.php file.');
  499. }
  500. $plugin = new stdClass();
  501. $plugin->version = NULL;
  502. $plugin->cron = 0;
  503. include($fullblock.'/version.php');
  504. $block = $plugin;
  505. // if plugin tells us it's full name we may check the location
  506. if (isset($block->component)) {
  507. if ($block->component !== $component) {
  508. throw new plugin_defective_exception($component, 'Plugin installed in wrong folder.');
  509. }
  510. }
  511. if (!empty($plugin->requires)) {
  512. if ($plugin->requires > $CFG->version) {
  513. throw new upgrade_requires_exception($component, $plugin->version, $CFG->version, $plugin->requires);
  514. } else if ($plugin->requires < 2010000000) {
  515. throw new plugin_defective_exception($component, 'Plugin is not compatible with Moodle 2.x or later.');
  516. }
  517. }
  518. if (!is_readable($fullblock.'/block_'.$blockname.'.php')) {
  519. throw new plugin_defective_exception('block/'.$blockname, 'Missing main block class file.');
  520. }
  521. include_once($fullblock.'/block_'.$blockname.'.php');
  522. $classname = 'block_'.$blockname;
  523. if (!class_exists($classname)) {
  524. throw new plugin_defective_exception($component, 'Can not load main class.');
  525. }
  526. $blockobj = new $classname; // This is what we'll be testing
  527. $blocktitle = $blockobj->get_title();
  528. // OK, it's as we all hoped. For further tests, the object will do them itself.
  529. if (!$blockobj->_self_test()) {
  530. throw new plugin_defective_exception($component, 'Self test failed.');
  531. }
  532. $block->name = $blockname; // The name MUST match the directory
  533. if (empty($block->version)) {
  534. throw new plugin_defective_exception($component, 'Missing block version.');
  535. }
  536. $currblock = $DB->get_record('block', array('name'=>$block->name));
  537. if (file_exists($fullblock.'/db/install.php')) {
  538. if (get_config('block_'.$blockname, 'installrunning')) {
  539. require_once($fullblock.'/db/install.php');
  540. $recover_install_function = 'xmldb_block_'.$blockname.'_install_recovery';
  541. if (function_exists($recover_install_function)) {
  542. $startcallback($component, true, $verbose);
  543. $recover_install_function();
  544. unset_config('installrunning', 'block_'.$blockname);
  545. // Install various components
  546. update_capabilities($component);
  547. log_update_descriptions($component);
  548. external_update_descriptions($component);
  549. events_update_definition($component);
  550. message_update_providers($component);
  551. upgrade_plugin_mnet_functions($component);
  552. $endcallback($component, true, $verbose);
  553. }
  554. }
  555. }
  556. if (empty($currblock->version)) { // block not installed yet, so install it
  557. $conflictblock = array_search($blocktitle, $blocktitles);
  558. if ($conflictblock !== false) {
  559. // Duplicate block titles are not allowed, they confuse people
  560. // AND PHP's associative arrays ;)
  561. throw new plugin_defective_exception($component, get_string('blocknameconflict', 'error', (object)array('name'=>$block->name, 'conflict'=>$conflictblock)));
  562. }
  563. $startcallback($component, true, $verbose);
  564. if (file_exists($fullblock.'/db/install.xml')) {
  565. $DB->get_manager()->install_from_xmldb_file($fullblock.'/db/install.xml');
  566. }
  567. $block->id = $DB->insert_record('block', $block);
  568. if (file_exists($fullblock.'/db/install.php')) {
  569. require_once($fullblock.'/db/install.php');
  570. // Set installation running flag, we need to recover after exception or error
  571. set_config('installrunning', 1, 'block_'.$blockname);
  572. $post_install_function = 'xmldb_block_'.$blockname.'_install';;
  573. $post_install_function();
  574. unset_config('installrunning', 'block_'.$blockname);
  575. }
  576. $blocktitles[$block->name] = $blocktitle;
  577. // Install various components
  578. update_capabilities($component);
  579. log_update_descriptions($component);
  580. external_update_descriptions($component);
  581. events_update_definition($component);
  582. message_update_providers($component);
  583. upgrade_plugin_mnet_functions($component);
  584. purge_all_caches();
  585. $endcallback($component, true, $verbose);
  586. } else if ($currblock->version < $block->version) {
  587. $startcallback($component, false, $verbose);
  588. if (is_readable($fullblock.'/db/upgrade.php')) {
  589. require_once($fullblock.'/db/upgrade.php'); // defines new upgrading function
  590. $newupgrade_function = 'xmldb_block_'.$blockname.'_upgrade';
  591. $result = $newupgrade_function($currblock->version, $block);
  592. } else {
  593. $result = true;
  594. }
  595. $currblock = $DB->get_record('block', array('name'=>$block->name));
  596. if ($currblock->version < $block->version) {
  597. // store version if not already there
  598. upgrade_block_savepoint($result, $block->version, $block->name, false);
  599. }
  600. if ($currblock->cron != $block->cron) {
  601. // update cron flag if needed
  602. $currblock->cron = $block->cron;
  603. $DB->update_record('block', $currblock);
  604. }
  605. // Upgrade various components
  606. update_capabilities($component);
  607. log_update_descriptions($component);
  608. external_update_descriptions($component);
  609. events_update_definition($component);
  610. message_update_providers($component);
  611. upgrade_plugin_mnet_functions($component);
  612. purge_all_caches();
  613. $endcallback($component, false, $verbose);
  614. } else if ($currblock->version > $block->version) {
  615. throw new downgrade_exception($component, $currblock->version, $block->version);
  616. }
  617. }
  618. // Finally, if we are in the first_install of BLOCKS setup frontpage and admin page blocks
  619. if ($first_install) {
  620. //Iterate over each course - there should be only site course here now
  621. if ($courses = $DB->get_records('course')) {
  622. foreach ($courses as $course) {
  623. blocks_add_default_course_blocks($course);
  624. }
  625. }
  626. blocks_add_default_system_blocks();
  627. }
  628. }
  629. /**
  630. * Log_display description function used during install and upgrade.
  631. *
  632. * @param string $component name of component (moodle, mod_assignment, etc.)
  633. * @return void
  634. */
  635. function log_update_descriptions($component) {
  636. global $DB;
  637. $defpath = get_component_directory($component).'/db/log.php';
  638. if (!file_exists($defpath)) {
  639. $DB->delete_records('log_display', array('component'=>$component));
  640. return;
  641. }
  642. // load new info
  643. $logs = array();
  644. include($defpath);
  645. $newlogs = array();
  646. foreach ($logs as $log) {
  647. $newlogs[$log['module'].'-'.$log['action']] = $log; // kind of unique name
  648. }
  649. unset($logs);
  650. $logs = $newlogs;
  651. $fields = array('module', 'action', 'mtable', 'field');
  652. // update all log fist
  653. $dblogs = $DB->get_records('log_display', array('component'=>$component));
  654. foreach ($dblogs as $dblog) {
  655. $name = $dblog->module.'-'.$dblog->action;
  656. if (empty($logs[$name])) {
  657. $DB->delete_records('log_display', array('id'=>$dblog->id));
  658. continue;
  659. }
  660. $log = $logs[$name];
  661. unset($logs[$name]);
  662. $update = false;
  663. foreach ($fields as $field) {
  664. if ($dblog->$field != $log[$field]) {
  665. $dblog->$field = $log[$field];
  666. $update = true;
  667. }
  668. }
  669. if ($update) {
  670. $DB->update_record('log_display', $dblog);
  671. }
  672. }
  673. foreach ($logs as $log) {
  674. $dblog = (object)$log;
  675. $dblog->component = $component;
  676. $DB->insert_record('log_display', $dblog);
  677. }
  678. }
  679. /**
  680. * Web service discovery function used during install and upgrade.
  681. * @param string $component name of component (moodle, mod_assignment, etc.)
  682. * @return void
  683. */
  684. function external_update_descriptions($component) {
  685. global $DB;
  686. $defpath = get_component_directory($component).'/db/services.php';
  687. if (!file_exists($defpath)) {
  688. external_delete_descriptions($component);
  689. return;
  690. }
  691. // load new info
  692. $functions = array();
  693. $services = array();
  694. include($defpath);
  695. // update all function fist
  696. $dbfunctions = $DB->get_records('external_functions', array('component'=>$component));
  697. foreach ($dbfunctions as $dbfunction) {
  698. if (empty($functions[$dbfunction->name])) {
  699. $DB->delete_records('external_functions', array('id'=>$dbfunction->id));
  700. // do not delete functions from external_services_functions, beacuse
  701. // we want to notify admins when functions used in custom services disappear
  702. //TODO: this looks wrong, we have to delete it eventually (skodak)
  703. continue;
  704. }
  705. $function = $functions[$dbfunction->name];
  706. unset($functions[$dbfunction->name]);
  707. $function['classpath'] = empty($function['classpath']) ? null : $function['classpath'];
  708. $update = false;
  709. if ($dbfunction->classname != $function['classname']) {
  710. $dbfunction->classname = $function['classname'];
  711. $update = true;
  712. }
  713. if ($dbfunction->methodname != $function['methodname']) {
  714. $dbfunction->methodname = $function['methodname'];
  715. $update = true;
  716. }
  717. if ($dbfunction->classpath != $function['classpath']) {
  718. $dbfunction->classpath = $function['classpath'];
  719. $update = true;
  720. }
  721. $functioncapabilities = key_exists('capabilities', $function)?$function['capabilities']:'';
  722. if ($dbfunction->capabilities != $functioncapabilities) {
  723. $dbfunction->capabilities = $functioncapabilities;
  724. $update = true;
  725. }
  726. if ($update) {
  727. $DB->update_record('external_functions', $dbfunction);
  728. }
  729. }
  730. foreach ($functions as $fname => $function) {
  731. $dbfunction = new stdClass();
  732. $dbfunction->name = $fname;
  733. $dbfunction->classname = $function['classname'];
  734. $dbfunction->methodname = $function['methodname'];
  735. $dbfunction->classpath = empty($function['classpath']) ? null : $function['classpath'];
  736. $dbfunction->component = $component;
  737. $dbfunction->capabilities = key_exists('capabilities', $function)?$function['capabilities']:'';
  738. $dbfunction->id = $DB->insert_record('external_functions', $dbfunction);
  739. }
  740. unset($functions);
  741. // now deal with services
  742. $dbservices = $DB->get_records('external_services', array('component'=>$component));
  743. foreach ($dbservices as $dbservice) {
  744. if (empty($services[$dbservice->name])) {
  745. $DB->delete_records('external_services_functions', array('externalserviceid'=>$dbservice->id));
  746. $DB->delete_records('external_services_users', array('externalserviceid'=>$dbservice->id));
  747. $DB->delete_records('external_services', array('id'=>$dbservice->id));
  748. continue;
  749. }
  750. $service = $services[$dbservice->name];
  751. unset($services[$dbservice->name]);
  752. $service['enabled'] = empty($service['enabled']) ? 0 : $service['enabled'];
  753. $service['requiredcapability'] = empty($service['requiredcapability']) ? null : $service['requiredcapability'];
  754. $service['restrictedusers'] = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers'];
  755. $update = false;
  756. if ($dbservice->enabled != $service['enabled']) {
  757. $dbservice->enabled = $service['enabled'];
  758. $update = true;
  759. }
  760. if ($dbservice->requiredcapability != $service['requiredcapability']) {
  761. $dbservice->requiredcapability = $service['requiredcapability'];
  762. $update = true;
  763. }
  764. if ($dbservice->restrictedusers != $service['restrictedusers']) {
  765. $dbservice->restrictedusers = $service['restrictedusers'];
  766. $update = true;
  767. }
  768. if ($update) {
  769. $DB->update_record('external_services', $dbservice);
  770. }
  771. $functions = $DB->get_records('external_services_functions', array('externalserviceid'=>$dbservice->id));
  772. foreach ($functions as $function) {
  773. $key = array_search($function->functionname, $service['functions']);
  774. if ($key === false) {
  775. $DB->delete_records('external_services_functions', array('id'=>$function->id));
  776. } else {
  777. unset($service['functions'][$key]);
  778. }
  779. }
  780. foreach ($service['functions'] as $fname) {
  781. $newf = new stdClass();
  782. $newf->externalserviceid = $dbservice->id;
  783. $newf->functionname = $fname;
  784. $DB->insert_record('external_services_functions', $newf);
  785. }
  786. unset($functions);
  787. }
  788. foreach ($services as $name => $service) {
  789. $dbservice = new stdClass();
  790. $dbservice->name = $name;
  791. $dbservice->enabled = empty($service['enabled']) ? 0 : $service['enabled'];
  792. $dbservice->requiredcapability = empty($service['requiredcapability']) ? null : $service['requiredcapability'];
  793. $dbservice->restrictedusers = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers'];
  794. $dbservice->component = $component;
  795. $dbservice->timecreated = time();
  796. $dbservice->id = $DB->insert_record('external_services', $dbservice);
  797. foreach ($service['functions'] as $fname) {
  798. $newf = new stdClass();
  799. $newf->externalserviceid = $dbservice->id;
  800. $newf->functionname = $fname;
  801. $DB->insert_record('external_services_functions', $newf);
  802. }
  803. }
  804. }
  805. /**
  806. * Delete all service and external functions information defined in the specified component.
  807. * @param string $component name of component (moodle, mod_assignment, etc.)
  808. * @return void
  809. */
  810. function external_delete_descriptions($component) {
  811. global $DB;
  812. $params = array($component);
  813. $DB->delete_records_select('external_services_users', "externalserviceid IN (SELECT id FROM {external_services} WHERE component = ?)", $params);
  814. $DB->delete_records_select('external_services_functions', "externalserviceid IN (SELECT id FROM {external_services} WHERE component = ?)", $params);
  815. $DB->delete_records('external_services', array('component'=>$component));
  816. $DB->delete_records('external_functions', array('component'=>$component));
  817. }
  818. /**
  819. * upgrade logging functions
  820. */
  821. function upgrade_handle_exception($ex, $plugin = null) {
  822. global $CFG;
  823. // rollback everything, we need to log all upgrade problems
  824. abort_all_db_transactions();
  825. $info = get_exception_info($ex);
  826. // First log upgrade error
  827. upgrade_log(UPGRADE_LOG_ERROR, $plugin, 'Exception: ' . get_class($ex), $info->message, $info->backtrace);
  828. // Always turn on debugging - admins need to know what is going on
  829. $CFG->debug = DEBUG_DEVELOPER;
  830. default_exception_handler($ex, true, $plugin);
  831. }
  832. /**
  833. * Adds log entry into upgrade_log table
  834. *
  835. * @param int $type UPGRADE_LOG_NORMAL, UPGRADE_LOG_NOTICE or UPGRADE_LOG_ERROR
  836. * @param string $plugin frankenstyle component name
  837. * @param string $info short description text of log entry
  838. * @param string $details long problem description
  839. * @param string $backtrace string used for errors only
  840. * @return void
  841. */
  842. function upgrade_log($type, $plugin, $info, $details=null, $backtrace=null) {
  843. global $DB, $USER, $CFG;
  844. if (empty($plugin)) {
  845. $plugin = 'core';
  846. }
  847. list($plugintype, $pluginname) = normalize_component($plugin);
  848. $component = is_null($pluginname) ? $plugintype : $plugintype . '_' . $pluginname;
  849. $backtrace = format_backtrace($backtrace, true);
  850. $currentversion = null;
  851. $targetversion = null;
  852. //first try to find out current version number
  853. if ($plugintype === 'core') {
  854. //main
  855. $currentversion = $CFG->version;
  856. $version = null;
  857. include("$CFG->dirroot/version.php");
  858. $targetversion = $version;
  859. } else if ($plugintype === 'mod') {
  860. try {
  861. $currentversion = $DB->get_field('modules', 'version', array('name'=>$pluginname));
  862. $currentversion = ($currentversion === false) ? null : $currentversion;
  863. } catch (Exception $ignored) {
  864. }
  865. $cd = get_component_directory($component);
  866. if (file_exists("$cd/version.php")) {
  867. $module = new stdClass();
  868. $module->version = null;
  869. include("$cd/version.php");
  870. $targetversion = $module->version;
  871. }
  872. } else if ($plugintype === 'block') {
  873. try {
  874. if ($block = $DB->get_record('block', array('name'=>$pluginname))) {
  875. $currentversion = $block->version;
  876. }
  877. } catch (Exception $ignored) {
  878. }
  879. $cd = get_component_directory($component);
  880. if (file_exists("$cd/version.php")) {
  881. $plugin = new stdClass();
  882. $plugin->version = null;
  883. include("$cd/version.php");
  884. $targetversion = $plugin->version;
  885. }
  886. } else {
  887. $pluginversion = get_config($component, 'version');
  888. if (!empty($pluginversion)) {
  889. $currentversion = $pluginversion;
  890. }
  891. $cd = get_component_directory($component);
  892. if (file_exists("$cd/version.php")) {
  893. $plugin = new stdClass();
  894. $plugin->version = null;
  895. include("$cd/version.php");
  896. $targetversion = $plugin->version;
  897. }
  898. }
  899. $log = new stdClass();
  900. $log->type = $type;
  901. $log->plugin = $component;
  902. $log->version = $currentversion;
  903. $log->targetversion = $targetversion;
  904. $log->info = $info;
  905. $log->details = $details;
  906. $log->backtrace = $backtrace;
  907. $log->userid = $USER->id;
  908. $log->timemodified = time();
  909. try {
  910. $DB->insert_record('upgrade_log', $log);
  911. } catch (Exception $ignored) {
  912. // possible during install or 2.0 upgrade
  913. }
  914. }
  915. /**
  916. * Marks start of upgrade, blocks any other access to site.
  917. * The upgrade is finished at the end of script or after timeout.
  918. *
  919. * @global object
  920. * @global object
  921. * @global object
  922. */
  923. function upgrade_started($preinstall=false) {
  924. global $CFG, $DB, $PAGE, $OUTPUT;
  925. static $started = false;
  926. if ($preinstall) {
  927. ignore_user_abort(true);
  928. upgrade_setup_debug(true);
  929. } else if ($started) {
  930. upgrade_set_timeout(120);
  931. } else {
  932. if (!CLI_SCRIPT and !$PAGE->headerprinted) {
  933. $strupgrade = get_string('upgradingversion', 'admin');
  934. $PAGE->set_pagelayout('maintenance');
  935. upgrade_init_javascript();
  936. $PAGE->set_title($strupgrade.' - Moodle '.$CFG->target_release);
  937. $PAGE->set_heading($strupgrade);
  938. $PAGE->navbar->add($strupgrade);
  939. $PAGE->set_cacheable(false);
  940. echo $OUTPUT->header();
  941. }
  942. ignore_user_abort(true);
  943. register_shutdown_function('upgrade_finished_handler');
  944. upgrade_setup_debug(true);
  945. set_config('upgraderunning', time()+300);
  946. $started = true;
  947. }
  948. }
  949. /**
  950. * Internal function - executed if upgrade interrupted.
  951. */
  952. function upgrade_finished_handler() {
  953. upgrade_finished();
  954. }
  955. /**
  956. * Indicates upgrade is finished.
  957. *
  958. * This function may be called repeatedly.
  959. *
  960. * @global object
  961. * @global object
  962. */
  963. function upgrade_finished($continueurl=null) {
  964. global $CFG, $DB, $OUTPUT;
  965. if (!empty($CFG->upgraderunning)) {
  966. unset_config('upgraderunning');
  967. upgrade_setup_debug(false);
  968. ignore_user_abort(false);
  969. if ($continueurl) {
  970. echo $OUTPUT->continue_button($continueurl);
  971. echo $OUTPUT->footer();
  972. die;
  973. }
  974. }
  975. }
  976. /**
  977. * @global object
  978. * @global object
  979. */
  980. function upgrade_setup_debug($starting) {
  981. global $CFG, $DB;
  982. static $originaldebug = null;
  983. if ($starting) {
  984. if ($originaldebug === null) {
  985. $originaldebug = $DB->get_debug();
  986. }
  987. if (!empty($CFG->upgradeshowsql)) {
  988. $DB->set_debug(true);
  989. }
  990. } else {
  991. $DB->set_debug($originaldebug);
  992. }
  993. }
  994. /**
  995. * @global object
  996. */
  997. function print_upgrade_reload($url) {
  998. global $OUTPUT;
  999. echo "<br />";
  1000. echo '<div class="continuebutton">';
  1001. echo '<a href="'.$url.'" title="'.get_string('reload').'" ><img src="'.$OUTPUT->pix_url('i/reload') . '" alt="" /> '.get_string('reload').'</a>';
  1002. echo '</div><br />';
  1003. }
  1004. function print_upgrade_separator() {
  1005. if (!CLI_SCRIPT) {
  1006. echo '<hr />';
  1007. }
  1008. }
  1009. /**
  1010. * Default start upgrade callback
  1011. * @param string $plugin
  1012. * @param bool $installation true if installation, false means upgrade
  1013. */
  1014. function print_upgrade_part_start($plugin, $installation, $verbose) {
  1015. global $OUTPUT;
  1016. if (empty($plugin) or $plugin == 'moodle') {
  1017. upgrade_started($installation); // does not store upgrade running flag yet
  1018. if ($verbose) {
  1019. echo $OUTPUT->heading(get_string('coresystem'));
  1020. }
  1021. } else {
  1022. upgrade_started();
  1023. if ($verbose) {
  1024. echo $OUTPUT->heading($plugin);
  1025. }
  1026. }
  1027. if ($installation) {
  1028. if (empty($plugin) or $plugin == 'moodle') {
  1029. // no need to log - log table not yet there ;-)
  1030. } else {
  1031. upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting plugin installation');
  1032. }
  1033. } else {
  1034. if (empty($plugin) or $plugin == 'moodle') {
  1035. upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting core upgrade');
  1036. } else {
  1037. upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting plugin upgrade');
  1038. }
  1039. }
  1040. }
  1041. /**
  1042. * Default end upgrade callback
  1043. * @param string $plugin
  1044. * @param bool $installation true if installation, false means upgrade
  1045. */
  1046. function print_upgrade_part_end($plugin, $installation, $verbose) {
  1047. global $OUTPUT;
  1048. upgrade_started();
  1049. if ($installation) {
  1050. if (empty($plugin) or $plugin == 'moodle') {
  1051. upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Core installed');
  1052. } else {
  1053. upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Plugin installed');
  1054. }
  1055. } else {
  1056. if (empty($plugin) or $plugin == 'moodle') {
  1057. upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Core upgraded');
  1058. } else {
  1059. upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Plugin upgraded');
  1060. }
  1061. }
  1062. if ($verbose) {
  1063. echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
  1064. print_upgrade_separator();
  1065. }
  1066. }
  1067. /**
  1068. * Sets up JS code required for all upgrade scripts.
  1069. * @global object
  1070. */
  1071. function upgrade_init_javascript() {
  1072. global $PAGE;
  1073. // scroll to the end of each upgrade page so that ppl see either error or continue button,
  1074. // no need to scroll continuously any more, it is enough to jump to end once the footer is printed ;-)
  1075. $js = "window.scrollTo(0, 5000000);";
  1076. $PAGE->requires->js_init_code($js);
  1077. }
  1078. /**
  1079. * Try to upgrade the given language pack (or current language)
  1080. *
  1081. * @todo hardcoded Moodle version here - shall be provided by version.php or similar script
  1082. */
  1083. function upgrade_language_pack($lang='') {
  1084. global $CFG, $OUTPUT;
  1085. get_string_manager()->reset_caches();
  1086. if (empty($lang)) {
  1087. $lang = current_language();
  1088. }
  1089. if ($lang == 'en') {
  1090. return true; // Nothing to do
  1091. }
  1092. upgrade_started(false);
  1093. echo $OUTPUT->heading(get_string('langimport', 'admin').': '.$lang);
  1094. @mkdir ($CFG->dataroot.'/temp/'); //make it in case it's a fresh install, it might not be there
  1095. @mkdir ($CFG->dataroot.'/lang/');
  1096. require_once($CFG->libdir.'/componentlib.class.php');
  1097. if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $lang.'.zip', 'languages.md5', 'lang')) {
  1098. $status = $cd->install(); //returns COMPONENT_(ERROR | UPTODATE | INSTALLED)
  1099. if ($status == COMPONENT_INSTALLED) {
  1100. remove_dir($CFG->dataroot.'/cache/languages');
  1101. if ($parentlang = get_parent_language($lang)) {
  1102. if ($cd = new component_installer('http://download.moodle.org', 'langpack/2.0', $parentlang.'.zip', 'languages.md5', 'lang')) {
  1103. $cd->install();
  1104. }
  1105. }
  1106. echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
  1107. }
  1108. }
  1109. get_string_manager()->reset_caches();
  1110. print_upgrade_separator();
  1111. }
  1112. /**
  1113. * Install core moodle tables and initialize
  1114. * @param float $version target version
  1115. * @param bool $verbose
  1116. * @return void, may throw exception
  1117. */
  1118. function install_core($version, $verbose) {
  1119. global $CFG, $DB;
  1120. try {
  1121. set_time_limit(600);
  1122. print_upgrade_part_start('moodle', true, $verbose); // does not store upgrade running flag
  1123. $DB->get_manager()->install_from_xmldb_file("$CFG->libdir/db/install.xml");
  1124. upgrade_started(); // we want the flag to be stored in config table ;-)
  1125. // set all core default records and default settings
  1126. require_once("$CFG->libdir/db/install.php");
  1127. xmldb_main_install(); // installs the capabilities too
  1128. // store version
  1129. upgrade_main_savepoint(true, $version, false);
  1130. // Continue with the installation
  1131. log_update_descriptions('moodle');
  1132. external_update_descriptions('moodle');
  1133. events_update_definition('moodle');
  1134. message_update_providers('moodle');
  1135. // Write default settings unconditionally
  1136. admin_apply_default_settings(NULL, true);
  1137. print_upgrade_part_end(null, true, $verbose);
  1138. } catch (exception $ex) {
  1139. upgrade_handle_exception($ex);
  1140. }
  1141. }
  1142. /**
  1143. * Upgrade moodle core
  1144. * @param float $version target version
  1145. * @param bool $verbose
  1146. * @return void, may throw exception
  1147. */
  1148. function upgrade_core($version, $verbose) {
  1149. global $CFG;
  1150. raise_memory_limit(MEMORY_EXTRA);
  1151. require_once($CFG->libdir.'/db/upgrade.php'); // Defines upgrades
  1152. try {
  1153. // Reset caches before any output
  1154. purge_all_caches();
  1155. // Upgrade current language pack if we can
  1156. if (empty($CFG->skiplangupgrade)) {
  1157. if (get_string_manager()->translation_exists(current_language())) {
  1158. upgrade_language_pack(false);
  1159. }
  1160. }
  1161. print_upgrade_part_start('moodle', false, $verbose);
  1162. // one time special local migration pre 2.0 upgrade script
  1163. if ($CFG->version < 2007101600) {
  1164. $pre20upgradefile = "$CFG->dirroot/local/upgrade_pre20.php";
  1165. if (file_exists($pre20upgradefile)) {
  1166. set_

Large files files are truncated, but you can click here to view the full file