MDL-41437 rework plugin_manager caching and version info in blocks and modules

This patch includes:

* version column removed from modules table, now using standard config, this allows decimal version for modules
* version column removed from block table, now using standard config, this allows decimal version for blocks
* module version.php can safely use $plugins instead of module
* new plugin_manager bulk caching, this should help with MUC performance when logged in as admin
* all missing plugins are now in plugin overview (previously only blocks and modules)
* simplified code and improved coding style
* reworked plugin_manager unit tests - now using real plugins instead of mocks
* unit tests now fail if any plugin does not contain proper version.php file
* allow uninstall of deleted filters
This commit is contained in:
Petr Škoda 2013-09-14 23:57:21 +02:00
parent 81881cb9d6
commit bde002b81a
50 changed files with 1601 additions and 1940 deletions

View file

@ -222,21 +222,25 @@ function upgrade_main_savepoint($result, $version, $allowabort=true) {
function upgrade_mod_savepoint($result, $version, $modname, $allowabort=true) {
global $DB;
$component = 'mod_'.$modname;
if (!$result) {
throw new upgrade_exception("mod_$modname", $version);
throw new upgrade_exception($component, $version);
}
$dbversion = $DB->get_field('config_plugins', 'value', array('plugin'=>$component, 'name'=>'version'));
if (!$module = $DB->get_record('modules', array('name'=>$modname))) {
print_error('modulenotexist', 'debug', '', $modname);
}
if ($module->version >= $version) {
if ($dbversion >= $version) {
// something really wrong is going on in upgrade script
throw new downgrade_exception("mod_$modname", $module->version, $version);
throw new downgrade_exception($component, $dbversion, $version);
}
$module->version = $version;
$DB->update_record('modules', $module);
upgrade_log(UPGRADE_LOG_NORMAL, "mod_$modname", 'Upgrade savepoint reached');
set_config('version', $version, $component);
upgrade_log(UPGRADE_LOG_NORMAL, $component, 'Upgrade savepoint reached');
// reset upgrade timeout to default
upgrade_set_timeout();
@ -262,21 +266,25 @@ function upgrade_mod_savepoint($result, $version, $modname, $allowabort=true) {
function upgrade_block_savepoint($result, $version, $blockname, $allowabort=true) {
global $DB;
$component = 'block_'.$blockname;
if (!$result) {
throw new upgrade_exception("block_$blockname", $version);
throw new upgrade_exception($component, $version);
}
$dbversion = $DB->get_field('config_plugins', 'value', array('plugin'=>$component, 'name'=>'version'));
if (!$block = $DB->get_record('block', array('name'=>$blockname))) {
print_error('blocknotexist', 'debug', '', $blockname);
}
if ($block->version >= $version) {
if ($dbversion >= $version) {
// something really wrong is going on in upgrade script
throw new downgrade_exception("block_$blockname", $block->version, $version);
throw new downgrade_exception($component, $dbversion, $version);
}
$block->version = $version;
$DB->update_record('block', $block);
upgrade_log(UPGRADE_LOG_NORMAL, "block_$blockname", 'Upgrade savepoint reached');
set_config('version', $version, $component);
upgrade_log(UPGRADE_LOG_NORMAL, $component, 'Upgrade savepoint reached');
// reset upgrade timeout to default
upgrade_set_timeout();
@ -301,16 +309,19 @@ function upgrade_block_savepoint($result, $version, $blockname, $allowabort=true
* @return void
*/
function upgrade_plugin_savepoint($result, $version, $type, $plugin, $allowabort=true) {
global $DB;
$component = $type.'_'.$plugin;
if (!$result) {
throw new upgrade_exception($component, $version);
}
$installedversion = get_config($component, 'version');
if ($installedversion >= $version) {
$dbversion = $DB->get_field('config_plugins', 'value', array('plugin'=>$component, 'name'=>'version'));
if ($dbversion >= $version) {
// Something really wrong is going on in the upgrade script
throw new downgrade_exception($component, $installedversion, $version);
throw new downgrade_exception($component, $dbversion, $version);
}
set_config('version', $version, $component);
upgrade_log(UPGRADE_LOG_NORMAL, $component, 'Upgrade savepoint reached');
@ -338,6 +349,7 @@ function upgrade_stale_php_files_present() {
$someexamplesofremovedfiles = array(
// removed in 2.6dev
'/admin/block.php',
'/admin/oacleanup.php',
// removed in 2.5dev
'/backup/lib.php',
@ -402,12 +414,10 @@ function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
}
$plugin = new stdClass();
$module = new stdClass(); // Prevent some notices when plugin placed in wrong directory.
$plugin->version = null;
$module = $plugin; // Prevent some notices when plugin placed in wrong directory.
require($fullplug.'/version.php'); // defines $plugin with version etc
if (!isset($plugin->version) and isset($module->version)) {
$plugin = $module;
}
unset($module);
// if plugin tells us it's full name we may check the location
if (isset($plugin->component)) {
@ -425,7 +435,6 @@ function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
$plugin->name = $plug;
$plugin->fullname = $component;
if (!empty($plugin->requires)) {
if ($plugin->requires > $CFG->version) {
throw new upgrade_requires_exception($component, $plugin->version, $CFG->version, $plugin->requires);
@ -457,7 +466,7 @@ function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
}
}
$installedversion = get_config($plugin->fullname, 'version');
$installedversion = $DB->get_field('config_plugins', 'value', array('name'=>'version', 'plugin'=>$component)); // No caching!
if (empty($installedversion)) { // new installation
$startcallback($component, true, $verbose);
@ -503,7 +512,7 @@ function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
$result = true;
}
$installedversion = get_config($plugin->fullname, 'version');
$installedversion = $DB->get_field('config_plugins', 'value', array('name'=>'version', 'plugin'=>$component)); // No caching!
if ($installedversion < $plugin->version) {
// store version if not already there
upgrade_plugin_savepoint($result, $plugin->version, $type, $plug, false);
@ -516,6 +525,7 @@ function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
events_update_definition($component);
message_update_providers($component);
if ($type === 'message') {
// Ugly hack!
message_update_processors($plug);
}
upgrade_plugin_mnet_functions($component);
@ -555,36 +565,34 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
throw new plugin_defective_exception($component, 'Missing version.php');
}
$module = new stdClass();
$plugin = new stdClass(); // Prevent some notices when plugin placed in wrong directory.
require($fullmod .'/version.php'); // defines $module with version etc
if (!isset($module->version) and isset($plugin->version)) {
$module = $plugin;
}
$plugin = new stdClass();
$plugin->version = null;
$module = $plugin;
require($fullmod .'/version.php'); // Defines $module/$plugin with version etc.
$plugin = clone($module);
unset($module->version);
unset($module->component);
unset($module->dependencies);
unset($module->release);
// if plugin tells us it's full name we may check the location
if (isset($module->component)) {
if ($module->component !== $component) {
if (isset($plugin->component)) {
if ($plugin->component !== $component) {
$current = str_replace($CFG->dirroot, '$CFG->dirroot', $fullmod);
$expected = str_replace($CFG->dirroot, '$CFG->dirroot', core_component::get_component_directory($module->component));
$expected = str_replace($CFG->dirroot, '$CFG->dirroot', core_component::get_component_directory($plugin->component));
throw new plugin_misplaced_exception($component, $expected, $current);
}
}
if (empty($module->version)) {
if (isset($module->version)) {
// Version is empty but is set - it means its value is 0 or ''. Let us skip such module.
// This is intended for developers so they can work on the early stages of the module.
continue;
}
if (empty($plugin->version)) {
// Version must be always set now!
throw new plugin_defective_exception($component, 'Missing version value in version.php');
}
if (!empty($module->requires)) {
if ($module->requires > $CFG->version) {
throw new upgrade_requires_exception($component, $module->version, $CFG->version, $module->requires);
} else if ($module->requires < 2010000000) {
if (!empty($plugin->requires)) {
if ($plugin->requires > $CFG->version) {
throw new upgrade_requires_exception($component, $plugin->version, $CFG->version, $plugin->requires);
} else if ($plugin->requires < 2010000000) {
throw new plugin_defective_exception($component, 'Plugin is not compatible with Moodle 2.x or later.');
}
}
@ -600,7 +608,7 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
$module->name = $mod; // The name MUST match the directory
$currmodule = $DB->get_record('modules', array('name'=>$module->name));
$installedversion = $DB->get_field('config_plugins', 'value', array('name'=>'version', 'plugin'=>$component)); // No caching!
if (file_exists($fullmod.'/db/install.php')) {
if (get_config($module->name, 'installrunning')) {
@ -622,7 +630,7 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
}
}
if (empty($currmodule->version)) {
if (empty($installedversion)) {
$startcallback($component, true, $verbose);
/// Execute install.xml (XMLDB) - must be present in all modules
@ -630,6 +638,7 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
/// Add record into modules table - may be needed in install.php already
$module->id = $DB->insert_record('modules', $module);
upgrade_mod_savepoint(true, $plugin->version, $module->name, false);
/// Post installation hook - optional
if (file_exists("$fullmod/db/install.php")) {
@ -651,22 +660,23 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
$endcallback($component, true, $verbose);
} else if ($currmodule->version < $module->version) {
} else if ($installedversion < $plugin->version) {
/// If versions say that we need to upgrade but no upgrade files are available, notify and continue
$startcallback($component, false, $verbose);
if (is_readable($fullmod.'/db/upgrade.php')) {
require_once($fullmod.'/db/upgrade.php'); // defines new upgrading function
$newupgrade_function = 'xmldb_'.$module->name.'_upgrade';
$result = $newupgrade_function($currmodule->version, $module);
$result = $newupgrade_function($installedversion, $module);
} else {
$result = true;
}
$installedversion = $DB->get_field('config_plugins', 'value', array('name'=>'version', 'plugin'=>$component)); // No caching!
$currmodule = $DB->get_record('modules', array('name'=>$module->name));
if ($currmodule->version < $module->version) {
if ($installedversion < $plugin->version) {
// store version if not already there
upgrade_mod_savepoint($result, $module->version, $mod, false);
upgrade_mod_savepoint($result, $plugin->version, $mod, false);
}
// update cron flag if needed
@ -684,8 +694,8 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
$endcallback($component, false, $verbose);
} else if ($currmodule->version > $module->version) {
throw new downgrade_exception($component, $currmodule->version, $module->version);
} else if ($installedversion > $plugin->version) {
throw new downgrade_exception($component, $installedversion, $plugin->version);
}
}
}
@ -731,24 +741,30 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
throw new plugin_defective_exception('block/'.$blockname, 'Missing version.php file.');
}
$plugin = new stdClass();
$module = new stdClass(); // Prevent some notices when module placed in wrong directory.
$plugin->version = NULL;
$plugin->version = null;
$plugin->cron = 0;
$module = $plugin; // Prevent some notices when module placed in wrong directory.
include($fullblock.'/version.php');
if (!isset($plugin->version) and isset($module->version)) {
$plugin = $module;
}
$block = $plugin;
unset($module);
$block = clone($plugin);
unset($block->version);
unset($block->component);
unset($block->dependencies);
unset($block->release);
// if plugin tells us it's full name we may check the location
if (isset($block->component)) {
if ($block->component !== $component) {
if (isset($plugin->component)) {
if ($plugin->component !== $component) {
$current = str_replace($CFG->dirroot, '$CFG->dirroot', $fullblock);
$expected = str_replace($CFG->dirroot, '$CFG->dirroot', core_component::get_component_directory($block->component));
$expected = str_replace($CFG->dirroot, '$CFG->dirroot', core_component::get_component_directory($plugin->component));
throw new plugin_misplaced_exception($component, $expected, $current);
}
}
if (empty($plugin->version)) {
throw new plugin_defective_exception($component, 'Missing block version.');
}
if (!empty($plugin->requires)) {
if ($plugin->requires > $CFG->version) {
throw new upgrade_requires_exception($component, $plugin->version, $CFG->version, $plugin->requires);
@ -778,11 +794,7 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
$block->name = $blockname; // The name MUST match the directory
if (empty($block->version)) {
throw new plugin_defective_exception($component, 'Missing block version.');
}
$currblock = $DB->get_record('block', array('name'=>$block->name));
$installedversion = $DB->get_field('config_plugins', 'value', array('name'=>'version', 'plugin'=>$component)); // No caching!
if (file_exists($fullblock.'/db/install.php')) {
if (get_config('block_'.$blockname, 'installrunning')) {
@ -804,7 +816,7 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
}
}
if (empty($currblock->version)) { // block not installed yet, so install it
if (empty($installedversion)) { // block not installed yet, so install it
$conflictblock = array_search($blocktitle, $blocktitles);
if ($conflictblock !== false) {
// Duplicate block titles are not allowed, they confuse people
@ -817,6 +829,7 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
$DB->get_manager()->install_from_xmldb_file($fullblock.'/db/install.xml');
}
$block->id = $DB->insert_record('block', $block);
upgrade_block_savepoint(true, $plugin->version, $block->name, false);
if (file_exists($fullblock.'/db/install.php')) {
require_once($fullblock.'/db/install.php');
@ -839,21 +852,22 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
$endcallback($component, true, $verbose);
} else if ($currblock->version < $block->version) {
} else if ($installedversion < $plugin->version) {
$startcallback($component, false, $verbose);
if (is_readable($fullblock.'/db/upgrade.php')) {
require_once($fullblock.'/db/upgrade.php'); // defines new upgrading function
$newupgrade_function = 'xmldb_block_'.$blockname.'_upgrade';
$result = $newupgrade_function($currblock->version, $block);
$result = $newupgrade_function($installedversion, $block);
} else {
$result = true;
}
$installedversion = $DB->get_field('config_plugins', 'value', array('name'=>'version', 'plugin'=>$component)); // No caching!
$currblock = $DB->get_record('block', array('name'=>$block->name));
if ($currblock->version < $block->version) {
if ($installedversion < $plugin->version) {
// store version if not already there
upgrade_block_savepoint($result, $block->version, $block->name, false);
upgrade_block_savepoint($result, $plugin->version, $block->name, false);
}
if ($currblock->cron != $block->cron) {
@ -871,8 +885,8 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
$endcallback($component, false, $verbose);
} else if ($currblock->version > $block->version) {
throw new downgrade_exception($component, $currblock->version, $block->version);
} else if ($installedversion > $plugin->version) {
throw new downgrade_exception($component, $installedversion, $plugin->version);
}
}
@ -1178,35 +1192,6 @@ function upgrade_log($type, $plugin, $info, $details=null, $backtrace=null) {
include("$CFG->dirroot/version.php");
$targetversion = $version;
} else if ($plugintype === 'mod') {
try {
$currentversion = $DB->get_field('modules', 'version', array('name'=>$pluginname));
$currentversion = ($currentversion === false) ? null : $currentversion;
} catch (Exception $ignored) {
}
$cd = core_component::get_component_directory($component);
if (file_exists("$cd/version.php")) {
$module = new stdClass();
$module->version = null;
include("$cd/version.php");
$targetversion = $module->version;
}
} else if ($plugintype === 'block') {
try {
if ($block = $DB->get_record('block', array('name'=>$pluginname))) {
$currentversion = $block->version;
}
} catch (Exception $ignored) {
}
$cd = core_component::get_component_directory($component);
if (file_exists("$cd/version.php")) {
$plugin = new stdClass();
$plugin->version = null;
include("$cd/version.php");
$targetversion = $plugin->version;
}
} else {
$pluginversion = get_config($component, 'version');
if (!empty($pluginversion)) {
@ -1216,6 +1201,7 @@ function upgrade_log($type, $plugin, $info, $details=null, $backtrace=null) {
if (file_exists("$cd/version.php")) {
$plugin = new stdClass();
$plugin->version = null;
$module = $plugin;
include("$cd/version.php");
$targetversion = $plugin->version;
}