Merge branch 'w39_MDL-41437_m26_mia' of https://github.com/skodak/moodle

Conflicts:
	admin/auth.php
	lib/db/upgrade.php
	version.php
This commit is contained in:
Eloy Lafuente (stronk7) 2013-09-24 20:18:03 +02:00
commit 161f995849
50 changed files with 1601 additions and 1940 deletions

View File

@ -10,6 +10,7 @@
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
require_once($CFG->libdir.'/pluginlib.php');
require_login();
require_capability('moodle/site:config', context_system::instance());
@ -52,6 +53,7 @@ switch ($action) {
set_config('registerauth', '');
}
\core\session\manager::gc(); // Remove stale sessions.
plugin_manager::reset_caches();
break;
case 'enable':
@ -62,6 +64,7 @@ switch ($action) {
set_config('auth', implode(',', $authsenabled));
}
\core\session\manager::gc(); // Remove stale sessions.
plugin_manager::reset_caches();
break;
case 'down':

View File

@ -1,76 +0,0 @@
<?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();

View File

@ -5,6 +5,7 @@
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
require_once($CFG->libdir.'/pluginlib.php');
admin_externalpage_setup('manageblocks');
@ -29,9 +30,6 @@
$strprotect = get_string('blockprotect', 'admin');
$strunprotect = get_string('blockunprotect', 'admin');
// Purge all caches related to blocks administration.
cache::make('core', 'plugininfo_block')->purge();
/// If data submitted, then process and store.
if (!empty($hide) && confirm_sesskey()) {
@ -39,6 +37,7 @@
print_error('blockdoesnotexist', 'error');
}
$DB->set_field('block', 'visible', '0', array('id'=>$block->id)); // Hide block
plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
@ -47,6 +46,7 @@
print_error('blockdoesnotexist', 'error');
}
$DB->set_field('block', 'visible', '1', array('id'=>$block->id)); // Show block
plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
@ -120,12 +120,13 @@
foreach ($blocknames as $blockid=>$strblockname) {
$block = $blocks[$blockid];
$blockname = $block->name;
$dbversion = get_config('block_'.$block->name, 'version');
if (!file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
$blockobject = false;
$strblockname = '<span class="notifyproblem">'.$strblockname.' ('.get_string('missingfromdisk').')</span>';
$plugin = new stdClass();
$plugin->version = $block->version;
$plugin->version = $dbversion;
} else {
$plugin = new stdClass();
@ -186,10 +187,10 @@
$class = ' class="dimmed_text"'; // Leading space required!
}
if ($block->version == $plugin->version) {
$version = $block->version;
if ($dbversion == $plugin->version) {
$version = $dbversion;
} else {
$version = "$block->version ($plugin->version)";
$version = "$dbversion ($plugin->version)";
}
if (!$blockobject) {

View File

@ -53,11 +53,13 @@ switch ($action) {
print_error('cannotdisableformat', 'error', $return);
}
set_config('disabled', 1, 'format_'. $formatname);
plugin_manager::reset_caches();
}
break;
case 'enable':
if (!$formatplugins[$formatname]->is_enabled()) {
unset_config('disabled', 'format_'. $formatname);
plugin_manager::reset_caches();
}
break;
case 'up':

View File

@ -7,6 +7,7 @@
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
require_once($CFG->libdir.'/pluginlib.php');
$action = required_param('action', PARAM_ALPHANUMEXT);
$editor = required_param('editor', PARAM_PLUGIN);
@ -93,6 +94,7 @@ if (empty($active_editors)) {
}
set_config('texteditors', implode(',', $active_editors));
plugin_manager::reset_caches();
if ($return) {
redirect ($returnurl);

View File

@ -27,6 +27,7 @@ define('NO_OUTPUT_BUFFERING', true);
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/pluginlib.php');
$action = required_param('action', PARAM_ALPHANUMEXT);
$enrol = required_param('enrol', PARAM_PLUGIN);
@ -50,6 +51,7 @@ switch ($action) {
case 'disable':
unset($enabled[$enrol]);
set_config('enrol_plugins_enabled', implode(',', array_keys($enabled)));
plugin_manager::reset_caches();
$syscontext->mark_dirty(); // resets all enrol caches
break;
@ -60,6 +62,7 @@ switch ($action) {
$enabled = array_keys($enabled);
$enabled[] = $enrol;
set_config('enrol_plugins_enabled', implode(',', $enabled));
plugin_manager::reset_caches();
$syscontext->mark_dirty(); // resets all enrol caches
break;

View File

@ -33,6 +33,7 @@
require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/pluginlib.php');
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
$filterpath = optional_param('filterpath', '', PARAM_SAFEDIR);
@ -44,9 +45,6 @@
$returnurl = "$CFG->wwwroot/$CFG->admin/filters.php";
admin_externalpage_setup('managefilters');
// Purge all caches related to filter administration.
cache::make('core', 'plugininfo_filter')->purge();
$filters = filter_get_global_states();
// In case any new filters have been installed, but not put in the table yet.
@ -59,7 +57,7 @@
/// Process actions ============================================================
if ($action) {
if (!isset($filters[$filterpath]) && !isset($newfilters[$filterpath])) {
if ($action !== 'delete' and !isset($filters[$filterpath]) and !isset($newfilters[$filterpath])) {
throw new moodle_exception('filternotinstalled', 'error', $returnurl, $filterpath);
}
@ -138,6 +136,7 @@
// Reset caches and return
if ($action) {
plugin_manager::reset_caches();
reset_text_filters_cache();
redirect($returnurl);
}

View File

@ -30,6 +30,7 @@
require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
require_once($CFG->libdir.'/pluginlib.php');
admin_externalpage_setup('managelocalplugins');

View File

@ -24,6 +24,7 @@
require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->dirroot . '/message/lib.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/pluginlib.php');
// This is an admin page
admin_externalpage_setup('managemessageoutputs');
@ -44,6 +45,7 @@ if (!empty($disable) && confirm_sesskey()) {
print_error('outputdoesnotexist', 'message');
}
$DB->set_field('message_processors', 'enabled', '0', array('id'=>$processor->id)); // Disable output
plugin_manager::reset_caches();
}
if (!empty($enable) && confirm_sesskey()) {
@ -51,6 +53,7 @@ if (!empty($enable) && confirm_sesskey()) {
print_error('outputdoesnotexist', 'message');
}
$DB->set_field('message_processors', 'enabled', '1', array('id'=>$processor->id)); // Enable output
plugin_manager::reset_caches();
}
if (!empty($uninstall) && confirm_sesskey()) {

View File

@ -5,6 +5,7 @@
require_once('../course/lib.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
require_once($CFG->libdir.'/pluginlib.php');
// defines
define('MODULE_TABLE','module_administration_table');
@ -27,9 +28,6 @@
$stractivitymodule = get_string("activitymodule");
$strshowmodulecourse = get_string('showmodulecourse');
// Purge all caches related to activity modules administration.
cache::make('core', 'plugininfo_mod')->purge();
/// If data submitted, then process and store.
if (!empty($hide) and confirm_sesskey()) {
@ -50,6 +48,7 @@
FROM {course_modules}
WHERE visibleold=1 AND module=?)",
array($module->id));
plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
@ -66,6 +65,7 @@
FROM {course_modules}
WHERE visible=1 AND module=?)",
array($module->id));
plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
@ -143,12 +143,12 @@
$visible = "";
$class = "";
}
$version = get_config('mod_'.$module->name, 'version');
$table->add_data(array(
'<span'.$class.'>'.$strmodulename.'</span>',
$countlink,
'<span'.$class.'>'.$module->version.'</span>',
'<span'.$class.'>'.$version.'</span>',
$visible,
$uninstall,
$settings

View File

@ -29,6 +29,8 @@
require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
require_once($CFG->libdir.'/pluginlib.php');
admin_externalpage_setup('manageplagiarismplugins');

View File

@ -4,6 +4,7 @@ require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->libdir . '/portfoliolib.php');
require_once($CFG->libdir . '/portfolio/forms.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/pluginlib.php');
$portfolio = optional_param('pf', '', PARAM_ALPHANUMEXT);
$action = optional_param('action', '', PARAM_ALPHA);
@ -43,9 +44,6 @@ $configstr = get_string('manageportfolios', 'portfolio');
$return = true; // direct back to the main page
// Purge all caches related to portfolio administration.
cache::make('core', 'plugininfo_portfolio')->purge();
/**
* Helper function that generates a moodle_url object
* relevant to the portfolio
@ -91,6 +89,7 @@ if (($action == 'edit') || ($action == 'new')) {
} else {
portfolio_static_function($plugin, 'create_instance', $plugin, $fromform->name, $fromform);
}
plugin_manager::reset_caches();
$savedstr = get_string('instancesaved', 'portfolio');
redirect($baseurl, $savedstr, 1);
exit;
@ -119,6 +118,7 @@ if (($action == 'edit') || ($action == 'new')) {
$instance->set('visible', $visible);
$instance->save();
plugin_manager::reset_caches();
$return = true;
} else if ($action == 'delete') {
$instance = portfolio_instance($portfolio);

View File

@ -92,6 +92,7 @@ if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey(
$disabledbehaviours[] = $disable;
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
}
plugin_manager::reset_caches();
redirect($thispageurl);
}
@ -109,6 +110,7 @@ if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey())
unset($disabledbehaviours[$key]);
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
}
plugin_manager::reset_caches();
redirect($thispageurl);
}

View File

@ -30,6 +30,7 @@
require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
require_once($CFG->libdir.'/pluginlib.php');
admin_externalpage_setup('managereports');

View File

@ -17,6 +17,7 @@
require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->dirroot . '/repository/lib.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/pluginlib.php');
$repository = optional_param('repos', '', PARAM_ALPHANUMEXT);
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
@ -61,9 +62,6 @@ if (!empty($action)) {
require_sesskey();
}
// Purge all caches related to repositories administration.
cache::make('core', 'plugininfo_repository')->purge();
/**
* Helper function that generates a moodle_url object
* relevant to the repository
@ -151,6 +149,7 @@ if (($action == 'edit') || ($action == 'new')) {
}
if ($success) {
// configs saved
plugin_manager::reset_caches();
redirect($baseurl);
} else {
print_error('instancenotsaved', 'repository', $baseurl);
@ -191,6 +190,7 @@ if (($action == 'edit') || ($action == 'new')) {
print_error('invalidplugin', 'repository', '', $repository);
}
$repositorytype->update_visibility(true);
plugin_manager::reset_caches();
$return = true;
} else if ($action == 'hide') {
if (!confirm_sesskey()) {
@ -201,6 +201,7 @@ if (($action == 'edit') || ($action == 'new')) {
print_error('invalidplugin', 'repository', '', $repository);
}
$repositorytype->update_visibility(false);
plugin_manager::reset_caches();
$return = true;
} else if ($action == 'delete') {
$repositorytype = repository::get_type_by_typename($repository);
@ -211,6 +212,7 @@ if (($action == 'edit') || ($action == 'new')) {
}
if ($repositorytype->delete($downloadcontents)) {
plugin_manager::reset_caches();
redirect($baseurl);
} else {
print_error('instancenotdeleted', 'repository', $baseurl);

View File

@ -17,6 +17,7 @@
require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->dirroot . '/repository/lib.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/pluginlib.php');
require_sesskey();
@ -102,6 +103,7 @@ if (!empty($edit) || !empty($new)) {
$data = data_submitted();
}
if ($success) {
plugin_manager::reset_caches();
redirect($parenturl);
} else {
print_error('instancenotsaved', 'repository', $parenturl);
@ -118,6 +120,7 @@ if (!empty($edit) || !empty($new)) {
} else if (!empty($hide)) {
$instance = repository::get_type_by_typename($hide);
$instance->hide();
plugin_manager::reset_caches();
$return = true;
} else if (!empty($delete)) {
$instance = repository::get_instance($delete);
@ -130,6 +133,7 @@ if (!empty($edit) || !empty($new)) {
if ($sure) {
if ($instance->delete($downloadcontents)) {
$deletedstr = get_string('instancedeleted', 'repository');
plugin_manager::reset_caches();
redirect($parenturl, $deletedstr, 3);
} else {
print_error('instancenotdeleted', 'repository', $parenturl);

View File

@ -866,9 +866,11 @@ class moodle1_course_outline_handler extends moodle1_xml_handler {
// host...
$versionfile = $CFG->dirroot.'/mod/'.$data['modulename'].'/version.php';
if (file_exists($versionfile)) {
$module = new stdClass();
$plugin = new stdClass();
$plugin->version = null;
$module = $plugin;
include($versionfile);
$data['version'] = $module->version;
$data['version'] = $plugin->version;
} else {
$data['version'] = null;
}

View File

@ -307,6 +307,7 @@ abstract class backup_block_structure_step extends backup_structure_step {
class backup_module_structure_step extends backup_structure_step {
protected function define_structure() {
global $DB;
// Define each element separated
@ -339,12 +340,14 @@ class backup_module_structure_step extends backup_structure_step {
$availinfo->add_child($availabilityfield);
// Set the sources
$module->set_source_sql('
SELECT cm.*, m.version, m.name AS modulename, s.id AS sectionid, s.section AS sectionnumber
$concat = $DB->sql_concat("'mod_'", 'm.name');
$module->set_source_sql("
SELECT cm.*, cp.value AS version, m.name AS modulename, s.id AS sectionid, s.section AS sectionnumber
FROM {course_modules} cm
JOIN {modules} m ON m.id = cm.module
JOIN {config_plugins} cp ON cp.plugin = $concat AND cp.name = 'version'
JOIN {course_sections} s ON s.id = cm.section
WHERE cm.id = ?', array(backup::VAR_MODID));
WHERE cm.id = ?", array(backup::VAR_MODID));
$availability->set_source_table('course_modules_availability', array('coursemoduleid' => backup::VAR_MODID));
$availabilityfield->set_source_sql('
@ -1363,7 +1366,7 @@ class backup_block_instance_structure_step extends backup_structure_step {
}
$blockrec->contextid = $this->task->get_contextid();
// Get the version of the block
$blockrec->version = $DB->get_field('block', 'version', array('name' => $this->task->get_blockname()));
$blockrec->version = get_config('block_'.$this->task->get_blockname(), 'version');
// Define sources

View File

@ -1,6 +1,10 @@
This files describes API changes in /blocks/* - activity modules,
information provided here is intended especially for developers.
=== 2.6 ===
* Deprecated /admin/block.php was removed, make sure blocks are using settings.php instead.
=== 2.4 ===
Created new capability 'blocks/xxx:myaddinstance' that determines whether a user can add

30
cache/locks/file/version.php vendored Normal file
View File

@ -0,0 +1,30 @@
<?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)

View File

@ -25,6 +25,7 @@
require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/pluginlib.php');
$contextid = required_param('contextid',PARAM_INT);
$forfilter = optional_param('filter', '', PARAM_SAFEDIR);
@ -36,9 +37,6 @@ require_login($course, false, $cm);
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)) {

View File

@ -51,12 +51,7 @@ $string['cachedef_htmlpurifier'] = 'HTML Purifier - cleaned content';
$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';

View File

@ -298,7 +298,10 @@ function uninstall_plugin($type, $name) {
$DB->delete_records('log_display', array('component' => $component));
// delete the module configuration records
unset_all_config_for_plugin($pluginname);
unset_all_config_for_plugin($component);
if ($type === 'mod') {
unset_all_config_for_plugin($pluginname);
}
// delete message provider
message_provider_uninstall($component);
@ -375,9 +378,11 @@ function get_component_version($component, $source='installed') {
if (empty($mods[$name]) or !is_readable($mods[$name].'/version.php')) {
return false;
} else {
$module = new stdclass();
$plugin = new stdClass();
$plugin->version = null;
$module = $plugin;
include($mods[$name].'/version.php');
return $module->version;
return $plugin->version;
}
}
}

View File

@ -927,17 +927,11 @@ $cache = '.var_export($cache, true).';
$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;
}
}

View File

@ -141,58 +141,13 @@ $definitions = array(
'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

View File

@ -1,5 +1,5 @@
<?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"
>
@ -668,7 +668,6 @@
<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"/>
@ -2527,7 +2526,6 @@
<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"/>

View File

@ -2508,5 +2508,52 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2013092000.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;
}

View File

@ -74,25 +74,20 @@ class atto_texteditor extends texteditor {
* @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');
$plugins = core_component::get_plugin_list('atto');
$sortedplugins = array();
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));
}
}

View File

@ -24,8 +24,6 @@
defined('MOODLE_INTERNAL') || die();
require_once("$CFG->libdir/pluginlib.php");
/**
* Editor subplugin info class.
@ -35,6 +33,34 @@ require_once("$CFG->libdir/pluginlib.php");
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class plugininfo_tinymce extends plugininfo_base {
/**
* Finds all enabled plugins, the result may include missing plugins.
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
*/
public static function get_enabled_plugins() {
$disabledsubplugins = array();
$config = get_config('editor_tinymce', 'disabledsubplugins');
if ($config) {
$config = explode(',', $config);
foreach ($config as $sp) {
$sp = trim($sp);
if ($sp !== '') {
$disabledsubplugins[$sp] = $sp;
}
}
}
$enabled = array();
$installed = core_component::get_plugin_list('tinymce');
foreach ($installed as $plugin => $fulldir) {
if (isset($disabledsubplugins[$plugin])) {
continue;
}
$enabled[$plugin] = $plugin;
}
return $enabled;
}
public function is_uninstall_allowed() {
return true;
@ -59,26 +85,6 @@ class plugininfo_tinymce extends plugininfo_base {
$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]);
}
}

View File

@ -24,6 +24,7 @@
require(__DIR__ . '/../../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/pluginlib.php');
$disable = optional_param('disable', '', PARAM_PLUGIN);
$enable = optional_param('enable', '', PARAM_PLUGIN);
@ -61,5 +62,6 @@ if ($disable) {
}
set_config('disabledsubplugins', implode(',', $disabled), 'editor_tinymce');
plugin_manager::reset_caches();
redirect($returnurl);

View File

@ -1589,6 +1589,9 @@ function purge_all_caches() {
theme_reset_all_caches();
get_string_manager()->reset_caches();
core_text::reset_caches();
if (class_exists('plugin_manager')) {
plugin_manager::reset_caches();
}
// Bump up cacherev field for all courses.
try {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,290 @@
<?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)'));
}
}

View File

@ -0,0 +1,209 @@
<?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 {
}

View File

@ -1,4 +0,0 @@
<?php
$module->version = 2012030500;
$module->requires = 2012010100;

View File

@ -1,5 +0,0 @@
<?php
$plugin->version = 2013041103;
$plugin->requires = 2013010100;
$plugin->component = 'bazmeg_one';

View File

@ -1,4 +0,0 @@
<?php
$module->version = 2012030500;
$module->requires = 2012010100;

View File

@ -1,6 +0,0 @@
<?php
$plugin->version = 2013041103;
$plugin->requires = 2013010100;
$plugin->component = 'foolish_frog';
$plugin->dependencies = array('mod_foo' => 2012030500);

View File

@ -1,6 +0,0 @@
<?php
$plugin->version = 2013041103;
$plugin->requires = 2012010100;
$plugin->component = 'foolish_hippo';
$plugin->dependencies = array('foolish_frog' => ANY_VERSION);

View File

@ -1,10 +0,0 @@
<?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,
);

View File

@ -1,5 +0,0 @@
<?php
$module->version = 2013041900;
$module->requires = 2012010100;
$module->component = 'mod_new';

View File

@ -1,6 +0,0 @@
<?php
$plugin->version = 2013041103;
$plugin->requires = 2013010100;
$plugin->component = 'quxcat_one';
$plugin->dependencies = array('bazmeg_one' => 2013010100);

View File

@ -1,5 +0,0 @@
<?php
$plugin->version = 2013041103;
$plugin->requires = 2013010100;
$plugin->component = 'mod_qux';

View File

@ -0,0 +1,232 @@
<?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');
}
}
}
}
}

View File

@ -1,950 +0,0 @@
<?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]);
}
}

View File

@ -36,6 +36,9 @@ information provided here is intended especially for developers.
Use core_user::get_noreply_user() and core_user::get_support_user() to get noreply and support user's respectively.
Real users can be used as noreply/support users by setting $CFG->noreplyuserid and $CFG->supportuserid
* New function readfile_allow_large() in filelib.php for use when very large files may need sending to user.
* Use plugin_manager::reset_caches() when changing visibility of plugins.
* Implement new method get_enabled_plugins() method in subplugin info classes.
* Each plugin should include version information in version.php.
DEPRECATIONS:
Various previously deprecated functions have now been altered to throw DEBUG_DEVELOPER debugging notices

View File

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

View File

@ -113,9 +113,11 @@ class moodle1_mod_resource_handler extends moodle1_mod_handler {
// 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();

View File

@ -29,6 +29,7 @@ if (empty($CFG->enableportfolios)) {
print_error('disabled', 'portfolio');
}
require_once($CFG->libdir . '/pluginlib.php');
require_once($CFG->libdir . '/portfoliolib.php');
require_once($CFG->libdir . '/portfolio/forms.php');
@ -57,9 +58,6 @@ $display = true; // set this to false in the conditions to stop processing
require_login($course, false);
// Purge all caches related to portfolio administration.
cache::make('core', 'plugininfo_portfolio')->purge();
$PAGE->set_url($url);
$PAGE->set_context(context_user::instance($user->id));
$PAGE->set_title("$course->fullname: $fullname: $strportfolios");
@ -84,6 +82,7 @@ if (!empty($config)) {
$success = $instance->set_user_config($fromform, $USER->id);
//$success = $success && $instance->save();
if ($success) {
plugin_manager::reset_caches();
redirect($baseurl, get_string('instancesaved', 'portfolio'), 3);
} else {
print_error('instancenotsaved', 'portfolio', $baseurl);
@ -100,6 +99,7 @@ if (!empty($config)) {
} 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) {

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2013092000.01; // 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.