Commit bde002b8 authored by Petr Škoda's avatar Petr Škoda
Browse files

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

This patch includes:

* version column removed from modules table, now using standard config, this allows decimal version for modules
* version column removed from block table, now using standard config, this allows decimal version for blocks
* module version.php can safely use $plugins instead of module
* new plugin_manager bulk caching, this should help with MUC performance when logged in as admin
* all missing plugins are now in plugin overview (previously only blocks and modules)
* simplified code and improved coding style
* reworked plugin_manager unit tests - now using real plugins instead of mocks
* unit tests now fail if any plugin does not contain proper version.php file
* allow uninstall of deleted filters
parent 81881cb9
......@@ -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 @@ switch ($action) {
set_config('registerauth', '');
}
session_gc(); // remove stale sessions
plugin_manager::reset_caches();
break;
case 'enable':
......@@ -62,6 +64,7 @@ switch ($action) {
set_config('auth', implode(',', $authsenabled));
}
session_gc(); // remove stale sessions
plugin_manager::reset_caches();
break;
case 'down':
......
<?php
// block.php - allows admin to edit all local configuration variables for a block
require_once('../config.php');
require_once($CFG->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 '<br />';
echo '<form method="post" action="block.php">';
echo '<p>';
foreach($hiddendata as $name => $val) {
echo '<input type="hidden" name="'. $name .'" value="'. $val .'" />';
}
echo '</p>';
echo $OUTPUT->box_start();
include($CFG->dirroot.'/blocks/'. $block->name() .'/config_global.html');
echo $OUTPUT->box_end();
echo '</form>';
echo $OUTPUT->footer();
......@@ -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 = '<span class="notifyproblem">'.$strblockname.' ('.get_string('missingfromdisk').')</span>';
$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) {
......
......@@ -53,11 +53,13 @@ switch ($action) {
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':
......
......@@ -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 @@ if (empty($active_editors)) {
}
set_config('texteditors', implode(',', $active_editors));
plugin_manager::reset_caches();
if ($return) {
redirect ($returnurl);
......
......@@ -27,6 +27,7 @@ define('NO_OUTPUT_BUFFERING', true);
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 @@ switch ($action) {
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 @@ switch ($action) {
$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;
......
......@@ -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);
}
......
......@@ -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');
......
......@@ -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 @@ if (!empty($disable) && confirm_sesskey()) {
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 @@ if (!empty($enable) && confirm_sesskey()) {
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()) {
......
......@@ -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(
'<span'.$class.'>'.$strmodulename.'</span>',
$countlink,
'<span'.$class.'>'.$module->version.'</span>',
'<span'.$class.'>'.$version.'</span>',
$visible,
$uninstall,
$settings
......
......@@ -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');
......
......@@ -4,6 +4,7 @@ require_once(dirname(dirname(__FILE__)) . '/config.php');
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 @@ $configstr = get_string('manageportfolios', 'portfolio');
$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 @@ if (($action == 'edit') || ($action == 'new')) {
} 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 @@ if (($action == 'edit') || ($action == 'new')) {
$instance->set('visible', $visible);
$instance->save();
plugin_manager::reset_caches();
$return = true;
} else if ($action == 'delete') {
$instance = portfolio_instance($portfolio);
......
......@@ -92,6 +92,7 @@ if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey(
$disabledbehaviours[] = $disable;
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
}
plugin_manager::reset_caches();
redirect($thispageurl);
}
......@@ -109,6 +110,7 @@ if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey())
unset($disabledbehaviours[$key]);
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
}
plugin_manager::reset_caches();
redirect($thispageurl);
}
......
......@@ -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');
......
......@@ -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 @@ if (!empty($action)) {
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 @@ if (($action == 'edit') || ($action == 'new')) {
}
if ($success) {
// configs saved
plugin_manager::reset_caches();
redirect($baseurl);
} else {
print_error('instancenotsaved', 'repository', $baseurl);
......@@ -191,6 +190,7 @@ if (($action == 'edit') || ($action == 'new')) {
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 @@ if (($action == 'edit') || ($action == 'new')) {
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 @@ if (($action == 'edit') || ($action == 'new')) {
}
if ($repositorytype->delete($downloadcontents)) {
plugin_manager::reset_caches();
redirect($baseurl);
} else {
print_error('instancenotdeleted', 'repository', $baseurl);
......
......@@ -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 @@ if (!empty($edit) || !empty($new)) {
$data = data_submitted();
}
if ($success) {
plugin_manager::reset_caches();
redirect($parenturl);
} else {
print_error('instancenotsaved', 'repository', $parenturl);
......@@ -118,6 +120,7 @@ if (!empty($edit) || !empty($new)) {
} 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 (!empty($edit) || !empty($new)) {
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);
......
......@@ -866,9 +866,11 @@ class moodle1_course_outline_handler extends moodle1_xml_handler {
// 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;
}
......
......@@ -307,6 +307,7 @@ abstract class backup_block_structure_step extends backup_structure_step {
class backup_module_structure_step extends backup_structure_step {
protected function define_structure() {
global $DB;
// Define each element separated
......@@ -339,12 +340,14 @@ class backup_module_structure_step extends backup_structure_step {
$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 @@ class backup_block_instance_structure_step extends backup_structure_step {
}
$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
......
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
......
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* 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)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment