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());
set_config('registerauth', '');
}
session_gc(); // remove stale sessions
+ plugin_manager::reset_caches();
break;
case 'enable':
set_config('auth', implode(',', $authsenabled));
}
session_gc(); // remove stale sessions
+ plugin_manager::reset_caches();
break;
case 'down':
+++ /dev/null
-<?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();
-
-
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');
$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()) {
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
}
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
}
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();
$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) {
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':
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);
}
set_config('texteditors', implode(',', $active_editors));
+plugin_manager::reset_caches();
if ($return) {
redirect ($returnurl);
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);
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;
$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;
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);
$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.
/// 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);
}
// Reset caches and return
if ($action) {
+ plugin_manager::reset_caches();
reset_text_filters_cache();
redirect($returnurl);
}
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');
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');
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()) {
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()) {
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');
$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()) {
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
}
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
}
$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
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');
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);
$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
} 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;
$instance->set('visible', $visible);
$instance->save();
+ plugin_manager::reset_caches();
$return = true;
} else if ($action == 'delete') {
$instance = portfolio_instance($portfolio);
$disabledbehaviours[] = $disable;
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
}
+ plugin_manager::reset_caches();
redirect($thispageurl);
}
unset($disabledbehaviours[$key]);
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
}
+ plugin_manager::reset_caches();
redirect($thispageurl);
}
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');
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);
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
}
if ($success) {
// configs saved
+ plugin_manager::reset_caches();
redirect($baseurl);
} else {
print_error('instancenotsaved', 'repository', $baseurl);
print_error('invalidplugin', 'repository', '', $repository);
}
$repositorytype->update_visibility(true);
+ plugin_manager::reset_caches();
$return = true;
} else if ($action == 'hide') {
if (!confirm_sesskey()) {
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);
}
if ($repositorytype->delete($downloadcontents)) {
+ plugin_manager::reset_caches();
redirect($baseurl);
} else {
print_error('instancenotdeleted', 'repository', $baseurl);
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();
$data = data_submitted();
}
if ($success) {
+ plugin_manager::reset_caches();
redirect($parenturl);
} else {
print_error('instancenotsaved', 'repository', $parenturl);
} 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);
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);
// 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;
}
class backup_module_structure_step extends backup_structure_step {
protected function define_structure() {
+ global $DB;
// Define each element separated
$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('
}
$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
--- /dev/null
+<?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)
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);
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)) {
$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';
$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);
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;
}
}
}
$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;
}
}
'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
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20130913" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20130921" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="name" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false"/>
- <FIELD NAME="version" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="cron" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="lastcron" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="search" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="name" TYPE="char" LENGTH="40" NOTNULL="true" SEQUENCE="false"/>
- <FIELD NAME="version" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="cron" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="lastcron" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="visible" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
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;
}
* @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));
}
}
defined('MOODLE_INTERNAL') || die();
-require_once("$CFG->libdir/pluginlib.php");
-
/**
* Editor subplugin info class.
* @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;
$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]);
- }
}
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);
}
set_config('disabledsubplugins', implode(',', $disabled), 'editor_tinymce');
+plugin_manager::reset_caches();
redirect($returnurl);
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 {
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()}
}
/**
- * 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);
}
}
}
}
/**
- * 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();
* 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;
}
}
}
* 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 {
$plugins = array(
'qformat' => array('blackboard'),
'enrol' => array('authorize'),
+ 'tool' => array('bloglevelupgrade'),
);
if (!isset($plugins[$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
*
$plugin->init_display_name();
$plugin->load_disk_version();
$plugin->load_db_version();
- $plugin->load_required_main_version();
$plugin->init_is_standard();
return $plugin;
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;
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
* @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;
}
/**
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.
* 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.
}
}
*/
public function get_other_required_plugins() {
if (is_null($this->dependencies)) {
- $this->load_other_required_plugins();
+ $this->load_disk_version();
}
return $this->dependencies;
}
* 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;
}
}
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) {
* @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]);
}
/**
* 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() {
));
}
- /**
- * 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();
* 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');
}
/**
}
}
- 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;
}
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)) {
$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) {
return '<p>'.get_string('uninstallextraconfirmblock', 'core_plugin', array('instances'=>$count)).'</p>';
}
-
- /**
- * 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;
- }
-}
+}
/**
*/
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() {
$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();
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;
- }
}
* 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');
}
/**
}
}
- /**
- * 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;
}
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
return '<p>'.get_string('uninstallextraconfirmmod', 'core_plugin', array('instances'=>$count, 'courses'=>$courses)).'</p>';
}
-
- /**
- * 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;
- }
}
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;
* 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() {
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;
* 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() {
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;
}
* 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;
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;
}
}
}
- /**
- * @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])) {
* 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() {
}
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();
$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;
- }
}
* 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;
* 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;
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;
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;
- }
}
/**
}
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();
* 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;
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;
}
}
- 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;
}
* 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
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;
}
}
- 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;
--- /dev/null
+<?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/>.
+
+/**
+ * Unit tests for the update checker.
+ *
+ * @package core
+ * @category phpunit
+ * @copyright 2012 David Mudrak <david@moodle.com>
+ * @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)'));
+ }
+}
--- /dev/null
+<?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/>.
+
+/**
+ * Unit tests for the update deployer.
+ *
+ * @package core
+ * @category phpunit
+ * @copyright 2012 David Mudrak <david@moodle.com>
+ * @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 {
+}
+++ /dev/null
-<?php
-
-$module->version = 2012030500;
-$module->requires = 2012010100;
+++ /dev/null
-<?php
-
-$plugin->version = 2013041103;
-$plugin->requires = 2013010100;
-$plugin->component = 'bazmeg_one';
+++ /dev/null
-<?php
-
-$module->version = 2012030500;
-$module->requires = 2012010100;
+++ /dev/null
-<?php
-
-$plugin->version = 2013041103;
-$plugin->requires = 2013010100;
-$plugin->component = 'foolish_frog';
-$plugin->dependencies = array('mod_foo' => 2012030500);
+++ /dev/null
-<?php
-
-$plugin->version = 2013041103;
-$plugin->requires = 2012010100;
-$plugin->component = 'foolish_hippo';
-$plugin->dependencies = array('foolish_frog' => ANY_VERSION);
+++ /dev/null
-<?php
-
-$module->version = 2012030500;
-$module->requires = 2012010100;
-$module->component = 'mod_foo';
-$module->dependencies = array(
- 'mod_bar' => 2012030500,
- 'mod_missing' => ANY_VERSION,
- 'foolish_frog' => ANY_VERSION,
-);
+++ /dev/null
-<?php
-
-$module->version = 2013041900;
-$module->requires = 2012010100;
-$module->component = 'mod_new';
+++ /dev/null
-<?php
-
-$plugin->version = 2013041103;
-$plugin->requires = 2013010100;
-$plugin->component = 'quxcat_one';
-$plugin->dependencies = array('bazmeg_one' => 2013010100);
+++ /dev/null
-<?php
-
-$plugin->version = 2013041103;
-$plugin->requires = 2013010100;
-$plugin->component = 'mod_qux';
--- /dev/null
+<?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/>.
+
+/**
+ * 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');
+ }
+ }
+ }
+ }
+}
+++ /dev/null
-<?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/>.
-
-/**
- * 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 <david@moodle.com>
- * @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]);
- }
-}
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
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();
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();
* @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');
$someexamplesofremovedfiles = array(
// removed in 2.6dev
+ '/admin/block.php',
'/admin/oacleanup.php',
// removed in 2.5dev
'/backup/lib.php',
}
$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)) {
$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);
}
}
- $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);
$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);
events_update_definition($component);
message_update_providers($component);
if ($type === 'message') {
+ // Ugly hack!
message_update_processors($plug);
}
upgrade_plugin_mnet_functions($component);
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.');
}
}
$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')) {
}
}
- if (empty($currmodule->version)) {
+ if (empty($installedversion)) {
$startcallback($component, true, $verbose);
/// Execute install.xml (XMLDB) - must be present in all modules
/// 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")) {
$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
$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);
}
}
}
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);
$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')) {
}
}
- 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
$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');
$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) {
$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);
}
}
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)) {
if (file_exists("$cd/version.php")) {
$plugin = new stdClass();
$plugin->version = null;
+ $module = $plugin;
include("$cd/version.php");
$targetversion = $plugin->version;
}
// 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();
print_error('disabled', 'portfolio');
}
+require_once($CFG->libdir . '/pluginlib.php');
require_once($CFG->libdir . '/portfoliolib.php');
require_once($CFG->libdir . '/portfolio/forms.php');
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");
$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);
} 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) {
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.