diff --git a/admin/auth.php b/admin/auth.php
index 934acd371ef01..4dc0a0d15d78e 100644
--- a/admin/auth.php
+++ b/admin/auth.php
@@ -10,6 +10,7 @@
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
+require_once($CFG->libdir.'/pluginlib.php');
require_login();
require_capability('moodle/site:config', context_system::instance());
@@ -52,6 +53,7 @@
set_config('registerauth', '');
}
session_gc(); // remove stale sessions
+ plugin_manager::reset_caches();
break;
case 'enable':
@@ -62,6 +64,7 @@
set_config('auth', implode(',', $authsenabled));
}
session_gc(); // remove stale sessions
+ plugin_manager::reset_caches();
break;
case 'down':
diff --git a/admin/block.php b/admin/block.php
deleted file mode 100644
index 59938ec1fef94..0000000000000
--- a/admin/block.php
+++ /dev/null
@@ -1,76 +0,0 @@
-libdir.'/adminlib.php');
-
- $blockid = required_param('block', PARAM_INT);
-
- if(!$blockrecord = blocks_get_record($blockid)) {
- print_error('blockdoesnotexist', 'error');
- }
-
- admin_externalpage_setup('blocksetting'.$blockrecord->name);
-
- $block = block_instance($blockrecord->name);
- if($block === false) {
- print_error('blockcannotinistantiate', 'error');
- }
-
- // Define the data we're going to silently include in the instance config form here,
- // so we can strip them from the submitted data BEFORE handling it.
- $hiddendata = array(
- 'block' => $blockid,
- 'sesskey' => sesskey()
- );
-
- /// If data submitted, then process and store.
-
- if ($config = data_submitted()) {
-
- if (!confirm_sesskey()) {
- print_error('confirmsesskeybad', 'error');
- }
- if(!$block->has_config()) {
- print_error('blockcannotconfig', 'error');
- }
- $remove = array_keys($hiddendata);
- foreach($remove as $item) {
- unset($config->$item);
- }
- $block->config_save($config);
- redirect("$CFG->wwwroot/$CFG->admin/blocks.php", get_string("changessaved"), 1);
- exit;
- }
-
- /// Otherwise print the form.
-
- $strmanageblocks = get_string('manageblocks');
- $strblockname = $block->get_title();
-
- echo $OUTPUT->header();
-
- echo $OUTPUT->heading($strblockname);
-
- echo $OUTPUT->notification('This block still uses an old-style config_global.html file. ' .
- 'It must be updated by a developer to use a settings.php file.');
-
- echo $OUTPUT->box(get_string('configwarning', 'admin'), 'generalbox boxwidthnormal boxaligncenter');
- echo '
';
-
- echo '
';
- echo $OUTPUT->footer();
-
-
diff --git a/admin/blocks.php b/admin/blocks.php
index 6a2d31efd6e03..1e37dd26d737a 100644
--- a/admin/blocks.php
+++ b/admin/blocks.php
@@ -5,6 +5,7 @@
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
+ require_once($CFG->libdir.'/pluginlib.php');
admin_externalpage_setup('manageblocks');
@@ -29,9 +30,6 @@
$strprotect = get_string('blockprotect', 'admin');
$strunprotect = get_string('blockunprotect', 'admin');
- // Purge all caches related to blocks administration.
- cache::make('core', 'plugininfo_block')->purge();
-
/// If data submitted, then process and store.
if (!empty($hide) && confirm_sesskey()) {
@@ -39,6 +37,7 @@
print_error('blockdoesnotexist', 'error');
}
$DB->set_field('block', 'visible', '0', array('id'=>$block->id)); // Hide block
+ plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
@@ -47,6 +46,7 @@
print_error('blockdoesnotexist', 'error');
}
$DB->set_field('block', 'visible', '1', array('id'=>$block->id)); // Show block
+ plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
@@ -120,12 +120,13 @@
foreach ($blocknames as $blockid=>$strblockname) {
$block = $blocks[$blockid];
$blockname = $block->name;
+ $dbversion = get_config('block_'.$block->name, 'version');
if (!file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
$blockobject = false;
$strblockname = ''.$strblockname.' ('.get_string('missingfromdisk').')';
$plugin = new stdClass();
- $plugin->version = $block->version;
+ $plugin->version = $dbversion;
} else {
$plugin = new stdClass();
@@ -186,10 +187,10 @@
$class = ' class="dimmed_text"'; // Leading space required!
}
- if ($block->version == $plugin->version) {
- $version = $block->version;
+ if ($dbversion == $plugin->version) {
+ $version = $dbversion;
} else {
- $version = "$block->version ($plugin->version)";
+ $version = "$dbversion ($plugin->version)";
}
if (!$blockobject) {
diff --git a/admin/courseformats.php b/admin/courseformats.php
index 7ea15e86d165b..f86c4becc8cae 100644
--- a/admin/courseformats.php
+++ b/admin/courseformats.php
@@ -53,11 +53,13 @@
print_error('cannotdisableformat', 'error', $return);
}
set_config('disabled', 1, 'format_'. $formatname);
+ plugin_manager::reset_caches();
}
break;
case 'enable':
if (!$formatplugins[$formatname]->is_enabled()) {
unset_config('disabled', 'format_'. $formatname);
+ plugin_manager::reset_caches();
}
break;
case 'up':
diff --git a/admin/editors.php b/admin/editors.php
index da846faf2f846..50ee7a510864c 100644
--- a/admin/editors.php
+++ b/admin/editors.php
@@ -7,6 +7,7 @@
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
+require_once($CFG->libdir.'/pluginlib.php');
$action = required_param('action', PARAM_ALPHANUMEXT);
$editor = required_param('editor', PARAM_PLUGIN);
@@ -93,6 +94,7 @@
}
set_config('texteditors', implode(',', $active_editors));
+plugin_manager::reset_caches();
if ($return) {
redirect ($returnurl);
diff --git a/admin/enrol.php b/admin/enrol.php
index 59f77c53aee3c..14a7649f8992f 100644
--- a/admin/enrol.php
+++ b/admin/enrol.php
@@ -27,6 +27,7 @@
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
+require_once($CFG->libdir.'/pluginlib.php');
$action = required_param('action', PARAM_ALPHANUMEXT);
$enrol = required_param('enrol', PARAM_PLUGIN);
@@ -50,6 +51,7 @@
case 'disable':
unset($enabled[$enrol]);
set_config('enrol_plugins_enabled', implode(',', array_keys($enabled)));
+ plugin_manager::reset_caches();
$syscontext->mark_dirty(); // resets all enrol caches
break;
@@ -60,6 +62,7 @@
$enabled = array_keys($enabled);
$enabled[] = $enrol;
set_config('enrol_plugins_enabled', implode(',', $enabled));
+ plugin_manager::reset_caches();
$syscontext->mark_dirty(); // resets all enrol caches
break;
diff --git a/admin/filters.php b/admin/filters.php
index 6c585046ab9bc..334dc719fbf3d 100644
--- a/admin/filters.php
+++ b/admin/filters.php
@@ -33,6 +33,7 @@
require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->libdir . '/adminlib.php');
+ require_once($CFG->libdir . '/pluginlib.php');
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
$filterpath = optional_param('filterpath', '', PARAM_SAFEDIR);
@@ -44,9 +45,6 @@
$returnurl = "$CFG->wwwroot/$CFG->admin/filters.php";
admin_externalpage_setup('managefilters');
- // Purge all caches related to filter administration.
- cache::make('core', 'plugininfo_filter')->purge();
-
$filters = filter_get_global_states();
// In case any new filters have been installed, but not put in the table yet.
@@ -59,7 +57,7 @@
/// Process actions ============================================================
if ($action) {
- if (!isset($filters[$filterpath]) && !isset($newfilters[$filterpath])) {
+ if ($action !== 'delete' and !isset($filters[$filterpath]) and !isset($newfilters[$filterpath])) {
throw new moodle_exception('filternotinstalled', 'error', $returnurl, $filterpath);
}
@@ -138,6 +136,7 @@
// Reset caches and return
if ($action) {
+ plugin_manager::reset_caches();
reset_text_filters_cache();
redirect($returnurl);
}
diff --git a/admin/localplugins.php b/admin/localplugins.php
index be09151a5a342..8286e96fee5fd 100644
--- a/admin/localplugins.php
+++ b/admin/localplugins.php
@@ -30,6 +30,7 @@
require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
+require_once($CFG->libdir.'/pluginlib.php');
admin_externalpage_setup('managelocalplugins');
diff --git a/admin/message.php b/admin/message.php
index 88e8f856617ca..67a60b08b8812 100644
--- a/admin/message.php
+++ b/admin/message.php
@@ -24,6 +24,7 @@
require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->dirroot . '/message/lib.php');
require_once($CFG->libdir.'/adminlib.php');
+require_once($CFG->libdir.'/pluginlib.php');
// This is an admin page
admin_externalpage_setup('managemessageoutputs');
@@ -44,6 +45,7 @@
print_error('outputdoesnotexist', 'message');
}
$DB->set_field('message_processors', 'enabled', '0', array('id'=>$processor->id)); // Disable output
+ plugin_manager::reset_caches();
}
if (!empty($enable) && confirm_sesskey()) {
@@ -51,6 +53,7 @@
print_error('outputdoesnotexist', 'message');
}
$DB->set_field('message_processors', 'enabled', '1', array('id'=>$processor->id)); // Enable output
+ plugin_manager::reset_caches();
}
if (!empty($uninstall) && confirm_sesskey()) {
diff --git a/admin/modules.php b/admin/modules.php
index c8f69d45f3798..a964c73dfe4e4 100644
--- a/admin/modules.php
+++ b/admin/modules.php
@@ -5,6 +5,7 @@
require_once('../course/lib.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
+ require_once($CFG->libdir.'/pluginlib.php');
// defines
define('MODULE_TABLE','module_administration_table');
@@ -27,9 +28,6 @@
$stractivitymodule = get_string("activitymodule");
$strshowmodulecourse = get_string('showmodulecourse');
- // Purge all caches related to activity modules administration.
- cache::make('core', 'plugininfo_mod')->purge();
-
/// If data submitted, then process and store.
if (!empty($hide) and confirm_sesskey()) {
@@ -50,6 +48,7 @@
FROM {course_modules}
WHERE visibleold=1 AND module=?)",
array($module->id));
+ plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
@@ -66,6 +65,7 @@
FROM {course_modules}
WHERE visible=1 AND module=?)",
array($module->id));
+ plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
@@ -143,12 +143,12 @@
$visible = "";
$class = "";
}
-
+ $version = get_config('mod_'.$module->name, 'version');
$table->add_data(array(
''.$strmodulename.'',
$countlink,
- ''.$module->version.'',
+ ''.$version.'',
$visible,
$uninstall,
$settings
diff --git a/admin/plagiarism.php b/admin/plagiarism.php
index ace710fd7bde4..d5fc85ae12599 100644
--- a/admin/plagiarism.php
+++ b/admin/plagiarism.php
@@ -29,6 +29,8 @@
require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
+require_once($CFG->libdir.'/pluginlib.php');
+
admin_externalpage_setup('manageplagiarismplugins');
diff --git a/admin/portfolio.php b/admin/portfolio.php
index f5940536139f8..3b460fdce2e7f 100644
--- a/admin/portfolio.php
+++ b/admin/portfolio.php
@@ -4,6 +4,7 @@
require_once($CFG->libdir . '/portfoliolib.php');
require_once($CFG->libdir . '/portfolio/forms.php');
require_once($CFG->libdir . '/adminlib.php');
+require_once($CFG->libdir . '/pluginlib.php');
$portfolio = optional_param('pf', '', PARAM_ALPHANUMEXT);
$action = optional_param('action', '', PARAM_ALPHA);
@@ -43,9 +44,6 @@
$return = true; // direct back to the main page
-// Purge all caches related to portfolio administration.
-cache::make('core', 'plugininfo_portfolio')->purge();
-
/**
* Helper function that generates a moodle_url object
* relevant to the portfolio
@@ -91,6 +89,7 @@ function portfolio_action_url($portfolio) {
} else {
portfolio_static_function($plugin, 'create_instance', $plugin, $fromform->name, $fromform);
}
+ plugin_manager::reset_caches();
$savedstr = get_string('instancesaved', 'portfolio');
redirect($baseurl, $savedstr, 1);
exit;
@@ -119,6 +118,7 @@ function portfolio_action_url($portfolio) {
$instance->set('visible', $visible);
$instance->save();
+ plugin_manager::reset_caches();
$return = true;
} else if ($action == 'delete') {
$instance = portfolio_instance($portfolio);
diff --git a/admin/qbehaviours.php b/admin/qbehaviours.php
index 85f0c8ef9053d..8e98af4237ead 100644
--- a/admin/qbehaviours.php
+++ b/admin/qbehaviours.php
@@ -92,6 +92,7 @@
$disabledbehaviours[] = $disable;
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
}
+ plugin_manager::reset_caches();
redirect($thispageurl);
}
@@ -109,6 +110,7 @@
unset($disabledbehaviours[$key]);
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
}
+ plugin_manager::reset_caches();
redirect($thispageurl);
}
diff --git a/admin/reports.php b/admin/reports.php
index 0a73d226db9ba..879497c5222f6 100644
--- a/admin/reports.php
+++ b/admin/reports.php
@@ -30,6 +30,7 @@
require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
+require_once($CFG->libdir.'/pluginlib.php');
admin_externalpage_setup('managereports');
diff --git a/admin/repository.php b/admin/repository.php
index 8f976cf32228c..05fc7557893ba 100644
--- a/admin/repository.php
+++ b/admin/repository.php
@@ -17,6 +17,7 @@
require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->dirroot . '/repository/lib.php');
require_once($CFG->libdir . '/adminlib.php');
+require_once($CFG->libdir . '/pluginlib.php');
$repository = optional_param('repos', '', PARAM_ALPHANUMEXT);
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
@@ -61,9 +62,6 @@
require_sesskey();
}
-// Purge all caches related to repositories administration.
-cache::make('core', 'plugininfo_repository')->purge();
-
/**
* Helper function that generates a moodle_url object
* relevant to the repository
@@ -151,6 +149,7 @@ function repository_action_url($repository) {
}
if ($success) {
// configs saved
+ plugin_manager::reset_caches();
redirect($baseurl);
} else {
print_error('instancenotsaved', 'repository', $baseurl);
@@ -191,6 +190,7 @@ function repository_action_url($repository) {
print_error('invalidplugin', 'repository', '', $repository);
}
$repositorytype->update_visibility(true);
+ plugin_manager::reset_caches();
$return = true;
} else if ($action == 'hide') {
if (!confirm_sesskey()) {
@@ -201,6 +201,7 @@ function repository_action_url($repository) {
print_error('invalidplugin', 'repository', '', $repository);
}
$repositorytype->update_visibility(false);
+ plugin_manager::reset_caches();
$return = true;
} else if ($action == 'delete') {
$repositorytype = repository::get_type_by_typename($repository);
@@ -211,6 +212,7 @@ function repository_action_url($repository) {
}
if ($repositorytype->delete($downloadcontents)) {
+ plugin_manager::reset_caches();
redirect($baseurl);
} else {
print_error('instancenotdeleted', 'repository', $baseurl);
diff --git a/admin/repositoryinstance.php b/admin/repositoryinstance.php
index b5eab73ffeaba..3def4f3ab5d77 100644
--- a/admin/repositoryinstance.php
+++ b/admin/repositoryinstance.php
@@ -17,6 +17,7 @@
require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->dirroot . '/repository/lib.php');
require_once($CFG->libdir . '/adminlib.php');
+require_once($CFG->libdir . '/pluginlib.php');
require_sesskey();
@@ -102,6 +103,7 @@
$data = data_submitted();
}
if ($success) {
+ plugin_manager::reset_caches();
redirect($parenturl);
} else {
print_error('instancenotsaved', 'repository', $parenturl);
@@ -118,6 +120,7 @@
} else if (!empty($hide)) {
$instance = repository::get_type_by_typename($hide);
$instance->hide();
+ plugin_manager::reset_caches();
$return = true;
} else if (!empty($delete)) {
$instance = repository::get_instance($delete);
@@ -130,6 +133,7 @@
if ($sure) {
if ($instance->delete($downloadcontents)) {
$deletedstr = get_string('instancedeleted', 'repository');
+ plugin_manager::reset_caches();
redirect($parenturl, $deletedstr, 3);
} else {
print_error('instancenotdeleted', 'repository', $parenturl);
diff --git a/backup/converter/moodle1/handlerlib.php b/backup/converter/moodle1/handlerlib.php
index c3df06bec7d59..3973a8bf3fc77 100644
--- a/backup/converter/moodle1/handlerlib.php
+++ b/backup/converter/moodle1/handlerlib.php
@@ -866,9 +866,11 @@ public function process_course_module($data, $raw) {
// host...
$versionfile = $CFG->dirroot.'/mod/'.$data['modulename'].'/version.php';
if (file_exists($versionfile)) {
- $module = new stdClass();
+ $plugin = new stdClass();
+ $plugin->version = null;
+ $module = $plugin;
include($versionfile);
- $data['version'] = $module->version;
+ $data['version'] = $plugin->version;
} else {
$data['version'] = null;
}
diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php
index e2f47f6498c15..ed53da7a5a7e2 100644
--- a/backup/moodle2/backup_stepslib.php
+++ b/backup/moodle2/backup_stepslib.php
@@ -307,6 +307,7 @@ protected function prepare_block_structure($blockstructure) {
class backup_module_structure_step extends backup_structure_step {
protected function define_structure() {
+ global $DB;
// Define each element separated
@@ -339,12 +340,14 @@ protected function define_structure() {
$availinfo->add_child($availabilityfield);
// Set the sources
- $module->set_source_sql('
- SELECT cm.*, m.version, m.name AS modulename, s.id AS sectionid, s.section AS sectionnumber
+ $concat = $DB->sql_concat("'mod_'", 'm.name');
+ $module->set_source_sql("
+ SELECT cm.*, cp.value AS version, m.name AS modulename, s.id AS sectionid, s.section AS sectionnumber
FROM {course_modules} cm
JOIN {modules} m ON m.id = cm.module
+ JOIN {config_plugins} cp ON cp.plugin = $concat AND cp.name = 'version'
JOIN {course_sections} s ON s.id = cm.section
- WHERE cm.id = ?', array(backup::VAR_MODID));
+ WHERE cm.id = ?", array(backup::VAR_MODID));
$availability->set_source_table('course_modules_availability', array('coursemoduleid' => backup::VAR_MODID));
$availabilityfield->set_source_sql('
@@ -1363,7 +1366,7 @@ protected function define_structure() {
}
$blockrec->contextid = $this->task->get_contextid();
// Get the version of the block
- $blockrec->version = $DB->get_field('block', 'version', array('name' => $this->task->get_blockname()));
+ $blockrec->version = get_config('block_'.$this->task->get_blockname(), 'version');
// Define sources
diff --git a/blocks/upgrade.txt b/blocks/upgrade.txt
index 23518050e1335..1a9ad4863dcf7 100644
--- a/blocks/upgrade.txt
+++ b/blocks/upgrade.txt
@@ -1,6 +1,10 @@
This files describes API changes in /blocks/* - activity modules,
information provided here is intended especially for developers.
+=== 2.6 ===
+
+* Deprecated /admin/block.php was removed, make sure blocks are using settings.php instead.
+
=== 2.4 ===
Created new capability 'blocks/xxx:myaddinstance' that determines whether a user can add
diff --git a/cache/locks/file/version.php b/cache/locks/file/version.php
new file mode 100644
index 0000000000000..b7955dab63ff6
--- /dev/null
+++ b/cache/locks/file/version.php
@@ -0,0 +1,30 @@
+.
+
+/**
+ * File locking for the Cache API
+ *
+ * @package cachelock_file
+ * @category cache
+ * @copyright 2012 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$plugin->version = 2013091300; // The current plugin version (Date: YYYYMMDDXX)
+$plugin->requires = 2013091300; // Requires this Moodle version
+$plugin->component = 'cachelock_file'; // Full name of the plugin (used for diagnostics)
diff --git a/filter/manage.php b/filter/manage.php
index 49d80ce1c2757..15b493cde35dd 100644
--- a/filter/manage.php
+++ b/filter/manage.php
@@ -25,6 +25,7 @@
require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->libdir . '/adminlib.php');
+require_once($CFG->libdir . '/pluginlib.php');
$contextid = required_param('contextid',PARAM_INT);
$forfilter = optional_param('filter', '', PARAM_SAFEDIR);
@@ -36,9 +37,6 @@
require_capability('moodle/filter:manage', $context);
$PAGE->set_context($context);
-// Purge all caches related to filter administration.
-cache::make('core', 'plugininfo_filter')->purge();
-
$args = array('contextid'=>$contextid);
$baseurl = new moodle_url('/filter/manage.php', $args);
if (!empty($forfilter)) {
diff --git a/lang/en/cache.php b/lang/en/cache.php
index 2ec0c97bc4c06..40021ed5c781b 100644
--- a/lang/en/cache.php
+++ b/lang/en/cache.php
@@ -51,12 +51,7 @@
$string['cachedef_langmenu'] = 'List of available languages';
$string['cachedef_locking'] = 'Locking';
$string['cachedef_observers'] = 'Event observers';
-$string['cachedef_plugininfo_base'] = 'Plugin info - base';
-$string['cachedef_plugininfo_block'] = 'Plugin info - blocks';
-$string['cachedef_plugininfo_filter'] = 'Plugin info - filters';
-$string['cachedef_plugininfo_mod'] = 'Plugin info - activity modules';
-$string['cachedef_plugininfo_portfolio'] = 'Plugin info - portfolios';
-$string['cachedef_plugininfo_repository'] = 'Plugin info - repositories';
+$string['cachedef_plugin_manager'] = 'Plugin info manager';
$string['cachedef_questiondata'] = 'Question definitions';
$string['cachedef_repositories'] = 'Repositories instances data';
$string['cachedef_string'] = 'Language string cache';
diff --git a/lib/adminlib.php b/lib/adminlib.php
index efcf9a1be1382..7ca212768d93e 100644
--- a/lib/adminlib.php
+++ b/lib/adminlib.php
@@ -298,7 +298,10 @@ function uninstall_plugin($type, $name) {
$DB->delete_records('log_display', array('component' => $component));
// delete the module configuration records
- unset_all_config_for_plugin($pluginname);
+ unset_all_config_for_plugin($component);
+ if ($type === 'mod') {
+ unset_all_config_for_plugin($pluginname);
+ }
// delete message provider
message_provider_uninstall($component);
@@ -375,9 +378,11 @@ function get_component_version($component, $source='installed') {
if (empty($mods[$name]) or !is_readable($mods[$name].'/version.php')) {
return false;
} else {
- $module = new stdclass();
+ $plugin = new stdClass();
+ $plugin->version = null;
+ $module = $plugin;
include($mods[$name].'/version.php');
- return $module->version;
+ return $plugin->version;
}
}
}
diff --git a/lib/classes/component.php b/lib/classes/component.php
index 0e21af390b48a..e193399b316ea 100644
--- a/lib/classes/component.php
+++ b/lib/classes/component.php
@@ -927,17 +927,11 @@ public static function get_all_versions_hash() {
$plugs = self::fetch_plugins($type, $typedir);
}
foreach ($plugs as $plug => $fullplug) {
- if ($type === 'mod') {
- $module = new stdClass();
- $module->version = null;
- include($fullplug.'/version.php');
- $versions[$type.'_'.$plug] = $module->version;
- } else {
- $plugin = new stdClass();
- $plugin->version = null;
- @include($fullplug.'/version.php');
- $versions[$type.'_'.$plug] = $plugin->version;
- }
+ $plugin = new stdClass();
+ $plugin->version = null;
+ $module = $plugin;
+ @include($fullplug.'/version.php');
+ $versions[$type.'_'.$plug] = $plugin->version;
}
}
diff --git a/lib/db/caches.php b/lib/db/caches.php
index 305fdbca82529..0b1a99d45a415 100644
--- a/lib/db/caches.php
+++ b/lib/db/caches.php
@@ -141,58 +141,13 @@
'persistentmaxsize' => 2,
),
- // Cache used by the {@link plugininfo_base} class.
- 'plugininfo_base' => array(
+ // Cache used by the {@link plugin_manager} class.
+ // NOTE: this must be a shared cache.
+ 'plugin_manager' => array(
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => true,
'simpledata' => true,
- 'persistent' => true,
- 'persistentmaxsize' => 2,
- ),
-
- // Cache used by the {@link plugininfo_mod} class.
- 'plugininfo_mod' => array(
- 'mode' => cache_store::MODE_APPLICATION,
- 'simplekeys' => true,
- 'simpledata' => true,
- 'persistent' => true,
- 'persistentmaxsize' => 1,
- ),
-
- // Cache used by the {@link plugininfo_block} class.
- 'plugininfo_block' => array(
- 'mode' => cache_store::MODE_APPLICATION,
- 'simplekeys' => true,
- 'simpledata' => true,
- 'persistent' => true,
- 'persistentmaxsize' => 1,
- ),
-
- // Cache used by the {@link plugininfo_filter} class.
- 'plugininfo_filter' => array(
- 'mode' => cache_store::MODE_APPLICATION,
- 'simplekeys' => true,
- 'simpledata' => true,
- 'persistent' => true,
- 'persistentmaxsize' => 1,
- ),
-
- // Cache used by the {@link plugininfo_repository} class.
- 'plugininfo_repository' => array(
- 'mode' => cache_store::MODE_APPLICATION,
- 'simplekeys' => true,
- 'simpledata' => true,
- 'persistent' => true,
- 'persistentmaxsize' => 1,
- ),
-
- // Cache used by the {@link plugininfo_portfolio} class.
- 'plugininfo_portfolio' => array(
- 'mode' => cache_store::MODE_APPLICATION,
- 'simplekeys' => true,
- 'simpledata' => true,
- 'persistent' => true,
- 'persistentmaxsize' => 1,
+ 'persistent' => false,
),
// Used to store the full tree of course categories
diff --git a/lib/db/install.xml b/lib/db/install.xml
index d79981f92ad3d..8fe1b98babc14 100644
--- a/lib/db/install.xml
+++ b/lib/db/install.xml
@@ -1,5 +1,5 @@
-
@@ -668,7 +668,6 @@
-
@@ -2487,7 +2486,6 @@
-
diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php
index 543d1b3dd6867..4768e85a91aa3 100644
--- a/lib/db/upgrade.php
+++ b/lib/db/upgrade.php
@@ -2450,5 +2450,52 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2013091300.01);
}
+ if ($oldversion < 2013092001.01) {
+ // Force uninstall of deleted tool.
+ if (!file_exists("$CFG->dirroot/$CFG->admin/tool/bloglevelupgrade")) {
+ // Remove capabilities.
+ capabilities_cleanup('tool_bloglevelupgrade');
+ // Remove all other associated config.
+ unset_all_config_for_plugin('tool_bloglevelupgrade');
+ }
+ upgrade_main_savepoint(true, 2013092001.01);
+ }
+
+ if ($oldversion < 2013092001.02) {
+ // Define field version to be dropped from modules.
+ $table = new xmldb_table('modules');
+ $field = new xmldb_field('version');
+
+ // Conditionally launch drop field version.
+ if ($dbman->field_exists($table, $field)) {
+ // Migrate all plugin version info to config_plugins table.
+ $modules = $DB->get_records('modules');
+ foreach ($modules as $module) {
+ set_config('version', $module->version, 'mod_'.$module->name);
+ }
+ unset($modules);
+
+ $dbman->drop_field($table, $field);
+ }
+
+ // Define field version to be dropped from block.
+ $table = new xmldb_table('block');
+ $field = new xmldb_field('version');
+
+ // Conditionally launch drop field version.
+ if ($dbman->field_exists($table, $field)) {
+ $blocks = $DB->get_records('block');
+ foreach ($blocks as $block) {
+ set_config('version', $block->version, 'block_'.$block->name);
+ }
+ unset($blocks);
+
+ $dbman->drop_field($table, $field);
+ }
+
+ // Main savepoint reached.
+ upgrade_main_savepoint(true, 2013092001.02);
+ }
+
return true;
}
diff --git a/lib/editor/atto/lib.php b/lib/editor/atto/lib.php
index f2ec963c1aaad..2b9b8a68c6f39 100644
--- a/lib/editor/atto/lib.php
+++ b/lib/editor/atto/lib.php
@@ -74,25 +74,20 @@ public function supports_repositories() {
* @param null $fpoptions
*/
public function use_editor($elementid, array $options=null, $fpoptions=null) {
- global $PAGE, $CFG;
+ global $PAGE;
$PAGE->requires->yui_module('moodle-editor_atto-editor',
'M.editor_atto.init',
array($this->get_init_params($elementid, $options, $fpoptions)), true);
- require_once($CFG->libdir . '/pluginlib.php');
-
- $pluginman = plugin_manager::instance();
- $plugins = $pluginman->get_subplugins_of_plugin('editor_atto');
- $sortedplugins = array();
+ $plugins = core_component::get_plugin_list('atto');
- foreach ($plugins as $id => $plugin) {
- $sortorder = component_callback($plugin->type . '_' . $plugin->name, 'sort_order', array($elementid));
- $sortedplugins[$sortorder] = $plugin;
+ foreach ($plugins as $name => $fulldir) {
+ $plugins[$name] = component_callback('atto_' . $name, 'sort_order', array($elementid));
}
- ksort($sortedplugins);
- foreach ($sortedplugins as $plugin) {
- component_callback($plugin->type . '_' . $plugin->name, 'init_editor', array($elementid));
+ asort($plugins);
+ foreach ($plugins as $name => $sort) {
+ component_callback('atto_' . $name, 'init_editor', array($elementid));
}
}
diff --git a/lib/editor/tinymce/adminlib.php b/lib/editor/tinymce/adminlib.php
index d30f3bf56890a..2bc6130f06869 100644
--- a/lib/editor/tinymce/adminlib.php
+++ b/lib/editor/tinymce/adminlib.php
@@ -24,8 +24,6 @@
defined('MOODLE_INTERNAL') || die();
-require_once("$CFG->libdir/pluginlib.php");
-
/**
* Editor subplugin info class.
@@ -35,6 +33,34 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class plugininfo_tinymce extends plugininfo_base {
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ $disabledsubplugins = array();
+ $config = get_config('editor_tinymce', 'disabledsubplugins');
+ if ($config) {
+ $config = explode(',', $config);
+ foreach ($config as $sp) {
+ $sp = trim($sp);
+ if ($sp !== '') {
+ $disabledsubplugins[$sp] = $sp;
+ }
+ }
+ }
+
+ $enabled = array();
+ $installed = core_component::get_plugin_list('tinymce');
+ foreach ($installed as $plugin => $fulldir) {
+ if (isset($disabledsubplugins[$plugin])) {
+ continue;
+ }
+ $enabled[$plugin] = $plugin;
+ }
+
+ return $enabled;
+ }
public function is_uninstall_allowed() {
return true;
@@ -59,26 +85,6 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
$ADMIN->add($parentnodename, $settings);
}
}
-
- public function is_enabled() {
- static $disabledsubplugins = null; // TODO: MDL-34344 remove this once get_config() is cached via MUC!
-
- if (is_null($disabledsubplugins)) {
- $disabledsubplugins = array();
- $config = get_config('editor_tinymce', 'disabledsubplugins');
- if ($config) {
- $config = explode(',', $config);
- foreach ($config as $sp) {
- $sp = trim($sp);
- if ($sp !== '') {
- $disabledsubplugins[$sp] = $sp;
- }
- }
- }
- }
-
- return !isset($disabledsubplugins[$this->name]);
- }
}
diff --git a/lib/editor/tinymce/subplugins.php b/lib/editor/tinymce/subplugins.php
index 29236e81fd34b..6eb01c416601d 100644
--- a/lib/editor/tinymce/subplugins.php
+++ b/lib/editor/tinymce/subplugins.php
@@ -24,6 +24,7 @@
require(__DIR__ . '/../../../config.php');
require_once($CFG->libdir.'/adminlib.php');
+require_once($CFG->libdir.'/pluginlib.php');
$disable = optional_param('disable', '', PARAM_PLUGIN);
$enable = optional_param('enable', '', PARAM_PLUGIN);
@@ -61,5 +62,6 @@
}
set_config('disabledsubplugins', implode(',', $disabled), 'editor_tinymce');
+plugin_manager::reset_caches();
redirect($returnurl);
diff --git a/lib/moodlelib.php b/lib/moodlelib.php
index 92091ea16dfc2..ad1e363caa497 100644
--- a/lib/moodlelib.php
+++ b/lib/moodlelib.php
@@ -1589,6 +1589,9 @@ function purge_all_caches() {
theme_reset_all_caches();
get_string_manager()->reset_caches();
core_text::reset_caches();
+ if (class_exists('plugin_manager')) {
+ plugin_manager::reset_caches();
+ }
// Bump up cacherev field for all courses.
try {
diff --git a/lib/pluginlib.php b/lib/pluginlib.php
index cc8ae89267678..9172fc1cd4521 100644
--- a/lib/pluginlib.php
+++ b/lib/pluginlib.php
@@ -61,6 +61,12 @@ class plugin_manager {
protected $pluginsinfo = null;
/** @var array of raw subplugins information */
protected $subpluginsinfo = null;
+ /** @var array list of installed plugins $name=>$version */
+ protected $installedplugins = null;
+ /** @var array list of all enabled plugins $name=>$name */
+ protected $enabledplugins = null;
+ /** @var array list of all enabled plugins $name=>$diskversion */
+ protected $presentplugins = null;
/**
* Direct initiation not allowed, use the factory method {@link self::instance()}
@@ -87,94 +93,273 @@ public static function instance() {
}
/**
- * Reset any caches
+ * Reset all caches.
* @param bool $phpunitreset
*/
public static function reset_caches($phpunitreset = false) {
if ($phpunitreset) {
self::$singletoninstance = null;
+ } else {
+ if (self::$singletoninstance) {
+ self::$singletoninstance->pluginsinfo = null;
+ self::$singletoninstance->subpluginsinfo = null;
+ self::$singletoninstance->installedplugins = null;
+ self::$singletoninstance->enabledplugins = null;
+ self::$singletoninstance->presentplugins = null;
+ }
}
+ $cache = cache::make('core', 'plugin_manager');
+ $cache->purge();
}
/**
* Returns the result of {@link core_component::get_plugin_types()} ordered for humans
*
* @see self::reorder_plugin_types()
- * @param bool $fullpaths false means relative paths from dirroot
* @return array (string)name => (string)location
*/
- public function get_plugin_types($fullpaths = true) {
- return $this->reorder_plugin_types(core_component::get_plugin_types($fullpaths));
+ public function get_plugin_types() {
+ if (func_num_args() > 0) {
+ if (!func_get_arg(0)) {
+ throw coding_exception('plugin_manager->get_plugin_types() does not support relative paths.');
+ }
+ }
+ return $this->reorder_plugin_types(core_component::get_plugin_types());
}
/**
- * Returns list of known plugins of the given type
+ * Load list of installed plugins,
+ * always call before using $this->installedplugins.
*
- * This method returns the subset of the tree returned by {@link self::get_plugins()}.
- * If the given type is not known, empty array is returned.
+ * This method is caching results for all plugins.
+ */
+ protected function load_installed_plugins() {
+ global $DB, $CFG;
+
+ if ($this->installedplugins) {
+ return;
+ }
+
+ if (empty($CFG->version)) {
+ // Nothing installed yet.
+ $this->installedplugins = array();
+ return;
+ }
+
+ $cache = cache::make('core', 'plugin_manager');
+ $installed = $cache->get('installed');
+
+ if (is_array($installed)) {
+ $this->installedplugins = $installed;
+ return;
+ }
+
+ $this->installedplugins = array();
+
+ if ($CFG->version < 2013092001.02) {
+ // We did not upgrade the database yet.
+ $modules = $DB->get_records('modules', array(), 'name ASC', 'id, name, version');
+ foreach ($modules as $module) {
+ $this->installedplugins['mod'][$module->name] = $module->version;
+ }
+ $blocks = $DB->get_records('block', array(), 'name ASC', 'id, name, version');
+ foreach ($blocks as $block) {
+ $this->installedplugins['block'][$block->name] = $block->version;
+ }
+ }
+
+ $versions = $DB->get_records('config_plugins', array('name'=>'version'));
+ foreach ($versions as $version) {
+ $parts = explode('_', $version->plugin, 2);
+ if (!isset($parts[1])) {
+ // Invalid component, there must be at least one "_".
+ continue;
+ }
+ // Do not verify here if plugin type and name are valid.
+ $this->installedplugins[$parts[0]][$parts[1]] = $version->value;
+ }
+
+ foreach ($this->installedplugins as $key => $value) {
+ ksort($this->installedplugins[$key]);
+ }
+
+ $cache->set('installed', $this->installedplugins);
+ }
+
+ /**
+ * Return list of installed plugins of given type.
+ * @param string $type
+ * @return array $name=>$version
+ */
+ public function get_installed_plugins($type) {
+ $this->load_installed_plugins();
+ if (isset($this->installedplugins[$type])) {
+ return $this->installedplugins[$type];
+ }
+ return array();
+ }
+
+ /**
+ * Load list of all enabled plugins,
+ * call before using $this->enabledplugins.
*
- * @param string $type plugin type, e.g. 'mod' or 'workshopallocation'
- * @param bool $disablecache force reload, cache can be used otherwise
- * @return array (string)plugin name (e.g. 'workshop') => corresponding subclass of {@link plugininfo_base}
+ * This method is caching results from individual plugin info classes.
*/
- public function get_plugins_of_type($type, $disablecache=false) {
+ protected function load_enabled_plugins() {
+ global $CFG;
- $plugins = $this->get_plugins($disablecache);
+ if ($this->enabledplugins) {
+ return;
+ }
- if (!isset($plugins[$type])) {
- return array();
+ if (empty($CFG->version)) {
+ $this->enabledplugins = array();
+ return;
}
- return $plugins[$type];
+ $cache = cache::make('core', 'plugin_manager');
+ $enabled = $cache->get('enabled');
+
+ if (is_array($enabled)) {
+ $this->enabledplugins = $enabled;
+ return;
+ }
+
+ $this->enabledplugins = array();
+
+ require_once($CFG->libdir.'/adminlib.php');
+
+ $plugintypes = core_component::get_plugin_types();
+ foreach ($plugintypes as $plugintype => $fulldir) {
+ // Hack: include mod and editor subplugin management classes first,
+ // the adminlib.php is supposed to contain extra admin settings too.
+ $plugininfoclass = 'plugininfo_' . $plugintype;
+ if (!class_exists($plugininfoclass) and file_exists("$fulldir/adminlib.php")) {
+ include_once("$fulldir/adminlib.php");
+ }
+ if (class_exists($plugininfoclass)) {
+ $enabled = $plugininfoclass::get_enabled_plugins();
+ if (!is_array($enabled)) {
+ continue;
+ }
+ $this->enabledplugins[$plugintype] = $enabled;
+ }
+ }
+
+ $cache->set('enabled', $this->enabledplugins);
+ }
+
+ /**
+ * Get list of enabled plugins of given type,
+ * the result may contain missing plugins.
+ *
+ * @param string $type
+ * @return array|null list of enabled plugins of this type, null if unknown
+ */
+ public function get_enabled_plugins($type) {
+ $this->load_enabled_plugins();
+ if (isset($this->enabledplugins[$type])) {
+ return $this->enabledplugins[$type];
+ }
+ return null;
+ }
+
+ /**
+ * Load list of all present plugins - call before using $this->presentplugins.
+ */
+ protected function load_present_plugins() {
+ if ($this->presentplugins) {
+ return;
+ }
+
+ $cache = cache::make('core', 'plugin_manager');
+ $present = $cache->get('present');
+
+ if (is_array($present)) {
+ $this->presentplugins = $present;
+ return;
+ }
+
+ $this->presentplugins = array();
+
+ $plugintypes = core_component::get_plugin_types();
+ foreach ($plugintypes as $type => $typedir) {
+ $plugs = core_component::get_plugin_list($type);
+ foreach ($plugs as $plug => $fullplug) {
+ $plugin = new stdClass();
+ $plugin->version = null;
+ $module = $plugin;
+ @include($fullplug.'/version.php');
+ $this->presentplugins[$type][$plug] = $plugin;
+ }
+ }
+
+ $cache->set('present', $this->presentplugins);
+ }
+
+ /**
+ * Get list of present plugins of given type.
+ *
+ * @param string $type
+ * @return array|null list of presnet plugins $name=>$diskversion, null if unknown
+ */
+ public function get_present_plugins($type) {
+ $this->load_present_plugins();
+ if (isset($this->presentplugins[$type])) {
+ return $this->presentplugins[$type];
+ }
+ return null;
}
/**
* Returns a tree of known plugins and information about them
*
- * @param bool $disablecache force reload, cache can be used otherwise
* @return array 2D array. The first keys are plugin type names (e.g. qtype);
* the second keys are the plugin local name (e.g. multichoice); and
* the values are the corresponding objects extending {@link plugininfo_base}
*/
- public function get_plugins($disablecache=false) {
+ public function get_plugins() {
global $CFG;
- if ($disablecache or is_null($this->pluginsinfo)) {
- // Hack: include mod and editor subplugin management classes first,
- // the adminlib.php is supposed to contain extra admin settings too.
- require_once($CFG->libdir.'/adminlib.php');
- foreach (core_component::get_plugin_types_with_subplugins() as $type => $ignored) {
- foreach (core_component::get_plugin_list($type) as $dir) {
- if (file_exists("$dir/adminlib.php")) {
- include_once("$dir/adminlib.php");
- }
+ if (is_array($this->pluginsinfo)) {
+ return $this->pluginsinfo;
+ }
+
+ $this->pluginsinfo = array();
+
+ // Hack: include mod and editor subplugin management classes first,
+ // the adminlib.php is supposed to contain extra admin settings too.
+ require_once($CFG->libdir.'/adminlib.php');
+ foreach (core_component::get_plugin_types_with_subplugins() as $type => $ignored) {
+ foreach (core_component::get_plugin_list($type) as $dir) {
+ if (file_exists("$dir/adminlib.php")) {
+ include_once("$dir/adminlib.php");
}
}
- $this->pluginsinfo = array();
- $plugintypes = $this->get_plugin_types();
- foreach ($plugintypes as $plugintype => $plugintyperootdir) {
- if (in_array($plugintype, array('base', 'general'))) {
- throw new coding_exception('Illegal usage of reserved word for plugin type');
- }
- if (class_exists('plugininfo_' . $plugintype)) {
- $plugintypeclass = 'plugininfo_' . $plugintype;
- } else {
- $plugintypeclass = 'plugininfo_general';
- }
- if (!in_array('plugininfo_base', class_parents($plugintypeclass))) {
- throw new coding_exception('Class ' . $plugintypeclass . ' must extend plugininfo_base');
- }
- $plugins = call_user_func(array($plugintypeclass, 'get_plugins'), $plugintype, $plugintyperootdir, $plugintypeclass);
- $this->pluginsinfo[$plugintype] = $plugins;
+ }
+ $plugintypes = $this->get_plugin_types();
+ foreach ($plugintypes as $plugintype => $plugintyperootdir) {
+ if (in_array($plugintype, array('base', 'general'))) {
+ throw new coding_exception('Illegal usage of reserved word for plugin type');
+ }
+ if (class_exists('plugininfo_' . $plugintype)) {
+ $plugintypeclass = 'plugininfo_' . $plugintype;
+ } else {
+ $plugintypeclass = 'plugininfo_general';
+ }
+ if (!in_array('plugininfo_base', class_parents($plugintypeclass))) {
+ throw new coding_exception('Class ' . $plugintypeclass . ' must extend plugininfo_base');
}
+ $plugins = $plugintypeclass::get_plugins($plugintype, $plugintyperootdir, $plugintypeclass);
+ $this->pluginsinfo[$plugintype] = $plugins;
+ }
- if (empty($CFG->disableupdatenotifications) and !during_initial_install()) {
- // append the information about available updates provided by {@link available_update_checker()}
- $provider = available_update_checker::instance();
- foreach ($this->pluginsinfo as $plugintype => $plugins) {
- foreach ($plugins as $plugininfoholder) {
- $plugininfoholder->check_available_updates($provider);
- }
+ if (empty($CFG->disableupdatenotifications) and !during_initial_install()) {
+ // append the information about available updates provided by {@link available_update_checker()}
+ $provider = available_update_checker::instance();
+ foreach ($this->pluginsinfo as $plugintype => $plugins) {
+ foreach ($plugins as $plugininfoholder) {
+ $plugininfoholder->check_available_updates($provider);
}
}
}
@@ -183,24 +368,43 @@ public function get_plugins($disablecache=false) {
}
/**
- * Returns list of all known subplugins of the given plugin
+ * Returns list of known plugins of the given type.
+ *
+ * This method returns the subset of the tree returned by {@link self::get_plugins()}.
+ * If the given type is not known, empty array is returned.
+ *
+ * @param string $type plugin type, e.g. 'mod' or 'workshopallocation'
+ * @return array (string)plugin name (e.g. 'workshop') => corresponding subclass of {@link plugininfo_base}
+ */
+ public function get_plugins_of_type($type) {
+
+ $plugins = $this->get_plugins();
+
+ if (!isset($plugins[$type])) {
+ return array();
+ }
+
+ return $plugins[$type];
+ }
+
+ /**
+ * Returns list of all known subplugins of the given plugin.
*
* For plugins that do not provide subplugins (i.e. there is no support for it),
* empty array is returned.
*
* @param string $component full component name, e.g. 'mod_workshop'
- * @param bool $disablecache force reload, cache can be used otherwise
* @return array (string) component name (e.g. 'workshopallocation_random') => subclass of {@link plugininfo_base}
*/
- public function get_subplugins_of_plugin($component, $disablecache=false) {
+ public function get_subplugins_of_plugin($component) {
- $pluginfo = $this->get_plugin_info($component, $disablecache);
+ $pluginfo = $this->get_plugin_info($component);
if (is_null($pluginfo)) {
return array();
}
- $subplugins = $this->get_subplugins($disablecache);
+ $subplugins = $this->get_subplugins();
if (!isset($subplugins[$pluginfo->component])) {
return array();
@@ -221,28 +425,29 @@ public function get_subplugins_of_plugin($component, $disablecache=false) {
* Returns list of plugins that define their subplugins and the information
* about them from the db/subplugins.php file.
*
- * @param bool $disablecache force reload, cache can be used otherwise
* @return array with keys like 'mod_quiz', and values the data from the
* corresponding db/subplugins.php file.
*/
- public function get_subplugins($disablecache=false) {
-
- if ($disablecache or is_null($this->subpluginsinfo)) {
- $this->subpluginsinfo = array();
- foreach (core_component::get_plugin_types_with_subplugins() as $type => $ignored) {
- foreach (core_component::get_plugin_list($type) as $component => $ownerdir) {
- $componentsubplugins = array();
- if (file_exists($ownerdir . '/db/subplugins.php')) {
- $subplugins = array();
- include($ownerdir . '/db/subplugins.php');
- foreach ($subplugins as $subplugintype => $subplugintyperootdir) {
- $subplugin = new stdClass();
- $subplugin->type = $subplugintype;
- $subplugin->typerootdir = $subplugintyperootdir;
- $componentsubplugins[$subplugintype] = $subplugin;
- }
- $this->subpluginsinfo[$type . '_' . $component] = $componentsubplugins;
+ public function get_subplugins() {
+
+ if (is_array($this->subpluginsinfo)) {
+ return $this->subpluginsinfo;
+ }
+
+ $this->subpluginsinfo = array();
+ foreach (core_component::get_plugin_types_with_subplugins() as $type => $ignored) {
+ foreach (core_component::get_plugin_list($type) as $component => $ownerdir) {
+ $componentsubplugins = array();
+ if (file_exists($ownerdir . '/db/subplugins.php')) {
+ $subplugins = array();
+ include($ownerdir . '/db/subplugins.php');
+ foreach ($subplugins as $subplugintype => $subplugintyperootdir) {
+ $subplugin = new stdClass();
+ $subplugin->type = $subplugintype;
+ $subplugin->typerootdir = $subplugintyperootdir;
+ $componentsubplugins[$subplugintype] = $subplugin;
}
+ $this->subpluginsinfo[$type . '_' . $component] = $componentsubplugins;
}
}
}
@@ -350,12 +555,11 @@ public function plugintype_name_plural($type) {
* Returns information about the known plugin, or null
*
* @param string $component frankenstyle component name.
- * @param bool $disablecache force reload, cache can be used otherwise
* @return plugininfo_base|null the corresponding plugin information.
*/
- public function get_plugin_info($component, $disablecache=false) {
- list($type, $name) = $this->normalize_component($component);
- $plugins = $this->get_plugins($disablecache);
+ public function get_plugin_info($component) {
+ list($type, $name) = core_component::normalize_component($component);
+ $plugins = $this->get_plugins();
if (isset($plugins[$type][$name])) {
return $plugins[$type][$name];
} else {
@@ -637,6 +841,7 @@ public static function is_deleted_standard_plugin($type, $name) {
$plugins = array(
'qformat' => array('blackboard'),
'enrol' => array('authorize'),
+ 'tool' => array('bloglevelupgrade'),
);
if (!isset($plugins[$type])) {
@@ -879,18 +1084,6 @@ public static function standard_plugins_list($type) {
}
}
- /**
- * Wrapper for the core function {@link core_component::normalize_component()}.
- *
- * This is here just to make it possible to mock it in unit tests.
- *
- * @param string $component
- * @return array
- */
- protected function normalize_component($component) {
- return core_component::normalize_component($component);
- }
-
/**
* Reorders plugin types into a sequence to be displayed
*
@@ -2420,7 +2613,6 @@ public static function make($type, $typerootdir, $name, $namerootdir, $typeclass
$plugin->init_display_name();
$plugin->load_disk_version();
$plugin->load_db_version();
- $plugin->load_required_main_version();
$plugin->init_is_standard();
return $plugin;
@@ -2445,7 +2637,7 @@ abstract class plugininfo_base {
public $displayname;
/** @var string the plugin source, one of plugin_manager::PLUGIN_SOURCE_xxx constants */
public $source;
- /** @var fullpath to the location of this plugin */
+ /** @var string fullpath to the location of this plugin */
public $rootdir;
/** @var int|string the version of the plugin's source code */
public $versiondisk;
@@ -2463,7 +2655,16 @@ abstract class plugininfo_base {
public $availableupdates;
/**
- * Gathers and returns the information about all plugins of the given type
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ return null;
+ }
+
+ /**
+ * Gathers and returns the information about all plugins of the given type,
+ * either on disk or previously installed.
*
* @param string $type the name of the plugintype, eg. mod, auth or workshopform
* @param string $typerootdir full path to the location of the plugin dir
@@ -2471,15 +2672,35 @@ abstract class plugininfo_base {
* @return array of plugintype classes, indexed by the plugin name
*/
public static function get_plugins($type, $typerootdir, $typeclass) {
-
- // get the information about plugins at the disk
+ // Get the information about plugins at the disk.
$plugins = core_component::get_plugin_list($type);
- $ondisk = array();
+ $return = array();
foreach ($plugins as $pluginname => $pluginrootdir) {
- $ondisk[$pluginname] = plugininfo_default_factory::make($type, $typerootdir,
+ $return[$pluginname] = plugininfo_default_factory::make($type, $typerootdir,
$pluginname, $pluginrootdir, $typeclass);
}
- return $ondisk;
+
+ // Fetch missing incorrectly uninstalled plugins.
+ $manager = plugin_manager::instance();
+ $plugins = $manager->get_installed_plugins($type);
+
+ foreach ($plugins as $name => $version) {
+ if (isset($return[$name])) {
+ continue;
+ }
+ $plugin = new $typeclass();
+ $plugin->type = $type;
+ $plugin->typerootdir = $typerootdir;
+ $plugin->name = $name;
+ $plugin->rootdir = null;
+ $plugin->displayname = $name;
+ $plugin->versiondb = $version;
+ $plugin->init_is_standard();
+
+ $return[$name] = $plugin;
+ }
+
+ return $return;
}
/**
@@ -2524,34 +2745,6 @@ public function full_path($relativepath) {
return $this->rootdir . '/' . $relativepath;
}
- /**
- * Load the data from version.php.
- *
- * @param bool $disablecache do not attempt to obtain data from the cache
- * @return stdClass the object called $plugin defined in version.php
- */
- protected function load_version_php($disablecache=false) {
-
- $cache = cache::make('core', 'plugininfo_base');
-
- $versionsphp = $cache->get('versions_php');
-
- if (!$disablecache and $versionsphp !== false and isset($versionsphp[$this->component])) {
- return $versionsphp[$this->component];
- }
-
- $versionfile = $this->full_path('version.php');
-
- $plugin = new stdClass();
- if (is_readable($versionfile)) {
- include($versionfile);
- }
- $versionsphp[$this->component] = $plugin;
- $cache->set('versions_php', $versionsphp);
-
- return $plugin;
- }
-
/**
* Sets {@link $versiondisk} property to a numerical value representing the
* version of the plugin's source code.
@@ -2561,33 +2754,26 @@ protected function load_version_php($disablecache=false) {
* data) or is missing from disk.
*/
public function load_disk_version() {
- $plugin = $this->load_version_php();
+ $versions = plugin_manager::instance()->get_present_plugins($this->type);
+
+ $this->versiondisk = null;
+ $this->versionrequires = null;
+ $this->dependencies = array();
+
+ if (!isset($versions[$this->name])) {
+ return;
+ }
+
+ $plugin = $versions[$this->name];
+
if (isset($plugin->version)) {
$this->versiondisk = $plugin->version;
}
- }
-
- /**
- * Sets {@link $versionrequires} property to a numerical value representing
- * the version of Moodle core that this plugin requires.
- */
- public function load_required_main_version() {
- $plugin = $this->load_version_php();
if (isset($plugin->requires)) {
$this->versionrequires = $plugin->requires;
}
- }
-
- /**
- * Initialise {@link $dependencies} to the list of other plugins (in any)
- * that this one requires to be installed.
- */
- protected function load_other_required_plugins() {
- $plugin = $this->load_version_php();
- if (!empty($plugin->dependencies)) {
+ if (isset($plugin->dependencies)) {
$this->dependencies = $plugin->dependencies;
- } else {
- $this->dependencies = array(); // By default, no dependencies.
}
}
@@ -2599,7 +2785,7 @@ protected function load_other_required_plugins() {
*/
public function get_other_required_plugins() {
if (is_null($this->dependencies)) {
- $this->load_other_required_plugins();
+ $this->load_disk_version();
}
return $this->dependencies;
}
@@ -2631,8 +2817,12 @@ public function get_parent_plugin() {
* data) or has not been installed yet.
*/
public function load_db_version() {
- if ($ver = self::get_version_from_config_plugins($this->component)) {
- $this->versiondb = $ver;
+ $versions = plugin_manager::instance()->get_installed_plugins($this->type);
+
+ if (isset($versions[$this->name])) {
+ $this->versiondb = $versions[$this->name];
+ } else {
+ $this->versiondb = null;
}
}
@@ -2707,7 +2897,9 @@ public function get_status() {
return plugin_manager::PLUGIN_STATUS_MISSING;
}
- } else if ((string)$this->versiondb === (string)$this->versiondisk) {
+ } else if ((float)$this->versiondb === (float)$this->versiondisk) {
+ // Note: the float comparison should work fine here
+ // because there are no arithmetic operations with the numbers.
return plugin_manager::PLUGIN_STATUS_UPTODATE;
} else if ($this->versiondb < $this->versiondisk) {
@@ -2733,7 +2925,18 @@ public function get_status() {
* @return null|bool
*/
public function is_enabled() {
- return null;
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return false;
+ }
+
+ $enabled = plugin_manager::instance()->get_enabled_plugins($this->type);
+
+ if (!is_array($enabled)) {
+ return null;
+ }
+
+ return isset($enabled[$this->name]);
}
/**
@@ -2842,7 +3045,7 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
* Note that even if true is returned, the core may still prohibit the uninstallation,
* e.g. in case there are other plugins that depend on this one.
*
- * @return boolean
+ * @return bool
*/
public function is_uninstall_allowed() {
@@ -2920,41 +3123,10 @@ protected final function get_default_uninstall_url() {
));
}
- /**
- * Provides access to plugin versions from the {config_plugins} table
- *
- * @param string $plugin plugin name
- * @param bool $disablecache do not attempt to obtain data from the cache
- * @return int|bool the stored value or false if not found
- */
- protected function get_version_from_config_plugins($plugin, $disablecache=false) {
- global $DB;
-
- $cache = cache::make('core', 'plugininfo_base');
-
- $pluginversions = $cache->get('versions_db');
-
- if ($pluginversions === false or $disablecache) {
- try {
- $pluginversions = $DB->get_records_menu('config_plugins', array('name' => 'version'), 'plugin', 'plugin,value');
- } catch (dml_exception $e) {
- // before install
- $pluginversions = array();
- }
- $cache->set('versions_db', $pluginversions);
- }
-
- if (isset($pluginversions[$plugin])) {
- return $pluginversions[$plugin];
- } else {
- return false;
- }
- }
-
/**
* Provides access to the plugin_manager singleton.
*
- * @return plugin_manmager
+ * @return plugin_manager
*/
protected function get_plugin_manager() {
return plugin_manager::instance();
@@ -2973,31 +3145,14 @@ class plugininfo_general extends plugininfo_base {
* Class for page side blocks
*/
class plugininfo_block extends plugininfo_base {
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ global $DB;
- public static function get_plugins($type, $typerootdir, $typeclass) {
-
- // get the information about blocks at the disk
- $blocks = parent::get_plugins($type, $typerootdir, $typeclass);
-
- // add blocks missing from disk
- $blocksinfo = self::get_blocks_info();
- foreach ($blocksinfo as $blockname => $blockinfo) {
- if (isset($blocks[$blockname])) {
- continue;
- }
- $plugin = new $typeclass();
- $plugin->type = $type;
- $plugin->typerootdir = $typerootdir;
- $plugin->name = $blockname;
- $plugin->rootdir = null;
- $plugin->displayname = $blockname;
- $plugin->versiondb = $blockinfo->version;
- $plugin->init_is_standard();
-
- $blocks[$blockname] = $plugin;
- }
-
- return $blocks;
+ return $DB->get_records_menu('block', array('visible'=>1), 'name ASC', 'name, name AS val');
}
/**
@@ -3030,29 +3185,6 @@ public function init_display_name() {
}
}
- public function load_db_version() {
- global $DB;
-
- $blocksinfo = self::get_blocks_info();
- if (isset($blocksinfo[$this->name]->version)) {
- $this->versiondb = $blocksinfo[$this->name]->version;
- }
- }
-
- public function is_enabled() {
-
- $blocksinfo = self::get_blocks_info();
- if (isset($blocksinfo[$this->name]->visible)) {
- if ($blocksinfo[$this->name]->visible) {
- return true;
- } else {
- return false;
- }
- } else {
- return parent::is_enabled();
- }
- }
-
public function get_settings_section_name() {
return 'blocksetting' . $this->name;
}
@@ -3061,6 +3193,12 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // in case settings.php wants to refer to them
$ADMIN = $adminroot; // may be used in settings.php
$block = $this; // also can be used inside settings.php
+
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
$section = $this->get_settings_section_name();
if (!$hassiteconfig || (($blockinstance = block_instance($this->name)) === false)) {
@@ -3073,11 +3211,6 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
$settings = new admin_settingpage($section, $this->displayname,
'moodle/site:config', $this->is_enabled() === false);
include($this->full_path('settings.php')); // this may also set $settings to null
- } else {
- $blocksinfo = self::get_blocks_info();
- $settingsurl = new moodle_url('/admin/block.php', array('block' => $blocksinfo[$this->name]->id));
- $settings = new admin_externalpage($section, $this->displayname,
- $settingsurl, 'moodle/site:config', $this->is_enabled() === false);
}
}
if ($settings) {
@@ -3103,33 +3236,7 @@ public function get_uninstall_extra_warning() {
return ''.get_string('uninstallextraconfirmblock', 'core_plugin', array('instances'=>$count)).'
';
}
-
- /**
- * Provides access to the records in {block} table
- *
- * @param bool $disablecache do not attempt to obtain data from the cache
- * @return array array of stdClasses
- */
- protected static function get_blocks_info($disablecache=false) {
- global $DB;
-
- $cache = cache::make('core', 'plugininfo_block');
-
- $blocktypes = $cache->get('blocktypes');
-
- if ($blocktypes === false or $disablecache) {
- try {
- $blocktypes = $DB->get_records('block', null, 'name', 'name,id,version,visible');
- } catch (dml_exception $e) {
- // before install
- $blocktypes = array();
- }
- $cache->set('blocktypes', $blocktypes);
- }
-
- return $blocktypes;
- }
-}
+}
/**
@@ -3137,80 +3244,29 @@ protected static function get_blocks_info($disablecache=false) {
*/
class plugininfo_filter extends plugininfo_base {
- public static function get_plugins($type, $typerootdir, $typeclass) {
- global $CFG, $DB;
-
- $filters = array();
-
- // get the list of filters in /filter location
- $installed = filter_get_all_installed();
-
- foreach ($installed as $name => $displayname) {
- $plugin = new $typeclass();
- $plugin->type = $type;
- $plugin->typerootdir = $typerootdir;
- $plugin->name = $name;
- $plugin->rootdir = "$CFG->dirroot/filter/$name";
- $plugin->displayname = $displayname;
-
- $plugin->load_disk_version();
- $plugin->load_db_version();
- $plugin->load_required_main_version();
- $plugin->init_is_standard();
-
- $filters[$plugin->name] = $plugin;
- }
-
- // Do not mess with filter registration here!
-
- $globalstates = self::get_global_states();
-
- // make sure that all registered filters are installed, just in case
- foreach ($globalstates as $name => $info) {
- if (!isset($filters[$name])) {
- // oops, there is a record in filter_active but the filter is not installed
- $plugin = new $typeclass();
- $plugin->type = $type;
- $plugin->typerootdir = $typerootdir;
- $plugin->name = $name;
- $plugin->rootdir = "$CFG->dirroot/filter/$name";
- $plugin->displayname = $name;
-
- $plugin->load_db_version();
-
- if (is_null($plugin->versiondb)) {
- // this is a hack to stimulate 'Missing from disk' error
- // because $plugin->versiondisk will be null !== false
- $plugin->versiondb = false;
- }
-
- $filters[$plugin->name] = $plugin;
- }
- }
-
- return $filters;
- }
-
public function init_display_name() {
- // do nothing, the name is set in self::get_plugins()
+ if (!get_string_manager()->string_exists('filtername', $this->component)) {
+ $this->displayname = '[filtername,' . $this->component . ']';
+ } else {
+ $this->displayname = get_string('filtername', $this->component);
+ }
}
- public function is_enabled() {
-
- $globalstates = self::get_global_states();
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ global $DB, $CFG;
+ require_once("$CFG->libdir/filterlib.php");
- foreach ($globalstates as $name => $info) {
- if ($name === $this->name) {
- if ($info->active == TEXTFILTER_DISABLED) {
- return false;
- } else {
- // it may be 'On' or 'Off, but available'
- return null;
- }
- }
+ $enabled = array();
+ $filters = $DB->get_records_select('filter_active', "active <> :disabled", array('disabled'=>TEXTFILTER_DISABLED), 'filter ASC', 'id, filter');
+ foreach ($filters as $filter) {
+ $enabled[$filter->filter] = $filter->filter;
}
- return null;
+ return $enabled;
}
public function get_settings_section_name() {
@@ -3222,6 +3278,11 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
$ADMIN = $adminroot; // may be used in settings.php
$filter = $this; // also can be used inside settings.php
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
$settings = null;
if ($hassiteconfig && file_exists($this->full_path('filtersettings.php'))) {
$section = $this->get_settings_section_name();
@@ -3241,50 +3302,6 @@ public function is_uninstall_allowed() {
public function get_uninstall_url() {
return new moodle_url('/admin/filters.php', array('sesskey' => sesskey(), 'filterpath' => $this->name, 'action' => 'delete'));
}
-
- /**
- * Provides access to the results of {@link filter_get_global_states()}
- * but indexed by the normalized filter name
- *
- * The legacy filter name is available as ->legacyname property.
- *
- * @param bool $disablecache do not attempt to obtain data from the cache
- * @return array
- */
- protected static function get_global_states($disablecache=false) {
- global $DB;
-
- $cache = cache::make('core', 'plugininfo_filter');
-
- $globalstates = $cache->get('globalstates');
-
- if ($globalstates === false or $disablecache) {
-
- if (!$DB->get_manager()->table_exists('filter_active')) {
- // Not installed yet.
- $cache->set('globalstates', array());
- return array();
- }
-
- $globalstates = array();
-
- foreach (filter_get_global_states() as $name => $info) {
- if (strpos($name, '/') !== false) {
- // Skip existing before upgrade to new names.
- continue;
- }
-
- $filterinfo = new stdClass();
- $filterinfo->active = $info->active;
- $filterinfo->sortorder = $info->sortorder;
- $globalstates[$name] = $filterinfo;
- }
-
- $cache->set('globalstates', $globalstates);
- }
-
- return $globalstates;
- }
}
@@ -3292,31 +3309,13 @@ protected static function get_global_states($disablecache=false) {
* Class for activity modules
*/
class plugininfo_mod extends plugininfo_base {
-
- public static function get_plugins($type, $typerootdir, $typeclass) {
-
- // get the information about plugins at the disk
- $modules = parent::get_plugins($type, $typerootdir, $typeclass);
-
- // add modules missing from disk
- $modulesinfo = self::get_modules_info();
- foreach ($modulesinfo as $modulename => $moduleinfo) {
- if (isset($modules[$modulename])) {
- continue;
- }
- $plugin = new $typeclass();
- $plugin->type = $type;
- $plugin->typerootdir = $typerootdir;
- $plugin->name = $modulename;
- $plugin->rootdir = null;
- $plugin->displayname = $modulename;
- $plugin->versiondb = $moduleinfo->version;
- $plugin->init_is_standard();
-
- $modules[$modulename] = $plugin;
- }
-
- return $modules;
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ global $DB;
+ return $DB->get_records_menu('modules', array('visible'=>1), 'name ASC', 'name, name AS val');
}
/**
@@ -3344,61 +3343,6 @@ public function init_display_name() {
}
}
- /**
- * Load the data from version.php.
- *
- * @param bool $disablecache do not attempt to obtain data from the cache
- * @return object the data object defined in version.php.
- */
- protected function load_version_php($disablecache=false) {
-
- $cache = cache::make('core', 'plugininfo_mod');
-
- $versionsphp = $cache->get('versions_php');
-
- if (!$disablecache and $versionsphp !== false and isset($versionsphp[$this->component])) {
- return $versionsphp[$this->component];
- }
-
- $versionfile = $this->full_path('version.php');
-
- $module = new stdClass();
- $plugin = new stdClass();
- if (is_readable($versionfile)) {
- include($versionfile);
- }
- if (!isset($module->version) and isset($plugin->version)) {
- $module = $plugin;
- }
- $versionsphp[$this->component] = $module;
- $cache->set('versions_php', $versionsphp);
-
- return $module;
- }
-
- public function load_db_version() {
- global $DB;
-
- $modulesinfo = self::get_modules_info();
- if (isset($modulesinfo[$this->name]->version)) {
- $this->versiondb = $modulesinfo[$this->name]->version;
- }
- }
-
- public function is_enabled() {
-
- $modulesinfo = self::get_modules_info();
- if (isset($modulesinfo[$this->name]->visible)) {
- if ($modulesinfo[$this->name]->visible) {
- return true;
- } else {
- return false;
- }
- } else {
- return parent::is_enabled();
- }
- }
-
public function get_settings_section_name() {
return 'modsetting' . $this->name;
}
@@ -3407,11 +3351,16 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // in case settings.php wants to refer to them
$ADMIN = $adminroot; // may be used in settings.php
$module = $this; // also can be used inside settings.php
+
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
$section = $this->get_settings_section_name();
- $modulesinfo = self::get_modules_info();
$settings = null;
- if ($hassiteconfig && isset($modulesinfo[$this->name]) && file_exists($this->full_path('settings.php'))) {
+ if ($hassiteconfig && file_exists($this->full_path('settings.php'))) {
$settings = new admin_settingpage($section, $this->displayname,
'moodle/site:config', $this->is_enabled() === false);
include($this->full_path('settings.php')); // this may also set $settings to null
@@ -3462,32 +3411,6 @@ public function get_uninstall_extra_warning() {
return ''.get_string('uninstallextraconfirmmod', 'core_plugin', array('instances'=>$count, 'courses'=>$courses)).'
';
}
-
- /**
- * Provides access to the records in {modules} table
- *
- * @param bool $disablecache do not attempt to obtain data from the cache
- * @return array array of stdClasses
- */
- protected static function get_modules_info($disablecache=false) {
- global $DB;
-
- $cache = cache::make('core', 'plugininfo_mod');
-
- $modulesinfo = $cache->get('modulesinfo');
-
- if ($modulesinfo === false or $disablecache) {
- try {
- $modulesinfo = $DB->get_records('modules', null, 'name', 'name,id,version,visible');
- } catch (dml_exception $e) {
- // before install
- $modulesinfo = array();
- }
- $cache->set('modulesinfo', $modulesinfo);
- }
-
- return $modulesinfo;
- }
}
@@ -3529,6 +3452,11 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // in case settings.php wants to refer to them
$ADMIN = $adminroot; // may be used in settings.php
$qtype = $this; // also can be used inside settings.php
+
+ if (!$this->rootdir) {
+ // Most probably somebody deleted dir without proper uninstall.
+ return;
+ }
$section = $this->get_settings_section_name();
$settings = null;
@@ -3550,18 +3478,20 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
* Class for authentication plugins
*/
class plugininfo_auth extends plugininfo_base {
-
- public function is_enabled() {
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
global $CFG;
- if (in_array($this->name, array('nologin', 'manual'))) {
- // these two are always enabled and can't be disabled
- return null;
+ // These two are always enabled and can't be disabled.
+ $enabled = array('nologin'=>'nologin', 'manual'=>'manual');
+ foreach (explode(',', $CFG->auth) as $auth) {
+ $enabled[$auth] = $auth;
}
- $enabled = array_flip(explode(',', $CFG->auth));
-
- return isset($enabled[$this->name]);
+ return $enabled;
}
public function get_settings_section_name() {
@@ -3572,6 +3502,12 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // in case settings.php wants to refer to them
$ADMIN = $adminroot; // may be used in settings.php
$auth = $this; // also to be used inside settings.php
+
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
$section = $this->get_settings_section_name();
$settings = null;
@@ -3598,18 +3534,19 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
* Class for enrolment plugins
*/
class plugininfo_enrol extends plugininfo_base {
-
- public function is_enabled() {
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
global $CFG;
- // We do not actually need whole enrolment classes here so we do not call
- // {@link enrol_get_plugins()}. Note that this may produce slightly different
- // results, for example if the enrolment plugin does not contain lib.php
- // but it is listed in $CFG->enrol_plugins_enabled
-
- $enabled = array_flip(explode(',', $CFG->enrol_plugins_enabled));
+ $enabled = array();
+ foreach (explode(',', $CFG->enrol_plugins_enabled) as $enrol) {
+ $enabled[$enrol] = $enrol;
+ }
- return isset($enabled[$this->name]);
+ return $enabled;
}
public function get_settings_section_name() {
@@ -3623,6 +3560,11 @@ public function get_settings_section_name() {
public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) {
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // in case settings.php wants to refer to them
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) {
return;
}
@@ -3681,6 +3623,14 @@ public function get_uninstall_extra_warning() {
* Class for messaging processors
*/
class plugininfo_message extends plugininfo_base {
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ global $DB;
+ return $DB->get_records_menu('message_processors', array('enabled'=>1), 'name ASC', 'name, name AS val');
+ }
public function get_settings_section_name() {
return 'messagesetting' . $this->name;
@@ -3689,6 +3639,12 @@ public function get_settings_section_name() {
public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) {
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // in case settings.php wants to refer to them
$ADMIN = $adminroot; // may be used in settings.php
+
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
if (!$hassiteconfig) {
return;
}
@@ -3709,18 +3665,6 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
}
}
- /**
- * @see plugintype_interface::is_enabled()
- */
- public function is_enabled() {
- $processors = get_message_processors();
- if (isset($processors[$this->name])) {
- return $processors[$this->name]->configured && $processors[$this->name]->enabled;
- } else {
- return parent::is_enabled();
- }
- }
-
public function is_uninstall_allowed() {
$processors = get_message_processors();
if (isset($processors[$this->name])) {
@@ -3744,12 +3688,13 @@ public function get_uninstall_url() {
* Class for repositories
*/
class plugininfo_repository extends plugininfo_base {
-
- public function is_enabled() {
-
- $enabled = self::get_enabled_repositories();
-
- return isset($enabled[$this->name]);
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ global $DB;
+ return $DB->get_records_menu('repository', array('visible'=>1), 'type ASC', 'type, type AS val');
}
public function get_settings_section_name() {
@@ -3757,6 +3702,11 @@ public function get_settings_section_name() {
}
public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) {
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
if ($hassiteconfig && $this->is_enabled()) {
// completely no access to repository setting when it is not enabled
$sectionname = $this->get_settings_section_name();
@@ -3767,27 +3717,6 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
$adminroot->add($parentnodename, $settings);
}
}
-
- /**
- * Provides access to the records in {repository} table
- *
- * @param bool $disablecache do not attempt to obtain data from the cache
- * @return array array of stdClasses
- */
- protected static function get_enabled_repositories($disablecache=false) {
- global $DB;
-
- $cache = cache::make('core', 'plugininfo_repository');
-
- $enabled = $cache->get('enabled');
-
- if ($enabled === false or $disablecache) {
- $enabled = $DB->get_records('repository', null, 'type', 'type,visible,sortorder');
- $cache->set('enabled', $enabled);
- }
-
- return $enabled;
- }
}
@@ -3795,44 +3724,17 @@ protected static function get_enabled_repositories($disablecache=false) {
* Class for portfolios
*/
class plugininfo_portfolio extends plugininfo_base {
-
- public function is_enabled() {
-
- $enabled = self::get_enabled_portfolios();
-
- return isset($enabled[$this->name]);
- }
-
/**
- * Returns list of enabled portfolio plugins
- *
- * Portfolio plugin is enabled if there is at least one record in the {portfolio_instance}
- * table for it.
- *
- * @param bool $disablecache do not attempt to obtain data from the cache
- * @return array array of stdClasses with properties plugin and visible indexed by plugin
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
*/
- protected static function get_enabled_portfolios($disablecache=false) {
+ public static function get_enabled_plugins() {
global $DB;
- $cache = cache::make('core', 'plugininfo_portfolio');
-
- $enabled = $cache->get('enabled');
-
- if ($enabled === false or $disablecache) {
- $enabled = array();
- $instances = $DB->get_recordset('portfolio_instance', null, '', 'plugin,visible');
- foreach ($instances as $instance) {
- if (isset($enabled[$instance->plugin])) {
- if ($instance->visible) {
- $enabled[$instance->plugin]->visible = $instance->visible;
- }
- } else {
- $enabled[$instance->plugin] = $instance;
- }
- }
- $instances->close();
- $cache->set('enabled', $enabled);
+ $enabled = array();
+ $rs = $DB->get_recordset('portfolio_instance', array('visible'=>1), 'plugin ASC', 'plugin');
+ foreach ($rs as $repository) {
+ $enabled[$repository->plugin] = $repository->plugin;
}
return $enabled;
@@ -3911,6 +3813,24 @@ public function is_uninstall_allowed() {
* Class for HTML editors
*/
class plugininfo_editor extends plugininfo_base {
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ global $CFG;
+
+ if (empty($CFG->texteditors)) {
+ return array('tinymce'=>'tinymce', 'textarea'=>'textarea');
+ }
+
+ $enabled = array();
+ foreach (explode(',', $CFG->texteditors) as $editor) {
+ $enabled[$editor] = $editor;
+ }
+
+ return $enabled;
+ }
public function get_settings_section_name() {
return 'editorsettings' . $this->name;
@@ -3920,6 +3840,12 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // in case settings.php wants to refer to them
$ADMIN = $adminroot; // may be used in settings.php
$editor = $this; // also can be used inside settings.php
+
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
$section = $this->get_settings_section_name();
$settings = null;
@@ -3943,27 +3869,6 @@ public function is_uninstall_allowed() {
return true;
}
}
-
- /**
- * Returns the information about plugin availability
- *
- * True means that the plugin is enabled. False means that the plugin is
- * disabled. Null means that the information is not available, or the
- * plugin does not support configurable availability or the availability
- * can not be changed.
- *
- * @return null|bool
- */
- public function is_enabled() {
- global $CFG;
- if (empty($CFG->texteditors)) {
- $CFG->texteditors = 'tinymce,textarea';
- }
- if (in_array($this->name, explode(',', $CFG->texteditors))) {
- return true;
- }
- return false;
- }
}
/**
@@ -3976,6 +3881,11 @@ public function get_settings_section_name() {
}
public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) {
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
// plagiarism plugin just redirect to settings.php in the plugins directory
if ($hassiteconfig && file_exists($this->full_path('settings.php'))) {
$section = $this->get_settings_section_name();
@@ -3995,6 +3905,24 @@ public function is_uninstall_allowed() {
* Class for webservice protocols
*/
class plugininfo_webservice extends plugininfo_base {
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ global $CFG;
+
+ if (empty($CFG->enablewebservices) or empty($CFG->webserviceprotocols)) {
+ return array();
+ }
+
+ $enabled = array();
+ foreach (explode(',', $CFG->webserviceprotocols) as $protocol) {
+ $enabled[$protocol] = $protocol;
+ }
+
+ return $enabled;
+ }
public function get_settings_section_name() {
return 'webservicesetting' . $this->name;
@@ -4004,6 +3932,12 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // in case settings.php wants to refer to them
$ADMIN = $adminroot; // may be used in settings.php
$webservice = $this; // also can be used inside settings.php
+
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
$section = $this->get_settings_section_name();
$settings = null;
@@ -4017,18 +3951,6 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
}
}
- public function is_enabled() {
- global $CFG;
- if (empty($CFG->enablewebservices)) {
- return false;
- }
- $active_webservices = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
- if (in_array($this->name, $active_webservices)) {
- return true;
- }
- return false;
- }
-
public function is_uninstall_allowed() {
return false;
}
@@ -4038,6 +3960,36 @@ public function is_uninstall_allowed() {
* Class for course formats
*/
class plugininfo_format extends plugininfo_base {
+ /**
+ * Finds all enabled plugins, the result may include missing plugins.
+ * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
+ */
+ public static function get_enabled_plugins() {
+ global $DB;
+
+ $plugins = plugin_manager::instance()->get_installed_plugins('format');
+ $installed = array();
+ foreach ($plugins as $plugin => $version) {
+ $installed[] = 'format_'.$plugin;
+ }
+
+ list($installed, $params) = $DB->get_in_or_equal($installed, SQL_PARAMS_NAMED);
+ $disabled = $DB->get_recordset_select('config_plugins', "plugin $installed AND name = 'disabled'", $params, 'plugin ASC');
+ foreach ($disabled as $conf) {
+ if (empty($conf->value)) {
+ continue;
+ }
+ list($type, $name) = explode('_', $conf->component, 2);
+ unset($plugins[$name]);
+ }
+
+ $enabled = array();
+ foreach ($plugins as $plugin => $version) {
+ $enabled[$plugin] = $plugin;
+ }
+
+ return $enabled;
+ }
/**
* Gathers and returns the information about all plugins of the given type
@@ -4066,6 +4018,12 @@ public function get_settings_section_name() {
public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) {
global $CFG, $USER, $DB, $OUTPUT, $PAGE; // in case settings.php wants to refer to them
$ADMIN = $adminroot; // also may be used in settings.php
+
+ if (!$this->rootdir) {
+ // Plugin missing.
+ return;
+ }
+
$section = $this->get_settings_section_name();
$settings = null;
@@ -4079,10 +4037,6 @@ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $h
}
}
- public function is_enabled() {
- return !get_config($this->component, 'disabled');
- }
-
public function is_uninstall_allowed() {
if ($this->name !== get_config('moodlecourse', 'format') && $this->name !== 'site') {
return true;
diff --git a/lib/tests/available_update_checker_test.php b/lib/tests/available_update_checker_test.php
new file mode 100644
index 0000000000000..b1d9f27bb29ea
--- /dev/null
+++ b/lib/tests/available_update_checker_test.php
@@ -0,0 +1,290 @@
+.
+
+/**
+ * Unit tests for the update checker.
+ *
+ * @package core
+ * @category phpunit
+ * @copyright 2012 David Mudrak
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->libdir.'/pluginlib.php');
+require_once(__DIR__.'/available_update_deployer_test.php');
+
+
+/**
+ * Tests of the basic API of the available update checker.
+ */
+class core_available_update_checker_testcase extends advanced_testcase {
+
+ public function test_core_available_update() {
+ $provider = testable_available_update_checker::instance();
+ $this->assertInstanceOf('available_update_checker', $provider);
+
+ $provider->fake_current_environment(2012060102.00, '2.3.2 (Build: 20121012)', '2.3', array());
+ $updates = $provider->get_update_info('core');
+ $this->assertCount(2, $updates);
+
+ $provider->fake_current_environment(2012060103.00, '2.3.3 (Build: 20121212)', '2.3', array());
+ $updates = $provider->get_update_info('core');
+ $this->assertCount(1, $updates);
+
+ $provider->fake_current_environment(2012060103.00, '2.3.3 (Build: 20121212)', '2.3', array());
+ $updates = $provider->get_update_info('core', array('minmaturity' => MATURITY_STABLE));
+ $this->assertNull($updates);
+ }
+
+ /**
+ * If there are no fetched data yet, the first cron should fetch them.
+ */
+ public function test_cron_initial_fetch() {
+ $provider = testable_available_update_checker::instance();
+ $provider->fakerecentfetch = null;
+ $provider->fakecurrenttimestamp = -1;
+ $this->setExpectedException('testable_available_update_checker_cron_executed');
+ $provider->cron();
+ }
+
+ /**
+ * If there is a fresh fetch available, no cron execution is expected.
+ */
+ public function test_cron_has_fresh_fetch() {
+ $provider = testable_available_update_checker::instance();
+ $provider->fakerecentfetch = time() - 23 * HOURSECS; // Fetched 23 hours ago.
+ $provider->fakecurrenttimestamp = -1;
+ $provider->cron();
+ $this->assertTrue(true); // We should get here with no exception thrown.
+ }
+
+ /**
+ * If there is an outdated fetch, the cron execution is expected.
+ */
+ public function test_cron_has_outdated_fetch() {
+ $provider = testable_available_update_checker::instance();
+ $provider->fakerecentfetch = time() - 49 * HOURSECS; // Fetched 49 hours ago.
+ $provider->fakecurrenttimestamp = -1;
+ $this->setExpectedException('testable_available_update_checker_cron_executed');
+ $provider->cron();
+ }
+
+ /**
+ * The first cron after 01:42 AM today should fetch the data.
+ *
+ * @see testable_available_update_checker::cron_execution_offset()
+ */
+ public function test_cron_offset_execution_not_yet() {
+ $provider = testable_available_update_checker::instance();
+ $provider->fakecurrenttimestamp = mktime(1, 40, 02); // 01:40:02 AM today
+ $provider->fakerecentfetch = $provider->fakecurrenttimestamp - 24 * HOURSECS;
+ $provider->cron();
+ $this->assertTrue(true); // We should get here with no exception thrown.
+ }
+
+ /**
+ * The first cron after 01:42 AM today should fetch the data and then
+ * it is supposed to wait next 24 hours.
+ *
+ * @see testable_available_update_checker::cron_execution_offset()
+ */
+ public function test_cron_offset_execution() {
+ $provider = testable_available_update_checker::instance();
+
+ // The cron at 01:45 should fetch the data.
+ $provider->fakecurrenttimestamp = mktime(1, 45, 02); // 01:45:02 AM today
+ $provider->fakerecentfetch = $provider->fakecurrenttimestamp - 24 * HOURSECS - 1;
+ $executed = false;
+ try {
+ $provider->cron();
+ } catch (testable_available_update_checker_cron_executed $e) {
+ $executed = true;
+ }
+ $this->assertTrue($executed, 'Cron should be executed at 01:45:02 but it was not.');
+
+ // Another cron at 06:45 should still consider data as fresh enough.
+ $provider->fakerecentfetch = $provider->fakecurrenttimestamp;
+ $provider->fakecurrenttimestamp = mktime(6, 45, 03); // 06:45:03 AM
+ $executed = false;
+ try {
+ $provider->cron();
+ } catch (testable_available_update_checker_cron_executed $e) {
+ $executed = true;
+ }
+ $this->assertFalse($executed, 'Cron should not be executed at 06:45:03 but it was.');
+
+ // The next scheduled execution should happen the next day.
+ $provider->fakecurrenttimestamp = $provider->fakerecentfetch + 24 * HOURSECS + 1;
+ $executed = false;
+ try {
+ $provider->cron();
+ } catch (testable_available_update_checker_cron_executed $e) {
+ $executed = true;
+ }
+ $this->assertTrue($executed, 'Cron should be executed the next night but it was not.');
+ }
+
+ public function test_compare_responses_both_empty() {
+ $provider = testable_available_update_checker::instance();
+ $old = array();
+ $new = array();
+ $cmp = $provider->compare_responses($old, $new);
+ $this->assertInternalType('array', $cmp);
+ $this->assertEmpty($cmp);
+ }
+
+ public function test_compare_responses_old_empty() {
+ $provider = testable_available_update_checker::instance();
+ $old = array();
+ $new = array(
+ 'updates' => array(
+ 'core' => array(
+ array(
+ 'version' => 2012060103
+ )
+ )
+ )
+ );
+ $cmp = $provider->compare_responses($old, $new);
+ $this->assertInternalType('array', $cmp);
+ $this->assertNotEmpty($cmp);
+ $this->assertTrue(isset($cmp['core'][0]['version']));
+ $this->assertEquals(2012060103, $cmp['core'][0]['version']);
+ }
+
+ public function test_compare_responses_no_change() {
+ $provider = testable_available_update_checker::instance();
+ $old = $new = array(
+ 'updates' => array(
+ 'core' => array(
+ array(
+ 'version' => 2012060104
+ ),
+ array(
+ 'version' => 2012120100
+ )
+ ),
+ 'mod_foo' => array(
+ array(
+ 'version' => 2011010101
+ )
+ )
+ )
+ );
+ $cmp = $provider->compare_responses($old, $new);
+ $this->assertInternalType('array', $cmp);
+ $this->assertEmpty($cmp);
+ }
+
+ public function test_compare_responses_new_and_missing_update() {
+ $provider = testable_available_update_checker::instance();
+ $old = array(
+ 'updates' => array(
+ 'core' => array(
+ array(
+ 'version' => 2012060104
+ )
+ ),
+ 'mod_foo' => array(
+ array(
+ 'version' => 2011010101
+ )
+ )
+ )
+ );
+ $new = array(
+ 'updates' => array(
+ 'core' => array(
+ array(
+ 'version' => 2012060104
+ ),
+ array(
+ 'version' => 2012120100
+ )
+ )
+ )
+ );
+ $cmp = $provider->compare_responses($old, $new);
+ $this->assertInternalType('array', $cmp);
+ $this->assertNotEmpty($cmp);
+ $this->assertCount(1, $cmp);
+ $this->assertCount(1, $cmp['core']);
+ $this->assertEquals(2012120100, $cmp['core'][0]['version']);
+ }
+
+ public function test_compare_responses_modified_update() {
+ $provider = testable_available_update_checker::instance();
+ $old = array(
+ 'updates' => array(
+ 'mod_foo' => array(
+ array(
+ 'version' => 2011010101
+ )
+ )
+ )
+ );
+ $new = array(
+ 'updates' => array(
+ 'mod_foo' => array(
+ array(
+ 'version' => 2011010102
+ )
+ )
+ )
+ );
+ $cmp = $provider->compare_responses($old, $new);
+ $this->assertInternalType('array', $cmp);
+ $this->assertNotEmpty($cmp);
+ $this->assertCount(1, $cmp);
+ $this->assertCount(1, $cmp['mod_foo']);
+ $this->assertEquals(2011010102, $cmp['mod_foo'][0]['version']);
+ }
+
+ public function test_compare_responses_invalid_format() {
+ $provider = testable_available_update_checker::instance();
+ $broken = array(
+ 'status' => 'ERROR' // No 'updates' key here.
+ );
+ $this->setExpectedException('available_update_checker_exception');
+ $cmp = $provider->compare_responses($broken, $broken);
+ }
+
+ public function test_is_same_release_explicit() {
+ $provider = testable_available_update_checker::instance();
+ $this->assertTrue($provider->is_same_release('2.3dev (Build: 20120323)', '2.3dev (Build: 20120323)'));
+ $this->assertTrue($provider->is_same_release('2.3dev (Build: 20120323)', '2.3dev (Build: 20120330)'));
+ $this->assertFalse($provider->is_same_release('2.3dev (Build: 20120529)', '2.3 (Build: 20120601)'));
+ $this->assertFalse($provider->is_same_release('2.3dev', '2.3 dev'));
+ $this->assertFalse($provider->is_same_release('2.3.1', '2.3'));
+ $this->assertFalse($provider->is_same_release('2.3.1', '2.3.2'));
+ $this->assertTrue($provider->is_same_release('2.3.2+', '2.3.2')); // Yes, really!
+ $this->assertTrue($provider->is_same_release('2.3.2 (Build: 123456)', '2.3.2+ (Build: 123457)'));
+ $this->assertFalse($provider->is_same_release('3.0 Community Edition', '3.0 Enterprise Edition'));
+ $this->assertTrue($provider->is_same_release('3.0 Community Edition', '3.0 Community Edition (Build: 20290101)'));
+ }
+
+ public function test_is_same_release_implicit() {
+ $provider = testable_available_update_checker::instance();
+ $provider->fake_current_environment(2012060102.00, '2.3.2 (Build: 20121012)', '2.3', array());
+ $this->assertTrue($provider->is_same_release('2.3.2'));
+ $this->assertTrue($provider->is_same_release('2.3.2+'));
+ $this->assertTrue($provider->is_same_release('2.3.2+ (Build: 20121013)'));
+ $this->assertFalse($provider->is_same_release('2.4dev (Build: 20121012)'));
+ }
+}
diff --git a/lib/tests/available_update_deployer_test.php b/lib/tests/available_update_deployer_test.php
new file mode 100644
index 0000000000000..23e75c52d8ce5
--- /dev/null
+++ b/lib/tests/available_update_deployer_test.php
@@ -0,0 +1,209 @@
+.
+
+/**
+ * Unit tests for the update deployer.
+ *
+ * @package core
+ * @category phpunit
+ * @copyright 2012 David Mudrak
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->libdir.'/pluginlib.php');
+
+
+/**
+ * Test cases for {@link available_update_deployer} class.
+ */
+class core_available_update_deployer_testcase extends advanced_testcase {
+
+ public function test_magic_setters() {
+ $deployer = testable_available_update_deployer::instance();
+ $value = new moodle_url('/');
+ $deployer->set_returnurl($value);
+ $this->assertSame($deployer->get_returnurl(), $value);
+ }
+
+ public function test_prepare_authorization() {
+ global $CFG;
+
+ $deployer = testable_available_update_deployer::instance();
+ list($passfile, $password) = $deployer->prepare_authorization();
+ $filename = $CFG->phpunit_dataroot.'/mdeploy/auth/'.$passfile;
+ $this->assertFileExists($filename);
+ $stored = file($filename, FILE_IGNORE_NEW_LINES);
+ $this->assertCount(2, $stored);
+ $this->assertGreaterThan(23, strlen($stored[0]));
+ $this->assertSame($stored[0], $password);
+ $this->assertLessThan(60, time() - (int)$stored[1]);
+ }
+}
+
+
+/**
+ * Modified version of {@link available_update_checker} suitable for testing.
+ */
+class testable_available_update_checker extends available_update_checker {
+
+ /** @var replaces the default DB table storage for the fetched response */
+ protected $fakeresponsestorage;
+ /** @var int stores the fake recentfetch value */
+ public $fakerecentfetch = -1;
+ /** @var int stores the fake value of time() */
+ public $fakecurrenttimestamp = -1;
+
+ /**
+ * Factory method for this class.
+ *
+ * @return testable_available_update_checker the singleton instance
+ */
+ public static function instance() {
+ global $CFG;
+
+ if (is_null(self::$singletoninstance)) {
+ self::$singletoninstance = new self();
+ }
+ return self::$singletoninstance;
+ }
+
+ protected function validate_response($response) {
+ }
+
+ protected function store_response($response) {
+ $this->fakeresponsestorage = $response;
+ }
+
+ protected function restore_response($forcereload = false) {
+ $this->recentfetch = time();
+ $this->recentresponse = $this->decode_response($this->get_fake_response());
+ }
+
+ public function compare_responses(array $old, array $new) {
+ return parent::compare_responses($old, $new);
+ }
+
+ public function is_same_release($remote, $local=null) {
+ return parent::is_same_release($remote, $local);
+ }
+
+ protected function load_current_environment($forcereload=false) {
+ }
+
+ public function fake_current_environment($version, $release, $branch, array $plugins) {
+ $this->currentversion = $version;
+ $this->currentrelease = $release;
+ $this->currentbranch = $branch;
+ $this->currentplugins = $plugins;
+ }
+
+ public function get_last_timefetched() {
+ if ($this->fakerecentfetch == -1) {
+ return parent::get_last_timefetched();
+ } else {
+ return $this->fakerecentfetch;
+ }
+ }
+
+ private function get_fake_response() {
+ $fakeresponse = array(
+ 'status' => 'OK',
+ 'provider' => 'http://download.moodle.org/api/1.0/updates.php',
+ 'apiver' => '1.0',
+ 'timegenerated' => time(),
+ 'forversion' => '2012010100.00',
+ 'forbranch' => '2.3',
+ 'ticket' => sha1('No, I am not going to mention the word "frog" here. Oh crap. I just did.'),
+ 'updates' => array(
+ 'core' => array(
+ array(
+ 'version' => 2012060103.00,
+ 'release' => '2.3.3 (Build: 20121201)',
+ 'maturity' => 200,
+ 'url' => 'http://download.moodle.org/',
+ 'download' => 'http://download.moodle.org/download.php/MOODLE_23_STABLE/moodle-2.3.3-latest.zip',
+ ),
+ array(
+ 'version' => 2012120100.00,
+ 'release' => '2.4dev (Build: 20121201)',
+ 'maturity' => 50,
+ 'url' => 'http://download.moodle.org/',
+ 'download' => 'http://download.moodle.org/download.php/MOODLE_24_STABLE/moodle-2.4.0-latest.zip',
+ ),
+ ),
+ 'mod_foo' => array(
+ array(
+ 'version' => 2012030501,
+ 'requires' => 2012010100,
+ 'maturity' => 200,
+ 'release' => '1.1',
+ 'url' => 'http://moodle.org/plugins/blahblahblah/',
+ 'download' => 'http://moodle.org/plugins/download.php/blahblahblah',
+ ),
+ array(
+ 'version' => 2012030502,
+ 'requires' => 2012010100,
+ 'maturity' => 100,
+ 'release' => '1.2 beta',
+ 'url' => 'http://moodle.org/plugins/',
+ ),
+ ),
+ ),
+ );
+
+ return json_encode($fakeresponse);
+ }
+
+ protected function cron_current_timestamp() {
+ if ($this->fakecurrenttimestamp == -1) {
+ return parent::cron_current_timestamp();
+ } else {
+ return $this->fakecurrenttimestamp;
+ }
+ }
+
+ protected function cron_mtrace($msg, $eol = PHP_EOL) {
+ }
+
+ protected function cron_autocheck_enabled() {
+ return true;
+ }
+
+ protected function cron_execution_offset() {
+ // Autofetch should run by the first cron after 01:42 AM.
+ return 42 * MINSECS;
+ }
+
+ protected function cron_execute() {
+ throw new testable_available_update_checker_cron_executed('Cron executed!');
+ }
+}
+
+
+/**
+ * Exception used to detect {@link available_update_checker::cron_execute()} calls.
+ */
+class testable_available_update_checker_cron_executed extends Exception {
+}
+
+/**
+ * Modified {@link available_update_deployer} suitable for testing purposes.
+ */
+class testable_available_update_deployer extends available_update_deployer {
+}
diff --git a/lib/tests/fixtures/mockplugins/mod/bar/version.php b/lib/tests/fixtures/mockplugins/mod/bar/version.php
deleted file mode 100644
index 47613f65a4c4a..0000000000000
--- a/lib/tests/fixtures/mockplugins/mod/bar/version.php
+++ /dev/null
@@ -1,4 +0,0 @@
-version = 2012030500;
-$module->requires = 2012010100;
diff --git a/lib/tests/fixtures/mockplugins/mod/baz/meg/one/version.php b/lib/tests/fixtures/mockplugins/mod/baz/meg/one/version.php
deleted file mode 100644
index b099a779bbfde..0000000000000
--- a/lib/tests/fixtures/mockplugins/mod/baz/meg/one/version.php
+++ /dev/null
@@ -1,5 +0,0 @@
-version = 2013041103;
-$plugin->requires = 2013010100;
-$plugin->component = 'bazmeg_one';
diff --git a/lib/tests/fixtures/mockplugins/mod/baz/version.php b/lib/tests/fixtures/mockplugins/mod/baz/version.php
deleted file mode 100644
index 47613f65a4c4a..0000000000000
--- a/lib/tests/fixtures/mockplugins/mod/baz/version.php
+++ /dev/null
@@ -1,4 +0,0 @@
-version = 2012030500;
-$module->requires = 2012010100;
diff --git a/lib/tests/fixtures/mockplugins/mod/foo/lish/frog/version.php b/lib/tests/fixtures/mockplugins/mod/foo/lish/frog/version.php
deleted file mode 100644
index b5dd0eeba04ec..0000000000000
--- a/lib/tests/fixtures/mockplugins/mod/foo/lish/frog/version.php
+++ /dev/null
@@ -1,6 +0,0 @@
-version = 2013041103;
-$plugin->requires = 2013010100;
-$plugin->component = 'foolish_frog';
-$plugin->dependencies = array('mod_foo' => 2012030500);
diff --git a/lib/tests/fixtures/mockplugins/mod/foo/lish/hippo/version.php b/lib/tests/fixtures/mockplugins/mod/foo/lish/hippo/version.php
deleted file mode 100644
index f64b02d59ffd8..0000000000000
--- a/lib/tests/fixtures/mockplugins/mod/foo/lish/hippo/version.php
+++ /dev/null
@@ -1,6 +0,0 @@
-version = 2013041103;
-$plugin->requires = 2012010100;
-$plugin->component = 'foolish_hippo';
-$plugin->dependencies = array('foolish_frog' => ANY_VERSION);
diff --git a/lib/tests/fixtures/mockplugins/mod/foo/version.php b/lib/tests/fixtures/mockplugins/mod/foo/version.php
deleted file mode 100644
index a12a76a40dcb3..0000000000000
--- a/lib/tests/fixtures/mockplugins/mod/foo/version.php
+++ /dev/null
@@ -1,10 +0,0 @@
-version = 2012030500;
-$module->requires = 2012010100;
-$module->component = 'mod_foo';
-$module->dependencies = array(
- 'mod_bar' => 2012030500,
- 'mod_missing' => ANY_VERSION,
- 'foolish_frog' => ANY_VERSION,
-);
diff --git a/lib/tests/fixtures/mockplugins/mod/new/version.php b/lib/tests/fixtures/mockplugins/mod/new/version.php
deleted file mode 100644
index 976ddf1204b77..0000000000000
--- a/lib/tests/fixtures/mockplugins/mod/new/version.php
+++ /dev/null
@@ -1,5 +0,0 @@
-version = 2013041900;
-$module->requires = 2012010100;
-$module->component = 'mod_new';
diff --git a/lib/tests/fixtures/mockplugins/mod/qux/cat/one/version.php b/lib/tests/fixtures/mockplugins/mod/qux/cat/one/version.php
deleted file mode 100644
index 4c9e9781270d7..0000000000000
--- a/lib/tests/fixtures/mockplugins/mod/qux/cat/one/version.php
+++ /dev/null
@@ -1,6 +0,0 @@
-version = 2013041103;
-$plugin->requires = 2013010100;
-$plugin->component = 'quxcat_one';
-$plugin->dependencies = array('bazmeg_one' => 2013010100);
diff --git a/lib/tests/fixtures/mockplugins/mod/qux/version.php b/lib/tests/fixtures/mockplugins/mod/qux/version.php
deleted file mode 100644
index 9c1c5f01a28b5..0000000000000
--- a/lib/tests/fixtures/mockplugins/mod/qux/version.php
+++ /dev/null
@@ -1,5 +0,0 @@
-version = 2013041103;
-$plugin->requires = 2013010100;
-$plugin->component = 'mod_qux';
diff --git a/lib/tests/plugin_manager_test.php b/lib/tests/plugin_manager_test.php
new file mode 100644
index 0000000000000..4a8f3788354e5
--- /dev/null
+++ b/lib/tests/plugin_manager_test.php
@@ -0,0 +1,232 @@
+.
+
+/**
+ * Unit tests for plugin manager class.
+ *
+ * @package core
+ * @category phpunit
+ * @copyright 2013 Petr Skoda {@link http://skodak.org}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->libdir.'/pluginlib.php');
+
+
+/**
+ * Tests of the basic API of the plugin manager.
+ */
+class core_plugin_manager_testcase extends advanced_testcase {
+
+ public function test_instance() {
+ $pluginman = plugin_manager::instance();
+ $this->assertInstanceOf('plugin_manager', $pluginman);
+ $pluginman2 = plugin_manager::instance();
+ $this->assertSame($pluginman, $pluginman2);
+ }
+
+ public function test_reset_caches() {
+ // Make sure there are no warnings or errors.
+ plugin_manager::reset_caches();
+ }
+
+ public function test_get_plugin_types() {
+ // Make sure there are no warnings or errors.
+ $types = plugin_manager::instance()->get_plugin_types();
+ $this->assertInternalType('array', $types);
+ foreach ($types as $type => $fulldir) {
+ $this->assertFileExists($fulldir);
+ }
+ }
+
+ public function test_get_installed_plugins() {
+ $types = plugin_manager::instance()->get_plugin_types();
+ foreach ($types as $type => $fulldir) {
+ $installed = plugin_manager::instance()->get_installed_plugins($type);
+ foreach ($installed as $plugin => $version) {
+ $this->assertRegExp('/^[a-z]+[a-z0-9_]*$/', $plugin);
+ $this->assertTrue(is_numeric($version), 'All plugins should have a version, plugin '.$type.'_'.$plugin.' does not have version info.');
+ }
+ }
+ }
+
+ public function test_get_enabled_plugins() {
+ $types = plugin_manager::instance()->get_plugin_types();
+ foreach ($types as $type => $fulldir) {
+ $enabled = plugin_manager::instance()->get_enabled_plugins($type);
+ if (is_array($enabled)) {
+ foreach ($enabled as $key => $val) {
+ $this->assertRegExp('/^[a-z]+[a-z0-9_]*$/', $key);
+ $this->assertSame($key, $val);
+ }
+ } else {
+ $this->assertNull($enabled);
+ }
+ }
+ }
+
+ public function test_get_present_plugins() {
+ $types = plugin_manager::instance()->get_plugin_types();
+ foreach ($types as $type => $fulldir) {
+ $present = plugin_manager::instance()->get_present_plugins($type);
+ if (is_array($present)) {
+ foreach ($present as $plugin => $version) {
+ $this->assertRegExp('/^[a-z]+[a-z0-9_]*$/', $plugin, 'All plugins are supposed to have version.php file.');
+ $this->assertInternalType('object', $version);
+ $this->assertTrue(is_numeric($version->version), 'All plugins should have a version, plugin '.$type.'_'.$plugin.' does not have version info.');
+ }
+ } else {
+ // No plugins of this type exist.
+ $this->assertNull($present);
+ }
+ }
+ }
+
+ public function test_get_plugins() {
+ $plugininfos = plugin_manager::instance()->get_plugins();
+ foreach ($plugininfos as $type => $infos) {
+ foreach ($infos as $name => $info) {
+ $this->assertInstanceOf('plugininfo_base', $info);
+ }
+ }
+ }
+
+ public function test_get_plugins_of_type() {
+ $plugininfos = plugin_manager::instance()->get_plugins();
+ foreach ($plugininfos as $type => $infos) {
+ $this->assertSame($infos, plugin_manager::instance()->get_plugins_of_type($type));
+ }
+ }
+
+ public function test_get_subplugins_of_plugin() {
+ global $CFG;
+
+ // Any standard plugin with subplugins is suitable.
+ $this->assertFileExists("$CFG->dirroot/lib/editor/tinymce", 'TinyMCE is not present.');
+
+ $subplugins = plugin_manager::instance()->get_subplugins_of_plugin('editor_tinymce');
+ foreach ($subplugins as $component => $info) {
+ $this->assertInstanceOf('plugininfo_base', $info);
+ }
+ }
+
+ public function test_get_subplugins() {
+ // Tested already indirectly from test_get_subplugins_of_plugin().
+ $subplugins = plugin_manager::instance()->get_subplugins();
+ $this->assertInternalType('array', $subplugins);
+ }
+
+ public function test_get_parent_of_subplugin() {
+ global $CFG;
+
+ // Any standard plugin with subplugins is suitable.
+ $this->assertFileExists("$CFG->dirroot/lib/editor/tinymce", 'TinyMCE is not present.');
+
+ $parent = plugin_manager::instance()->get_parent_of_subplugin('tinymce');
+ $this->assertSame('editor_tinymce', $parent);
+ }
+
+ public function test_plugin_name() {
+ global $CFG;
+
+ // Any standard plugin is suitable.
+ $this->assertFileExists("$CFG->dirroot/lib/editor/tinymce", 'TinyMCE is not present.');
+
+ $name = plugin_manager::instance()->plugin_name('editor_tinymce');
+ $this->assertSame(get_string('pluginname', 'editor_tinymce'), $name);
+ }
+
+ public function test_plugintype_name() {
+ $name = plugin_manager::instance()->plugintype_name('editor');
+ $this->assertSame(get_string('type_editor', 'core_plugin'), $name);
+ }
+
+ public function test_plugintype_name_plural() {
+ $name = plugin_manager::instance()->plugintype_name_plural('editor');
+ $this->assertSame(get_string('type_editor_plural', 'core_plugin'), $name);
+ }
+
+ public function test_get_plugin_info() {
+ global $CFG;
+
+ // Any standard plugin is suitable.
+ $this->assertFileExists("$CFG->dirroot/lib/editor/tinymce", 'TinyMCE is not present.');
+
+ $info = plugin_manager::instance()->get_plugin_info('editor_tinymce');
+ $this->assertInstanceOf('plugininfo_editor', $info);
+ }
+
+ public function test_can_uninstall_plugin() {
+ global $CFG;
+
+ // Any standard plugin that is required by some other standard plugin is ok.
+ $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/assignmentupgrade", 'assign upgrade tool is not present');
+ $this->assertFileExists("$CFG->dirroot/mod/assign", 'assign module is not present');
+
+ $this->assertFalse(plugin_manager::instance()->can_uninstall_plugin('mod_assign'));
+ $this->assertTrue(plugin_manager::instance()->can_uninstall_plugin('tool_assignmentupgrade'));
+ }
+
+ public function test_plugin_states() {
+ global $CFG;
+ $this->resetAfterTest();
+
+ // Any standard plugin that is ok.
+ $this->assertFileExists("$CFG->dirroot/mod/assign", 'assign module is not present');
+ $this->assertFileExists("$CFG->dirroot/mod/forum", 'forum module is not present');
+ $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/phpunit", 'phpunit tool is not present');
+ $this->assertFileNotExists("$CFG->dirroot/mod/xxxxxxx");
+ $this->assertFileNotExists("$CFG->dirroot/enrol/autorize");
+
+ // Ready for upgrade.
+ $assignversion = get_config('mod_assign', 'version');
+ set_config('version', $assignversion - 1, 'mod_assign');
+ // Downgrade problem.
+ $forumversion = get_config('mod_forum', 'version');
+ set_config('version', $forumversion + 1, 'mod_forum');
+ // Not installed yet.
+ unset_config('version', 'tool_phpunit');
+ // Missing already installed.
+ set_config('version', 2013091300, 'mod_xxxxxxx');
+ // Deleted present.
+ set_config('version', 2013091300, 'enrol_authorize');
+
+ plugin_manager::reset_caches();
+
+ $plugininfos = plugin_manager::instance()->get_plugins();
+ foreach ($plugininfos as $type => $infos) {
+ foreach ($infos as $name => $info) {
+ /** @var plugininfo_base $info */
+ if ($info->component === 'mod_assign') {
+ $this->assertSame(plugin_manager::PLUGIN_STATUS_UPGRADE, $info->get_status(), 'Invalid '.$info->component.' state');
+ } else if ($info->component === 'mod_forum') {
+ $this->assertSame(plugin_manager::PLUGIN_STATUS_DOWNGRADE, $info->get_status(), 'Invalid '.$info->component.' state');
+ } else if ($info->component === 'tool_phpunit') {
+ $this->assertSame(plugin_manager::PLUGIN_STATUS_NEW, $info->get_status(), 'Invalid '.$info->component.' state');
+ } else if ($info->component === 'mod_xxxxxxx') {
+ $this->assertSame(plugin_manager::PLUGIN_STATUS_MISSING, $info->get_status(), 'Invalid '.$info->component.' state');
+ } else if ($info->component === 'enrol_authorize') {
+ $this->assertSame(plugin_manager::PLUGIN_STATUS_DELETE, $info->get_status(), 'Invalid '.$info->component.' state');
+ } else {
+ $this->assertSame(plugin_manager::PLUGIN_STATUS_UPTODATE, $info->get_status(), 'Invalid '.$info->component.' state');
+ }
+ }
+ }
+ }
+}
diff --git a/lib/tests/pluginlib_test.php b/lib/tests/pluginlib_test.php
deleted file mode 100644
index d6f47d135fb50..0000000000000
--- a/lib/tests/pluginlib_test.php
+++ /dev/null
@@ -1,950 +0,0 @@
-.
-
-/**
- * Unit tests for the lib/pluginlib.php library
- *
- * Execute the core_plugin group to run all tests in this file:
- *
- * $ phpunit --group core_plugin
- *
- * @package core
- * @category phpunit
- * @copyright 2012 David Mudrak
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-global $CFG;
-require_once($CFG->libdir.'/pluginlib.php');
-
-
-/**
- * Tests of the basic API of the plugin manager.
- *
- * @group core_plugin
- */
-class core_plugin_manager_testcase extends advanced_testcase {
-
- public function setUp() {
- $this->resetAfterTest();
- }
-
- public function test_plugin_manager_instance() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertInstanceOf('testable_plugin_manager', $pluginman);
- }
-
- public function test_get_plugins_of_type() {
- $pluginman = testable_plugin_manager::instance();
- $mods = $pluginman->get_plugins_of_type('mod');
- $this->assertInternalType('array', $mods);
- $this->assertCount(5, $mods);
- $this->assertInstanceOf('testable_plugininfo_mod', $mods['foo']);
- $this->assertInstanceOf('testable_plugininfo_mod', $mods['bar']);
- $this->assertInstanceOf('testable_plugininfo_mod', $mods['baz']);
- $this->assertInstanceOf('testable_plugininfo_mod', $mods['qux']);
- $this->assertInstanceOf('testable_plugininfo_mod', $mods['new']);
- $foolishes = $pluginman->get_plugins_of_type('foolish');
- $this->assertCount(2, $foolishes);
- $this->assertInstanceOf('testable_pluginfo_foolish', $foolishes['frog']);
- $this->assertInstanceOf('testable_pluginfo_foolish', $foolishes['hippo']);
- $bazmegs = $pluginman->get_plugins_of_type('bazmeg');
- $this->assertCount(1, $bazmegs);
- $this->assertInstanceOf('testable_pluginfo_bazmeg', $bazmegs['one']);
- $quxcats = $pluginman->get_plugins_of_type('quxcat');
- $this->assertCount(1, $quxcats);
- $this->assertInstanceOf('testable_pluginfo_quxcat', $quxcats['one']);
- $unknown = $pluginman->get_plugins_of_type('muhehe');
- $this->assertSame(array(), $unknown);
- }
-
- public function test_get_plugins() {
- $pluginman = testable_plugin_manager::instance();
- $plugins = $pluginman->get_plugins();
- $this->assertInternalType('array', $plugins);
- $this->assertTrue(isset($plugins['mod']['foo']));
- $this->assertTrue(isset($plugins['mod']['bar']));
- $this->assertTrue(isset($plugins['mod']['baz']));
- $this->assertTrue(isset($plugins['mod']['new']));
- $this->assertTrue(isset($plugins['foolish']['frog']));
- $this->assertTrue(isset($plugins['foolish']['hippo']));
- $this->assertInstanceOf('testable_plugininfo_mod', $plugins['mod']['foo']);
- $this->assertInstanceOf('testable_plugininfo_mod', $plugins['mod']['bar']);
- $this->assertInstanceOf('testable_plugininfo_mod', $plugins['mod']['baz']);
- $this->assertInstanceOf('testable_plugininfo_mod', $plugins['mod']['new']);
- $this->assertInstanceOf('testable_pluginfo_foolish', $plugins['foolish']['frog']);
- $this->assertInstanceOf('testable_pluginfo_foolish', $plugins['foolish']['hippo']);
- $this->assertInstanceOf('testable_pluginfo_bazmeg', $plugins['bazmeg']['one']);
- $this->assertInstanceOf('testable_pluginfo_quxcat', $plugins['quxcat']['one']);
- }
-
- public function test_get_subplugins_of_plugin() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertSame(array(), $pluginman->get_subplugins_of_plugin('mod_missing'));
- $this->assertSame(array(), $pluginman->get_subplugins_of_plugin('mod_bar'));
- $foosubs = $pluginman->get_subplugins_of_plugin('mod_foo');
- $this->assertInternalType('array', $foosubs);
- $this->assertCount(2, $foosubs);
- $this->assertInstanceOf('testable_pluginfo_foolish', $foosubs['foolish_frog']);
- $this->assertInstanceOf('testable_pluginfo_foolish', $foosubs['foolish_hippo']);
- $bazsubs = $pluginman->get_subplugins_of_plugin('mod_baz');
- $this->assertInternalType('array', $bazsubs);
- $this->assertCount(1, $bazsubs);
- $this->assertInstanceOf('testable_pluginfo_bazmeg', $bazsubs['bazmeg_one']);
- $quxsubs = $pluginman->get_subplugins_of_plugin('mod_qux');
- $this->assertInternalType('array', $quxsubs);
- $this->assertCount(1, $quxsubs);
- $this->assertInstanceOf('testable_pluginfo_quxcat', $quxsubs['quxcat_one']);
- }
-
- public function test_get_subplugins() {
- $pluginman = testable_plugin_manager::instance();
- $subplugins = $pluginman->get_subplugins();
- $this->assertTrue(isset($subplugins['mod_foo']['foolish']));
- $this->assertTrue(isset($subplugins['mod_baz']['bazmeg']));
- $this->assertTrue(isset($subplugins['mod_qux']['quxcat']));
- }
-
- public function test_get_parent_of_subplugin() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertSame('mod_foo', $pluginman->get_parent_of_subplugin('foolish'));
- $this->assertSame('mod_baz', $pluginman->get_parent_of_subplugin('bazmeg'));
- $this->assertSame('mod_qux', $pluginman->get_parent_of_subplugin('quxcat'));
- $this->assertFalse($pluginman->get_parent_of_subplugin('mod'));
- $this->assertFalse($pluginman->get_parent_of_subplugin('unknown'));
- $plugins = $pluginman->get_plugins();
- $this->assertFalse($plugins['mod']['foo']->is_subplugin());
- $this->assertFalse($plugins['mod']['foo']->get_parent_plugin());
- $this->assertTrue($plugins['foolish']['frog']->is_subplugin());
- $this->assertSame('mod_foo', $plugins['foolish']['frog']->get_parent_plugin());
- }
-
- public function test_plugin_name() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertSame('Foo', $pluginman->plugin_name('mod_foo'));
- $this->assertSame('Bar', $pluginman->plugin_name('mod_bar'));
- $this->assertSame('Frog', $pluginman->plugin_name('foolish_frog'));
- $this->assertSame('Hippo', $pluginman->plugin_name('foolish_hippo'));
- $this->assertSame('One', $pluginman->plugin_name('bazmeg_one'));
- $this->assertSame('One', $pluginman->plugin_name('quxcat_one'));
- }
-
- public function test_get_plugin_info() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertInstanceOf('testable_plugininfo_mod', $pluginman->get_plugin_info('mod_foo'));
- $this->assertInstanceOf('testable_pluginfo_foolish', $pluginman->get_plugin_info('foolish_frog'));
- }
-
- public function test_other_plugins_that_require() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertEquals(array('foolish_frog'), $pluginman->other_plugins_that_require('mod_foo'));
- $this->assertCount(2, $pluginman->other_plugins_that_require('foolish_frog'));
- $this->assertContains('foolish_hippo', $pluginman->other_plugins_that_require('foolish_frog'));
- $this->assertContains('mod_foo', $pluginman->other_plugins_that_require('foolish_frog'));
- $this->assertEquals(array(), $pluginman->other_plugins_that_require('foolish_hippo'));
- $this->assertEquals(array('mod_foo'), $pluginman->other_plugins_that_require('mod_bar'));
- $this->assertEquals(array('mod_foo'), $pluginman->other_plugins_that_require('mod_missing'));
- $this->assertEquals(array('quxcat_one'), $pluginman->other_plugins_that_require('bazmeg_one'));
- }
-
- public function test_are_dependencies_satisfied() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertTrue($pluginman->are_dependencies_satisfied(array()));
- $this->assertTrue($pluginman->are_dependencies_satisfied(array(
- 'mod_bar' => 2012030500,
- )));
- $this->assertTrue($pluginman->are_dependencies_satisfied(array(
- 'mod_bar' => ANY_VERSION,
- )));
- $this->assertFalse($pluginman->are_dependencies_satisfied(array(
- 'mod_bar' => 2099010000,
- )));
- $this->assertFalse($pluginman->are_dependencies_satisfied(array(
- 'mod_bar' => 2012030500,
- 'mod_missing' => ANY_VERSION,
- )));
- }
-
- public function test_all_plugins_ok() {
- $pluginman = testable_plugin_manager::instance();
- $failedplugins = array();
- $this->assertFalse($pluginman->all_plugins_ok(2013010100, $failedplugins));
- $this->assertContains('mod_foo', $failedplugins); // Requires mod_missing.
- $this->assertNotContains('mod_bar', $failedplugins);
- $this->assertNotContains('foolish_frog', $failedplugins);
- $this->assertNotContains('foolish_hippo', $failedplugins);
-
- $failedplugins = array();
- $this->assertFalse($pluginman->all_plugins_ok(2012010100, $failedplugins));
- $this->assertContains('mod_foo', $failedplugins); // Requires mod_missing.
- $this->assertNotContains('mod_bar', $failedplugins);
- $this->assertContains('foolish_frog', $failedplugins); // Requires Moodle 2013010100.
- $this->assertNotContains('foolish_hippo', $failedplugins);
-
- $failedplugins = array();
- $this->assertFalse($pluginman->all_plugins_ok(2011010100, $failedplugins));
- $this->assertContains('mod_foo', $failedplugins); // Requires mod_missing and Moodle 2012010100.
- $this->assertContains('mod_bar', $failedplugins); // Requires Moodle 2012010100.
- $this->assertContains('foolish_frog', $failedplugins); // Requires Moodle 2013010100.
- $this->assertContains('foolish_hippo', $failedplugins); // Requires Moodle 2012010100.
- }
-
- public function test_some_plugins_updatable() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertTrue($pluginman->some_plugins_updatable()); // We have available update for mod_foo.
- }
-
- public function test_is_standard() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertTrue($pluginman->get_plugin_info('mod_bar')->is_standard());
- $this->assertFalse($pluginman->get_plugin_info('mod_foo')->is_standard());
- $this->assertFalse($pluginman->get_plugin_info('foolish_frog')->is_standard());
- }
-
- public function test_get_status() {
- $pluginman = testable_plugin_manager::instance();
- $plugins = $pluginman->get_plugins();
- $this->assertEquals(plugin_manager::PLUGIN_STATUS_UPGRADE, $plugins['mod']['foo']->get_status());
- $this->assertEquals(plugin_manager::PLUGIN_STATUS_NEW, $plugins['mod']['new']->get_status());
- $this->assertEquals(plugin_manager::PLUGIN_STATUS_NEW, $plugins['bazmeg']['one']->get_status());
- $this->assertEquals(plugin_manager::PLUGIN_STATUS_UPTODATE, $plugins['quxcat']['one']->get_status());
- }
-
- public function test_available_update() {
- $pluginman = testable_plugin_manager::instance();
- $plugins = $pluginman->get_plugins();
- $this->assertNull($plugins['mod']['bar']->available_updates());
- $this->assertInternalType('array', $plugins['mod']['foo']->available_updates());
- foreach ($plugins['mod']['foo']->available_updates() as $availableupdate) {
- $this->assertInstanceOf('available_update_info', $availableupdate);
- }
- }
-
- public function test_can_uninstall_plugin() {
- $pluginman = testable_plugin_manager::instance();
- $this->assertFalse($pluginman->can_uninstall_plugin('mod_missing'));
- $this->assertTrue($pluginman->can_uninstall_plugin('mod_foo')); // Because mod_foo is required by foolish_frog only
- // and foolish_frog is required by mod_foo and foolish_hippo only.
- $this->assertFalse($pluginman->can_uninstall_plugin('mod_bar')); // Because mod_bar is required by mod_foo.
- $this->assertFalse($pluginman->can_uninstall_plugin('mod_qux')); // Because even if no plugin (not even subplugins) declare
- // dependency on it, but its subplugin can't be uninstalled.
- $this->assertFalse($pluginman->can_uninstall_plugin('mod_baz')); // Because it's subplugin bazmeg_one is required by quxcat_one.
- $this->assertFalse($pluginman->can_uninstall_plugin('mod_new')); // Because it is not installed.
- $this->assertFalse($pluginman->can_uninstall_plugin('quxcat_one')); // Because of testable_pluginfo_quxcat::is_uninstall_allowed().
- $this->assertFalse($pluginman->can_uninstall_plugin('foolish_frog')); // Because foolish_hippo requires it.
- }
-
- public function test_get_uninstall_url() {
- $pluginman = testable_plugin_manager::instance();
- foreach ($pluginman->get_plugins() as $plugintype => $plugininfos) {
- foreach ($plugininfos as $plugininfo) {
- $this->assertInstanceOf('moodle_url', $plugininfo->get_uninstall_url());
- }
- }
- }
-}
-
-
-/**
- * Tests of the basic API of the available update checker.
- *
- * @group core_plugin
- */
-class core_available_update_checker_testcase extends advanced_testcase {
-
- public function test_core_available_update() {
- $provider = testable_available_update_checker::instance();
- $this->assertInstanceOf('available_update_checker', $provider);
-
- $provider->fake_current_environment(2012060102.00, '2.3.2 (Build: 20121012)', '2.3', array());
- $updates = $provider->get_update_info('core');
- $this->assertCount(2, $updates);
-
- $provider->fake_current_environment(2012060103.00, '2.3.3 (Build: 20121212)', '2.3', array());
- $updates = $provider->get_update_info('core');
- $this->assertCount(1, $updates);
-
- $provider->fake_current_environment(2012060103.00, '2.3.3 (Build: 20121212)', '2.3', array());
- $updates = $provider->get_update_info('core', array('minmaturity' => MATURITY_STABLE));
- $this->assertNull($updates);
- }
-
- /**
- * If there are no fetched data yet, the first cron should fetch them.
- */
- public function test_cron_initial_fetch() {
- $provider = testable_available_update_checker::instance();
- $provider->fakerecentfetch = null;
- $provider->fakecurrenttimestamp = -1;
- $this->setExpectedException('testable_available_update_checker_cron_executed');
- $provider->cron();
- }
-
- /**
- * If there is a fresh fetch available, no cron execution is expected.
- */
- public function test_cron_has_fresh_fetch() {
- $provider = testable_available_update_checker::instance();
- $provider->fakerecentfetch = time() - 23 * HOURSECS; // Fetched 23 hours ago.
- $provider->fakecurrenttimestamp = -1;
- $provider->cron();
- $this->assertTrue(true); // We should get here with no exception thrown.
- }
-
- /**
- * If there is an outdated fetch, the cron execution is expected.
- */
- public function test_cron_has_outdated_fetch() {
- $provider = testable_available_update_checker::instance();
- $provider->fakerecentfetch = time() - 49 * HOURSECS; // Fetched 49 hours ago.
- $provider->fakecurrenttimestamp = -1;
- $this->setExpectedException('testable_available_update_checker_cron_executed');
- $provider->cron();
- }
-
- /**
- * The first cron after 01:42 AM today should fetch the data.
- *
- * @see testable_available_update_checker::cron_execution_offset()
- */
- public function test_cron_offset_execution_not_yet() {
- $provider = testable_available_update_checker::instance();
- $provider->fakecurrenttimestamp = mktime(1, 40, 02); // 01:40:02 AM today
- $provider->fakerecentfetch = $provider->fakecurrenttimestamp - 24 * HOURSECS;
- $provider->cron();
- $this->assertTrue(true); // We should get here with no exception thrown.
- }
-
- /**
- * The first cron after 01:42 AM today should fetch the data and then
- * it is supposed to wait next 24 hours.
- *
- * @see testable_available_update_checker::cron_execution_offset()
- */
- public function test_cron_offset_execution() {
- $provider = testable_available_update_checker::instance();
-
- // The cron at 01:45 should fetch the data.
- $provider->fakecurrenttimestamp = mktime(1, 45, 02); // 01:45:02 AM today
- $provider->fakerecentfetch = $provider->fakecurrenttimestamp - 24 * HOURSECS - 1;
- $executed = false;
- try {
- $provider->cron();
- } catch (testable_available_update_checker_cron_executed $e) {
- $executed = true;
- }
- $this->assertTrue($executed, 'Cron should be executed at 01:45:02 but it was not.');
-
- // Another cron at 06:45 should still consider data as fresh enough.
- $provider->fakerecentfetch = $provider->fakecurrenttimestamp;
- $provider->fakecurrenttimestamp = mktime(6, 45, 03); // 06:45:03 AM
- $executed = false;
- try {
- $provider->cron();
- } catch (testable_available_update_checker_cron_executed $e) {
- $executed = true;
- }
- $this->assertFalse($executed, 'Cron should not be executed at 06:45:03 but it was.');
-
- // The next scheduled execution should happen the next day.
- $provider->fakecurrenttimestamp = $provider->fakerecentfetch + 24 * HOURSECS + 1;
- $executed = false;
- try {
- $provider->cron();
- } catch (testable_available_update_checker_cron_executed $e) {
- $executed = true;
- }
- $this->assertTrue($executed, 'Cron should be executed the next night but it was not.');
- }
-
- public function test_compare_responses_both_empty() {
- $provider = testable_available_update_checker::instance();
- $old = array();
- $new = array();
- $cmp = $provider->compare_responses($old, $new);
- $this->assertInternalType('array', $cmp);
- $this->assertEmpty($cmp);
- }
-
- public function test_compare_responses_old_empty() {
- $provider = testable_available_update_checker::instance();
- $old = array();
- $new = array(
- 'updates' => array(
- 'core' => array(
- array(
- 'version' => 2012060103
- )
- )
- )
- );
- $cmp = $provider->compare_responses($old, $new);
- $this->assertInternalType('array', $cmp);
- $this->assertNotEmpty($cmp);
- $this->assertTrue(isset($cmp['core'][0]['version']));
- $this->assertEquals(2012060103, $cmp['core'][0]['version']);
- }
-
- public function test_compare_responses_no_change() {
- $provider = testable_available_update_checker::instance();
- $old = $new = array(
- 'updates' => array(
- 'core' => array(
- array(
- 'version' => 2012060104
- ),
- array(
- 'version' => 2012120100
- )
- ),
- 'mod_foo' => array(
- array(
- 'version' => 2011010101
- )
- )
- )
- );
- $cmp = $provider->compare_responses($old, $new);
- $this->assertInternalType('array', $cmp);
- $this->assertEmpty($cmp);
- }
-
- public function test_compare_responses_new_and_missing_update() {
- $provider = testable_available_update_checker::instance();
- $old = array(
- 'updates' => array(
- 'core' => array(
- array(
- 'version' => 2012060104
- )
- ),
- 'mod_foo' => array(
- array(
- 'version' => 2011010101
- )
- )
- )
- );
- $new = array(
- 'updates' => array(
- 'core' => array(
- array(
- 'version' => 2012060104
- ),
- array(
- 'version' => 2012120100
- )
- )
- )
- );
- $cmp = $provider->compare_responses($old, $new);
- $this->assertInternalType('array', $cmp);
- $this->assertNotEmpty($cmp);
- $this->assertCount(1, $cmp);
- $this->assertCount(1, $cmp['core']);
- $this->assertEquals(2012120100, $cmp['core'][0]['version']);
- }
-
- public function test_compare_responses_modified_update() {
- $provider = testable_available_update_checker::instance();
- $old = array(
- 'updates' => array(
- 'mod_foo' => array(
- array(
- 'version' => 2011010101
- )
- )
- )
- );
- $new = array(
- 'updates' => array(
- 'mod_foo' => array(
- array(
- 'version' => 2011010102
- )
- )
- )
- );
- $cmp = $provider->compare_responses($old, $new);
- $this->assertInternalType('array', $cmp);
- $this->assertNotEmpty($cmp);
- $this->assertCount(1, $cmp);
- $this->assertCount(1, $cmp['mod_foo']);
- $this->assertEquals(2011010102, $cmp['mod_foo'][0]['version']);
- }
-
- public function test_compare_responses_invalid_format() {
- $provider = testable_available_update_checker::instance();
- $broken = array(
- 'status' => 'ERROR' // No 'updates' key here.
- );
- $this->setExpectedException('available_update_checker_exception');
- $cmp = $provider->compare_responses($broken, $broken);
- }
-
- public function test_is_same_release_explicit() {
- $provider = testable_available_update_checker::instance();
- $this->assertTrue($provider->is_same_release('2.3dev (Build: 20120323)', '2.3dev (Build: 20120323)'));
- $this->assertTrue($provider->is_same_release('2.3dev (Build: 20120323)', '2.3dev (Build: 20120330)'));
- $this->assertFalse($provider->is_same_release('2.3dev (Build: 20120529)', '2.3 (Build: 20120601)'));
- $this->assertFalse($provider->is_same_release('2.3dev', '2.3 dev'));
- $this->assertFalse($provider->is_same_release('2.3.1', '2.3'));
- $this->assertFalse($provider->is_same_release('2.3.1', '2.3.2'));
- $this->assertTrue($provider->is_same_release('2.3.2+', '2.3.2')); // Yes, really!
- $this->assertTrue($provider->is_same_release('2.3.2 (Build: 123456)', '2.3.2+ (Build: 123457)'));
- $this->assertFalse($provider->is_same_release('3.0 Community Edition', '3.0 Enterprise Edition'));
- $this->assertTrue($provider->is_same_release('3.0 Community Edition', '3.0 Community Edition (Build: 20290101)'));
- }
-
- public function test_is_same_release_implicit() {
- $provider = testable_available_update_checker::instance();
- $provider->fake_current_environment(2012060102.00, '2.3.2 (Build: 20121012)', '2.3', array());
- $this->assertTrue($provider->is_same_release('2.3.2'));
- $this->assertTrue($provider->is_same_release('2.3.2+'));
- $this->assertTrue($provider->is_same_release('2.3.2+ (Build: 20121013)'));
- $this->assertFalse($provider->is_same_release('2.4dev (Build: 20121012)'));
- }
-}
-
-
-/**
- * Base class for testable plugininfo classes.
- */
-class testable_plugininfo_base extends plugininfo_base {
-
- protected function get_plugin_manager() {
- return testable_plugin_manager::instance();
- }
-}
-
-
-/**
- * Modified {@link plugininfo_mod} suitable for testing purposes.
- */
-class testable_plugininfo_mod extends plugininfo_mod {
-
- public function init_display_name() {
- $this->displayname = ucfirst($this->name);
- }
-
- public function is_standard() {
- if ($this->component === 'mod_foo') {
- return false;
- } else {
- return true;
- }
- }
-
- public function load_db_version() {
- if ($this->component !== 'mod_new') {
- $this->versiondb = 2012022900;
- }
- }
-
- public function is_uninstall_allowed() {
- return true; // Allow uninstall for standard plugins too.
- }
-
- protected function get_plugin_manager() {
- return testable_plugin_manager::instance();
- }
-}
-
-
-/**
- * Testable class representing subplugins of testable mod_foo.
- */
-class testable_pluginfo_foolish extends testable_plugininfo_base {
-
- public function init_display_name() {
- $this->displayname = ucfirst($this->name);
- }
-
- public function is_standard() {
- return false;
- }
-
- public function load_db_version() {
- $this->versiondb = 2012022900;
- }
-}
-
-
-/**
- * Testable class representing subplugins of testable mod_baz.
- */
-class testable_pluginfo_bazmeg extends testable_plugininfo_base {
-
- public function init_display_name() {
- $this->displayname = ucfirst($this->name);
- }
-
- public function is_standard() {
- return false;
- }
-
- public function load_db_version() {
- $this->versiondb = null;
- }
-}
-
-
-/**
- * Testable class representing subplugins of testable mod_qux.
- */
-class testable_pluginfo_quxcat extends testable_plugininfo_base {
-
- public function init_display_name() {
- $this->displayname = ucfirst($this->name);
- }
-
- public function is_standard() {
- return false;
- }
-
- public function load_db_version() {
- $this->versiondb = 2013041103;
- }
-
- public function is_uninstall_allowed() {
- return false;
- }
-}
-
-
-/**
- * Modified {@link plugin_manager} suitable for testing purposes
- */
-class testable_plugin_manager extends plugin_manager {
-
- /**
- * Factory method for this class
- *
- * @return plugin_manager the singleton instance
- */
- public static function instance() {
- global $CFG;
-
- if (is_null(self::$singletoninstance)) {
- self::$singletoninstance = new self();
- }
- return self::$singletoninstance;
- }
-
- /**
- * A version of {@link plugin_manager::get_plugins()} that prepares some faked
- * testable instances.
- *
- * @param bool $disablecache ignored in this class
- * @return array
- */
- public function get_plugins($disablecache = false) {
-
- $dirroot = dirname(__FILE__).'/fixtures/mockplugins';
-
- $this->pluginsinfo = array(
- 'mod' => array(
- 'foo' => plugininfo_default_factory::make('mod', $dirroot.'/mod', 'foo',
- $dirroot.'/mod/foo', 'testable_plugininfo_mod'),
- 'bar' => plugininfo_default_factory::make('mod', $dirroot.'/bar', 'bar',
- $dirroot.'/mod/bar', 'testable_plugininfo_mod'),
- 'baz' => plugininfo_default_factory::make('mod', $dirroot.'/baz', 'baz',
- $dirroot.'/mod/baz', 'testable_plugininfo_mod'),
- 'qux' => plugininfo_default_factory::make('mod', $dirroot.'/qux', 'qux',
- $dirroot.'/mod/qux', 'testable_plugininfo_mod'),
- 'new' => plugininfo_default_factory::make('mod', $dirroot.'/new', 'new',
- $dirroot.'/mod/new', 'testable_plugininfo_mod'),
- ),
- 'foolish' => array(
- 'frog' => plugininfo_default_factory::make('foolish', $dirroot.'/mod/foo/lish', 'frog',
- $dirroot.'/mod/foo/lish/frog', 'testable_pluginfo_foolish'),
- 'hippo' => plugininfo_default_factory::make('foolish', $dirroot.'/mod/foo/lish', 'hippo',
- $dirroot.'/mod/foo/lish/hippo', 'testable_pluginfo_foolish'),
- ),
- 'bazmeg' => array(
- 'one' => plugininfo_default_factory::make('bazmeg', $dirroot.'/mod/baz/meg', 'one',
- $dirroot.'/mod/baz/meg/one', 'testable_pluginfo_bazmeg'),
- ),
- 'quxcat' => array(
- 'one' => plugininfo_default_factory::make('quxcat', $dirroot.'/mod/qux/cat', 'one',
- $dirroot.'/mod/qux/cat/one', 'testable_pluginfo_quxcat'),
- ),
- );
-
- $checker = testable_available_update_checker::instance();
- $this->pluginsinfo['mod']['foo']->check_available_updates($checker);
- $this->pluginsinfo['mod']['bar']->check_available_updates($checker);
- $this->pluginsinfo['mod']['baz']->check_available_updates($checker);
- $this->pluginsinfo['mod']['new']->check_available_updates($checker);
- $this->pluginsinfo['bazmeg']['one']->check_available_updates($checker);
- $this->pluginsinfo['quxcat']['one']->check_available_updates($checker);
-
- return $this->pluginsinfo;
- }
-
- /**
- * Testable version of {@link plugin_manager::get_subplugins()} that works with
- * the simulated environment.
- *
- * In this case, the mod_foo fake module provides subplugins of type 'foolish',
- * mod_baz provides subplugins of type 'bazmeg' and mod_qux has 'quxcat'.
- *
- * @param bool $disablecache ignored in this class
- * @return array
- */
- public function get_subplugins($disablecache = false) {
-
- $this->subpluginsinfo = array(
- 'mod_foo' => array(
- 'foolish' => (object)array(
- 'type' => 'foolish',
- 'typerootdir' => 'mod/foo/lish',
- ),
- ),
- 'mod_baz' => array(
- 'bazmeg' => (object)array(
- 'type' => 'bazmeg',
- 'typerootdir' => 'mod/baz/meg',
- ),
- ),
- 'mod_qux' => array(
- 'quxcat' => (object)array(
- 'type' => 'quxcat',
- 'typerootdir' => 'mod/qux/cat',
- ),
- ),
- );
-
- return $this->subpluginsinfo;
- }
-
- /**
- * Adds support for mock plugin types.
- */
- protected function normalize_component($component) {
-
- // List of mock plugin types used in these unit tests.
- $faketypes = array('foolish', 'bazmeg', 'quxcat');
-
- foreach ($faketypes as $faketype) {
- if (strpos($component, $faketype.'_') === 0) {
- return explode('_', $component, 2);
- }
- }
-
- return parent::normalize_component($component);
- }
-
- public function plugintype_name($type) {
- return ucfirst($type);
- }
-
- public function plugintype_name_plural($type) {
- return ucfirst($type).'s'; // Simple, isn't it? ;-).
- }
-
- public function plugin_external_source($component) {
- if ($component === 'foolish_frog') {
- return true;
- }
- return false;
- }
-}
-
-
-/**
- * Modified version of {@link available_update_checker} suitable for testing.
- */
-class testable_available_update_checker extends available_update_checker {
-
- /** @var replaces the default DB table storage for the fetched response */
- protected $fakeresponsestorage;
- /** @var int stores the fake recentfetch value */
- public $fakerecentfetch = -1;
- /** @var int stores the fake value of time() */
- public $fakecurrenttimestamp = -1;
-
- /**
- * Factory method for this class.
- *
- * @return testable_available_update_checker the singleton instance
- */
- public static function instance() {
- global $CFG;
-
- if (is_null(self::$singletoninstance)) {
- self::$singletoninstance = new self();
- }
- return self::$singletoninstance;
- }
-
- protected function validate_response($response) {
- }
-
- protected function store_response($response) {
- $this->fakeresponsestorage = $response;
- }
-
- protected function restore_response($forcereload = false) {
- $this->recentfetch = time();
- $this->recentresponse = $this->decode_response($this->get_fake_response());
- }
-
- public function compare_responses(array $old, array $new) {
- return parent::compare_responses($old, $new);
- }
-
- public function is_same_release($remote, $local=null) {
- return parent::is_same_release($remote, $local);
- }
-
- protected function load_current_environment($forcereload=false) {
- }
-
- public function fake_current_environment($version, $release, $branch, array $plugins) {
- $this->currentversion = $version;
- $this->currentrelease = $release;
- $this->currentbranch = $branch;
- $this->currentplugins = $plugins;
- }
-
- public function get_last_timefetched() {
- if ($this->fakerecentfetch == -1) {
- return parent::get_last_timefetched();
- } else {
- return $this->fakerecentfetch;
- }
- }
-
- private function get_fake_response() {
- $fakeresponse = array(
- 'status' => 'OK',
- 'provider' => 'http://download.moodle.org/api/1.0/updates.php',
- 'apiver' => '1.0',
- 'timegenerated' => time(),
- 'forversion' => '2012010100.00',
- 'forbranch' => '2.3',
- 'ticket' => sha1('No, I am not going to mention the word "frog" here. Oh crap. I just did.'),
- 'updates' => array(
- 'core' => array(
- array(
- 'version' => 2012060103.00,
- 'release' => '2.3.3 (Build: 20121201)',
- 'maturity' => 200,
- 'url' => 'http://download.moodle.org/',
- 'download' => 'http://download.moodle.org/download.php/MOODLE_23_STABLE/moodle-2.3.3-latest.zip',
- ),
- array(
- 'version' => 2012120100.00,
- 'release' => '2.4dev (Build: 20121201)',
- 'maturity' => 50,
- 'url' => 'http://download.moodle.org/',
- 'download' => 'http://download.moodle.org/download.php/MOODLE_24_STABLE/moodle-2.4.0-latest.zip',
- ),
- ),
- 'mod_foo' => array(
- array(
- 'version' => 2012030501,
- 'requires' => 2012010100,
- 'maturity' => 200,
- 'release' => '1.1',
- 'url' => 'http://moodle.org/plugins/blahblahblah/',
- 'download' => 'http://moodle.org/plugins/download.php/blahblahblah',
- ),
- array(
- 'version' => 2012030502,
- 'requires' => 2012010100,
- 'maturity' => 100,
- 'release' => '1.2 beta',
- 'url' => 'http://moodle.org/plugins/',
- ),
- ),
- ),
- );
-
- return json_encode($fakeresponse);
- }
-
- protected function cron_current_timestamp() {
- if ($this->fakecurrenttimestamp == -1) {
- return parent::cron_current_timestamp();
- } else {
- return $this->fakecurrenttimestamp;
- }
- }
-
- protected function cron_mtrace($msg, $eol = PHP_EOL) {
- }
-
- protected function cron_autocheck_enabled() {
- return true;
- }
-
- protected function cron_execution_offset() {
- // Autofetch should run by the first cron after 01:42 AM.
- return 42 * MINSECS;
- }
-
- protected function cron_execute() {
- throw new testable_available_update_checker_cron_executed('Cron executed!');
- }
-}
-
-
-/**
- * Exception used to detect {@link available_update_checker::cron_execute()} calls.
- */
-class testable_available_update_checker_cron_executed extends Exception {
-}
-
-
-/**
- * Modified {@link available_update_deployer} suitable for testing purposes.
- */
-class testable_available_update_deployer extends available_update_deployer {
-}
-
-
-/**
- * Test cases for {@link available_update_deployer} class.
- *
- * @group core_plugin
- */
-class core_available_update_deployer_testcase extends advanced_testcase {
-
- public function test_magic_setters() {
- $deployer = testable_available_update_deployer::instance();
- $value = new moodle_url('/');
- $deployer->set_returnurl($value);
- $this->assertSame($deployer->get_returnurl(), $value);
- }
-
- public function test_prepare_authorization() {
- global $CFG;
-
- $deployer = testable_available_update_deployer::instance();
- list($passfile, $password) = $deployer->prepare_authorization();
- $filename = $CFG->phpunit_dataroot.'/mdeploy/auth/'.$passfile;
- $this->assertFileExists($filename);
- $stored = file($filename, FILE_IGNORE_NEW_LINES);
- $this->assertCount(2, $stored);
- $this->assertGreaterThan(23, strlen($stored[0]));
- $this->assertSame($stored[0], $password);
- $this->assertLessThan(60, time() - (int)$stored[1]);
- }
-}
diff --git a/lib/upgrade.txt b/lib/upgrade.txt
index ae667267642fe..2473c306def6f 100644
--- a/lib/upgrade.txt
+++ b/lib/upgrade.txt
@@ -36,6 +36,9 @@ information provided here is intended especially for developers.
Use core_user::get_noreply_user() and core_user::get_support_user() to get noreply and support user's respectively.
Real users can be used as noreply/support users by setting $CFG->noreplyuserid and $CFG->supportuserid
* New function readfile_allow_large() in filelib.php for use when very large files may need sending to user.
+* Use plugin_manager::reset_caches() when changing visibility of plugins.
+* Implement new method get_enabled_plugins() method in subplugin info classes.
+* Each plugin should include version information in version.php.
DEPRECATIONS:
Various previously deprecated functions have now been altered to throw DEBUG_DEVELOPER debugging notices
diff --git a/lib/upgradelib.php b/lib/upgradelib.php
index 0ca4493b39ccd..12ed9b9a82569 100644
--- a/lib/upgradelib.php
+++ b/lib/upgradelib.php
@@ -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;
}
diff --git a/mod/resource/backup/moodle1/lib.php b/mod/resource/backup/moodle1/lib.php
index 8fb5af344da4e..30eaba7058e5c 100644
--- a/mod/resource/backup/moodle1/lib.php
+++ b/mod/resource/backup/moodle1/lib.php
@@ -113,9 +113,11 @@ public function process_resource(array $data, array $raw) {
// use the version of the successor instead of the current mod/resource
// beware - the version.php declares info via $module object, do not use
// a variable of such name here
- $module = new stdClass();
+ $plugin = new stdClass();
+ $plugin->version = null;
+ $module = $plugin;
include $CFG->dirroot.'/mod/'.$successor->get_modname().'/version.php';
- $cminfo['version'] = $module->version;
+ $cminfo['version'] = $plugin->version;
// stash the new course module information for this successor
$cminfo['modulename'] = $successor->get_modname();
diff --git a/user/portfolio.php b/user/portfolio.php
index a84935ce45899..e8b0b39137188 100644
--- a/user/portfolio.php
+++ b/user/portfolio.php
@@ -29,6 +29,7 @@
print_error('disabled', 'portfolio');
}
+require_once($CFG->libdir . '/pluginlib.php');
require_once($CFG->libdir . '/portfoliolib.php');
require_once($CFG->libdir . '/portfolio/forms.php');
@@ -57,9 +58,6 @@
require_login($course, false);
-// Purge all caches related to portfolio administration.
-cache::make('core', 'plugininfo_portfolio')->purge();
-
$PAGE->set_url($url);
$PAGE->set_context(context_user::instance($user->id));
$PAGE->set_title("$course->fullname: $fullname: $strportfolios");
@@ -84,6 +82,7 @@
$success = $instance->set_user_config($fromform, $USER->id);
//$success = $success && $instance->save();
if ($success) {
+ plugin_manager::reset_caches();
redirect($baseurl, get_string('instancesaved', 'portfolio'), 3);
} else {
print_error('instancenotsaved', 'portfolio', $baseurl);
@@ -100,6 +99,7 @@
} else if (!empty($hide)) {
$instance = portfolio_instance($hide);
$instance->set_user_config(array('visible' => !$instance->get_user_config('visible', $USER->id)), $USER->id);
+ plugin_manager::reset_caches();
}
if ($display) {
diff --git a/version.php b/version.php
index 9474abd67b33c..8d77f2809d8ae 100644
--- a/version.php
+++ b/version.php
@@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
-$version = 2013092000.00; // YYYYMMDD = weekly release date of this DEV branch.
+$version = 2013092001.02; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.