Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/upgradelib.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00027 defined('MOODLE_INTERNAL') || die();
00028 
00030 define('UPGRADE_LOG_NORMAL', 0);
00032 define('UPGRADE_LOG_NOTICE', 1);
00034 define('UPGRADE_LOG_ERROR',  2);
00035 
00044 class upgrade_exception extends moodle_exception {
00045     function __construct($plugin, $version, $debuginfo=NULL) {
00046         global $CFG;
00047         $a = (object)array('plugin'=>$plugin, 'version'=>$version);
00048         parent::__construct('upgradeerror', 'admin', "$CFG->wwwroot/$CFG->admin/index.php", $a, $debuginfo);
00049     }
00050 }
00051 
00060 class downgrade_exception extends moodle_exception {
00061     function __construct($plugin, $oldversion, $newversion) {
00062         global $CFG;
00063         $plugin = is_null($plugin) ? 'moodle' : $plugin;
00064         $a = (object)array('plugin'=>$plugin, 'oldversion'=>$oldversion, 'newversion'=>$newversion);
00065         parent::__construct('cannotdowngrade', 'debug', "$CFG->wwwroot/$CFG->admin/index.php", $a);
00066     }
00067 }
00068 
00075 class upgrade_requires_exception extends moodle_exception {
00076     function __construct($plugin, $pluginversion, $currentmoodle, $requiremoodle) {
00077         global $CFG;
00078         $a = new stdClass();
00079         $a->pluginname     = $plugin;
00080         $a->pluginversion  = $pluginversion;
00081         $a->currentmoodle  = $currentmoodle;
00082         $a->requiremoodle  = $requiremoodle;
00083         parent::__construct('pluginrequirementsnotmet', 'error', "$CFG->wwwroot/$CFG->admin/index.php", $a);
00084     }
00085 }
00086 
00093 class plugin_defective_exception extends moodle_exception {
00094     function __construct($plugin, $details) {
00095         global $CFG;
00096         parent::__construct('detectedbrokenplugin', 'error', "$CFG->wwwroot/$CFG->admin/index.php", $plugin, $details);
00097     }
00098 }
00099 
00114 function upgrade_main_savepoint($result, $version, $allowabort=true) {
00115     global $CFG;
00116 
00117     //sanity check to avoid confusion with upgrade_mod_savepoint usage.
00118     if (!is_bool($allowabort)) {
00119         $errormessage = 'Parameter type mismatch. Are you mixing up upgrade_main_savepoint() and upgrade_mod_savepoint()?';
00120         throw new coding_exception($errormessage);
00121     }
00122 
00123     if (!$result) {
00124         throw new upgrade_exception(null, $version);
00125     }
00126 
00127     if ($CFG->version >= $version) {
00128         // something really wrong is going on in main upgrade script
00129         throw new downgrade_exception(null, $CFG->version, $version);
00130     }
00131 
00132     set_config('version', $version);
00133     upgrade_log(UPGRADE_LOG_NORMAL, null, 'Upgrade savepoint reached');
00134 
00135     // reset upgrade timeout to default
00136     upgrade_set_timeout();
00137 
00138     // this is a safe place to stop upgrades if user aborts page loading
00139     if ($allowabort and connection_aborted()) {
00140         die;
00141     }
00142 }
00143 
00156 function upgrade_mod_savepoint($result, $version, $modname, $allowabort=true) {
00157     global $DB;
00158 
00159     if (!$result) {
00160         throw new upgrade_exception("mod_$modname", $version);
00161     }
00162 
00163     if (!$module = $DB->get_record('modules', array('name'=>$modname))) {
00164         print_error('modulenotexist', 'debug', '', $modname);
00165     }
00166 
00167     if ($module->version >= $version) {
00168         // something really wrong is going on in upgrade script
00169         throw new downgrade_exception("mod_$modname", $module->version, $version);
00170     }
00171     $module->version = $version;
00172     $DB->update_record('modules', $module);
00173     upgrade_log(UPGRADE_LOG_NORMAL, "mod_$modname", 'Upgrade savepoint reached');
00174 
00175     // reset upgrade timeout to default
00176     upgrade_set_timeout();
00177 
00178     // this is a safe place to stop upgrades if user aborts page loading
00179     if ($allowabort and connection_aborted()) {
00180         die;
00181     }
00182 }
00183 
00196 function upgrade_block_savepoint($result, $version, $blockname, $allowabort=true) {
00197     global $DB;
00198 
00199     if (!$result) {
00200         throw new upgrade_exception("block_$blockname", $version);
00201     }
00202 
00203     if (!$block = $DB->get_record('block', array('name'=>$blockname))) {
00204         print_error('blocknotexist', 'debug', '', $blockname);
00205     }
00206 
00207     if ($block->version >= $version) {
00208         // something really wrong is going on in upgrade script
00209         throw new downgrade_exception("block_$blockname", $block->version, $version);
00210     }
00211     $block->version = $version;
00212     $DB->update_record('block', $block);
00213     upgrade_log(UPGRADE_LOG_NORMAL, "block_$blockname", 'Upgrade savepoint reached');
00214 
00215     // reset upgrade timeout to default
00216     upgrade_set_timeout();
00217 
00218     // this is a safe place to stop upgrades if user aborts page loading
00219     if ($allowabort and connection_aborted()) {
00220         die;
00221     }
00222 }
00223 
00236 function upgrade_plugin_savepoint($result, $version, $type, $plugin, $allowabort=true) {
00237     $component = $type.'_'.$plugin;
00238 
00239     if (!$result) {
00240         throw new upgrade_exception($component, $version);
00241     }
00242 
00243     $installedversion = get_config($component, 'version');
00244     if ($installedversion >= $version) {
00245         // Something really wrong is going on in the upgrade script
00246         throw new downgrade_exception($component, $installedversion, $version);
00247     }
00248     set_config('version', $version, $component);
00249     upgrade_log(UPGRADE_LOG_NORMAL, $component, 'Upgrade savepoint reached');
00250 
00251     // Reset upgrade timeout to default
00252     upgrade_set_timeout();
00253 
00254     // This is a safe place to stop upgrades if user aborts page loading
00255     if ($allowabort and connection_aborted()) {
00256         die;
00257     }
00258 }
00259 
00260 
00266 function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
00267     global $CFG, $DB;
00268 
00270     if ($type === 'mod') {
00271         return upgrade_plugins_modules($startcallback, $endcallback, $verbose);
00272     } else if ($type === 'block') {
00273         return upgrade_plugins_blocks($startcallback, $endcallback, $verbose);
00274     }
00275 
00276     $plugs = get_plugin_list($type);
00277 
00278     foreach ($plugs as $plug=>$fullplug) {
00279         $component = clean_param($type.'_'.$plug, PARAM_COMPONENT); // standardised plugin name
00280 
00281         // check plugin dir is valid name
00282         if (empty($component)) {
00283             throw new plugin_defective_exception($type.'_'.$plug, 'Invalid plugin directory name.');
00284         }
00285 
00286         if (!is_readable($fullplug.'/version.php')) {
00287             continue;
00288         }
00289 
00290         $plugin = new stdClass();
00291         require($fullplug.'/version.php');  // defines $plugin with version etc
00292 
00293         // if plugin tells us it's full name we may check the location
00294         if (isset($plugin->component)) {
00295             if ($plugin->component !== $component) {
00296                 throw new plugin_defective_exception($component, 'Plugin installed in wrong folder.');
00297             }
00298         }
00299 
00300         if (empty($plugin->version)) {
00301             throw new plugin_defective_exception($component, 'Missing version value in version.php');
00302         }
00303 
00304         $plugin->name     = $plug;
00305         $plugin->fullname = $component;
00306 
00307 
00308         if (!empty($plugin->requires)) {
00309             if ($plugin->requires > $CFG->version) {
00310                 throw new upgrade_requires_exception($component, $plugin->version, $CFG->version, $plugin->requires);
00311             } else if ($plugin->requires < 2010000000) {
00312                 throw new plugin_defective_exception($component, 'Plugin is not compatible with Moodle 2.x or later.');
00313             }
00314         }
00315 
00316         // try to recover from interrupted install.php if needed
00317         if (file_exists($fullplug.'/db/install.php')) {
00318             if (get_config($plugin->fullname, 'installrunning')) {
00319                 require_once($fullplug.'/db/install.php');
00320                 $recover_install_function = 'xmldb_'.$plugin->fullname.'_install_recovery';
00321                 if (function_exists($recover_install_function)) {
00322                     $startcallback($component, true, $verbose);
00323                     $recover_install_function();
00324                     unset_config('installrunning', $plugin->fullname);
00325                     update_capabilities($component);
00326                     log_update_descriptions($component);
00327                     external_update_descriptions($component);
00328                     events_update_definition($component);
00329                     message_update_providers($component);
00330                     if ($type === 'message') {
00331                         message_update_processors($plug);
00332                     }
00333                     upgrade_plugin_mnet_functions($component);
00334                     $endcallback($component, true, $verbose);
00335                 }
00336             }
00337         }
00338 
00339         $installedversion = get_config($plugin->fullname, 'version');
00340         if (empty($installedversion)) { // new installation
00341             $startcallback($component, true, $verbose);
00342 
00344             if (file_exists($fullplug.'/db/install.xml')) {
00345                 $DB->get_manager()->install_from_xmldb_file($fullplug.'/db/install.xml');
00346             }
00347 
00349             upgrade_plugin_savepoint(true, $plugin->version, $type, $plug, false);
00350 
00352             if (file_exists($fullplug.'/db/install.php')) {
00353                 require_once($fullplug.'/db/install.php');
00354                 set_config('installrunning', 1, $plugin->fullname);
00355                 $post_install_function = 'xmldb_'.$plugin->fullname.'_install';
00356                 $post_install_function();
00357                 unset_config('installrunning', $plugin->fullname);
00358             }
00359 
00361             update_capabilities($component);
00362             log_update_descriptions($component);
00363             external_update_descriptions($component);
00364             events_update_definition($component);
00365             message_update_providers($component);
00366             if ($type === 'message') {
00367                 message_update_processors($plug);
00368             }
00369             upgrade_plugin_mnet_functions($component);
00370 
00371             purge_all_caches();
00372             $endcallback($component, true, $verbose);
00373 
00374         } else if ($installedversion < $plugin->version) { // upgrade
00376             $startcallback($component, false, $verbose);
00377 
00378             if (is_readable($fullplug.'/db/upgrade.php')) {
00379                 require_once($fullplug.'/db/upgrade.php');  // defines upgrading function
00380 
00381                 $newupgrade_function = 'xmldb_'.$plugin->fullname.'_upgrade';
00382                 $result = $newupgrade_function($installedversion);
00383             } else {
00384                 $result = true;
00385             }
00386 
00387             $installedversion = get_config($plugin->fullname, 'version');
00388             if ($installedversion < $plugin->version) {
00389                 // store version if not already there
00390                 upgrade_plugin_savepoint($result, $plugin->version, $type, $plug, false);
00391             }
00392 
00394             update_capabilities($component);
00395             log_update_descriptions($component);
00396             external_update_descriptions($component);
00397             events_update_definition($component);
00398             message_update_providers($component);
00399             if ($type === 'message') {
00400                 message_update_processors($plug);
00401             }
00402             upgrade_plugin_mnet_functions($component);
00403 
00404             purge_all_caches();
00405             $endcallback($component, false, $verbose);
00406 
00407         } else if ($installedversion > $plugin->version) {
00408             throw new downgrade_exception($component, $installedversion, $plugin->version);
00409         }
00410     }
00411 }
00412 
00419 function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
00420     global $CFG, $DB;
00421 
00422     $mods = get_plugin_list('mod');
00423 
00424     foreach ($mods as $mod=>$fullmod) {
00425 
00426         if ($mod === 'NEWMODULE') {   // Someone has unzipped the template, ignore it
00427             continue;
00428         }
00429 
00430         $component = clean_param('mod_'.$mod, PARAM_COMPONENT);
00431 
00432         // check module dir is valid name
00433         if (empty($component)) {
00434             throw new plugin_defective_exception('mod_'.$mod, 'Invalid plugin directory name.');
00435         }
00436 
00437         if (!is_readable($fullmod.'/version.php')) {
00438             throw new plugin_defective_exception($component, 'Missing version.php');
00439         }
00440 
00441         $module = new stdClass();
00442         require($fullmod .'/version.php');  // defines $module with version etc
00443 
00444         // if plugin tells us it's full name we may check the location
00445         if (isset($module->component)) {
00446             if ($module->component !== $component) {
00447                 throw new plugin_defective_exception($component, 'Plugin installed in wrong folder.');
00448             }
00449         }
00450 
00451         if (empty($module->version)) {
00452             if (isset($module->version)) {
00453                 // Version is empty but is set - it means its value is 0 or ''. Let us skip such module.
00454                 // This is intended for developers so they can work on the early stages of the module.
00455                 continue;
00456             }
00457             throw new plugin_defective_exception($component, 'Missing version value in version.php');
00458         }
00459 
00460         if (!empty($module->requires)) {
00461             if ($module->requires > $CFG->version) {
00462                 throw new upgrade_requires_exception($component, $module->version, $CFG->version, $module->requires);
00463             } else if ($module->requires < 2010000000) {
00464                 throw new plugin_defective_exception($component, 'Plugin is not compatible with Moodle 2.x or later.');
00465             }
00466         }
00467 
00468         if (empty($module->cron)) {
00469             $module->cron = 0;
00470         }
00471 
00472         // all modules must have en lang pack
00473         if (!is_readable("$fullmod/lang/en/$mod.php")) {
00474             throw new plugin_defective_exception($component, 'Missing mandatory en language pack.');
00475         }
00476 
00477         $module->name = $mod;   // The name MUST match the directory
00478 
00479         $currmodule = $DB->get_record('modules', array('name'=>$module->name));
00480 
00481         if (file_exists($fullmod.'/db/install.php')) {
00482             if (get_config($module->name, 'installrunning')) {
00483                 require_once($fullmod.'/db/install.php');
00484                 $recover_install_function = 'xmldb_'.$module->name.'_install_recovery';
00485                 if (function_exists($recover_install_function)) {
00486                     $startcallback($component, true, $verbose);
00487                     $recover_install_function();
00488                     unset_config('installrunning', $module->name);
00489                     // Install various components too
00490                     update_capabilities($component);
00491                     log_update_descriptions($component);
00492                     external_update_descriptions($component);
00493                     events_update_definition($component);
00494                     message_update_providers($component);
00495                     upgrade_plugin_mnet_functions($component);
00496                     $endcallback($component, true, $verbose);
00497                 }
00498             }
00499         }
00500 
00501         if (empty($currmodule->version)) {
00502             $startcallback($component, true, $verbose);
00503 
00505             $DB->get_manager()->install_from_xmldb_file($fullmod.'/db/install.xml');
00506 
00508             $module->id = $DB->insert_record('modules', $module);
00509 
00511             if (file_exists("$fullmod/db/install.php")) {
00512                 require_once("$fullmod/db/install.php");
00513                 // Set installation running flag, we need to recover after exception or error
00514                 set_config('installrunning', 1, $module->name);
00515                 $post_install_function = 'xmldb_'.$module->name.'_install';
00516                 $post_install_function();
00517                 unset_config('installrunning', $module->name);
00518             }
00519 
00521             update_capabilities($component);
00522             log_update_descriptions($component);
00523             external_update_descriptions($component);
00524             events_update_definition($component);
00525             message_update_providers($component);
00526             upgrade_plugin_mnet_functions($component);
00527 
00528             purge_all_caches();
00529             $endcallback($component, true, $verbose);
00530 
00531         } else if ($currmodule->version < $module->version) {
00533             $startcallback($component, false, $verbose);
00534 
00535             if (is_readable($fullmod.'/db/upgrade.php')) {
00536                 require_once($fullmod.'/db/upgrade.php');  // defines new upgrading function
00537                 $newupgrade_function = 'xmldb_'.$module->name.'_upgrade';
00538                 $result = $newupgrade_function($currmodule->version, $module);
00539             } else {
00540                 $result = true;
00541             }
00542 
00543             $currmodule = $DB->get_record('modules', array('name'=>$module->name));
00544             if ($currmodule->version < $module->version) {
00545                 // store version if not already there
00546                 upgrade_mod_savepoint($result, $module->version, $mod, false);
00547             }
00548 
00549             // update cron flag if needed
00550             if ($currmodule->cron != $module->cron) {
00551                 $DB->set_field('modules', 'cron', $module->cron, array('name' => $module->name));
00552             }
00553 
00554             // Upgrade various components
00555             update_capabilities($component);
00556             log_update_descriptions($component);
00557             external_update_descriptions($component);
00558             events_update_definition($component);
00559             message_update_providers($component);
00560             upgrade_plugin_mnet_functions($component);
00561 
00562             purge_all_caches();
00563 
00564             $endcallback($component, false, $verbose);
00565 
00566         } else if ($currmodule->version > $module->version) {
00567             throw new downgrade_exception($component, $currmodule->version, $module->version);
00568         }
00569     }
00570 }
00571 
00572 
00580 function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
00581     global $CFG, $DB;
00582 
00583     require_once($CFG->dirroot.'/blocks/moodleblock.class.php');
00584 
00585     $blocktitles   = array(); // we do not want duplicate titles
00586 
00587     //Is this a first install
00588     $first_install = null;
00589 
00590     $blocks = get_plugin_list('block');
00591 
00592     foreach ($blocks as $blockname=>$fullblock) {
00593 
00594         if (is_null($first_install)) {
00595             $first_install = ($DB->count_records('block_instances') == 0);
00596         }
00597 
00598         if ($blockname === 'NEWBLOCK') {   // Someone has unzipped the template, ignore it
00599             continue;
00600         }
00601 
00602         $component = clean_param('block_'.$blockname, PARAM_COMPONENT);
00603 
00604         // check block dir is valid name
00605         if (empty($component)) {
00606             throw new plugin_defective_exception('block_'.$blockname, 'Invalid plugin directory name.');
00607         }
00608 
00609         if (!is_readable($fullblock.'/version.php')) {
00610             throw new plugin_defective_exception('block/'.$blockname, 'Missing version.php file.');
00611         }
00612         $plugin = new stdClass();
00613         $plugin->version = NULL;
00614         $plugin->cron    = 0;
00615         include($fullblock.'/version.php');
00616         $block = $plugin;
00617 
00618         // if plugin tells us it's full name we may check the location
00619         if (isset($block->component)) {
00620             if ($block->component !== $component) {
00621                 throw new plugin_defective_exception($component, 'Plugin installed in wrong folder.');
00622             }
00623         }
00624 
00625         if (!empty($plugin->requires)) {
00626             if ($plugin->requires > $CFG->version) {
00627                 throw new upgrade_requires_exception($component, $plugin->version, $CFG->version, $plugin->requires);
00628             } else if ($plugin->requires < 2010000000) {
00629                 throw new plugin_defective_exception($component, 'Plugin is not compatible with Moodle 2.x or later.');
00630             }
00631         }
00632 
00633         if (!is_readable($fullblock.'/block_'.$blockname.'.php')) {
00634             throw new plugin_defective_exception('block/'.$blockname, 'Missing main block class file.');
00635         }
00636         include_once($fullblock.'/block_'.$blockname.'.php');
00637 
00638         $classname = 'block_'.$blockname;
00639 
00640         if (!class_exists($classname)) {
00641             throw new plugin_defective_exception($component, 'Can not load main class.');
00642         }
00643 
00644         $blockobj    = new $classname;   // This is what we'll be testing
00645         $blocktitle  = $blockobj->get_title();
00646 
00647         // OK, it's as we all hoped. For further tests, the object will do them itself.
00648         if (!$blockobj->_self_test()) {
00649             throw new plugin_defective_exception($component, 'Self test failed.');
00650         }
00651 
00652         $block->name     = $blockname;   // The name MUST match the directory
00653 
00654         if (empty($block->version)) {
00655             throw new plugin_defective_exception($component, 'Missing block version.');
00656         }
00657 
00658         $currblock = $DB->get_record('block', array('name'=>$block->name));
00659 
00660         if (file_exists($fullblock.'/db/install.php')) {
00661             if (get_config('block_'.$blockname, 'installrunning')) {
00662                 require_once($fullblock.'/db/install.php');
00663                 $recover_install_function = 'xmldb_block_'.$blockname.'_install_recovery';
00664                 if (function_exists($recover_install_function)) {
00665                     $startcallback($component, true, $verbose);
00666                     $recover_install_function();
00667                     unset_config('installrunning', 'block_'.$blockname);
00668                     // Install various components
00669                     update_capabilities($component);
00670                     log_update_descriptions($component);
00671                     external_update_descriptions($component);
00672                     events_update_definition($component);
00673                     message_update_providers($component);
00674                     upgrade_plugin_mnet_functions($component);
00675                     $endcallback($component, true, $verbose);
00676                 }
00677             }
00678         }
00679 
00680         if (empty($currblock->version)) { // block not installed yet, so install it
00681             $conflictblock = array_search($blocktitle, $blocktitles);
00682             if ($conflictblock !== false) {
00683                 // Duplicate block titles are not allowed, they confuse people
00684                 // AND PHP's associative arrays ;)
00685                 throw new plugin_defective_exception($component, get_string('blocknameconflict', 'error', (object)array('name'=>$block->name, 'conflict'=>$conflictblock)));
00686             }
00687             $startcallback($component, true, $verbose);
00688 
00689             if (file_exists($fullblock.'/db/install.xml')) {
00690                 $DB->get_manager()->install_from_xmldb_file($fullblock.'/db/install.xml');
00691             }
00692             $block->id = $DB->insert_record('block', $block);
00693 
00694             if (file_exists($fullblock.'/db/install.php')) {
00695                 require_once($fullblock.'/db/install.php');
00696                 // Set installation running flag, we need to recover after exception or error
00697                 set_config('installrunning', 1, 'block_'.$blockname);
00698                 $post_install_function = 'xmldb_block_'.$blockname.'_install';;
00699                 $post_install_function();
00700                 unset_config('installrunning', 'block_'.$blockname);
00701             }
00702 
00703             $blocktitles[$block->name] = $blocktitle;
00704 
00705             // Install various components
00706             update_capabilities($component);
00707             log_update_descriptions($component);
00708             external_update_descriptions($component);
00709             events_update_definition($component);
00710             message_update_providers($component);
00711             upgrade_plugin_mnet_functions($component);
00712 
00713             purge_all_caches();
00714             $endcallback($component, true, $verbose);
00715 
00716         } else if ($currblock->version < $block->version) {
00717             $startcallback($component, false, $verbose);
00718 
00719             if (is_readable($fullblock.'/db/upgrade.php')) {
00720                 require_once($fullblock.'/db/upgrade.php');  // defines new upgrading function
00721                 $newupgrade_function = 'xmldb_block_'.$blockname.'_upgrade';
00722                 $result = $newupgrade_function($currblock->version, $block);
00723             } else {
00724                 $result = true;
00725             }
00726 
00727             $currblock = $DB->get_record('block', array('name'=>$block->name));
00728             if ($currblock->version < $block->version) {
00729                 // store version if not already there
00730                 upgrade_block_savepoint($result, $block->version, $block->name, false);
00731             }
00732 
00733             if ($currblock->cron != $block->cron) {
00734                 // update cron flag if needed
00735                 $currblock->cron = $block->cron;
00736                 $DB->update_record('block', $currblock);
00737             }
00738 
00739             // Upgrade various components
00740             update_capabilities($component);
00741             log_update_descriptions($component);
00742             external_update_descriptions($component);
00743             events_update_definition($component);
00744             message_update_providers($component);
00745             upgrade_plugin_mnet_functions($component);
00746 
00747             purge_all_caches();
00748             $endcallback($component, false, $verbose);
00749 
00750         } else if ($currblock->version > $block->version) {
00751             throw new downgrade_exception($component, $currblock->version, $block->version);
00752         }
00753     }
00754 
00755 
00756     // Finally, if we are in the first_install of BLOCKS setup frontpage and admin page blocks
00757     if ($first_install) {
00758         //Iterate over each course - there should be only site course here now
00759         if ($courses = $DB->get_records('course')) {
00760             foreach ($courses as $course) {
00761                 blocks_add_default_course_blocks($course);
00762             }
00763         }
00764 
00765         blocks_add_default_system_blocks();
00766     }
00767 }
00768 
00769 
00776 function log_update_descriptions($component) {
00777     global $DB;
00778 
00779     $defpath = get_component_directory($component).'/db/log.php';
00780 
00781     if (!file_exists($defpath)) {
00782         $DB->delete_records('log_display', array('component'=>$component));
00783         return;
00784     }
00785 
00786     // load new info
00787     $logs = array();
00788     include($defpath);
00789     $newlogs = array();
00790     foreach ($logs as $log) {
00791         $newlogs[$log['module'].'-'.$log['action']] = $log; // kind of unique name
00792     }
00793     unset($logs);
00794     $logs = $newlogs;
00795 
00796     $fields = array('module', 'action', 'mtable', 'field');
00797     // update all log fist
00798     $dblogs = $DB->get_records('log_display', array('component'=>$component));
00799     foreach ($dblogs as $dblog) {
00800         $name = $dblog->module.'-'.$dblog->action;
00801 
00802         if (empty($logs[$name])) {
00803             $DB->delete_records('log_display', array('id'=>$dblog->id));
00804             continue;
00805         }
00806 
00807         $log = $logs[$name];
00808         unset($logs[$name]);
00809 
00810         $update = false;
00811         foreach ($fields as $field) {
00812             if ($dblog->$field != $log[$field]) {
00813                 $dblog->$field = $log[$field];
00814                 $update = true;
00815             }
00816         }
00817         if ($update) {
00818             $DB->update_record('log_display', $dblog);
00819         }
00820     }
00821     foreach ($logs as $log) {
00822         $dblog = (object)$log;
00823         $dblog->component = $component;
00824         $DB->insert_record('log_display', $dblog);
00825     }
00826 }
00827 
00833 function external_update_descriptions($component) {
00834     global $DB;
00835 
00836     $defpath = get_component_directory($component).'/db/services.php';
00837 
00838     if (!file_exists($defpath)) {
00839         external_delete_descriptions($component);
00840         return;
00841     }
00842 
00843     // load new info
00844     $functions = array();
00845     $services = array();
00846     include($defpath);
00847 
00848     // update all function fist
00849     $dbfunctions = $DB->get_records('external_functions', array('component'=>$component));
00850     foreach ($dbfunctions as $dbfunction) {
00851         if (empty($functions[$dbfunction->name])) {
00852             $DB->delete_records('external_functions', array('id'=>$dbfunction->id));
00853             // do not delete functions from external_services_functions, beacuse
00854             // we want to notify admins when functions used in custom services disappear
00855 
00856             //TODO: this looks wrong, we have to delete it eventually (skodak)
00857             continue;
00858         }
00859 
00860         $function = $functions[$dbfunction->name];
00861         unset($functions[$dbfunction->name]);
00862         $function['classpath'] = empty($function['classpath']) ? null : $function['classpath'];
00863 
00864         $update = false;
00865         if ($dbfunction->classname != $function['classname']) {
00866             $dbfunction->classname = $function['classname'];
00867             $update = true;
00868         }
00869         if ($dbfunction->methodname != $function['methodname']) {
00870             $dbfunction->methodname = $function['methodname'];
00871             $update = true;
00872         }
00873         if ($dbfunction->classpath != $function['classpath']) {
00874             $dbfunction->classpath = $function['classpath'];
00875             $update = true;
00876         }
00877         $functioncapabilities = key_exists('capabilities', $function)?$function['capabilities']:'';
00878         if ($dbfunction->capabilities != $functioncapabilities) {
00879             $dbfunction->capabilities = $functioncapabilities;
00880             $update = true;
00881         }
00882         if ($update) {
00883             $DB->update_record('external_functions', $dbfunction);
00884         }
00885     }
00886     foreach ($functions as $fname => $function) {
00887         $dbfunction = new stdClass();
00888         $dbfunction->name       = $fname;
00889         $dbfunction->classname  = $function['classname'];
00890         $dbfunction->methodname = $function['methodname'];
00891         $dbfunction->classpath  = empty($function['classpath']) ? null : $function['classpath'];
00892         $dbfunction->component  = $component;
00893         $dbfunction->capabilities = key_exists('capabilities', $function)?$function['capabilities']:'';
00894         $dbfunction->id = $DB->insert_record('external_functions', $dbfunction);
00895     }
00896     unset($functions);
00897 
00898     // now deal with services
00899     $dbservices = $DB->get_records('external_services', array('component'=>$component));
00900     foreach ($dbservices as $dbservice) {
00901         if (empty($services[$dbservice->name])) {
00902             $DB->delete_records('external_services_functions', array('externalserviceid'=>$dbservice->id));
00903             $DB->delete_records('external_services_users', array('externalserviceid'=>$dbservice->id));
00904             $DB->delete_records('external_services', array('id'=>$dbservice->id));
00905             continue;
00906         }
00907         $service = $services[$dbservice->name];
00908         unset($services[$dbservice->name]);
00909         $service['enabled'] = empty($service['enabled']) ? 0 : $service['enabled'];
00910         $service['requiredcapability'] = empty($service['requiredcapability']) ? null : $service['requiredcapability'];
00911         $service['restrictedusers'] = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers'];
00912         $service['downloadfiles'] = !isset($service['downloadfiles']) ? 0 : $service['downloadfiles'];
00913         $service['shortname'] = !isset($service['shortname']) ? null : $service['shortname'];
00914 
00915         $update = false;
00916         if ($dbservice->requiredcapability != $service['requiredcapability']) {
00917             $dbservice->requiredcapability = $service['requiredcapability'];
00918             $update = true;
00919         }
00920         if ($dbservice->restrictedusers != $service['restrictedusers']) {
00921             $dbservice->restrictedusers = $service['restrictedusers'];
00922             $update = true;
00923         }
00924         if ($dbservice->downloadfiles != $service['downloadfiles']) {
00925             $dbservice->downloadfiles = $service['downloadfiles'];
00926             $update = true;
00927         }
00928         //if shortname is not a PARAM_ALPHANUMEXT, fail (tested here for service update and creation)
00929         if (isset($service['shortname']) and
00930                 (clean_param($service['shortname'], PARAM_ALPHANUMEXT) != $service['shortname'])) {
00931             throw new moodle_exception('installserviceshortnameerror', 'webservice', '', $service['shortname']);
00932         }
00933         if ($dbservice->shortname != $service['shortname']) {
00934             //check that shortname is unique
00935             if (isset($service['shortname'])) { //we currently accepts multiple shortname == null
00936                 $existingservice = $DB->get_record('external_services',
00937                         array('shortname' => $service['shortname']));
00938                 if (!empty($existingservice)) {
00939                     throw new moodle_exception('installexistingserviceshortnameerror', 'webservice', '', $service['shortname']);
00940                 }
00941             }
00942             $dbservice->shortname = $service['shortname'];
00943             $update = true;
00944         }
00945         if ($update) {
00946             $DB->update_record('external_services', $dbservice);
00947         }
00948 
00949         $functions = $DB->get_records('external_services_functions', array('externalserviceid'=>$dbservice->id));
00950         foreach ($functions as $function) {
00951             $key = array_search($function->functionname, $service['functions']);
00952             if ($key === false) {
00953                 $DB->delete_records('external_services_functions', array('id'=>$function->id));
00954             } else {
00955                 unset($service['functions'][$key]);
00956             }
00957         }
00958         foreach ($service['functions'] as $fname) {
00959             $newf = new stdClass();
00960             $newf->externalserviceid = $dbservice->id;
00961             $newf->functionname      = $fname;
00962             $DB->insert_record('external_services_functions', $newf);
00963         }
00964         unset($functions);
00965     }
00966     foreach ($services as $name => $service) {
00967         //check that shortname is unique
00968         if (isset($service['shortname'])) { //we currently accepts multiple shortname == null
00969             $existingservice = $DB->get_record('external_services',
00970                     array('shortname' => $service['shortname']));
00971             if (!empty($existingservice)) {
00972                 throw new moodle_exception('installserviceshortnameerror', 'webservice');
00973             }
00974         }
00975 
00976         $dbservice = new stdClass();
00977         $dbservice->name               = $name;
00978         $dbservice->enabled            = empty($service['enabled']) ? 0 : $service['enabled'];
00979         $dbservice->requiredcapability = empty($service['requiredcapability']) ? null : $service['requiredcapability'];
00980         $dbservice->restrictedusers    = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers'];
00981         $dbservice->downloadfiles      = !isset($service['downloadfiles']) ? 0 : $service['downloadfiles'];
00982         $dbservice->shortname          = !isset($service['shortname']) ? null : $service['shortname'];
00983         $dbservice->component          = $component;
00984         $dbservice->timecreated        = time();
00985         $dbservice->id = $DB->insert_record('external_services', $dbservice);
00986         foreach ($service['functions'] as $fname) {
00987             $newf = new stdClass();
00988             $newf->externalserviceid = $dbservice->id;
00989             $newf->functionname      = $fname;
00990             $DB->insert_record('external_services_functions', $newf);
00991         }
00992     }
00993 }
00994 
01000 function external_delete_descriptions($component) {
01001     global $DB;
01002 
01003     $params = array($component);
01004 
01005     $DB->delete_records_select('external_services_users', "externalserviceid IN (SELECT id FROM {external_services} WHERE component = ?)", $params);
01006     $DB->delete_records_select('external_services_functions', "externalserviceid IN (SELECT id FROM {external_services} WHERE component = ?)", $params);
01007     $DB->delete_records('external_services', array('component'=>$component));
01008     $DB->delete_records('external_functions', array('component'=>$component));
01009 }
01010 
01014 function upgrade_handle_exception($ex, $plugin = null) {
01015     global $CFG;
01016 
01017     // rollback everything, we need to log all upgrade problems
01018     abort_all_db_transactions();
01019 
01020     $info = get_exception_info($ex);
01021 
01022     // First log upgrade error
01023     upgrade_log(UPGRADE_LOG_ERROR, $plugin, 'Exception: ' . get_class($ex), $info->message, $info->backtrace);
01024 
01025     // Always turn on debugging - admins need to know what is going on
01026     $CFG->debug = DEBUG_DEVELOPER;
01027 
01028     default_exception_handler($ex, true, $plugin);
01029 }
01030 
01041 function upgrade_log($type, $plugin, $info, $details=null, $backtrace=null) {
01042     global $DB, $USER, $CFG;
01043 
01044     if (empty($plugin)) {
01045         $plugin = 'core';
01046     }
01047 
01048     list($plugintype, $pluginname) = normalize_component($plugin);
01049     $component = is_null($pluginname) ? $plugintype : $plugintype . '_' . $pluginname;
01050 
01051     $backtrace = format_backtrace($backtrace, true);
01052 
01053     $currentversion = null;
01054     $targetversion  = null;
01055 
01056     //first try to find out current version number
01057     if ($plugintype === 'core') {
01058         //main
01059         $currentversion = $CFG->version;
01060 
01061         $version = null;
01062         include("$CFG->dirroot/version.php");
01063         $targetversion = $version;
01064 
01065     } else if ($plugintype === 'mod') {
01066         try {
01067             $currentversion = $DB->get_field('modules', 'version', array('name'=>$pluginname));
01068             $currentversion = ($currentversion === false) ? null : $currentversion;
01069         } catch (Exception $ignored) {
01070         }
01071         $cd = get_component_directory($component);
01072         if (file_exists("$cd/version.php")) {
01073             $module = new stdClass();
01074             $module->version = null;
01075             include("$cd/version.php");
01076             $targetversion = $module->version;
01077         }
01078 
01079     } else if ($plugintype === 'block') {
01080         try {
01081             if ($block = $DB->get_record('block', array('name'=>$pluginname))) {
01082                 $currentversion = $block->version;
01083             }
01084         } catch (Exception $ignored) {
01085         }
01086         $cd = get_component_directory($component);
01087         if (file_exists("$cd/version.php")) {
01088             $plugin = new stdClass();
01089             $plugin->version = null;
01090             include("$cd/version.php");
01091             $targetversion = $plugin->version;
01092         }
01093 
01094     } else {
01095         $pluginversion = get_config($component, 'version');
01096         if (!empty($pluginversion)) {
01097             $currentversion = $pluginversion;
01098         }
01099         $cd = get_component_directory($component);
01100         if (file_exists("$cd/version.php")) {
01101             $plugin = new stdClass();
01102             $plugin->version = null;
01103             include("$cd/version.php");
01104             $targetversion = $plugin->version;
01105         }
01106     }
01107 
01108     $log = new stdClass();
01109     $log->type          = $type;
01110     $log->plugin        = $component;
01111     $log->version       = $currentversion;
01112     $log->targetversion = $targetversion;
01113     $log->info          = $info;
01114     $log->details       = $details;
01115     $log->backtrace     = $backtrace;
01116     $log->userid        = $USER->id;
01117     $log->timemodified  = time();
01118     try {
01119         $DB->insert_record('upgrade_log', $log);
01120     } catch (Exception $ignored) {
01121         // possible during install or 2.0 upgrade
01122     }
01123 }
01124 
01133 function upgrade_started($preinstall=false) {
01134     global $CFG, $DB, $PAGE, $OUTPUT;
01135 
01136     static $started = false;
01137 
01138     if ($preinstall) {
01139         ignore_user_abort(true);
01140         upgrade_setup_debug(true);
01141 
01142     } else if ($started) {
01143         upgrade_set_timeout(120);
01144 
01145     } else {
01146         if (!CLI_SCRIPT and !$PAGE->headerprinted) {
01147             $strupgrade  = get_string('upgradingversion', 'admin');
01148             $PAGE->set_pagelayout('maintenance');
01149             upgrade_init_javascript();
01150             $PAGE->set_title($strupgrade.' - Moodle '.$CFG->target_release);
01151             $PAGE->set_heading($strupgrade);
01152             $PAGE->navbar->add($strupgrade);
01153             $PAGE->set_cacheable(false);
01154             echo $OUTPUT->header();
01155         }
01156 
01157         ignore_user_abort(true);
01158         register_shutdown_function('upgrade_finished_handler');
01159         upgrade_setup_debug(true);
01160         set_config('upgraderunning', time()+300);
01161         $started = true;
01162     }
01163 }
01164 
01168 function upgrade_finished_handler() {
01169     upgrade_finished();
01170 }
01171 
01180 function upgrade_finished($continueurl=null) {
01181     global $CFG, $DB, $OUTPUT;
01182 
01183     if (!empty($CFG->upgraderunning)) {
01184         unset_config('upgraderunning');
01185         upgrade_setup_debug(false);
01186         ignore_user_abort(false);
01187         if ($continueurl) {
01188             echo $OUTPUT->continue_button($continueurl);
01189             echo $OUTPUT->footer();
01190             die;
01191         }
01192     }
01193 }
01194 
01199 function upgrade_setup_debug($starting) {
01200     global $CFG, $DB;
01201 
01202     static $originaldebug = null;
01203 
01204     if ($starting) {
01205         if ($originaldebug === null) {
01206             $originaldebug = $DB->get_debug();
01207         }
01208         if (!empty($CFG->upgradeshowsql)) {
01209             $DB->set_debug(true);
01210         }
01211     } else {
01212         $DB->set_debug($originaldebug);
01213     }
01214 }
01215 
01216 function print_upgrade_separator() {
01217     if (!CLI_SCRIPT) {
01218         echo '<hr />';
01219     }
01220 }
01221 
01227 function print_upgrade_part_start($plugin, $installation, $verbose) {
01228     global $OUTPUT;
01229     if (empty($plugin) or $plugin == 'moodle') {
01230         upgrade_started($installation); // does not store upgrade running flag yet
01231         if ($verbose) {
01232             echo $OUTPUT->heading(get_string('coresystem'));
01233         }
01234     } else {
01235         upgrade_started();
01236         if ($verbose) {
01237             echo $OUTPUT->heading($plugin);
01238         }
01239     }
01240     if ($installation) {
01241         if (empty($plugin) or $plugin == 'moodle') {
01242             // no need to log - log table not yet there ;-)
01243         } else {
01244             upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting plugin installation');
01245         }
01246     } else {
01247         if (empty($plugin) or $plugin == 'moodle') {
01248             upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting core upgrade');
01249         } else {
01250             upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Starting plugin upgrade');
01251         }
01252     }
01253 }
01254 
01260 function print_upgrade_part_end($plugin, $installation, $verbose) {
01261     global $OUTPUT;
01262     upgrade_started();
01263     if ($installation) {
01264         if (empty($plugin) or $plugin == 'moodle') {
01265             upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Core installed');
01266         } else {
01267             upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Plugin installed');
01268         }
01269     } else {
01270         if (empty($plugin) or $plugin == 'moodle') {
01271             upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Core upgraded');
01272         } else {
01273             upgrade_log(UPGRADE_LOG_NORMAL, $plugin, 'Plugin upgraded');
01274         }
01275     }
01276     if ($verbose) {
01277         echo $OUTPUT->notification(get_string('success'), 'notifysuccess');
01278         print_upgrade_separator();
01279     }
01280 }
01281 
01286 function upgrade_init_javascript() {
01287     global $PAGE;
01288     // scroll to the end of each upgrade page so that ppl see either error or continue button,
01289     // no need to scroll continuously any more, it is enough to jump to end once the footer is printed ;-)
01290     $js = "window.scrollTo(0, 5000000);";
01291     $PAGE->requires->js_init_code($js);
01292 }
01293 
01299 function upgrade_language_pack($lang = null) {
01300     global $CFG;
01301 
01302     if (!empty($CFG->skiplangupgrade)) {
01303         return;
01304     }
01305 
01306     if (!file_exists("$CFG->dirroot/$CFG->admin/tool/langimport/lib.php")) {
01307         // weird, somebody uninstalled the import utility
01308         return;
01309     }
01310 
01311     if (!$lang) {
01312         $lang = current_language();
01313     }
01314 
01315     if (!get_string_manager()->translation_exists($lang)) {
01316         return;
01317     }
01318 
01319     get_string_manager()->reset_caches();
01320 
01321     if ($lang === 'en') {
01322         return;  // Nothing to do
01323     }
01324 
01325     upgrade_started(false);
01326 
01327     require_once("$CFG->dirroot/$CFG->admin/tool/langimport/lib.php");
01328     tool_langimport_preupgrade_update($lang);
01329 
01330     get_string_manager()->reset_caches();
01331 
01332     print_upgrade_separator();
01333 }
01334 
01341 function install_core($version, $verbose) {
01342     global $CFG, $DB;
01343 
01344     try {
01345         set_time_limit(600);
01346         print_upgrade_part_start('moodle', true, $verbose); // does not store upgrade running flag
01347 
01348         $DB->get_manager()->install_from_xmldb_file("$CFG->libdir/db/install.xml");
01349         upgrade_started();     // we want the flag to be stored in config table ;-)
01350 
01351         // set all core default records and default settings
01352         require_once("$CFG->libdir/db/install.php");
01353         xmldb_main_install(); // installs the capabilities too
01354 
01355         // store version
01356         upgrade_main_savepoint(true, $version, false);
01357 
01358         // Continue with the installation
01359         log_update_descriptions('moodle');
01360         external_update_descriptions('moodle');
01361         events_update_definition('moodle');
01362         message_update_providers('moodle');
01363 
01364         // Write default settings unconditionally
01365         admin_apply_default_settings(NULL, true);
01366 
01367         print_upgrade_part_end(null, true, $verbose);
01368     } catch (exception $ex) {
01369         upgrade_handle_exception($ex);
01370     }
01371 }
01372 
01379 function upgrade_core($version, $verbose) {
01380     global $CFG;
01381 
01382     raise_memory_limit(MEMORY_EXTRA);
01383 
01384     require_once($CFG->libdir.'/db/upgrade.php');    // Defines upgrades
01385 
01386     try {
01387         // Reset caches before any output
01388         purge_all_caches();
01389 
01390         // Upgrade current language pack if we can
01391         upgrade_language_pack();
01392 
01393         print_upgrade_part_start('moodle', false, $verbose);
01394 
01395         // one time special local migration pre 2.0 upgrade script
01396         if ($CFG->version < 2007101600) {
01397             $pre20upgradefile = "$CFG->dirroot/local/upgrade_pre20.php";
01398             if (file_exists($pre20upgradefile)) {
01399                 set_time_limit(0);
01400                 require($pre20upgradefile);
01401                 // reset upgrade timeout to default
01402                 upgrade_set_timeout();
01403             }
01404         }
01405 
01406         $result = xmldb_main_upgrade($CFG->version);
01407         if ($version > $CFG->version) {
01408             // store version if not already there
01409             upgrade_main_savepoint($result, $version, false);
01410         }
01411 
01412         // perform all other component upgrade routines
01413         update_capabilities('moodle');
01414         log_update_descriptions('moodle');
01415         external_update_descriptions('moodle');
01416         events_update_definition('moodle');
01417         message_update_providers('moodle');
01418 
01419         // Reset caches again, just to be sure
01420         purge_all_caches();
01421 
01422         // Clean up contexts - more and more stuff depends on existence of paths and contexts
01423         context_helper::cleanup_instances();
01424         context_helper::create_instances(null, false);
01425         context_helper::build_all_paths(false);
01426         $syscontext = context_system::instance();
01427         $syscontext->mark_dirty();
01428 
01429         print_upgrade_part_end('moodle', false, $verbose);
01430     } catch (Exception $ex) {
01431         upgrade_handle_exception($ex);
01432     }
01433 }
01434 
01440 function upgrade_noncore($verbose) {
01441     global $CFG;
01442 
01443     raise_memory_limit(MEMORY_EXTRA);
01444 
01445     // upgrade all plugins types
01446     try {
01447         $plugintypes = get_plugin_types();
01448         foreach ($plugintypes as $type=>$location) {
01449             upgrade_plugins($type, 'print_upgrade_part_start', 'print_upgrade_part_end', $verbose);
01450         }
01451     } catch (Exception $ex) {
01452         upgrade_handle_exception($ex);
01453     }
01454 }
01455 
01460 function core_tables_exist() {
01461     global $DB;
01462 
01463     if (!$tables = $DB->get_tables() ) {    // No tables yet at all.
01464         return false;
01465 
01466     } else {                                 // Check for missing main tables
01467         $mtables = array('config', 'course', 'groupings'); // some tables used in 1.9 and 2.0, preferable something from the start and end of install.xml
01468         foreach ($mtables as $mtable) {
01469             if (!in_array($mtable, $tables)) {
01470                 return false;
01471             }
01472         }
01473         return true;
01474     }
01475 }
01476 
01483 function upgrade_plugin_mnet_functions($component) {
01484     global $DB, $CFG;
01485 
01486     list($type, $plugin) = explode('_', $component);
01487     $path = get_plugin_directory($type, $plugin);
01488 
01489     $publishes = array();
01490     $subscribes = array();
01491     if (file_exists($path . '/db/mnet.php')) {
01492         require_once($path . '/db/mnet.php'); // $publishes comes from this file
01493     }
01494     if (empty($publishes)) {
01495         $publishes = array(); // still need this to be able to disable stuff later
01496     }
01497     if (empty($subscribes)) {
01498         $subscribes = array(); // still need this to be able to disable stuff later
01499     }
01500 
01501     static $servicecache = array();
01502 
01503     // rekey an array based on the rpc method for easy lookups later
01504     $publishmethodservices = array();
01505     $subscribemethodservices = array();
01506     foreach($publishes as $servicename => $service) {
01507         if (is_array($service['methods'])) {
01508             foreach($service['methods'] as $methodname) {
01509                 $service['servicename'] = $servicename;
01510                 $publishmethodservices[$methodname][] = $service;
01511             }
01512         }
01513     }
01514 
01515     // Disable functions that don't exist (any more) in the source
01516     // Should these be deleted? What about their permissions records?
01517     foreach ($DB->get_records('mnet_rpc', array('pluginname'=>$plugin, 'plugintype'=>$type), 'functionname ASC ') as $rpc) {
01518         if (!array_key_exists($rpc->functionname, $publishmethodservices) && $rpc->enabled) {
01519             $DB->set_field('mnet_rpc', 'enabled', 0, array('id' => $rpc->id));
01520         } else if (array_key_exists($rpc->functionname, $publishmethodservices) && !$rpc->enabled) {
01521             $DB->set_field('mnet_rpc', 'enabled', 1, array('id' => $rpc->id));
01522         }
01523     }
01524 
01525     // reflect all the services we're publishing and save them
01526     require_once($CFG->dirroot . '/lib/zend/Zend/Server/Reflection.php');
01527     static $cachedclasses = array(); // to store reflection information in
01528     foreach ($publishes as $service => $data) {
01529         $f = $data['filename'];
01530         $c = $data['classname'];
01531         foreach ($data['methods'] as $method) {
01532             $dataobject = new stdClass();
01533             $dataobject->plugintype  = $type;
01534             $dataobject->pluginname  = $plugin;
01535             $dataobject->enabled     = 1;
01536             $dataobject->classname   = $c;
01537             $dataobject->filename    = $f;
01538 
01539             if (is_string($method)) {
01540                 $dataobject->functionname = $method;
01541 
01542             } else if (is_array($method)) { // wants to override file or class
01543                 $dataobject->functionname = $method['method'];
01544                 $dataobject->classname     = $method['classname'];
01545                 $dataobject->filename      = $method['filename'];
01546             }
01547             $dataobject->xmlrpcpath = $type.'/'.$plugin.'/'.$dataobject->filename.'/'.$method;
01548             $dataobject->static = false;
01549 
01550             require_once($path . '/' . $dataobject->filename);
01551             $functionreflect = null; // slightly different ways to get this depending on whether it's a class method or a function
01552             if (!empty($dataobject->classname)) {
01553                 if (!class_exists($dataobject->classname)) {
01554                     throw new moodle_exception('installnosuchmethod', 'mnet', '', (object)array('method' => $dataobject->functionname, 'class' => $dataobject->classname));
01555                 }
01556                 $key = $dataobject->filename . '|' . $dataobject->classname;
01557                 if (!array_key_exists($key, $cachedclasses)) { // look to see if we've already got a reflection object
01558                     try {
01559                         $cachedclasses[$key] = Zend_Server_Reflection::reflectClass($dataobject->classname);
01560                     } catch (Zend_Server_Reflection_Exception $e) { // catch these and rethrow them to something more helpful
01561                         throw new moodle_exception('installreflectionclasserror', 'mnet', '', (object)array('method' => $dataobject->functionname, 'class' => $dataobject->classname, 'error' => $e->getMessage()));
01562                     }
01563                 }
01564                 $r =& $cachedclasses[$key];
01565                 if (!$r->hasMethod($dataobject->functionname)) {
01566                     throw new moodle_exception('installnosuchmethod', 'mnet', '', (object)array('method' => $dataobject->functionname, 'class' => $dataobject->classname));
01567                 }
01568                 // stupid workaround for zend not having a getMethod($name) function
01569                 $ms = $r->getMethods();
01570                 foreach ($ms as $m) {
01571                     if ($m->getName() == $dataobject->functionname) {
01572                         $functionreflect = $m;
01573                         break;
01574                     }
01575                 }
01576                 $dataobject->static = (int)$functionreflect->isStatic();
01577             } else {
01578                 if (!function_exists($dataobject->functionname)) {
01579                     throw new moodle_exception('installnosuchfunction', 'mnet', '', (object)array('method' => $dataobject->functionname, 'file' => $dataobject->filename));
01580                 }
01581                 try {
01582                     $functionreflect = Zend_Server_Reflection::reflectFunction($dataobject->functionname);
01583                 } catch (Zend_Server_Reflection_Exception $e) { // catch these and rethrow them to something more helpful
01584                     throw new moodle_exception('installreflectionfunctionerror', 'mnet', '', (object)array('method' => $dataobject->functionname, '' => $dataobject->filename, 'error' => $e->getMessage()));
01585                 }
01586             }
01587             $dataobject->profile =  serialize(admin_mnet_method_profile($functionreflect));
01588             $dataobject->help = $functionreflect->getDescription();
01589 
01590             if ($record_exists = $DB->get_record('mnet_rpc', array('xmlrpcpath'=>$dataobject->xmlrpcpath))) {
01591                 $dataobject->id      = $record_exists->id;
01592                 $dataobject->enabled = $record_exists->enabled;
01593                 $DB->update_record('mnet_rpc', $dataobject);
01594             } else {
01595                 $dataobject->id = $DB->insert_record('mnet_rpc', $dataobject, true);
01596             }
01597 
01598             // TODO this API versioning must be reworked, here the recently processed method
01599             // sets the service API which may not be correct
01600             foreach ($publishmethodservices[$dataobject->functionname] as $service) {
01601                 if ($serviceobj = $DB->get_record('mnet_service', array('name'=>$service['servicename']))) {
01602                     $serviceobj->apiversion = $service['apiversion'];
01603                     $DB->update_record('mnet_service', $serviceobj);
01604                 } else {
01605                     $serviceobj = new stdClass();
01606                     $serviceobj->name        = $service['servicename'];
01607                     $serviceobj->description = empty($service['description']) ? '' : $service['description'];
01608                     $serviceobj->apiversion  = $service['apiversion'];
01609                     $serviceobj->offer       = 1;
01610                     $serviceobj->id          = $DB->insert_record('mnet_service', $serviceobj);
01611                 }
01612                 $servicecache[$service['servicename']] = $serviceobj;
01613                 if (!$DB->record_exists('mnet_service2rpc', array('rpcid'=>$dataobject->id, 'serviceid'=>$serviceobj->id))) {
01614                     $obj = new stdClass();
01615                     $obj->rpcid = $dataobject->id;
01616                     $obj->serviceid = $serviceobj->id;
01617                     $DB->insert_record('mnet_service2rpc', $obj, true);
01618                 }
01619             }
01620         }
01621     }
01622     // finished with methods we publish, now do subscribable methods
01623     foreach($subscribes as $service => $methods) {
01624         if (!array_key_exists($service, $servicecache)) {
01625             if (!$serviceobj = $DB->get_record('mnet_service', array('name' =>  $service))) {
01626                 debugging("TODO: skipping unknown service $service - somebody needs to fix MDL-21993");
01627                 continue;
01628             }
01629             $servicecache[$service] = $serviceobj;
01630         } else {
01631             $serviceobj = $servicecache[$service];
01632         }
01633         foreach ($methods as $method => $xmlrpcpath) {
01634             if (!$rpcid = $DB->get_field('mnet_remote_rpc', 'id', array('xmlrpcpath'=>$xmlrpcpath))) {
01635                 $remoterpc = (object)array(
01636                     'functionname' => $method,
01637                     'xmlrpcpath' => $xmlrpcpath,
01638                     'plugintype' => $type,
01639                     'pluginname' => $plugin,
01640                     'enabled'    => 1,
01641                 );
01642                 $rpcid = $remoterpc->id = $DB->insert_record('mnet_remote_rpc', $remoterpc, true);
01643             }
01644             if (!$DB->record_exists('mnet_remote_service2rpc', array('rpcid'=>$rpcid, 'serviceid'=>$serviceobj->id))) {
01645                 $obj = new stdClass();
01646                 $obj->rpcid = $rpcid;
01647                 $obj->serviceid = $serviceobj->id;
01648                 $DB->insert_record('mnet_remote_service2rpc', $obj, true);
01649             }
01650             $subscribemethodservices[$method][] = $service;
01651         }
01652     }
01653 
01654     foreach ($DB->get_records('mnet_remote_rpc', array('pluginname'=>$plugin, 'plugintype'=>$type), 'functionname ASC ') as $rpc) {
01655         if (!array_key_exists($rpc->functionname, $subscribemethodservices) && $rpc->enabled) {
01656             $DB->set_field('mnet_remote_rpc', 'enabled', 0, array('id' => $rpc->id));
01657         } else if (array_key_exists($rpc->functionname, $subscribemethodservices) && !$rpc->enabled) {
01658             $DB->set_field('mnet_remote_rpc', 'enabled', 1, array('id' => $rpc->id));
01659         }
01660     }
01661 
01662     return true;
01663 }
01664 
01672 function admin_mnet_method_profile(Zend_Server_Reflection_Function_Abstract $function) {
01673     $proto = array_pop($function->getPrototypes());
01674     $ret = $proto->getReturnValue();
01675     $profile = array(
01676         'parameters' =>  array(),
01677         'return'     =>  array(
01678             'type'        => $ret->getType(),
01679             'description' => $ret->getDescription(),
01680         ),
01681     );
01682     foreach ($proto->getParameters() as $p) {
01683         $profile['parameters'][] = array(
01684             'name' => $p->getName(),
01685             'type' => $p->getType(),
01686             'description' => $p->getDescription(),
01687         );
01688     }
01689     return $profile;
01690 }
 All Data Structures Namespaces Files Functions Variables Enumerations