MDL-17458 upgrade logging implemented + a lot more refactoring + exceptions implemented in install/upgrade code + lang pack cleanup + some more improvements
This commit is contained in:
@@ -18,70 +18,6 @@ define('BLOCKS_PINNED_BOTH',2);
|
||||
require_once($CFG->libdir.'/pagelib.php');
|
||||
require_once($CFG->dirroot.'/course/lib.php'); // needed to solve all those: Call to undefined function: print_recent_activity() when adding Recent Activity
|
||||
|
||||
// Returns false if this block is incompatible with the current version of Moodle.
|
||||
function block_is_compatible($blockname) {
|
||||
global $CFG;
|
||||
|
||||
$file = @file($CFG->dirroot.'/blocks/'.$blockname.'/block_'.$blockname.'.php'); // ignore errors when file does not exist
|
||||
if(empty($file)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
foreach($file as $line) {
|
||||
// If you find MoodleBlock (appearing in the class declaration) it's not compatible
|
||||
if(strpos($line, 'MoodleBlock')) {
|
||||
return false;
|
||||
}
|
||||
// But if we find a { it means the class declaration is over, so it's compatible
|
||||
else if(strpos($line, '{')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Returns the case-sensitive name of the class' constructor function. This includes both
|
||||
// PHP5- and PHP4-style constructors. If no appropriate constructor can be found, returns NULL.
|
||||
// If there is no such class, returns boolean false.
|
||||
function get_class_constructor($classname) {
|
||||
// Caching
|
||||
static $constructors = array();
|
||||
|
||||
if(!class_exists($classname)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tests indicate this doesn't hurt even in PHP5.
|
||||
$classname = strtolower($classname);
|
||||
|
||||
// Return cached value, if exists
|
||||
if(isset($constructors[$classname])) {
|
||||
return $constructors[$classname];
|
||||
}
|
||||
|
||||
// Get a list of methods. After examining several different ways of
|
||||
// doing the check, (is_callable, method_exists, function_exists etc)
|
||||
// it seems that this is the most reliable one.
|
||||
$methods = get_class_methods($classname);
|
||||
|
||||
// PHP5 constructor?
|
||||
if(phpversion() >= '5') {
|
||||
if(in_array('__construct', $methods)) {
|
||||
return $constructors[$classname] = '__construct';
|
||||
}
|
||||
}
|
||||
|
||||
// If we have PHP5 but no magic constructor, we have to lowercase the methods
|
||||
$methods = array_map('strtolower', $methods);
|
||||
|
||||
if(in_array($classname, $methods)) {
|
||||
return $constructors[$classname] = $classname;
|
||||
}
|
||||
|
||||
return $constructors[$classname] = NULL;
|
||||
}
|
||||
|
||||
//This function retrieves a method-defined property of a class WITHOUT instantiating an object
|
||||
function block_method_result($blockname, $method, $param = NULL) {
|
||||
if(!block_load_class($blockname)) {
|
||||
@@ -1069,227 +1005,4 @@ function blocks_repopulate_page($page) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//This function finds all available blocks and install them
|
||||
//into blocks table or do all the upgrade process if newer
|
||||
function upgrade_blocks_plugins() {
|
||||
global $CFG, $interactive, $DB, $SITE;
|
||||
|
||||
require_once($CFG->dirroot .'/blocks/moodleblock.class.php');
|
||||
|
||||
$updated_blocks = false;
|
||||
|
||||
$blocktitles = array();
|
||||
$invalidblocks = array();
|
||||
$validblocks = array();
|
||||
$notices = array();
|
||||
|
||||
//Count the number of blocks in db
|
||||
$blockcount = $DB->count_records('block');
|
||||
//If there isn't records. This is the first install, so I remember it
|
||||
$first_install = ($blockcount == 0);
|
||||
|
||||
if (!$blocks = get_list_of_plugins('blocks') ) {
|
||||
print_error('noblocks', 'debug');
|
||||
}
|
||||
|
||||
if (!class_exists('block_base')) {
|
||||
print_error('noblockbase');
|
||||
}
|
||||
|
||||
foreach ($blocks as $blockname) {
|
||||
|
||||
if ($blockname == 'NEWBLOCK') { // Someone has unzipped the template, ignore it
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!block_is_compatible($blockname)) {
|
||||
// This is an old-style block
|
||||
//$notices[] = 'Block '. $blockname .' is not compatible with the current version of Mooodle and needs to be updated by a programmer.';
|
||||
$invalidblocks[] = $blockname;
|
||||
continue;
|
||||
}
|
||||
|
||||
$fullblock = $CFG->dirroot .'/blocks/'. $blockname;
|
||||
|
||||
if ( is_readable($fullblock.'/block_'.$blockname.'.php')) {
|
||||
include_once($fullblock.'/block_'.$blockname.'.php');
|
||||
} else {
|
||||
$notices[] = 'Block '. $blockname .': '. $fullblock .'/block_'. $blockname .'.php was not readable';
|
||||
continue;
|
||||
}
|
||||
|
||||
$newupgrade = false;
|
||||
if ( @is_dir($fullblock .'/db/')) {
|
||||
if ( @is_readable($fullblock .'/db/upgrade.php')) {
|
||||
include_once($fullblock .'/db/upgrade.php'); // defines new upgrading function
|
||||
$newupgrade = true;
|
||||
}
|
||||
}
|
||||
|
||||
$classname = 'block_'.$blockname;
|
||||
if(!class_exists($classname)) {
|
||||
$notices[] = 'Block '. $blockname .': '. $classname .' not implemented';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Here is the place to see if the block implements a constructor (old style),
|
||||
// an init() function (new style) or nothing at all (error time).
|
||||
|
||||
$constructor = get_class_constructor($classname);
|
||||
if(empty($constructor)) {
|
||||
// No constructor
|
||||
$notices[] = 'Block '. $blockname .': class does not have a constructor';
|
||||
$invalidblocks[] = $blockname;
|
||||
continue;
|
||||
}
|
||||
|
||||
$block = new stdClass; // This may be used to update the db below
|
||||
$blockobj = new $classname; // This is what we 'll be testing
|
||||
|
||||
// Inherits from block_base?
|
||||
if(!is_subclass_of($blockobj, 'block_base')) {
|
||||
$notices[] = 'Block '. $blockname .': class does not inherit from block_base';
|
||||
continue;
|
||||
}
|
||||
|
||||
// OK, it's as we all hoped. For further tests, the object will do them itself.
|
||||
if(!$blockobj->_self_test()) {
|
||||
$notices[] = 'Block '. $blockname .': self test failed';
|
||||
continue;
|
||||
}
|
||||
$block->version = $blockobj->get_version();
|
||||
|
||||
if (!isset($block->version)) {
|
||||
$notices[] = 'Block '. $blockname .': has no version support. It must be updated by a programmer.';
|
||||
continue;
|
||||
}
|
||||
|
||||
$block->name = $blockname; // The name MUST match the directory
|
||||
$blocktitle = $blockobj->get_title();
|
||||
|
||||
if ($currblock = $DB->get_record('block', array('name'=>$block->name))) {
|
||||
if ($currblock->version == $block->version) {
|
||||
// do nothing
|
||||
} else if ($currblock->version < $block->version) {
|
||||
$updated_blocks = true;
|
||||
upgrade_started();
|
||||
|
||||
print_heading('New version of '.$blocktitle.' ('.$block->name.') exists');
|
||||
@set_time_limit(0); // To allow slow databases to complete the long SQL
|
||||
|
||||
/// Run de old and new upgrade functions for the module
|
||||
$newupgrade_function = 'xmldb_block_' . $block->name .'_upgrade';
|
||||
|
||||
/// Then, the new function if exists and the old one was ok
|
||||
$newupgrade_status = true;
|
||||
if ($newupgrade && function_exists($newupgrade_function)) {
|
||||
$newupgrade_status = $newupgrade_function($currblock->version, $block);
|
||||
} else if ($newupgrade) {
|
||||
notify ('Upgrade function ' . $newupgrade_function . ' was not available in ' .
|
||||
$fullblock . '/db/upgrade.php');
|
||||
}
|
||||
/// Now analyze upgrade results
|
||||
if ($newupgrade_status) { // No upgrading failed
|
||||
|
||||
// Set the block cron on upgrade
|
||||
$block->cron = !empty($blockobj->cron) ? $blockobj->cron : 0;
|
||||
|
||||
// OK so far, now update the block record
|
||||
$block->id = $currblock->id;
|
||||
if (!$DB->update_record('block', $block)) {
|
||||
print_error('cannotupdateblock', '', '', $block->name);
|
||||
}
|
||||
$component = 'block/'.$block->name;
|
||||
if (!update_capabilities($component)) {
|
||||
print_error('nopermissiontoupdateblock', '', '', $block->name);
|
||||
}
|
||||
|
||||
// Update events
|
||||
events_update_definition($component);
|
||||
|
||||
// Update message providers
|
||||
require_once($CFG->libdir .'/messagelib.php'); // Messagelib functions
|
||||
message_update_providers($component);
|
||||
|
||||
notify(get_string('blocksuccess', '', $blocktitle), 'notifysuccess');
|
||||
} else {
|
||||
notify('Upgrading block '. $block->name .' from '. $currblock->version .' to '. $block->version .' FAILED!');
|
||||
}
|
||||
print_upgrade_separator();
|
||||
} else {
|
||||
print_error('cannotdowngrade', 'debug', '', (object)array('oldversion'=>$currblock->version, 'newversion'=>$block->version));
|
||||
}
|
||||
|
||||
} else { // block not installed yet, so install it
|
||||
|
||||
// If it allows multiples, start with it enabled
|
||||
if ($blockobj->instance_allow_multiple()) {
|
||||
$block->multiple = 1;
|
||||
}
|
||||
|
||||
// Set the block cron on install
|
||||
$block->cron = !empty($blockobj->cron) ? $blockobj->cron : 0;
|
||||
|
||||
// [pj] Normally this would be inline in the if, but we need to
|
||||
// check for NULL (necessary for 4.0.5 <= PHP < 4.2.0)
|
||||
$conflictblock = array_search($blocktitle, $blocktitles);
|
||||
if ($conflictblock !== false && $conflictblock !== NULL) {
|
||||
// Duplicate block titles are not allowed, they confuse people
|
||||
// AND PHP's associative arrays ;)
|
||||
print_error('blocknameconflict', '', '', (object)array('name'=>$block->name, 'conflict'=>$conflictblock));
|
||||
}
|
||||
$updated_blocks = true;
|
||||
upgrade_started();
|
||||
print_heading($block->name);
|
||||
@set_time_limit(0); // To allow slow databases to complete the long SQL
|
||||
|
||||
/// Both old .sql files and new install.xml are supported
|
||||
/// but we priorize install.xml (XMLDB) if present
|
||||
if (file_exists($fullblock . '/db/install.xml')) {
|
||||
$DB->get_manager()->install_from_xmldb_file($fullblock . '/db/install.xml'); //New method
|
||||
}
|
||||
$block->id = $DB->insert_record('block', $block);
|
||||
$blockobj->after_install();
|
||||
$component = 'block/'.$block->name;
|
||||
update_capabilities($component);
|
||||
|
||||
// Update events
|
||||
events_update_definition($component);
|
||||
|
||||
// Update message providers
|
||||
require_once($CFG->libdir .'/messagelib.php'); // Messagelib functions
|
||||
message_update_providers($component);
|
||||
|
||||
notify(get_string('blocksuccess', '', $blocktitle), 'notifysuccess');
|
||||
print_upgrade_separator();
|
||||
}
|
||||
|
||||
$blocktitles[$block->name] = $blocktitle;
|
||||
}
|
||||
|
||||
if(!empty($notices)) {
|
||||
foreach($notices as $notice) {
|
||||
notify($notice);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, if we are in the first_install of BLOCKS setup frontpage and admin page blocks
|
||||
if ($first_install) {
|
||||
require_once($CFG->dirroot.'/'.$CFG->admin.'/pagelib.php');
|
||||
//Iterate over each course - there should be only site course here now
|
||||
if ($courses = $DB->get_records('course')) {
|
||||
foreach ($courses as $course) {
|
||||
$page = page_create_object(PAGE_COURSE_VIEW, $course->id);
|
||||
blocks_repopulate_page($page);
|
||||
}
|
||||
}
|
||||
|
||||
page_map_class(PAGE_ADMIN, 'page_admin');
|
||||
$page = page_create_object(PAGE_ADMIN, 0); // there must be some id number
|
||||
blocks_repopulate_page($page);
|
||||
}
|
||||
|
||||
return $updated_blocks;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user