Merge branch 'master' into install_master
This commit is contained in:
+5
-2
@@ -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());
|
||||
@@ -51,7 +52,8 @@ switch ($action) {
|
||||
if ($auth == $CFG->registerauth) {
|
||||
set_config('registerauth', '');
|
||||
}
|
||||
session_gc(); // remove stale sessions
|
||||
\core\session\manager::gc(); // Remove stale sessions.
|
||||
plugin_manager::reset_caches();
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
@@ -61,7 +63,8 @@ switch ($action) {
|
||||
$authsenabled = array_unique($authsenabled);
|
||||
set_config('auth', implode(',', $authsenabled));
|
||||
}
|
||||
session_gc(); // remove stale sessions
|
||||
\core\session\manager::gc(); // Remove stale sessions.
|
||||
plugin_manager::reset_caches();
|
||||
break;
|
||||
|
||||
case 'down':
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
+8
-7
@@ -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) {
|
||||
|
||||
@@ -151,6 +151,7 @@ if (version_compare(phpversion(), "5.3.3") < 0) {
|
||||
}
|
||||
|
||||
// set up configuration
|
||||
global $CFG;
|
||||
$CFG = new stdClass();
|
||||
$CFG->lang = 'en';
|
||||
$CFG->dirroot = dirname(dirname(dirname(__FILE__)));
|
||||
@@ -189,9 +190,37 @@ require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/componentlib.class.php');
|
||||
require_once($CFG->dirroot.'/cache/lib.php');
|
||||
|
||||
// Register our classloader, in theory somebody might want to replace it to load other hacked core classes.
|
||||
// Required because the database checks below lead to session interaction which is going to lead us to requiring autoloaded classes.
|
||||
if (defined('COMPONENT_CLASSLOADER')) {
|
||||
spl_autoload_register(COMPONENT_CLASSLOADER);
|
||||
} else {
|
||||
spl_autoload_register('core_component::classloader');
|
||||
}
|
||||
|
||||
require($CFG->dirroot.'/version.php');
|
||||
$CFG->target_release = $release;
|
||||
|
||||
$_SESSION = array();
|
||||
$_SESSION['SESSION'] = new stdClass();
|
||||
$_SESSION['SESSION']->lang = $CFG->lang;
|
||||
$_SESSION['USER'] = new stdClass();
|
||||
$_SESSION['USER']->id = 0;
|
||||
$_SESSION['USER']->mnethostid = 1;
|
||||
|
||||
global $SESSION;
|
||||
global $USER;
|
||||
$SESSION = &$_SESSION['SESSION'];
|
||||
$USER = &$_SESSION['USER'];
|
||||
|
||||
global $COURSE;
|
||||
$COURSE = new stdClass();
|
||||
$COURSE->id = 1;
|
||||
|
||||
global $SITE;
|
||||
$SITE = $COURSE;
|
||||
define('SITEID', 1);
|
||||
|
||||
//Database types
|
||||
$databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'),
|
||||
'mariadb'=> moodle_database::get_driver_instance('mariadb', 'native'),
|
||||
|
||||
@@ -172,7 +172,7 @@ set_config('branch', $branch);
|
||||
upgrade_noncore(true);
|
||||
|
||||
// log in as admin - we need doanything permission when applying defaults
|
||||
session_set_user(get_admin());
|
||||
\core\session\manager::set_user(get_admin());
|
||||
|
||||
// apply all default settings, just in case do it twice to fill all defaults
|
||||
admin_apply_default_settings(NULL, false);
|
||||
|
||||
@@ -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':
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ require_once($CFG->libdir.'/clilib.php');
|
||||
require_once($CFG->libdir.'/cronlib.php');
|
||||
|
||||
// extra safety
|
||||
session_get_instance()->write_close();
|
||||
\core\session\manager::write_close();
|
||||
|
||||
// check if execution allowed
|
||||
if (!empty($CFG->cronclionly)) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
require_once($CFG->libdir.'/pluginlib.php');
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$editor = required_param('editor', PARAM_PLUGIN);
|
||||
@@ -93,6 +94,7 @@ if (empty($active_editors)) {
|
||||
}
|
||||
|
||||
set_config('texteditors', implode(',', $active_editors));
|
||||
plugin_manager::reset_caches();
|
||||
|
||||
if ($return) {
|
||||
redirect ($returnurl);
|
||||
|
||||
@@ -27,6 +27,7 @@ define('NO_OUTPUT_BUFFERING', true);
|
||||
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/pluginlib.php');
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$enrol = required_param('enrol', PARAM_PLUGIN);
|
||||
@@ -50,6 +51,7 @@ switch ($action) {
|
||||
case 'disable':
|
||||
unset($enabled[$enrol]);
|
||||
set_config('enrol_plugins_enabled', implode(',', array_keys($enabled)));
|
||||
plugin_manager::reset_caches();
|
||||
$syscontext->mark_dirty(); // resets all enrol caches
|
||||
break;
|
||||
|
||||
@@ -60,6 +62,7 @@ switch ($action) {
|
||||
$enabled = array_keys($enabled);
|
||||
$enabled[] = $enrol;
|
||||
set_config('enrol_plugins_enabled', implode(',', $enabled));
|
||||
plugin_manager::reset_caches();
|
||||
$syscontext->mark_dirty(); // resets all enrol caches
|
||||
break;
|
||||
|
||||
|
||||
+6
-36
@@ -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);
|
||||
}
|
||||
|
||||
@@ -97,38 +95,6 @@
|
||||
filter_set_global_state($filterpath, $filters[$filterpath]->active, -1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
// If not yet confirmed, display a confirmation message.
|
||||
if (!optional_param('confirm', '', PARAM_BOOL)) {
|
||||
$filtername = filter_get_name($filterpath);
|
||||
|
||||
$title = get_string('deletefilterareyousure', 'admin', $filtername);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($title);
|
||||
|
||||
$linkcontinue = new moodle_url($returnurl, array('action' => 'delete', 'filterpath' => $filterpath, 'confirm' => 1));
|
||||
$formcancel = new single_button(new moodle_url($returnurl), get_string('no'), 'get');
|
||||
echo $OUTPUT->confirm(get_string('deletefilterareyousuremessage', 'admin', $filtername), $linkcontinue, $formcancel);
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
}
|
||||
|
||||
// Do the deletion.
|
||||
$title = get_string('deletingfilter', 'admin', $filterpath);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($title);
|
||||
|
||||
// Delete all data for this plugin.
|
||||
filter_delete_all_for_filter($filterpath);
|
||||
|
||||
$a = new stdClass;
|
||||
$a->filter = $filterpath;
|
||||
$a->directory = "$CFG->dirroot/filter/$filterpath";
|
||||
echo $OUTPUT->box(get_string('deletefilterfiles', 'admin', $a), 'generalbox', 'notice');
|
||||
echo $OUTPUT->continue_button($returnurl);
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
}
|
||||
|
||||
// Add any missing filters to the DB table.
|
||||
@@ -138,6 +104,7 @@
|
||||
|
||||
// Reset caches and return
|
||||
if ($action) {
|
||||
plugin_manager::reset_caches();
|
||||
reset_text_filters_cache();
|
||||
redirect($returnurl);
|
||||
}
|
||||
@@ -212,6 +179,9 @@
|
||||
/// Display helper functions ===================================================
|
||||
|
||||
function filters_action_url($filterpath, $action) {
|
||||
if ($action === 'delete') {
|
||||
return new moodle_url('/admin/plugins.php', array('sesskey'=>sesskey(), 'uninstall'=>'filter_'.$filterpath));
|
||||
}
|
||||
return new moodle_url('/admin/filters.php', array('sesskey'=>sesskey(), 'filterpath'=>$filterpath, 'action'=>$action));
|
||||
}
|
||||
|
||||
|
||||
+9
-2
@@ -163,7 +163,7 @@ if (!core_tables_exist()) {
|
||||
$strinstallation = get_string('installation', 'install');
|
||||
|
||||
// remove current session content completely
|
||||
session_get_instance()->terminate_current();
|
||||
\core\session\manager::terminate_current();
|
||||
|
||||
if (empty($agreelicense)) {
|
||||
$strlicense = get_string('license');
|
||||
@@ -249,6 +249,13 @@ if ($CFG->version != $DB->get_field('config', 'value', array('name'=>'version'))
|
||||
}
|
||||
|
||||
if (!$cache and $version > $CFG->version) { // upgrade
|
||||
|
||||
// Warning about upgrading a test site.
|
||||
$testsite = false;
|
||||
if (defined('BEHAT_SITE_RUNNING')) {
|
||||
$testsite = 'behat';
|
||||
}
|
||||
|
||||
// We purge all of MUC's caches here.
|
||||
// Caches are disabled for upgrade by CACHE_DISABLE_ALL so we must set the first arg to true.
|
||||
// This ensures a real config object is loaded and the stores will be purged.
|
||||
@@ -283,7 +290,7 @@ if (!$cache and $version > $CFG->version) { // upgrade
|
||||
|
||||
/** @var core_admin_renderer $output */
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
echo $output->upgrade_confirm_page($a->newversion, $maturity);
|
||||
echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite);
|
||||
die();
|
||||
|
||||
} else if (empty($confirmrelease)){
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
+5
-28
@@ -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');
|
||||
@@ -34,8 +35,6 @@ require_capability('moodle/site:config', context_system::instance());
|
||||
// Get the submitted params
|
||||
$disable = optional_param('disable', 0, PARAM_INT);
|
||||
$enable = optional_param('enable', 0, PARAM_INT);
|
||||
$uninstall = optional_param('uninstall', 0, PARAM_INT);
|
||||
$confirm = optional_param('confirm', false, PARAM_BOOL);
|
||||
|
||||
$headingtitle = get_string('managemessageoutputs', 'message');
|
||||
|
||||
@@ -44,6 +43,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,33 +51,10 @@ 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()) {
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($headingtitle);
|
||||
|
||||
if (!$processor = $DB->get_record('message_processors', array('id'=>$uninstall))) {
|
||||
print_error('outputdoesnotexist', 'message');
|
||||
}
|
||||
|
||||
$processorname = get_string('pluginname', 'message_'.$processor->name);
|
||||
|
||||
if (!$confirm) {
|
||||
echo $OUTPUT->confirm(get_string('processordeleteconfirm', 'message', $processorname), 'message.php?uninstall='.$processor->id.'&confirm=1', 'message.php');
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
|
||||
} else {
|
||||
message_processor_uninstall($processor->name);
|
||||
$a = new stdClass();
|
||||
$a->processor = $processorname;
|
||||
$a->directory = $CFG->dirroot.'/message/output/'.$processor->name;
|
||||
notice(get_string('processordeletefiles', 'message', $a), 'message.php');
|
||||
}
|
||||
}
|
||||
|
||||
if ($disable || $enable || $uninstall) {
|
||||
if ($disable || $enable) {
|
||||
$url = new moodle_url('message.php');
|
||||
redirect($url);
|
||||
}
|
||||
@@ -95,4 +72,4 @@ $messageoutputs = $renderer->manage_messageoutputs($processors);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($headingtitle);
|
||||
echo $messageoutputs;
|
||||
echo $OUTPUT->footer();
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
+5
-5
@@ -5,6 +5,7 @@
|
||||
require_once('../course/lib.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
require_once($CFG->libdir.'/pluginlib.php');
|
||||
|
||||
// defines
|
||||
define('MODULE_TABLE','module_administration_table');
|
||||
@@ -27,9 +28,6 @@
|
||||
$stractivitymodule = get_string("activitymodule");
|
||||
$strshowmodulecourse = get_string('showmodulecourse');
|
||||
|
||||
// Purge all caches related to activity modules administration.
|
||||
cache::make('core', 'plugininfo_mod')->purge();
|
||||
|
||||
/// If data submitted, then process and store.
|
||||
|
||||
if (!empty($hide) and confirm_sesskey()) {
|
||||
@@ -50,6 +48,7 @@
|
||||
FROM {course_modules}
|
||||
WHERE visibleold=1 AND module=?)",
|
||||
array($module->id));
|
||||
plugin_manager::reset_caches();
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
}
|
||||
|
||||
@@ -66,6 +65,7 @@
|
||||
FROM {course_modules}
|
||||
WHERE visible=1 AND module=?)",
|
||||
array($module->id));
|
||||
plugin_manager::reset_caches();
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
}
|
||||
|
||||
@@ -143,12 +143,12 @@
|
||||
$visible = "";
|
||||
$class = "";
|
||||
}
|
||||
|
||||
$version = get_config('mod_'.$module->name, 'version');
|
||||
|
||||
$table->add_data(array(
|
||||
'<span'.$class.'>'.$strmodulename.'</span>',
|
||||
$countlink,
|
||||
'<span'.$class.'>'.$module->version.'</span>',
|
||||
'<span'.$class.'>'.$version.'</span>',
|
||||
$visible,
|
||||
$uninstall,
|
||||
$settings
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
require_once(dirname(dirname(__FILE__)) . '/config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
require_once($CFG->libdir.'/pluginlib.php');
|
||||
|
||||
|
||||
admin_externalpage_setup('manageplagiarismplugins');
|
||||
|
||||
|
||||
+3
-3
@@ -4,6 +4,7 @@ require_once(dirname(dirname(__FILE__)) . '/config.php');
|
||||
require_once($CFG->libdir . '/portfoliolib.php');
|
||||
require_once($CFG->libdir . '/portfolio/forms.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/pluginlib.php');
|
||||
|
||||
$portfolio = optional_param('pf', '', PARAM_ALPHANUMEXT);
|
||||
$action = optional_param('action', '', PARAM_ALPHA);
|
||||
@@ -43,9 +44,6 @@ $configstr = get_string('manageportfolios', 'portfolio');
|
||||
|
||||
$return = true; // direct back to the main page
|
||||
|
||||
// Purge all caches related to portfolio administration.
|
||||
cache::make('core', 'plugininfo_portfolio')->purge();
|
||||
|
||||
/**
|
||||
* Helper function that generates a moodle_url object
|
||||
* relevant to the portfolio
|
||||
@@ -91,6 +89,7 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
} else {
|
||||
portfolio_static_function($plugin, 'create_instance', $plugin, $fromform->name, $fromform);
|
||||
}
|
||||
plugin_manager::reset_caches();
|
||||
$savedstr = get_string('instancesaved', 'portfolio');
|
||||
redirect($baseurl, $savedstr, 1);
|
||||
exit;
|
||||
@@ -119,6 +118,7 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
|
||||
$instance->set('visible', $visible);
|
||||
$instance->save();
|
||||
plugin_manager::reset_caches();
|
||||
$return = true;
|
||||
} else if ($action == 'delete') {
|
||||
$instance = portfolio_instance($portfolio);
|
||||
|
||||
@@ -92,6 +92,7 @@ if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey(
|
||||
$disabledbehaviours[] = $disable;
|
||||
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
|
||||
}
|
||||
plugin_manager::reset_caches();
|
||||
redirect($thispageurl);
|
||||
}
|
||||
|
||||
@@ -109,6 +110,7 @@ if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey())
|
||||
unset($disabledbehaviours[$key]);
|
||||
set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question');
|
||||
}
|
||||
plugin_manager::reset_caches();
|
||||
redirect($thispageurl);
|
||||
}
|
||||
|
||||
|
||||
+21
-1
@@ -135,9 +135,10 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
* during upgrade.
|
||||
* @param string $strnewversion
|
||||
* @param int $maturity
|
||||
* @param string $testsite
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
public function upgrade_confirm_page($strnewversion, $maturity) {
|
||||
public function upgrade_confirm_page($strnewversion, $maturity, $testsite) {
|
||||
$output = '';
|
||||
|
||||
$continueurl = new moodle_url('/admin/index.php', array('confirmupgrade' => 1));
|
||||
@@ -146,6 +147,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
|
||||
$output .= $this->header();
|
||||
$output .= $this->maturity_warning($maturity);
|
||||
$output .= $this->test_site_warning($testsite);
|
||||
$output .= $this->confirm(get_string('upgradesure', 'admin', $strnewversion), $continue, $cancelurl);
|
||||
$output .= $this->footer();
|
||||
|
||||
@@ -614,6 +616,24 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
'generalbox maturitywarning');
|
||||
}
|
||||
|
||||
/*
|
||||
* If necessary, displays a warning about upgrading a test site.
|
||||
*
|
||||
* @param string $testsite
|
||||
* @return string HTML
|
||||
*/
|
||||
protected function test_site_warning($testsite) {
|
||||
|
||||
if (!$testsite) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->box(
|
||||
$this->container(get_string('testsiteupgradewarning', 'admin', $testsite)),
|
||||
'generalbox testsitewarning'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the copyright notice.
|
||||
* @return string HTML to output.
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
require_once(dirname(__FILE__) . '/../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
require_once($CFG->libdir.'/pluginlib.php');
|
||||
|
||||
admin_externalpage_setup('managereports');
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
require_once(dirname(dirname(__FILE__)) . '/config.php');
|
||||
require_once($CFG->dirroot . '/repository/lib.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/pluginlib.php');
|
||||
|
||||
$repository = optional_param('repos', '', PARAM_ALPHANUMEXT);
|
||||
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
|
||||
@@ -61,9 +62,6 @@ if (!empty($action)) {
|
||||
require_sesskey();
|
||||
}
|
||||
|
||||
// Purge all caches related to repositories administration.
|
||||
cache::make('core', 'plugininfo_repository')->purge();
|
||||
|
||||
/**
|
||||
* Helper function that generates a moodle_url object
|
||||
* relevant to the repository
|
||||
@@ -151,6 +149,7 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
}
|
||||
if ($success) {
|
||||
// configs saved
|
||||
plugin_manager::reset_caches();
|
||||
redirect($baseurl);
|
||||
} else {
|
||||
print_error('instancenotsaved', 'repository', $baseurl);
|
||||
@@ -191,6 +190,7 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
print_error('invalidplugin', 'repository', '', $repository);
|
||||
}
|
||||
$repositorytype->update_visibility(true);
|
||||
plugin_manager::reset_caches();
|
||||
$return = true;
|
||||
} else if ($action == 'hide') {
|
||||
if (!confirm_sesskey()) {
|
||||
@@ -201,6 +201,7 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
print_error('invalidplugin', 'repository', '', $repository);
|
||||
}
|
||||
$repositorytype->update_visibility(false);
|
||||
plugin_manager::reset_caches();
|
||||
$return = true;
|
||||
} else if ($action == 'delete') {
|
||||
$repositorytype = repository::get_type_by_typename($repository);
|
||||
@@ -211,6 +212,7 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
}
|
||||
|
||||
if ($repositorytype->delete($downloadcontents)) {
|
||||
plugin_manager::reset_caches();
|
||||
redirect($baseurl);
|
||||
} else {
|
||||
print_error('instancenotdeleted', 'repository', $baseurl);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
require_once(dirname(dirname(__FILE__)) . '/config.php');
|
||||
require_once($CFG->dirroot . '/repository/lib.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/pluginlib.php');
|
||||
|
||||
require_sesskey();
|
||||
|
||||
@@ -102,6 +103,7 @@ if (!empty($edit) || !empty($new)) {
|
||||
$data = data_submitted();
|
||||
}
|
||||
if ($success) {
|
||||
plugin_manager::reset_caches();
|
||||
redirect($parenturl);
|
||||
} else {
|
||||
print_error('instancenotsaved', 'repository', $parenturl);
|
||||
@@ -118,6 +120,7 @@ if (!empty($edit) || !empty($new)) {
|
||||
} else if (!empty($hide)) {
|
||||
$instance = repository::get_type_by_typename($hide);
|
||||
$instance->hide();
|
||||
plugin_manager::reset_caches();
|
||||
$return = true;
|
||||
} else if (!empty($delete)) {
|
||||
$instance = repository::get_instance($delete);
|
||||
@@ -130,6 +133,7 @@ if (!empty($edit) || !empty($new)) {
|
||||
if ($sure) {
|
||||
if ($instance->delete($downloadcontents)) {
|
||||
$deletedstr = get_string('instancedeleted', 'repository');
|
||||
plugin_manager::reset_caches();
|
||||
redirect($parenturl, $deletedstr, 3);
|
||||
} else {
|
||||
print_error('instancenotdeleted', 'repository', $parenturl);
|
||||
|
||||
@@ -14,6 +14,9 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('modules', new admin_category('modsettings', new lang_string('activitymodules')));
|
||||
$ADMIN->add('modsettings', new admin_page_managemods());
|
||||
foreach ($allplugins['mod'] as $module) {
|
||||
if (!$module->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$module->load_settings($ADMIN, 'modsettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -23,6 +26,9 @@ if ($hassiteconfig) {
|
||||
$temp->add(new admin_setting_manageformats());
|
||||
$ADMIN->add('formatsettings', $temp);
|
||||
foreach ($allplugins['format'] as $format) {
|
||||
if (!$format->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$format->load_settings($ADMIN, 'formatsettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -30,6 +36,9 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('modules', new admin_category('blocksettings', new lang_string('blocks')));
|
||||
$ADMIN->add('blocksettings', new admin_page_manageblocks());
|
||||
foreach ($allplugins['block'] as $block) {
|
||||
if (!$block->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$block->load_settings($ADMIN, 'blocksettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -38,6 +47,9 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('messageoutputs', new admin_page_managemessageoutputs());
|
||||
$ADMIN->add('messageoutputs', new admin_page_defaultmessageoutputs());
|
||||
foreach ($allplugins['message'] as $processor) {
|
||||
if (!$processor->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$processor->load_settings($ADMIN, 'messageoutputs', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -67,6 +79,9 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('authsettings', $temp);
|
||||
|
||||
foreach ($allplugins['auth'] as $auth) {
|
||||
if (!$auth->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$auth->load_settings($ADMIN, 'authsettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -76,6 +91,9 @@ if ($hassiteconfig) {
|
||||
$temp->add(new admin_setting_manageenrols());
|
||||
$ADMIN->add('enrolments', $temp);
|
||||
foreach($allplugins['enrol'] as $enrol) {
|
||||
if (!$enrol->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$enrol->load_settings($ADMIN, 'enrolments', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -86,6 +104,9 @@ if ($hassiteconfig) {
|
||||
$temp->add(new admin_setting_manageeditors());
|
||||
$ADMIN->add('editorsettings', $temp);
|
||||
foreach ($allplugins['editor'] as $editor) {
|
||||
if (!$editor->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$editor->load_settings($ADMIN, 'editorsettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -148,6 +169,9 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('filtersettings', $temp);
|
||||
|
||||
foreach ($allplugins['filter'] as $filter) {
|
||||
if (!$filter->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$filter->load_settings($ADMIN, 'filtersettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -239,6 +263,9 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('repositorysettings', new admin_externalpage('repositoryinstanceedit',
|
||||
new lang_string('editrepositoryinstance', 'repository'), $url, 'moodle/site:config', true));
|
||||
foreach ($allplugins['repository'] as $repositorytype) {
|
||||
if (!$repositorytype->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$repositorytype->load_settings($ADMIN, 'repositorysettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -288,6 +315,9 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
/// links to protocol pages
|
||||
foreach ($allplugins['webservice'] as $webservice) {
|
||||
if (!$webservice->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$webservice->load_settings($ADMIN, 'webservicesettings', $hassiteconfig);
|
||||
}
|
||||
/// manage token page link
|
||||
@@ -363,6 +393,9 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext))
|
||||
|
||||
// Settings for particular question types.
|
||||
foreach ($allplugins['qtype'] as $qtype) {
|
||||
if (!$qtype->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$qtype->load_settings($ADMIN, 'qtypesettings', $hassiteconfig);
|
||||
}
|
||||
}
|
||||
@@ -374,6 +407,9 @@ if ($hassiteconfig && !empty($CFG->enableplagiarism)) {
|
||||
$CFG->wwwroot . '/' . $CFG->admin . '/plagiarism.php'));
|
||||
|
||||
foreach ($allplugins['plagiarism'] as $plugin) {
|
||||
if (!$plugin->is_updated()) {
|
||||
continue;
|
||||
}
|
||||
$plugin->load_settings($ADMIN, 'plagiarism', $hassiteconfig);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,9 @@ $ADMIN->add('server', $temp);
|
||||
|
||||
// "sessionhandling" settingpage
|
||||
$temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandling', 'admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'), new lang_string('configdbsessions', 'admin'), 1));
|
||||
if (empty($CFG->session_handler_class) and $DB->session_lock_supported()) {
|
||||
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'), new lang_string('configdbsessions', 'admin'), 0));
|
||||
}
|
||||
$temp->add(new admin_setting_configselect('sessiontimeout', new lang_string('sessiontimeout', 'admin'), new lang_string('configsessiontimeout', 'admin'), 7200, array(14400 => new lang_string('numhours', '', 4),
|
||||
10800 => new lang_string('numhours', '', 3),
|
||||
7200 => new lang_string('numhours', '', 2),
|
||||
|
||||
@@ -35,6 +35,14 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$optionalsubsystems->add(new admin_setting_configcheckbox('enablecompletion',
|
||||
new lang_string('enablecompletion','completion'),
|
||||
new lang_string('configenablecompletion','completion'), 0));
|
||||
|
||||
$options = array(
|
||||
1 => get_string('completionactivitydefault', 'completion'),
|
||||
0 => get_string('completion_none', 'completion')
|
||||
);
|
||||
$optionalsubsystems->add(new admin_setting_configselect('completiondefault', new lang_string('completiondefault', 'completion'),
|
||||
new lang_string('configcompletiondefault', 'completion'), 1, $options));
|
||||
|
||||
$optionalsubsystems->add($checkbox = new admin_setting_configcheckbox('enableavailability',
|
||||
new lang_string('enableavailability','condition'),
|
||||
new lang_string('configenableavailability','condition'), 0));
|
||||
|
||||
@@ -47,7 +47,7 @@ if (!$confirm) {
|
||||
}
|
||||
raise_memory_limit(MEMORY_EXTRA);
|
||||
// Release session.
|
||||
session_get_instance()->write_close();
|
||||
\core\session\manager::write_close();
|
||||
|
||||
echo $renderer->header();
|
||||
echo $renderer->heading(get_string('batchupgrade', 'tool_assignmentupgrade'));
|
||||
|
||||
@@ -52,7 +52,7 @@ require_once($CFG->libdir.'/dtllib.php');
|
||||
function tool_dbtransfer_export_xml_database($description, $mdb) {
|
||||
@set_time_limit(0);
|
||||
|
||||
session_get_instance()->write_close(); // Release session.
|
||||
\core\session\manager::write_close(); // Release session.
|
||||
|
||||
header('Content-Type: application/xhtml+xml; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename=database.xml');
|
||||
@@ -79,7 +79,7 @@ function tool_dbtransfer_export_xml_database($description, $mdb) {
|
||||
function tool_dbtransfer_transfer_database(moodle_database $sourcedb, moodle_database $targetdb, progress_trace $feedback = null) {
|
||||
@set_time_limit(0);
|
||||
|
||||
session_get_instance()->write_close(); // Release session.
|
||||
\core\session\manager::write_close(); // Release session.
|
||||
|
||||
$var = new database_mover($sourcedb, $targetdb, true, $feedback);
|
||||
$var->export_database(null);
|
||||
|
||||
@@ -51,6 +51,11 @@ abstract class tool_generator_backend {
|
||||
*/
|
||||
protected $fixeddataset;
|
||||
|
||||
/**
|
||||
* @var int|bool Maximum number of bytes for file.
|
||||
*/
|
||||
protected $filesizelimit;
|
||||
|
||||
/**
|
||||
* @var bool True if displaying progress
|
||||
*/
|
||||
@@ -81,10 +86,11 @@ abstract class tool_generator_backend {
|
||||
*
|
||||
* @param int $size Size as numeric index
|
||||
* @param bool $fixeddataset To use fixed or random data
|
||||
* @param int|bool $filesizelimit The max number of bytes for a generated file
|
||||
* @param bool $progress True if progress information should be displayed
|
||||
* @throws coding_exception If parameters are invalid
|
||||
*/
|
||||
public function __construct($size, $fixeddataset = false, $progress = true) {
|
||||
public function __construct($size, $fixeddataset = false, $filesizelimit = false, $progress = true) {
|
||||
|
||||
// Check parameter.
|
||||
if ($size < self::MIN_SIZE || $size > self::MAX_SIZE) {
|
||||
@@ -94,6 +100,7 @@ abstract class tool_generator_backend {
|
||||
// Set parameters.
|
||||
$this->size = $size;
|
||||
$this->fixeddataset = $fixeddataset;
|
||||
$this->filesizelimit = $filesizelimit;
|
||||
$this->progress = $progress;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,15 +100,24 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
* @param string $shortname Course shortname
|
||||
* @param int $size Size as numeric index
|
||||
* @param bool $fixeddataset To use fixed or random data
|
||||
* @param int|bool $filesizelimit The max number of bytes for a generated file
|
||||
* @param bool $progress True if progress information should be displayed
|
||||
* @return int Course id
|
||||
*/
|
||||
public function __construct($shortname, $size, $fixeddataset = false, $progress = true) {
|
||||
public function __construct($shortname, $size, $fixeddataset = false, $filesizelimit = false, $progress = true) {
|
||||
|
||||
// Set parameters.
|
||||
$this->shortname = $shortname;
|
||||
|
||||
parent::__construct($size, $fixeddataset, $progress);
|
||||
parent::__construct($size, $fixeddataset, $filesizelimit, $progress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relation between users and course sizes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_users_per_size() {
|
||||
return self::$paramusers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -280,6 +289,8 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
* @param int $last Number of last user
|
||||
*/
|
||||
private function create_user_accounts($first, $last) {
|
||||
global $CFG;
|
||||
|
||||
$this->log('createaccounts', (object)array('from' => $first, 'to' => $last), true);
|
||||
$count = $last - $first + 1;
|
||||
$done = 0;
|
||||
@@ -294,6 +305,12 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
// Create user account.
|
||||
$record = array('firstname' => get_string('firstname', 'tool_generator'),
|
||||
'lastname' => $number, 'username' => $username);
|
||||
|
||||
// We add a user password if it has been specified.
|
||||
if (!empty($CFG->tool_generator_users_password)) {
|
||||
$record['password'] = $CFG->tool_generator_users_password;
|
||||
}
|
||||
|
||||
$user = $this->generator->create_user($record);
|
||||
$this->userids[$number] = (int)$user->id;
|
||||
$this->dot($done, $count);
|
||||
@@ -311,7 +328,7 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
// Create pages.
|
||||
$number = self::$parampages[$this->size];
|
||||
$this->log('createpages', $number, true);
|
||||
for ($i=0; $i<$number; $i++) {
|
||||
for ($i = 0; $i < $number; $i++) {
|
||||
$record = array('course' => $this->course->id);
|
||||
$options = array('section' => $this->get_target_section());
|
||||
$pagegenerator->create_instance($record, $options);
|
||||
@@ -345,7 +362,7 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
|
||||
// Generate random binary data (different for each file so it
|
||||
// doesn't compress unrealistically).
|
||||
$data = self::get_random_binary(self::$paramsmallfilesize[$this->size]);
|
||||
$data = self::get_random_binary($this->limit_filesize(self::$paramsmallfilesize[$this->size]));
|
||||
|
||||
$fs->create_file_from_string($filerecord, $data);
|
||||
$this->dot($i, $count);
|
||||
@@ -362,13 +379,14 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
* @return Random data
|
||||
*/
|
||||
private static function get_random_binary($length) {
|
||||
|
||||
$data = microtime(true);
|
||||
if (strlen($data) > $length) {
|
||||
// Use last digits of data.
|
||||
return substr($data, -$length);
|
||||
}
|
||||
$length -= strlen($data);
|
||||
for ($j=0; $j < $length; $j++) {
|
||||
for ($j = 0; $j < $length; $j++) {
|
||||
$data .= chr(rand(1, 255));
|
||||
}
|
||||
return $data;
|
||||
@@ -382,8 +400,9 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
|
||||
// Work out how many files and how many blocks to use (up to 64KB).
|
||||
$count = self::$parambigfilecount[$this->size];
|
||||
$blocks = ceil(self::$parambigfilesize[$this->size] / 65536);
|
||||
$blocksize = floor(self::$parambigfilesize[$this->size] / $blocks);
|
||||
$filesize = $this->limit_filesize(self::$parambigfilesize[$this->size]);
|
||||
$blocks = ceil($filesize / 65536);
|
||||
$blocksize = floor($filesize / $blocks);
|
||||
|
||||
$this->log('createbigfiles', $count, true);
|
||||
|
||||
@@ -446,13 +465,13 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
|
||||
// Add discussions and posts.
|
||||
$sofar = 0;
|
||||
for ($i=0; $i < $discussions; $i++) {
|
||||
for ($i = 0; $i < $discussions; $i++) {
|
||||
$record = array('forum' => $forum->id, 'course' => $this->course->id,
|
||||
'userid' => $this->get_target_user());
|
||||
$discussion = $forumgenerator->create_discussion($record);
|
||||
$parentid = $DB->get_field('forum_posts', 'id', array('discussion' => $discussion->id), MUST_EXIST);
|
||||
$sofar++;
|
||||
for ($j=0; $j < $posts - 1; $j++, $sofar++) {
|
||||
for ($j = 0; $j < $posts - 1; $j++, $sofar++) {
|
||||
$record = array('discussion' => $discussion->id,
|
||||
'userid' => $this->get_target_user(), 'parent' => $parentid);
|
||||
$forumgenerator->create_post($record);
|
||||
@@ -504,4 +523,20 @@ class tool_generator_course_backend extends tool_generator_backend {
|
||||
return $userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricts the binary file size if necessary
|
||||
*
|
||||
* @param int $length The total length
|
||||
* @return int The limited length if a limit was specified.
|
||||
*/
|
||||
private function limit_filesize($length) {
|
||||
|
||||
// Limit to $this->filesizelimit.
|
||||
if (is_numeric($this->filesizelimit) && $length > $this->filesizelimit) {
|
||||
$length = floor($this->filesizelimit);
|
||||
}
|
||||
|
||||
return $length;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+22
-2
@@ -14,6 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Course form.
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/formslib.php');
|
||||
@@ -25,8 +33,13 @@ require_once($CFG->libdir . '/formslib.php');
|
||||
* @copyright 2013 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_generator_make_form extends moodleform {
|
||||
class tool_generator_make_course_form extends moodleform {
|
||||
|
||||
/**
|
||||
* Course generation tool form definition.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
@@ -41,6 +54,13 @@ class tool_generator_make_form extends moodleform {
|
||||
$mform->addElement('submit', 'submit', get_string('createcourse', 'tool_generator'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $files
|
||||
* @return void
|
||||
*/
|
||||
public function validation($data, $files) {
|
||||
global $DB;
|
||||
$errors = array();
|
||||
@@ -48,7 +68,7 @@ class tool_generator_make_form extends moodleform {
|
||||
// Check course doesn't already exist.
|
||||
if (!empty($data['shortname'])) {
|
||||
// Check shortname.
|
||||
$error = tool_generator_course_backend::check_shortname_available($data['shortname']);
|
||||
$error = tool_generator_course_backend::check_shortname_available($data['shortname']);
|
||||
if ($error) {
|
||||
$errors['shortname'] = $error;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Test plan form.
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/formslib.php');
|
||||
|
||||
/**
|
||||
* Form with options for creating large course.
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_generator_make_testplan_form extends moodleform {
|
||||
|
||||
/**
|
||||
* Test plan form definition.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
$mform->addElement('select', 'size', get_string('size', 'tool_generator'),
|
||||
tool_generator_testplan_backend::get_size_choices());
|
||||
$mform->setDefault('size', tool_generator_testplan_backend::DEFAULT_SIZE);
|
||||
|
||||
$mform->addElement('select', 'courseid', get_string('targetcourse', 'tool_generator'),
|
||||
tool_generator_testplan_backend::get_course_options());
|
||||
|
||||
$mform->addElement('advcheckbox', 'updateuserspassword', get_string('updateuserspassword', 'tool_generator'));
|
||||
$mform->addHelpButton('updateuserspassword', 'updateuserspassword', 'tool_generator');
|
||||
|
||||
$mform->addElement('submit', 'submit', get_string('createtestplan', 'tool_generator'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the submitted data allows us to create a test plan.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $files
|
||||
* @return array An array of errors
|
||||
*/
|
||||
public function validation($data, $files) {
|
||||
global $CFG;
|
||||
|
||||
$errors = array();
|
||||
if (empty($CFG->tool_generator_users_password) || is_bool($CFG->tool_generator_users_password)) {
|
||||
$errors['updateuserspassword'] = get_string('error_nouserspassword', 'tool_generator');
|
||||
}
|
||||
|
||||
// Better to repeat here the query than to do it afterwards and end up with an exception.
|
||||
if ($courseerrors = tool_generator_testplan_backend::has_selected_course_any_problem($data['courseid'], $data['size'])) {
|
||||
$errors = array_merge($errors, $courseerrors);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -61,15 +61,16 @@ class tool_generator_site_backend extends tool_generator_backend {
|
||||
* @param int $size Size as numeric index
|
||||
* @param bool $bypasscheck If debugging level checking was skipped.
|
||||
* @param bool $fixeddataset To use fixed or random data
|
||||
* @param int|bool $filesizelimit The max number of bytes for a generated file
|
||||
* @param bool $progress True if progress information should be displayed
|
||||
* @return int Course id
|
||||
*/
|
||||
public function __construct($size, $bypasscheck, $fixeddataset = false, $progress = true) {
|
||||
public function __construct($size, $bypasscheck, $fixeddataset = false, $filesizelimit = false, $progress = true) {
|
||||
|
||||
// Set parameters.
|
||||
$this->bypasscheck = $bypasscheck;
|
||||
|
||||
parent::__construct($size, $fixeddataset, $progress);
|
||||
parent::__construct($size, $fixeddataset, $filesizelimit, $progress);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,7 +105,7 @@ class tool_generator_site_backend extends tool_generator_backend {
|
||||
// Create courses.
|
||||
$prevchdir = getcwd();
|
||||
chdir($CFG->dirroot);
|
||||
$ncourse = $this->get_last_testcourse_id();
|
||||
$ncourse = self::get_last_testcourse_id();
|
||||
foreach (self::$sitecourses as $coursesize => $ncourses) {
|
||||
for ($i = 1; $i <= $ncourses[$this->size]; $i++) {
|
||||
// Non language-dependant shortname.
|
||||
@@ -148,6 +149,10 @@ class tool_generator_site_backend extends tool_generator_backend {
|
||||
$options[] = '--quiet';
|
||||
}
|
||||
|
||||
if ($this->filesizelimit) {
|
||||
$options[] = '--filesizelimit="' . $this->filesizelimit . '"';
|
||||
}
|
||||
|
||||
// Extend options.
|
||||
$optionstoextend = array(
|
||||
'fixeddataset' => 'fixeddataset',
|
||||
@@ -177,26 +182,30 @@ class tool_generator_site_backend extends tool_generator_backend {
|
||||
*
|
||||
* @return int The last generated numeric value.
|
||||
*/
|
||||
protected function get_last_testcourse_id() {
|
||||
protected static function get_last_testcourse_id() {
|
||||
global $DB;
|
||||
|
||||
$params = array();
|
||||
$params['shortnameprefix'] = $DB->sql_like_escape(self::SHORTNAMEPREFIX) . '%';
|
||||
$like = $DB->sql_like('shortname', ':shortnameprefix');
|
||||
|
||||
if (!$testcourses = $DB->get_records_select('course', $like, $params, 'shortname DESC')) {
|
||||
if (!$testcourses = $DB->get_records_select('course', $like, $params, '', 'shortname')) {
|
||||
return 0;
|
||||
}
|
||||
// SQL order by is not appropiate here as is ordering strings.
|
||||
$shortnames = array_keys($testcourses);
|
||||
core_collator::asort($shortnames, core_collator::SORT_NATURAL);
|
||||
$shortnames = array_reverse($shortnames);
|
||||
|
||||
// They come ordered by shortname DESC, so non-numeric values will be the first ones.
|
||||
foreach ($testcourses as $testcourse) {
|
||||
$sufix = substr($testcourse->shortname, strlen(self::SHORTNAMEPREFIX));
|
||||
if (is_numeric($sufix)) {
|
||||
$prefixnchars = strlen(self::SHORTNAMEPREFIX);
|
||||
foreach ($shortnames as $shortname) {
|
||||
$sufix = substr($shortname, $prefixnchars);
|
||||
if (preg_match('/^[\d]+$/', $sufix)) {
|
||||
return $sufix;
|
||||
}
|
||||
}
|
||||
|
||||
// If all sufixes are not numeric this is the fist make test site run.
|
||||
// If all sufixes are not numeric this is the first make test site run.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,328 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Test plan generator.
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Generates the files required by JMeter.
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_generator_testplan_backend extends tool_generator_backend {
|
||||
|
||||
/**
|
||||
* @var The URL to the repository of the external project.
|
||||
*/
|
||||
protected static $repourl = 'https://github.com/moodlehq/moodle-performance-comparison';
|
||||
|
||||
/**
|
||||
* @var Number of users depending on the selected size.
|
||||
*/
|
||||
protected static $users = array(1, 30, 200, 1000, 5000, 10000);
|
||||
|
||||
/**
|
||||
* @var Number of loops depending on the selected size.
|
||||
*/
|
||||
protected static $loops = array(1, 1, 2, 3, 3, 5);
|
||||
|
||||
/**
|
||||
* @var Rampup period depending on the selected size.
|
||||
*/
|
||||
protected static $rampups = array(1, 6, 40, 100, 500, 800);
|
||||
|
||||
/**
|
||||
* Gets a list of size choices supported by this backend.
|
||||
*
|
||||
* @return array List of size (int) => text description for display
|
||||
*/
|
||||
public static function get_size_choices() {
|
||||
|
||||
$options = array();
|
||||
for ($size = self::MIN_SIZE; $size <= self::MAX_SIZE; $size++) {
|
||||
$a = new stdClass();
|
||||
$a->users = self::$users[$size];
|
||||
$a->loops = self::$loops[$size];
|
||||
$a->rampup = self::$rampups[$size];
|
||||
$options[$size] = get_string('testplansize_' . $size, 'tool_generator', $a);
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of courses that can be used used to generate a test.
|
||||
*
|
||||
* @return array The list of options as courseid => name
|
||||
*/
|
||||
public static function get_course_options() {
|
||||
$courses = get_courses('all', 'c.sortorder ASC', 'c.id, c.shortname, c.fullname');
|
||||
if (!$courses) {
|
||||
print_error('error_nocourses', 'tool_generator');
|
||||
}
|
||||
|
||||
$options = array();
|
||||
unset($courses[1]);
|
||||
foreach ($courses as $course) {
|
||||
$options[$course->id] = $course->fullname . '(' . $course->shortname . ')';
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for moodle-performance-comparison project URL.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_repourl() {
|
||||
return self::$repourl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the test plan file.
|
||||
*
|
||||
* @param int $courseid The target course id
|
||||
* @param int $size The test plan size
|
||||
* @return stored_file
|
||||
*/
|
||||
public static function create_testplan_file($courseid, $size) {
|
||||
$jmxcontents = self::generate_test_plan($courseid, $size);
|
||||
|
||||
$fs = get_file_storage();
|
||||
$filerecord = self::get_file_record('testplan', 'jmx');
|
||||
return $fs->create_file_from_string($filerecord, $jmxcontents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the users data file.
|
||||
*
|
||||
* @param int $courseid The target course id
|
||||
* @param bool $updateuserspassword Updates the course users password to $CFG->tool_generator_users_password
|
||||
* @return stored_file
|
||||
*/
|
||||
public static function create_users_file($courseid, $updateuserspassword) {
|
||||
$csvcontents = self::generate_users_file($courseid, $updateuserspassword);
|
||||
|
||||
$fs = get_file_storage();
|
||||
$filerecord = self::get_file_record('users', 'csv');
|
||||
return $fs->create_file_from_string($filerecord, $csvcontents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the test plan according to the target course contents.
|
||||
*
|
||||
* @param int $targetcourseid The target course id
|
||||
* @param int $size The test plan size
|
||||
* @return string The test plan as a string
|
||||
*/
|
||||
protected static function generate_test_plan($targetcourseid, $size) {
|
||||
global $CFG;
|
||||
|
||||
// Getting the template.
|
||||
$template = file_get_contents(__DIR__ . '/../testplan.template.jmx');
|
||||
|
||||
// Getting the course modules data.
|
||||
$coursedata = self::get_course_test_data($targetcourseid);
|
||||
|
||||
// Host and path to the site.
|
||||
$urlcomponents = parse_url($CFG->wwwroot);
|
||||
if (empty($urlcomponents['path'])) {
|
||||
$urlcomponents['path'] = '';
|
||||
}
|
||||
|
||||
$replacements = array(
|
||||
self::$users[$size],
|
||||
self::$loops[$size],
|
||||
self::$rampups[$size],
|
||||
$urlcomponents['host'],
|
||||
$urlcomponents['path'],
|
||||
get_string('shortsize_' . $size, 'tool_generator'),
|
||||
$targetcourseid,
|
||||
$coursedata->pageid,
|
||||
$coursedata->forumid,
|
||||
$coursedata->forumdiscussionid,
|
||||
$coursedata->forumreplyid
|
||||
);
|
||||
|
||||
$placeholders = array(
|
||||
'{{USERS_PLACEHOLDER}}',
|
||||
'{{LOOPS_PLACEHOLDER}}',
|
||||
'{{RAMPUP_PLACEHOLDER}}',
|
||||
'{{HOST_PLACEHOLDER}}',
|
||||
'{{SITEPATH_PLACEHOLDER}}',
|
||||
'{{SIZE_PLACEHOLDER}}',
|
||||
'{{COURSEID_PLACEHOLDER}}',
|
||||
'{{PAGEACTIVITYID_PLACEHOLDER}}',
|
||||
'{{FORUMACTIVITYID_PLACEHOLDER}}',
|
||||
'{{FORUMDISCUSSIONID_PLACEHOLDER}}',
|
||||
'{{FORUMREPLYID_PLACEHOLDER}}'
|
||||
);
|
||||
|
||||
// Fill the template with the target course values.
|
||||
return str_replace($placeholders, $replacements, $template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the user's credentials file with all the course's users
|
||||
*
|
||||
* @param int $targetcourseid
|
||||
* @param bool $updateuserspassword Updates the course users password to $CFG->tool_generator_users_password
|
||||
* @return string The users csv file contents.
|
||||
*/
|
||||
protected static function generate_users_file($targetcourseid, $updateuserspassword) {
|
||||
global $CFG;
|
||||
|
||||
$coursecontext = context_course::instance($targetcourseid);
|
||||
|
||||
$users = get_enrolled_users($coursecontext, '', 0, 'u.id, u.username, u.auth', 'u.username ASC');
|
||||
if (!$users) {
|
||||
print_error('coursewithoutusers', 'tool_generator');
|
||||
}
|
||||
|
||||
$lines = array();
|
||||
foreach ($users as $user) {
|
||||
|
||||
// Updating password to the one set in config.php.
|
||||
if ($updateuserspassword) {
|
||||
$userauth = get_auth_plugin($user->auth);
|
||||
if (!$userauth->user_update_password($user, $CFG->tool_generator_users_password)) {
|
||||
print_error('errorpasswordupdate', 'auth');
|
||||
}
|
||||
}
|
||||
|
||||
// Here we already checked that $CFG->tool_generator_users_password is not null.
|
||||
$lines[] = $user->username . ',' . $CFG->tool_generator_users_password;
|
||||
}
|
||||
|
||||
return implode(PHP_EOL, $lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a tool_generator file record
|
||||
*
|
||||
* @param string $filearea testplan or users
|
||||
* @param string $filetype The file extension jmx or csv
|
||||
* @return stdClass The file record to use when creating tool_generator files
|
||||
*/
|
||||
protected static function get_file_record($filearea, $filetype) {
|
||||
|
||||
$systemcontext = context_system::instance();
|
||||
|
||||
$filerecord = new stdClass();
|
||||
$filerecord->contextid = $systemcontext->id;
|
||||
$filerecord->component = 'tool_generator';
|
||||
$filerecord->filearea = $filearea;
|
||||
$filerecord->itemid = 0;
|
||||
$filerecord->filepath = '/';
|
||||
|
||||
// Random generated number to avoid concurrent execution problems.
|
||||
$filerecord->filename = $filearea . '_' . date('YmdHi', time()) . '_' . rand(1000, 9999) . '.' . $filetype;
|
||||
|
||||
return $filerecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data required to fill the test plan template with the database contents.
|
||||
*
|
||||
* @param int $targetcourseid The target course id
|
||||
* @return stdClass The ids required by the test plan
|
||||
*/
|
||||
protected static function get_course_test_data($targetcourseid) {
|
||||
global $DB, $USER;
|
||||
|
||||
$data = new stdClass();
|
||||
|
||||
// Getting course contents info as the current user (will be an admin).
|
||||
$course = new stdClass();
|
||||
$course->id = $targetcourseid;
|
||||
$courseinfo = new course_modinfo($course, $USER->id);
|
||||
|
||||
// Getting the first page module instance.
|
||||
if (!$pages = $courseinfo->get_instances_of('page')) {
|
||||
print_error('error_nopageinstances', 'tool_generator');
|
||||
}
|
||||
$data->pageid = reset($pages)->id;
|
||||
|
||||
// Getting the first forum module instance and it's first discussion and reply as well.
|
||||
if (!$forums = $courseinfo->get_instances_of('forum')) {
|
||||
print_error('error_noforuminstances', 'tool_generator');
|
||||
}
|
||||
$forum = reset($forums);
|
||||
|
||||
// Getting the first discussion (and reply).
|
||||
if (!$discussions = forum_get_discussions($forum, 'd.timemodified ASC', false, -1, 1)) {
|
||||
print_error('error_noforumdiscussions', 'tool_generator');
|
||||
}
|
||||
$discussion = reset($discussions);
|
||||
|
||||
$data->forumid = $forum->id;
|
||||
$data->forumdiscussionid = $discussion->discussion;
|
||||
$data->forumreplyid = $discussion->id;
|
||||
|
||||
// According to the current test plan.
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the selected target course is ok.
|
||||
*
|
||||
* @param int|string $course
|
||||
* @param int $size
|
||||
* @return array Errors array or false if everything is ok
|
||||
*/
|
||||
public static function has_selected_course_any_problem($course, $size) {
|
||||
global $DB;
|
||||
|
||||
$errors = array();
|
||||
|
||||
if (!is_numeric($course)) {
|
||||
if (!$course = $DB->get_field('course', 'id', array('shortname' => $course))) {
|
||||
$errors['courseid'] = get_string('error_nonexistingcourse', 'tool_generator');
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
|
||||
$coursecontext = context_course::instance($course, IGNORE_MISSING);
|
||||
if (!$coursecontext) {
|
||||
$errors['courseid'] = get_string('error_nonexistingcourse', 'tool_generator');
|
||||
return $errors;
|
||||
}
|
||||
|
||||
if (!$users = get_enrolled_users($coursecontext, '', 0, 'u.id')) {
|
||||
$errors['courseid'] = get_string('coursewithoutusers', 'tool_generator');
|
||||
}
|
||||
|
||||
// Checks that the selected course has enough users.
|
||||
$coursesizes = tool_generator_course_backend::get_users_per_size();
|
||||
if (count($users) < $coursesizes[$size]) {
|
||||
$errors['size'] = get_string('notenoughusers', 'tool_generator');
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'shortname' => false,
|
||||
'size' => false,
|
||||
'fixeddataset' => false,
|
||||
'filesizelimit' => false,
|
||||
'bypasscheck' => false,
|
||||
'quiet' => false
|
||||
),
|
||||
@@ -52,11 +53,12 @@ Not for use on live sites; only normally works if debugging is set to DEVELOPER
|
||||
level.
|
||||
|
||||
Options:
|
||||
--shortname Shortname of course to create (required)
|
||||
--size Size of course to create XS, S, M, L, XL, or XXL (required)
|
||||
--fixeddataset Use a fixed data set instead of randomly generated data
|
||||
--bypasscheck Bypasses the developer-mode check (be careful!)
|
||||
--quiet Do not show any output
|
||||
--shortname Shortname of course to create (required)
|
||||
--size Size of course to create XS, S, M, L, XL, or XXL (required)
|
||||
--fixeddataset Use a fixed data set instead of randomly generated data
|
||||
--filesizelimit Limits the size of the generated files to the specified bytes
|
||||
--bypasscheck Bypasses the developer-mode check (be careful!)
|
||||
--quiet Do not show any output
|
||||
|
||||
-h, --help Print out this help
|
||||
|
||||
@@ -76,6 +78,7 @@ if (empty($options['bypasscheck']) && !debugging('', DEBUG_DEVELOPER)) {
|
||||
$shortname = $options['shortname'];
|
||||
$sizename = $options['size'];
|
||||
$fixeddataset = $options['fixeddataset'];
|
||||
$filesizelimit = $options['filesizelimit'];
|
||||
|
||||
// Check size.
|
||||
try {
|
||||
@@ -90,8 +93,8 @@ if ($error = tool_generator_course_backend::check_shortname_available($shortname
|
||||
}
|
||||
|
||||
// Switch to admin user account.
|
||||
session_set_user(get_admin());
|
||||
\core\session\manager::set_user(get_admin());
|
||||
|
||||
// Do backend code to generate course.
|
||||
$backend = new tool_generator_course_backend($shortname, $size, $fixeddataset, empty($options['quiet']));
|
||||
$backend = new tool_generator_course_backend($shortname, $size, $fixeddataset, $filesizelimit, empty($options['quiet']));
|
||||
$id = $backend->make();
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* CLI interface for creating a test plan
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
define('NO_OUTPUT_BUFFERING', true);
|
||||
|
||||
require(dirname(__FILE__) . '/../../../../config.php');
|
||||
require_once($CFG->libdir. '/clilib.php');
|
||||
|
||||
// CLI options.
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
array(
|
||||
'help' => false,
|
||||
'shortname' => false,
|
||||
'size' => false,
|
||||
'bypasscheck' => false,
|
||||
'updateuserspassword' => false
|
||||
),
|
||||
array(
|
||||
'h' => 'help'
|
||||
)
|
||||
);
|
||||
|
||||
$testplansizes = '* ' . implode(PHP_EOL . '* ', tool_generator_testplan_backend::get_size_choices());
|
||||
|
||||
// Display help.
|
||||
if (!empty($options['help']) || empty($options['shortname']) || empty($options['size'])) {
|
||||
|
||||
echo get_string('testplanexplanation', 'tool_generator', tool_generator_testplan_backend::get_repourl()) .
|
||||
"Options:
|
||||
-h, --help Print out this help
|
||||
--shortname Shortname of the test plan's target course (required)
|
||||
--size Size of the test plan to create XS, S, M, L, XL, or XXL (required)
|
||||
--bypasscheck Bypasses the developer-mode check (be careful!)
|
||||
--updateuserspassword Updates the target course users password according to \$CFG->tool_generator_users_password
|
||||
|
||||
$testplansizes
|
||||
|
||||
Consider that, the server resources you will need to run the test plan will be higher as the test plan size is higher.
|
||||
|
||||
Example from Moodle root directory:
|
||||
\$ sudo -u www-data /usr/bin/php admin/tool/generator/cli/maketestplan.php --shortname=\"testcourse_12\" --size=S
|
||||
";
|
||||
// Exit with error unless we're showing this because they asked for it.
|
||||
exit(empty($options['help']) ? 1 : 0);
|
||||
}
|
||||
|
||||
// Check debugging is set to developer level.
|
||||
if (empty($options['bypasscheck']) && !$CFG->debugdeveloper) {
|
||||
cli_error(get_string('error_notdebugging', 'tool_generator'));
|
||||
}
|
||||
|
||||
// Get options.
|
||||
$shortname = $options['shortname'];
|
||||
$sizename = $options['size'];
|
||||
|
||||
// Check size.
|
||||
try {
|
||||
$size = tool_generator_testplan_backend::size_for_name($sizename);
|
||||
} catch (coding_exception $e) {
|
||||
cli_error("Error: Invalid size ($sizename). Use --help for help.");
|
||||
}
|
||||
|
||||
// Check selected course.
|
||||
if ($errors = tool_generator_testplan_backend::has_selected_course_any_problem($shortname, $size)) {
|
||||
// Showing the first reported problem.
|
||||
cli_error("Error: " . reset($errors));
|
||||
}
|
||||
|
||||
// Checking if test users password is set.
|
||||
if (empty($CFG->tool_generator_users_password) || is_bool($CFG->tool_generator_users_password)) {
|
||||
cli_error("Error: " . get_string('error_nouserspassword', 'tool_generator'));
|
||||
}
|
||||
|
||||
// Switch to admin user account.
|
||||
session_set_user(get_admin());
|
||||
|
||||
// Create files.
|
||||
$courseid = $DB->get_field('course', 'id', array('shortname' => $shortname));
|
||||
$usersfile = tool_generator_testplan_backend::create_users_file($courseid, !empty($options['updateuserspassword']));
|
||||
$testplanfile = tool_generator_testplan_backend::create_testplan_file($courseid, $size);
|
||||
|
||||
// One file path per line so other CLI scripts can easily parse the output.
|
||||
echo moodle_url::make_pluginfile_url(
|
||||
$testplanfile->get_contextid(),
|
||||
$testplanfile->get_component(),
|
||||
$testplanfile->get_filearea(),
|
||||
$testplanfile->get_itemid(),
|
||||
$testplanfile->get_filepath(),
|
||||
$testplanfile->get_filename()
|
||||
) .
|
||||
PHP_EOL .
|
||||
moodle_url::make_pluginfile_url(
|
||||
$usersfile->get_contextid(),
|
||||
$usersfile->get_component(),
|
||||
$usersfile->get_filearea(),
|
||||
$usersfile->get_itemid(),
|
||||
$usersfile->get_filepath(),
|
||||
$usersfile->get_filename()
|
||||
) .
|
||||
PHP_EOL;
|
||||
@@ -34,6 +34,7 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'help' => false,
|
||||
'size' => false,
|
||||
'fixeddataset' => false,
|
||||
'filesizelimit' => false,
|
||||
'bypasscheck' => false,
|
||||
'quiet' => false
|
||||
),
|
||||
@@ -57,10 +58,11 @@ Consider that, depending on the size you select, this CLI tool can really genera
|
||||
$sitesizes
|
||||
|
||||
Options:
|
||||
--size Size of the generated site, this value affects the number of courses and their size. Accepted values: XS, S, M, L, XL, or XXL (required)
|
||||
--fixeddataset Use a fixed data set instead of randomly generated data
|
||||
--bypasscheck Bypasses the developer-mode check (be careful!)
|
||||
--quiet Do not show any output
|
||||
--size Size of the generated site, this value affects the number of courses and their size. Accepted values: XS, S, M, L, XL, or XXL (required)
|
||||
--fixeddataset Use a fixed data set instead of randomly generated data
|
||||
--filesizelimit Limits the size of the generated files to the specified bytes
|
||||
--bypasscheck Bypasses the developer-mode check (be careful!)
|
||||
--quiet Do not show any output
|
||||
|
||||
-h, --help Print out this help
|
||||
|
||||
@@ -79,6 +81,7 @@ if (empty($options['bypasscheck']) && !$CFG->debugdeveloper) {
|
||||
// Get options.
|
||||
$sizename = $options['size'];
|
||||
$fixeddataset = $options['fixeddataset'];
|
||||
$filesizelimit = $options['filesizelimit'];
|
||||
|
||||
// Check size.
|
||||
try {
|
||||
@@ -88,8 +91,8 @@ try {
|
||||
}
|
||||
|
||||
// Switch to admin user account.
|
||||
session_set_user(get_admin());
|
||||
\core\session\manager::set_user(get_admin());
|
||||
|
||||
// Do backend code to generate site.
|
||||
$backend = new tool_generator_site_backend($size, $options['bypasscheck'], $fixeddataset, empty($options['quiet']));
|
||||
$backend = new tool_generator_site_backend($size, $options['bypasscheck'], $fixeddataset, $filesizelimit, empty($options['quiet']));
|
||||
$backend->make();
|
||||
|
||||
@@ -15,34 +15,14 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Random course generator.
|
||||
* Development data generator.
|
||||
*
|
||||
* @package tool
|
||||
* @subpackage generator
|
||||
* @package tool_generator
|
||||
* @copyright 2009 Nicolas Connault
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(dirname(__FILE__) . '/../../../config.php');
|
||||
require_once('locallib.php');
|
||||
|
||||
|
||||
require_login();
|
||||
$systemcontext = context_system::instance();
|
||||
require_capability('moodle/site:config', $systemcontext);
|
||||
if (!is_siteadmin()) {
|
||||
error('Only for admins');
|
||||
}
|
||||
|
||||
if (!$CFG->debugdeveloper) {
|
||||
error('This script is for developers only!!!');
|
||||
}
|
||||
|
||||
$PAGE->set_url('/admin/tool/generator/index.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_pagelayout('base');
|
||||
$generator = new generator_web();
|
||||
$generator->setup();
|
||||
$generator->display();
|
||||
$generator->generate_data();
|
||||
$generator->complete();
|
||||
// This index page was previously in use, for now we redirect to the make test
|
||||
// course page - but we might reinstate this page in the future.
|
||||
redirect(new moodle_url('/admin/tool/generator/maketestcourse.php'));
|
||||
|
||||
@@ -23,16 +23,7 @@
|
||||
*/
|
||||
|
||||
$string['bigfile'] = 'Big file {$a}';
|
||||
$string['coursesize_0'] = 'XS (~10KB; create in ~1 second)';
|
||||
$string['coursesize_1'] = 'S (~10MB; create in ~30 seconds)';
|
||||
$string['coursesize_2'] = 'M (~100MB; create in ~5 minutes)';
|
||||
$string['coursesize_3'] = 'L (~1GB; create in ~1 hour)';
|
||||
$string['coursesize_4'] = 'XL (~10GB; create in ~4 hours)';
|
||||
$string['coursesize_5'] = 'XXL (~20GB; create in ~8 hours)';
|
||||
$string['createcourse'] = 'Create course';
|
||||
$string['creating'] = 'Creating course';
|
||||
$string['done'] = 'done ({$a}s)';
|
||||
$string['explanation'] = 'This tool creates standard test courses that include many
|
||||
$string['courseexplanation'] = 'This tool creates standard test courses that include many
|
||||
sections, activities, and files.
|
||||
|
||||
This is intended to provide a standardised measure for checking the reliability
|
||||
@@ -50,16 +41,38 @@ filesystem space (tens of gigabytes). You will need to delete the courses
|
||||
(To avoid accidental use, this feature is disabled unless you have also selected
|
||||
DEVELOPER debugging level.)';
|
||||
|
||||
$string['coursesize_0'] = 'XS (~10KB; create in ~1 second)';
|
||||
$string['coursesize_1'] = 'S (~10MB; create in ~30 seconds)';
|
||||
$string['coursesize_2'] = 'M (~100MB; create in ~5 minutes)';
|
||||
$string['coursesize_3'] = 'L (~1GB; create in ~1 hour)';
|
||||
$string['coursesize_4'] = 'XL (~10GB; create in ~4 hours)';
|
||||
$string['coursesize_5'] = 'XXL (~20GB; create in ~8 hours)';
|
||||
$string['coursewithoutusers'] = 'The selected course has no users';
|
||||
$string['createcourse'] = 'Create course';
|
||||
$string['createtestplan'] = 'Create test plan';
|
||||
$string['creating'] = 'Creating course';
|
||||
$string['done'] = 'done ({$a}s)';
|
||||
$string['downloadtestplan'] = 'Download test plan';
|
||||
$string['downloadusersfile'] = 'Download users file';
|
||||
$string['error_nocourses'] = 'There are no courses to generate the test plan';
|
||||
$string['error_noforumdiscussions'] = 'The selected course does not contain forum discussions';
|
||||
$string['error_noforuminstances'] = 'The selected course does not contain forum module instances';
|
||||
$string['error_noforumreplies'] = 'The selected course does not contain forum replies';
|
||||
$string['error_nonexistingcourse'] = 'The specified course does not exist';
|
||||
$string['error_nopageinstances'] = 'The selected course does not contain page module instances';
|
||||
$string['error_notdebugging'] = 'Not available on this server because debugging is not set to DEVELOPER';
|
||||
$string['error_nouserspassword'] = 'You need to set $CFG->tool_generator_users_password in config.php to generate the test plan';
|
||||
$string['firstname'] = 'Test course user';
|
||||
$string['fullname'] = 'Test course: {$a->size}';
|
||||
$string['maketestcourse'] = 'Make test course';
|
||||
$string['maketestplan'] = 'Make JMeter test plan';
|
||||
$string['notenoughusers'] = 'The selected course does not have enough users';
|
||||
$string['pluginname'] = 'Development data generator';
|
||||
$string['progress_createcourse'] = 'Creating course {$a}';
|
||||
$string['progress_checkaccounts'] = 'Checking user accounts ({$a})';
|
||||
$string['progress_coursecompleted'] = 'Course completed ({$a}s)';
|
||||
$string['progress_createaccounts'] = 'Creating user accounts ({$a->from} - {$a->to})';
|
||||
$string['progress_createbigfiles'] = 'Creating big files ({$a})';
|
||||
$string['progress_createcourse'] = 'Creating course {$a}';
|
||||
$string['progress_createforum'] = 'Creating forum ({$a} posts)';
|
||||
$string['progress_createpages'] = 'Creating pages ({$a})';
|
||||
$string['progress_createsmallfiles'] = 'Creating small files ({$a})';
|
||||
@@ -79,3 +92,33 @@ $string['sitesize_4'] = 'XL (~10GB; 1065 courses, created in ~5 hours)';
|
||||
$string['sitesize_5'] = 'XXL (~20GB; 4177 courses, created in ~10 hours)';
|
||||
$string['size'] = 'Size of course';
|
||||
$string['smallfiles'] = 'Small files';
|
||||
$string['targetcourse'] = 'Test target course';
|
||||
$string['testplanexplanation'] = 'This tool creates a JMeter test plan file along with the user credentials file.
|
||||
|
||||
This test plan is designed to work along with {$a}, which makes easier to run the test plan in a specific Moodle environment, gathers information about the runs and compares the results, so you will need to download it and use it\'s test_runner.sh script or follow the installation and usage instructions.
|
||||
|
||||
You need to set a password for the course users in config.php (e.g. $CFG->tool_generator_users_password = \'moodle\';). There is no default value for this password to prevent unintended usages of the tool. You need to use the update passwords option in case your course users have other passwords or they were generated by tool_generator but without setting a $CFG->tool_generator_users_password value.
|
||||
|
||||
It is part of tool_generator so it works well with the courses generated by the courses and the site generators, it can
|
||||
also be used with any course that contains, at least:
|
||||
|
||||
* Enough enrolled users (depends on the test plan size you select) with the password reset to \'moodle\'
|
||||
* A page module instance
|
||||
* A forum module instance with at least one discussion and one reply
|
||||
|
||||
You might want to consider your servers capacity when running large test plans as the amount to load generated by JMeter
|
||||
can be specially big. The ramp up period has been adjusted according to the number of threads (users) to reduce this kind
|
||||
of issues but the load is still huge.
|
||||
|
||||
**Do not run the test plan on a live system**. This feature only creates the files to feed JMeter so is not dangerous by
|
||||
itself, but you should **NEVER** run this test plan in a production site.
|
||||
|
||||
';
|
||||
$string['testplansize_0'] = 'XS ({$a->users} users, {$a->loops} loops and {$a->rampup} rampup period)';
|
||||
$string['testplansize_1'] = 'S ({$a->users} users, {$a->loops} loops and {$a->rampup} rampup period)';
|
||||
$string['testplansize_2'] = 'M ({$a->users} users, {$a->loops} loops and {$a->rampup} rampup period)';
|
||||
$string['testplansize_3'] = 'L ({$a->users} users, {$a->loops} loops and {$a->rampup} rampup period)';
|
||||
$string['testplansize_4'] = 'XL ({$a->users} users, {$a->loops} loops and {$a->rampup} rampup period)';
|
||||
$string['testplansize_5'] = 'XXL ({$a->users} users, {$a->loops} loops and {$a->rampup} rampup period)';
|
||||
$string['updateuserspassword'] = 'Update course users password';
|
||||
$string['updateuserspassword_help'] = 'JMeter needs to login as the course users, you can set the users password using $CFG->tool_generator_users_password in config.php; this setting updates the course user\'s password according to $CFG->tool_generator_users_password. It can be useful in case you are using a course not generated by tool_generator or $CFG->tool_generator_users_password was not set when you created the test courses.';
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Generator tool functions.
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Files support.
|
||||
*
|
||||
* Exits if the required permissions are not satisfied.
|
||||
*
|
||||
* @param stdClass $course course object
|
||||
* @param stdClass $cm
|
||||
* @param stdClass $context context object
|
||||
* @param string $filearea file area
|
||||
* @param array $args extra arguments
|
||||
* @param bool $forcedownload whether or not force download
|
||||
* @param array $options additional options affecting the file serving
|
||||
* @return void The file is sent along with it's headers
|
||||
*/
|
||||
function tool_generator_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
|
||||
|
||||
// Only for admins or CLI.
|
||||
if (!defined('CLI_SCRIPT') && !is_siteadmin()) {
|
||||
die;
|
||||
}
|
||||
|
||||
if ($context->contextlevel != CONTEXT_SYSTEM) {
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
$fs = get_file_storage();
|
||||
$file = $fs->get_file($context->id, 'tool_generator', $filearea, $args[0], '/', $args[1]);
|
||||
|
||||
// Send the file, always forcing download, we don't want options.
|
||||
session_get_instance()->write_close();
|
||||
send_stored_file($file, 0, 0, true);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,7 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Script creates a standardised large course for testing reliability and
|
||||
* performance.
|
||||
* Script creates a standardised large course for testing reliability and performance.
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 The Open University
|
||||
@@ -32,7 +31,7 @@ require('../../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
// Initialise page and check permissions.
|
||||
admin_externalpage_setup('toolgenerator');
|
||||
admin_externalpage_setup('toolgeneratorcourse');
|
||||
|
||||
// Start page.
|
||||
echo $OUTPUT->header();
|
||||
@@ -40,7 +39,7 @@ echo $OUTPUT->heading(get_string('maketestcourse', 'tool_generator'));
|
||||
|
||||
// Information message.
|
||||
$context = context_system::instance();
|
||||
echo $OUTPUT->box(format_text(get_string('explanation', 'tool_generator'),
|
||||
echo $OUTPUT->box(format_text(get_string('courseexplanation', 'tool_generator'),
|
||||
FORMAT_MARKDOWN, array('context' => $context)));
|
||||
|
||||
// Check debugging is set to DEVELOPER.
|
||||
@@ -51,7 +50,7 @@ if (!debugging('', DEBUG_DEVELOPER)) {
|
||||
}
|
||||
|
||||
// Set up the form.
|
||||
$mform = new tool_generator_make_form('maketestcourse.php');
|
||||
$mform = new tool_generator_make_course_form('maketestcourse.php');
|
||||
if ($data = $mform->get_data()) {
|
||||
// Do actual work.
|
||||
echo $OUTPUT->heading(get_string('creating', 'tool_generator'));
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Generates a JMeter test plan to performance comparison.
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
// Initialise page and check permissions.
|
||||
admin_externalpage_setup('toolgeneratortestplan');
|
||||
|
||||
// Start page.
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('maketestplan', 'tool_generator'));
|
||||
|
||||
// Information message.
|
||||
$context = context_system::instance();
|
||||
$markdownlink = '[' . tool_generator_testplan_backend::get_repourl() . '](' . tool_generator_testplan_backend::get_repourl() . ')';
|
||||
echo $OUTPUT->box(format_text(get_string('testplanexplanation', 'tool_generator', $markdownlink),
|
||||
FORMAT_MARKDOWN, array('context' => $context)));
|
||||
|
||||
// Check debugging is set to DEVELOPER.
|
||||
if (!$CFG->debugdeveloper) {
|
||||
echo $OUTPUT->notification(get_string('error_notdebugging', 'tool_generator'));
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
}
|
||||
|
||||
// Set up the form.
|
||||
$mform = new tool_generator_make_testplan_form('maketestplan.php');
|
||||
if ($data = $mform->get_data()) {
|
||||
|
||||
// Creating both test plan and users files.
|
||||
$testplanfile = tool_generator_testplan_backend::create_testplan_file($data->courseid, $data->size);
|
||||
$usersfile = tool_generator_testplan_backend::create_users_file($data->courseid, $data->updateuserspassword);
|
||||
|
||||
// Test plan link.
|
||||
$testplanurl = moodle_url::make_pluginfile_url(
|
||||
$testplanfile->get_contextid(),
|
||||
$testplanfile->get_component(),
|
||||
$testplanfile->get_filearea(),
|
||||
$testplanfile->get_itemid(),
|
||||
$testplanfile->get_filepath(),
|
||||
$testplanfile->get_filename()
|
||||
);
|
||||
echo html_writer::div(
|
||||
html_writer::link($testplanurl, get_string('downloadtestplan', 'tool_generator'))
|
||||
);
|
||||
|
||||
// Users file link.
|
||||
$usersfileurl = moodle_url::make_pluginfile_url(
|
||||
$usersfile->get_contextid(),
|
||||
$usersfile->get_component(),
|
||||
$usersfile->get_filearea(),
|
||||
$usersfile->get_itemid(),
|
||||
$usersfile->get_filepath(),
|
||||
$usersfile->get_filename()
|
||||
);
|
||||
echo html_writer::div(
|
||||
html_writer::link($usersfileurl, get_string('downloadusersfile', 'tool_generator'))
|
||||
);
|
||||
|
||||
} else {
|
||||
// Display form.
|
||||
$mform->display();
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
@@ -25,8 +25,12 @@
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
if ($hassiteconfig) {
|
||||
$ADMIN->add('development', new admin_externalpage('toolgenerator',
|
||||
$ADMIN->add('development', new admin_externalpage('toolgeneratorcourse',
|
||||
get_string('maketestcourse', 'tool_generator'),
|
||||
$CFG->wwwroot . '/' . $CFG->admin . '/tool/generator/maketestcourse.php'));
|
||||
|
||||
$ADMIN->add('development', new admin_externalpage('toolgeneratortestplan',
|
||||
get_string('maketestplan', 'tool_generator'),
|
||||
$CFG->wwwroot . '/' . $CFG->admin . '/tool/generator/maketestplan.php'));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,885 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jmeterTestPlan version="1.2" properties="2.4">
|
||||
<hashTree>
|
||||
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
|
||||
<stringProp name="TestPlan.comments"></stringProp>
|
||||
<boolProp name="TestPlan.functional_mode">false</boolProp>
|
||||
<boolProp name="TestPlan.serialize_threadgroups">true</boolProp>
|
||||
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="runtimestamp" elementType="Argument">
|
||||
<stringProp name="Argument.name">runtimestamp</stringProp>
|
||||
<stringProp name="Argument.value">${__time()}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="size" elementType="Argument">
|
||||
<stringProp name="Argument.name">size</stringProp>
|
||||
<stringProp name="Argument.value">{{SIZE_PLACEHOLDER}}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="host" elementType="Argument">
|
||||
<stringProp name="Argument.name">host</stringProp>
|
||||
<stringProp name="Argument.value">{{HOST_PLACEHOLDER}}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="sitepath" elementType="Argument">
|
||||
<stringProp name="Argument.name">sitepath</stringProp>
|
||||
<stringProp name="Argument.value">{{SITEPATH_PLACEHOLDER}}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="courseid" elementType="Argument">
|
||||
<stringProp name="Argument.name">courseid</stringProp>
|
||||
<stringProp name="Argument.value">{{COURSEID_PLACEHOLDER}}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="pageactivityid" elementType="Argument">
|
||||
<stringProp name="Argument.name">pageactivityid</stringProp>
|
||||
<stringProp name="Argument.value">{{PAGEACTIVITYID_PLACEHOLDER}}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="forumactivityid" elementType="Argument">
|
||||
<stringProp name="Argument.name">forumactivityid</stringProp>
|
||||
<stringProp name="Argument.value">{{FORUMACTIVITYID_PLACEHOLDER}}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="forumdiscussionid" elementType="Argument">
|
||||
<stringProp name="Argument.name">forumdiscussionid</stringProp>
|
||||
<stringProp name="Argument.value">{{FORUMDISCUSSIONID_PLACEHOLDER}}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="forumreplyid" elementType="Argument">
|
||||
<stringProp name="Argument.name">forumreplyid</stringProp>
|
||||
<stringProp name="Argument.value">{{FORUMREPLYID_PLACEHOLDER}}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="TestPlan.user_define_classpath"></stringProp>
|
||||
</TestPlan>
|
||||
<hashTree>
|
||||
<ConstantThroughputTimer guiclass="TestBeanGUI" testclass="ConstantThroughputTimer" testname="Samples per minute" enabled="true">
|
||||
<stringProp name="calcMode">all active threads (shared)</stringProp>
|
||||
<stringProp name="throughput">${__property(throughput,throughput,120.0)}</stringProp>
|
||||
</ConstantThroughputTimer>
|
||||
<hashTree/>
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Warm-up site" enabled="true">
|
||||
<stringProp name="TestPlan.comments">Used to fill the caches, logs in every user</stringProp>
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">${__P(users,{{USERS_PLACEHOLDER}})}</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">${__P(rampup,{{RAMPUP_PLACEHOLDER}})}</stringProp>
|
||||
<longProp name="ThreadGroup.start_time">1378187955000</longProp>
|
||||
<longProp name="ThreadGroup.end_time">1378187955000</longProp>
|
||||
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="Default site request" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">${host}</stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}</stringProp>
|
||||
<stringProp name="HTTPSampler.concurrentPool">4</stringProp>
|
||||
</ConfigTestElement>
|
||||
<hashTree/>
|
||||
<CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="CSV users data" enabled="true">
|
||||
<stringProp name="delimiter">,</stringProp>
|
||||
<stringProp name="fileEncoding"></stringProp>
|
||||
<stringProp name="filename">${__P(usersfile,YOU_FORGOT_TO_SPECIFY_USERS_CSV_FILE.csv)}</stringProp>
|
||||
<boolProp name="quotedData">false</boolProp>
|
||||
<boolProp name="recycle">true</boolProp>
|
||||
<stringProp name="shareMode">All threads</stringProp>
|
||||
<boolProp name="stopThread">false</boolProp>
|
||||
<stringProp name="variableNames">username,password</stringProp>
|
||||
</CSVDataSet>
|
||||
<hashTree/>
|
||||
<LoopController guiclass="LoopControlPanel" testclass="LoopController" testname="Test plan loop" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">true</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</LoopController>
|
||||
<hashTree>
|
||||
<CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
|
||||
<collectionProp name="CookieManager.cookies"/>
|
||||
<boolProp name="CookieManager.clearEachIteration">true</boolProp>
|
||||
<stringProp name="CookieManager.policy">rfc2109</stringProp>
|
||||
</CookieManager>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Frontpage not logged" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path"></stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Login" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="username" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${username}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">username</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="password" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${password}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">password</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/login/index.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Frontpage logged" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path"></stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="View course" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="id" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${courseid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">id</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/course/view.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="TestPlan.comments"> </stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor" enabled="true">
|
||||
<stringProp name="RegexExtractor.useHeaders">false</stringProp>
|
||||
<stringProp name="RegexExtractor.refname">SESSION_SESSKEY</stringProp>
|
||||
<stringProp name="RegexExtractor.regex">sesskey=([^"]+)"</stringProp>
|
||||
<stringProp name="RegexExtractor.template">$1$</stringProp>
|
||||
<stringProp name="RegexExtractor.default"></stringProp>
|
||||
<stringProp name="RegexExtractor.match_number">2</stringProp>
|
||||
<stringProp name="Sample.scope">all</stringProp>
|
||||
</RegexExtractor>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Logout" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="sesskey" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${SESSION_SESSKEY}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">sesskey</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/login/logout.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Moodle Test" enabled="true">
|
||||
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
|
||||
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">false</boolProp>
|
||||
<stringProp name="LoopController.loops">${__property(loops,loops,{{LOOPS_PLACEHOLDER}})}</stringProp>
|
||||
</elementProp>
|
||||
<stringProp name="ThreadGroup.num_threads">${__property(users,users,{{USERS_PLACEHOLDER}})}</stringProp>
|
||||
<stringProp name="ThreadGroup.ramp_time">${__property(rampup,rampup,{{RAMPUP_PLACEHOLDER}})}</stringProp>
|
||||
<longProp name="ThreadGroup.start_time">1376636813000</longProp>
|
||||
<longProp name="ThreadGroup.end_time">1376636813000</longProp>
|
||||
<boolProp name="ThreadGroup.scheduler">false</boolProp>
|
||||
<stringProp name="ThreadGroup.duration"></stringProp>
|
||||
<stringProp name="ThreadGroup.delay"></stringProp>
|
||||
</ThreadGroup>
|
||||
<hashTree>
|
||||
<ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="Default site request" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain">${host}</stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}</stringProp>
|
||||
<stringProp name="HTTPSampler.concurrentPool">4</stringProp>
|
||||
</ConfigTestElement>
|
||||
<hashTree/>
|
||||
<CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="CSV users data" enabled="true">
|
||||
<stringProp name="delimiter">,</stringProp>
|
||||
<stringProp name="fileEncoding"></stringProp>
|
||||
<stringProp name="filename">${__P(usersfile,YOU_FORGOT_TO_SPECIFY_USERS_CSV_FILE.csv)}</stringProp>
|
||||
<boolProp name="quotedData">false</boolProp>
|
||||
<boolProp name="recycle">true</boolProp>
|
||||
<stringProp name="shareMode">All threads</stringProp>
|
||||
<boolProp name="stopThread">false</boolProp>
|
||||
<stringProp name="variableNames">username,password</stringProp>
|
||||
</CSVDataSet>
|
||||
<hashTree/>
|
||||
<LoopController guiclass="LoopControlPanel" testclass="LoopController" testname="Test plan loop" enabled="true">
|
||||
<boolProp name="LoopController.continue_forever">true</boolProp>
|
||||
<stringProp name="LoopController.loops">1</stringProp>
|
||||
</LoopController>
|
||||
<hashTree>
|
||||
<CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
|
||||
<collectionProp name="CookieManager.cookies"/>
|
||||
<boolProp name="CookieManager.clearEachIteration">true</boolProp>
|
||||
<stringProp name="CookieManager.policy">rfc2109</stringProp>
|
||||
</CookieManager>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Frontpage not logged" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path"></stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Login" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="username" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${username}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">username</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="password" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${password}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">password</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/login/index.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Logged in" enabled="true">
|
||||
<collectionProp name="Asserion.test_strings">
|
||||
<stringProp name="615717117"><div class="logininfo">You are logged in as</stringProp>
|
||||
</collectionProp>
|
||||
<stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
|
||||
<boolProp name="Assertion.assume_success">false</boolProp>
|
||||
<intProp name="Assertion.test_type">2</intProp>
|
||||
</ResponseAssertion>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Frontpage logged" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments"/>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path"></stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="View course" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="id" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${courseid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">id</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/course/view.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
<stringProp name="TestPlan.comments"> </stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="View a page activity" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="id" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${pageactivityid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">id</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/mod/page/view.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="View course again" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="id" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${courseid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">id</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/course/view.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="View a forum activity" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="id" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${forumactivityid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">id</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/mod/forum/view.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="View a forum discussion" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="d" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${forumdiscussionid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">d</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/mod/forum/discuss.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Fill a form to reply a forum discussion" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="reply" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${forumreplyid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">reply</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/mod/forum/post.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree>
|
||||
<RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Get session userid" enabled="true">
|
||||
<stringProp name="RegexExtractor.useHeaders">false</stringProp>
|
||||
<stringProp name="RegexExtractor.refname">SESSION_USERID</stringProp>
|
||||
<stringProp name="RegexExtractor.regex">name="userid"\stype="hidden"\svalue="(\d+)"</stringProp>
|
||||
<stringProp name="RegexExtractor.template">$1$</stringProp>
|
||||
<stringProp name="RegexExtractor.default">0</stringProp>
|
||||
<stringProp name="RegexExtractor.match_number">1</stringProp>
|
||||
</RegexExtractor>
|
||||
<hashTree/>
|
||||
<RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Get session sesskey" enabled="true">
|
||||
<stringProp name="RegexExtractor.useHeaders">false</stringProp>
|
||||
<stringProp name="RegexExtractor.refname">SESSION_SESSKEY</stringProp>
|
||||
<stringProp name="RegexExtractor.regex">name="sesskey"\stype="hidden"\svalue="([^"]+)"</stringProp>
|
||||
<stringProp name="RegexExtractor.template">$1$</stringProp>
|
||||
<stringProp name="RegexExtractor.default">0</stringProp>
|
||||
<stringProp name="RegexExtractor.match_number">1</stringProp>
|
||||
</RegexExtractor>
|
||||
<hashTree/>
|
||||
<RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Get forum form attachments" enabled="true">
|
||||
<stringProp name="RegexExtractor.useHeaders">false</stringProp>
|
||||
<stringProp name="RegexExtractor.refname">SESSION_FORUMFORMATTACHMENTS</stringProp>
|
||||
<stringProp name="RegexExtractor.regex">value="(\d+)"\sname="attachments"\stype="hidden"</stringProp>
|
||||
<stringProp name="RegexExtractor.template">$1$</stringProp>
|
||||
<stringProp name="RegexExtractor.default">0</stringProp>
|
||||
<stringProp name="RegexExtractor.match_number">1</stringProp>
|
||||
</RegexExtractor>
|
||||
<hashTree/>
|
||||
<RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Get forum form itemid" enabled="true">
|
||||
<stringProp name="RegexExtractor.useHeaders">false</stringProp>
|
||||
<stringProp name="RegexExtractor.refname">SESSION_FORUMFORMITEMID</stringProp>
|
||||
<stringProp name="RegexExtractor.regex">type="hidden"\sname="message\[itemid\]"\svalue="(\d+)"</stringProp>
|
||||
<stringProp name="RegexExtractor.template">$1$</stringProp>
|
||||
<stringProp name="RegexExtractor.default">0</stringProp>
|
||||
<stringProp name="RegexExtractor.match_number">1</stringProp>
|
||||
</RegexExtractor>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Send the forum discussion reply" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="course" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${courseid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">course</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="forum" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">0</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">forum</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="discussion" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${forumdiscussionid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">discussion</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="userid" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${SESSION_USERID}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">userid</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="groupid" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">0</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">groupid</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="edit" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">0</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">edit</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="reply" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${forumreplyid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">reply</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="sesskey" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${SESSION_SESSKEY}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">sesskey</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="_qf__mod_forum_post_form" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">1</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">_qf__mod_forum_post_form</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="subject" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">Re: I am the test plan reply subject</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">subject</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="message[itemid]" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${SESSION_FORUMFORMITEMID}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">message[itemid]</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="message[format]" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">1</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">message[format]</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="message[text]" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">I am the test plan reply message</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">message[text]</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="parent" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${forumreplyid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">parent</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="subscribe" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">1</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">subscribe</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="attachments" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${SESSION_FORUMFORMATTACHMENTS}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">attachments</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="timestart" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">0</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">timestart</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="timeend" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">0</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">timeend</stringProp>
|
||||
</elementProp>
|
||||
<elementProp name="submitbutton" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">Post to forum</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">submitbutton</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/mod/forum/post.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">POST</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="View course once more" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="id" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${courseid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">id</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/course/view.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="View course participants" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="id" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${courseid}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">id</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/user/index.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Logout" enabled="true">
|
||||
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
||||
<collectionProp name="Arguments.arguments">
|
||||
<elementProp name="sesskey" elementType="HTTPArgument">
|
||||
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
||||
<stringProp name="Argument.value">${SESSION_SESSKEY}</stringProp>
|
||||
<stringProp name="Argument.metadata">=</stringProp>
|
||||
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
||||
<stringProp name="Argument.name">sesskey</stringProp>
|
||||
</elementProp>
|
||||
</collectionProp>
|
||||
</elementProp>
|
||||
<stringProp name="HTTPSampler.domain"></stringProp>
|
||||
<stringProp name="HTTPSampler.port"></stringProp>
|
||||
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.response_timeout"></stringProp>
|
||||
<stringProp name="HTTPSampler.protocol"></stringProp>
|
||||
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
|
||||
<stringProp name="HTTPSampler.path">${sitepath}/login/logout.php</stringProp>
|
||||
<stringProp name="HTTPSampler.method">GET</stringProp>
|
||||
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
|
||||
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
|
||||
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
|
||||
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
|
||||
<boolProp name="HTTPSampler.monitor">false</boolProp>
|
||||
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
|
||||
</HTTPSamplerProxy>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
<BeanShellListener guiclass="TestBeanGUI" testclass="BeanShellListener" testname="Create php array results" enabled="true">
|
||||
<stringProp name="filename">recorder.bsf</stringProp>
|
||||
<stringProp name="parameters"></stringProp>
|
||||
<boolProp name="resetInterpreter">false</boolProp>
|
||||
<stringProp name="script"></stringProp>
|
||||
</BeanShellListener>
|
||||
<hashTree/>
|
||||
<ResultCollector guiclass="SimpleDataWriter" testclass="ResultCollector" testname="Simple Data Writer" enabled="true">
|
||||
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
||||
<objProp>
|
||||
<name>saveConfig</name>
|
||||
<value class="SampleSaveConfiguration">
|
||||
<time>true</time>
|
||||
<latency>true</latency>
|
||||
<timestamp>true</timestamp>
|
||||
<success>true</success>
|
||||
<label>true</label>
|
||||
<code>true</code>
|
||||
<message>true</message>
|
||||
<threadName>true</threadName>
|
||||
<dataType>true</dataType>
|
||||
<encoding>false</encoding>
|
||||
<assertions>true</assertions>
|
||||
<subresults>true</subresults>
|
||||
<responseData>false</responseData>
|
||||
<samplerData>false</samplerData>
|
||||
<xml>true</xml>
|
||||
<fieldNames>false</fieldNames>
|
||||
<responseHeaders>false</responseHeaders>
|
||||
<requestHeaders>false</requestHeaders>
|
||||
<responseDataOnError>false</responseDataOnError>
|
||||
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
|
||||
<assertionsResultsToSave>0</assertionsResultsToSave>
|
||||
<bytes>true</bytes>
|
||||
</value>
|
||||
</objProp>
|
||||
<stringProp name="filename">runs_samples/data.${runtimestamp}.jtl</stringProp>
|
||||
</ResultCollector>
|
||||
<hashTree/>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</hashTree>
|
||||
</jmeterTestPlan>
|
||||
@@ -35,7 +35,7 @@ class tool_generator_maketestcourse_testcase extends advanced_testcase {
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create the XS course.
|
||||
$backend = new tool_generator_course_backend('TOOL_MAKELARGECOURSE_XS', 0, false, false);
|
||||
$backend = new tool_generator_course_backend('TOOL_MAKELARGECOURSE_XS', 0, false, false, false);
|
||||
$courseid = $backend->make();
|
||||
|
||||
// Get course details.
|
||||
@@ -118,7 +118,7 @@ class tool_generator_maketestcourse_testcase extends advanced_testcase {
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create the S course (more sections and activities than XS).
|
||||
$backend = new tool_generator_course_backend('TOOL_S_COURSE_1', 1, true, false);
|
||||
$backend = new tool_generator_course_backend('TOOL_S_COURSE_1', 1, true, false, false);
|
||||
$courseid = $backend->make();
|
||||
|
||||
// Get course details.
|
||||
@@ -151,4 +151,57 @@ class tool_generator_maketestcourse_testcase extends advanced_testcase {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a small test course specifying a maximum size and checks the generated files size is limited.
|
||||
*/
|
||||
public function test_filesize_limit() {
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
// Limit.
|
||||
$filesizelimit = 100;
|
||||
|
||||
// Create a limited XS course.
|
||||
$backend = new tool_generator_course_backend('TOOL_XS_LIMITED', 0, false, $filesizelimit, false);
|
||||
$courseid = $backend->make();
|
||||
|
||||
$course = get_course($courseid);
|
||||
$modinfo = get_fast_modinfo($course);
|
||||
|
||||
// Check there are small files.
|
||||
$fs = get_file_storage();
|
||||
$resources = $modinfo->get_instances_of('resource');
|
||||
foreach ($resources as $resource) {
|
||||
$resourcecontext = context_module::instance($resource->id);
|
||||
$files = $fs->get_area_files($resourcecontext->id, 'mod_resource', 'content', false, 'filename', false);
|
||||
foreach ($files as $file) {
|
||||
if ($file->get_mimetype() == 'application/octet-stream') {
|
||||
$this->assertLessThanOrEqual($filesizelimit, $file->get_filesize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a non-limited XS course.
|
||||
$backend = new tool_generator_course_backend('TOOL_XS_NOLIMITS', 0, false, false, false);
|
||||
$courseid = $backend->make();
|
||||
|
||||
$course = get_course($courseid);
|
||||
$modinfo = get_fast_modinfo($course);
|
||||
|
||||
// Check there are small files.
|
||||
$fs = get_file_storage();
|
||||
$resources = $modinfo->get_instances_of('resource');
|
||||
foreach ($resources as $resource) {
|
||||
$resourcecontext = context_module::instance($resource->id);
|
||||
$files = $fs->get_area_files($resourcecontext->id, 'mod_resource', 'content', false, 'filename', false);
|
||||
foreach ($files as $file) {
|
||||
if ($file->get_mimetype() == 'application/octet-stream') {
|
||||
$this->assertGreaterThan($filesizelimit, (int)$file->get_filesize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
<?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 test for the site generator
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Silly class to access site_backend internal methods.
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class testable_tool_generator_site_backend extends tool_generator_site_backend {
|
||||
|
||||
/**
|
||||
* Public accessor.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_last_testcourse_id() {
|
||||
return parent::get_last_testcourse_id();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit test for the site generator
|
||||
*
|
||||
* @package tool_generator
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_generator_maketestsite_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Checks that site courses shortnames are properly generated.
|
||||
*/
|
||||
public function test_shortnames_generation() {
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$generator = $this->getDataGenerator();
|
||||
|
||||
// Shortname common prefix.
|
||||
$prefix = tool_generator_site_backend::SHORTNAMEPREFIX;
|
||||
|
||||
$record = array();
|
||||
|
||||
// Without courses will be 0.
|
||||
$lastshortname = testable_tool_generator_site_backend::get_last_testcourse_id();
|
||||
$this->assertEquals(0, $lastshortname);
|
||||
|
||||
// Without {$prefix} + {no integer} courses will be 0.
|
||||
$record['shortname'] = $prefix . 'AA';
|
||||
$generator->create_course($record);
|
||||
$record['shortname'] = $prefix . '__';
|
||||
$generator->create_course($record);
|
||||
$record['shortname'] = $prefix . '12.2';
|
||||
$generator->create_course($record);
|
||||
|
||||
$lastshortname = testable_tool_generator_site_backend::get_last_testcourse_id();
|
||||
$this->assertEquals(0, $lastshortname);
|
||||
|
||||
// With {$prefix} + {integer} courses will be the higher one.
|
||||
$record['shortname'] = $prefix . '2';
|
||||
$generator->create_course($record);
|
||||
$record['shortname'] = $prefix . '20';
|
||||
$generator->create_course($record);
|
||||
$record['shortname'] = $prefix . '8';
|
||||
$generator->create_course($record);
|
||||
|
||||
$lastshortname = testable_tool_generator_site_backend::get_last_testcourse_id();
|
||||
$this->assertEquals(20, $lastshortname);
|
||||
|
||||
// Numeric order.
|
||||
for ($i = 9; $i < 14; $i++) {
|
||||
$record['shortname'] = $prefix . $i;
|
||||
$generator->create_course($record);
|
||||
}
|
||||
|
||||
$lastshortname = testable_tool_generator_site_backend::get_last_testcourse_id();
|
||||
$this->assertEquals(20, $lastshortname);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2013090200;
|
||||
$plugin->version = 2013091201;
|
||||
$plugin->requires = 2013090200;
|
||||
$plugin->component = 'tool_generator';
|
||||
|
||||
@@ -687,7 +687,7 @@ if ($formdata = $mform2->is_cancelled()) {
|
||||
}
|
||||
|
||||
if ($dologout) {
|
||||
session_kill_user($existinguser->id);
|
||||
\core\session\manager::kill_user_sessions($existinguser->id);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
+3
-3
@@ -82,10 +82,10 @@
|
||||
die;
|
||||
} else if (data_submitted() and !$user->deleted) {
|
||||
if (delete_user($user)) {
|
||||
session_gc(); // remove stale sessions
|
||||
\core\session\manager::gc(); // Remove stale sessions.
|
||||
redirect($returnurl);
|
||||
} else {
|
||||
session_gc(); // remove stale sessions
|
||||
\core\session\manager::gc(); // Remove stale sessions.
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->notification($returnurl, get_string('deletednot', '', fullname($user, true)));
|
||||
}
|
||||
@@ -125,7 +125,7 @@
|
||||
if (!is_siteadmin($user) and $USER->id != $user->id and $user->suspended != 1) {
|
||||
$user->suspended = 1;
|
||||
// Force logout.
|
||||
session_kill_user($user->id);
|
||||
\core\session\manager::kill_user_sessions($user->id);
|
||||
user_update_user($user, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ if ($confirm and confirm_sesskey()) {
|
||||
}
|
||||
}
|
||||
$rs->close();
|
||||
session_gc(); // remove stale sessions
|
||||
\core\session\manager::gc(); // Remove stale sessions.
|
||||
echo $OUTPUT->box_start('generalbox', 'notice');
|
||||
if (!empty($notifications)) {
|
||||
echo $notifications;
|
||||
|
||||
@@ -96,6 +96,7 @@ class auth_plugin_cas extends auth_plugin_ldap {
|
||||
$site = get_site();
|
||||
$CASform = get_string('CASform', 'auth_cas');
|
||||
$username = optional_param('username', '', PARAM_RAW);
|
||||
$courseid = optional_param('courseid', 0, PARAM_INT);
|
||||
|
||||
if (!empty($username)) {
|
||||
if (isset($SESSION->wantsurl) && (strstr($SESSION->wantsurl, 'ticket') ||
|
||||
@@ -117,6 +118,12 @@ class auth_plugin_cas extends auth_plugin_ldap {
|
||||
$frm = new stdClass();
|
||||
$frm->username = phpCAS::getUser();
|
||||
$frm->password = 'passwdCas';
|
||||
|
||||
// Redirect to a course if multi-auth is activated, authCAS is set to CAS and the courseid is specified.
|
||||
if ($this->config->multiauth && !empty($courseid)) {
|
||||
redirect(new moodle_url('/course/view.php', array('id'=>$courseid)));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -808,7 +808,7 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
$updateuser->suspended = 1;
|
||||
user_update_user($updateuser, false);
|
||||
echo "\t"; print_string('auth_dbsuspenduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
|
||||
session_kill_user($user->id);
|
||||
\core\session\manager::kill_user_sessions($user->id);
|
||||
}
|
||||
} else {
|
||||
print_string('nouserentriestoremove', 'auth_ldap');
|
||||
|
||||
+5
-5
@@ -141,7 +141,7 @@ class auth_plugin_mnet extends auth_plugin_base {
|
||||
global $CFG, $USER, $DB;
|
||||
require_once $CFG->dirroot . '/mnet/xmlrpc/client.php';
|
||||
|
||||
if (session_is_loggedinas()) {
|
||||
if (\core\session\manager::is_loggedinas()) {
|
||||
print_error('notpermittedtojumpas', 'mnet');
|
||||
}
|
||||
|
||||
@@ -919,7 +919,7 @@ class auth_plugin_mnet extends auth_plugin_base {
|
||||
$returnString .= "We failed to refresh the session for the following usernames: \n".implode("\n", $subArray)."\n\n";
|
||||
} else {
|
||||
foreach($results as $emigrant) {
|
||||
session_touch($emigrant->session_id);
|
||||
\core\session\manager::touch_session($emigrant->session_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1076,7 +1076,7 @@ class auth_plugin_mnet extends auth_plugin_base {
|
||||
array('useragent'=>$useragent, 'userid'=>$userid));
|
||||
|
||||
if (isset($remoteclient) && isset($remoteclient->id)) {
|
||||
session_kill_user($userid);
|
||||
\core\session\manager::kill_user_sessions($userid);
|
||||
}
|
||||
return $returnstring;
|
||||
}
|
||||
@@ -1096,7 +1096,7 @@ class auth_plugin_mnet extends auth_plugin_base {
|
||||
$session = $DB->get_record('mnet_session', array('username'=>$username, 'mnethostid'=>$remoteclient->id, 'useragent'=>$useragent));
|
||||
$DB->delete_records('mnet_session', array('username'=>$username, 'mnethostid'=>$remoteclient->id, 'useragent'=>$useragent));
|
||||
if (false != $session) {
|
||||
session_kill($session->session_id);
|
||||
\core\session\manager::kill_session($session->session_id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1113,7 +1113,7 @@ class auth_plugin_mnet extends auth_plugin_base {
|
||||
global $CFG;
|
||||
if (is_array($sessionArray)) {
|
||||
while($session = array_pop($sessionArray)) {
|
||||
session_kill($session->session_id);
|
||||
\core\session\manager::kill_session($session->session_id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
&& $user = authenticate_user_login($frm->username, $frm->password)) {
|
||||
|
||||
enrol_check_plugins($user);
|
||||
session_set_user($user);
|
||||
\core\session\manager::set_user($user);
|
||||
|
||||
$USER->loggedin = true;
|
||||
$USER->site = $CFG->wwwroot; // for added security, store the site in the
|
||||
|
||||
@@ -139,7 +139,7 @@ class imscc11_backup_convert extends backup_execution_step {
|
||||
|
||||
require_once($CFG->dirroot . '/backup/cc/cc_includes.php');
|
||||
|
||||
$tempdir = $CFG->dataroot . '/temp/backup/' . uniqid('', true);
|
||||
$tempdir = $CFG->tempdir . '/backup/' . uniqid('', true);
|
||||
|
||||
if (mkdir($tempdir, $CFG->directorypermissions, true)) {
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+9
-9
@@ -25,11 +25,9 @@ require_login($course);
|
||||
// Must hold restoretargetimport in the current course
|
||||
require_capability('moodle/restore:restoretargetimport', $context);
|
||||
|
||||
$heading = get_string('import');
|
||||
|
||||
// Set up the page
|
||||
$PAGE->set_title($heading);
|
||||
$PAGE->set_heading($heading);
|
||||
$PAGE->set_title($course->shortname . ': ' . get_string('import'));
|
||||
$PAGE->set_heading($course->fullname);
|
||||
$PAGE->set_url(new moodle_url('/backup/import.php', array('id'=>$courseid)));
|
||||
$PAGE->set_context($context);
|
||||
$PAGE->set_pagelayout('incourse');
|
||||
@@ -120,6 +118,10 @@ if ($backup->get_stage() == backup_ui::STAGE_FINAL) {
|
||||
// Prepare the restore controller. We don't need a UI here as we will just use what
|
||||
// ever the restore has (the user has just chosen).
|
||||
$rc = new restore_controller($backupid, $course->id, backup::INTERACTIVE_YES, backup::MODE_IMPORT, $USER->id, $restoretarget);
|
||||
|
||||
// Start a progress section for the restore, which will consist of 2 steps
|
||||
// (the precheck and then the actual restore).
|
||||
$progress->start_progress('Restore process', 2);
|
||||
$rc->set_progress($progress);
|
||||
// Convert the backup if required.... it should NEVER happed
|
||||
if ($rc->get_status() == backup::STATUS_REQUIRE_CONV) {
|
||||
@@ -155,6 +157,9 @@ if ($backup->get_stage() == backup_ui::STAGE_FINAL) {
|
||||
// Delete the temp directory now
|
||||
fulldelete($tempdestination);
|
||||
|
||||
// End restore section of progress tracking (restore/precheck).
|
||||
$progress->end_progress();
|
||||
|
||||
// All progress complete. Hide progress area.
|
||||
$progress->end_progress();
|
||||
echo html_writer::end_div();
|
||||
@@ -182,11 +187,6 @@ if ($backup->get_stage() == backup_ui::STAGE_FINAL) {
|
||||
$backup->save_controller();
|
||||
}
|
||||
|
||||
// Adjust the page for the stage
|
||||
$PAGE->set_title($heading.': '.$backup->get_stage_name());
|
||||
$PAGE->set_heading($heading.': '.$backup->get_stage_name());
|
||||
$PAGE->navbar->add($backup->get_stage_name());
|
||||
|
||||
// Display the current stage
|
||||
echo $OUTPUT->header();
|
||||
if ($backup->enforce_changed_dependencies()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1499,10 +1502,16 @@ class move_inforef_annotations_to_final extends backup_execution_step {
|
||||
|
||||
// Items we want to include in the inforef file
|
||||
$items = backup_helper::get_inforef_itemnames();
|
||||
$progress = $this->task->get_progress();
|
||||
$progress->start_progress($this->get_name(), count($items));
|
||||
$done = 1;
|
||||
foreach ($items as $itemname) {
|
||||
// Delegate to dbops
|
||||
backup_structure_dbops::move_annotations_to_final($this->get_backupid(), $itemname);
|
||||
backup_structure_dbops::move_annotations_to_final($this->get_backupid(),
|
||||
$itemname, $progress);
|
||||
$progress->progress($done++);
|
||||
}
|
||||
$progress->end_progress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1667,7 +1676,11 @@ class backup_main_structure_step extends backup_structure_step {
|
||||
/**
|
||||
* Execution step that will generate the final zip (.mbz) file with all the contents
|
||||
*/
|
||||
class backup_zip_contents extends backup_execution_step {
|
||||
class backup_zip_contents extends backup_execution_step implements file_progress {
|
||||
/**
|
||||
* @var bool True if we have started tracking progress
|
||||
*/
|
||||
protected $startedprogress;
|
||||
|
||||
protected function define_execution() {
|
||||
|
||||
@@ -1694,8 +1707,34 @@ class backup_zip_contents extends backup_execution_step {
|
||||
$zippacker = get_file_packer('application/zip');
|
||||
|
||||
// Zip files
|
||||
$zippacker->archive_to_pathname($files, $zipfile);
|
||||
$zippacker->archive_to_pathname($files, $zipfile, true, $this);
|
||||
|
||||
// If any progress happened, end it.
|
||||
if ($this->startedprogress) {
|
||||
$this->task->get_progress()->end_progress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation for file_progress interface to display unzip progress.
|
||||
*
|
||||
* @param int $progress Current progress
|
||||
* @param int $max Max value
|
||||
*/
|
||||
public function progress($progress = file_progress::INDETERMINATE, $max = file_progress::INDETERMINATE) {
|
||||
$reporter = $this->task->get_progress();
|
||||
|
||||
// Start tracking progress if necessary.
|
||||
if (!$this->startedprogress) {
|
||||
$reporter->start_progress('extract_file_to_dir', ($max == file_progress::INDETERMINATE)
|
||||
? core_backup_progress::INDETERMINATE : $max);
|
||||
$this->startedprogress = true;
|
||||
}
|
||||
|
||||
// Pass progress through to whatever handles it.
|
||||
$reporter->progress(($progress == file_progress::INDETERMINATE)
|
||||
? core_backup_progress::INDETERMINATE : $progress);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1955,6 +1994,8 @@ class backup_annotate_all_user_files extends backup_execution_step {
|
||||
// Fetch all annotated (final) users
|
||||
$rs = $DB->get_recordset('backup_ids_temp', array(
|
||||
'backupid' => $this->get_backupid(), 'itemname' => 'userfinal'));
|
||||
$progress = $this->task->get_progress();
|
||||
$progress->start_progress($this->get_name());
|
||||
foreach ($rs as $record) {
|
||||
$userid = $record->itemid;
|
||||
$userctx = context_user::instance($userid, IGNORE_MISSING);
|
||||
@@ -1966,8 +2007,10 @@ class backup_annotate_all_user_files extends backup_execution_step {
|
||||
// We don't need to specify itemid ($userid - 5th param) as far as by
|
||||
// context we can get all the associated files. See MDL-22092
|
||||
backup_structure_dbops::annotate_files($this->get_backupid(), $userctx->id, 'user', $filearea, null);
|
||||
$progress->progress();
|
||||
}
|
||||
}
|
||||
$progress->end_progress();
|
||||
$rs->close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,13 +594,17 @@ class restore_load_included_inforef_records extends restore_execution_step {
|
||||
|
||||
// Get all the included tasks
|
||||
$tasks = restore_dbops::get_included_tasks($this->get_restoreid());
|
||||
$progress = $this->task->get_progress();
|
||||
$progress->start_progress($this->get_name(), count($tasks));
|
||||
foreach ($tasks as $task) {
|
||||
// Load the inforef.xml file if exists
|
||||
$inforefpath = $task->get_taskbasepath() . '/inforef.xml';
|
||||
if (file_exists($inforefpath)) {
|
||||
restore_dbops::load_inforef_to_tempids($this->get_restoreid(), $inforefpath); // Load each inforef file to temp_ids
|
||||
// Load each inforef file to temp_ids.
|
||||
restore_dbops::load_inforef_to_tempids($this->get_restoreid(), $inforefpath, $progress);
|
||||
}
|
||||
}
|
||||
$progress->end_progress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,7 +691,8 @@ class restore_load_included_users extends restore_execution_step {
|
||||
return;
|
||||
}
|
||||
$file = $this->get_basepath() . '/users.xml';
|
||||
restore_dbops::load_users_to_tempids($this->get_restoreid(), $file); // Load needed users to temp_ids
|
||||
// Load needed users to temp_ids.
|
||||
restore_dbops::load_users_to_tempids($this->get_restoreid(), $file, $this->task->get_progress());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,7 +713,8 @@ class restore_process_included_users extends restore_execution_step {
|
||||
if (!$this->task->get_setting_value('users')) { // No userinfo being restored, nothing to do
|
||||
return;
|
||||
}
|
||||
restore_dbops::process_included_users($this->get_restoreid(), $this->task->get_courseid(), $this->task->get_userid(), $this->task->is_samesite());
|
||||
restore_dbops::process_included_users($this->get_restoreid(), $this->task->get_courseid(),
|
||||
$this->task->get_userid(), $this->task->is_samesite(), $this->task->get_progress());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-8
@@ -43,18 +43,15 @@ if ($stage & restore_ui::STAGE_CONFIRM + restore_ui::STAGE_DESTINATION) {
|
||||
}
|
||||
}
|
||||
|
||||
$heading = $course->fullname;
|
||||
|
||||
$PAGE->set_title($heading.': '.$restore->get_stage_name());
|
||||
$PAGE->set_heading($heading);
|
||||
$PAGE->navbar->add($restore->get_stage_name());
|
||||
$PAGE->set_title($course->shortname . ': ' . get_string('restore'));
|
||||
$PAGE->set_heading($course->fullname);
|
||||
|
||||
$renderer = $PAGE->get_renderer('core','backup');
|
||||
echo $OUTPUT->header();
|
||||
|
||||
// Prepare a progress bar which can display optionally during long-running
|
||||
// operations while setting up the UI.
|
||||
$slowprogress = new core_backup_display_progress_if_slow();
|
||||
$slowprogress = new core_backup_display_progress_if_slow(get_string('preparingui', 'backup'));
|
||||
// Depending on the code branch above, $restore may be a restore_ui or it may
|
||||
// be a restore_ui_independent_stage. Either way, this function exists.
|
||||
$restore->set_progress_reporter($slowprogress);
|
||||
@@ -65,13 +62,20 @@ if (!$restore->is_independent() && $restore->enforce_changed_dependencies()) {
|
||||
}
|
||||
|
||||
if (!$restore->is_independent()) {
|
||||
// Use a temporary (disappearing) progress bar to show the precheck progress if any.
|
||||
$precheckprogress = new core_backup_display_progress_if_slow(get_string('preparingdata', 'backup'));
|
||||
$restore->get_controller()->set_progress($precheckprogress);
|
||||
if ($restore->get_stage() == restore_ui::STAGE_PROCESS && !$restore->requires_substage()) {
|
||||
try {
|
||||
// Display an extra progress bar so that we can show the progress first.
|
||||
// Div used to hide the 'progress' step once the page gets onto 'finished'.
|
||||
echo html_writer::start_div('', array('id' => 'executionprogress'));
|
||||
// Show the current restore state (header with bolded item).
|
||||
echo $renderer->progress_bar($restore->get_progress_bar());
|
||||
$restore->get_controller()->set_progress(new core_backup_display_progress());
|
||||
// Start displaying the actual progress bar percentage.
|
||||
$restore->get_controller()->set_progress(new core_backup_display_progress(true));
|
||||
// Do actual restore.
|
||||
$restore->execute();
|
||||
// Hide this section because we are now going to make the page show 'finished'.
|
||||
echo html_writer::end_div();
|
||||
echo html_writer::script('document.getElementById("executionprogress").style.display = "none";');
|
||||
} catch(Exception $e) {
|
||||
|
||||
@@ -130,10 +130,16 @@ abstract class backup_structure_dbops extends backup_dbops {
|
||||
/**
|
||||
* Moves all the existing 'item' annotations to their final 'itemfinal' ones
|
||||
* for a given backup.
|
||||
*
|
||||
* @param string $backupid Backup ID
|
||||
* @param string $itemname Item name
|
||||
* @param core_backup_progress $progress Progress tracker
|
||||
*/
|
||||
public static function move_annotations_to_final($backupid, $itemname) {
|
||||
public static function move_annotations_to_final($backupid, $itemname, core_backup_progress $progress) {
|
||||
global $DB;
|
||||
$progress->start_progress('move_annotations_to_final');
|
||||
$rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $backupid, 'itemname' => $itemname));
|
||||
$progress->progress();
|
||||
foreach($rs as $annotation) {
|
||||
// If corresponding 'itemfinal' annotation does not exist, update 'item' to 'itemfinal'
|
||||
if (! $DB->record_exists('backup_ids_temp', array('backupid' => $backupid,
|
||||
@@ -141,10 +147,12 @@ abstract class backup_structure_dbops extends backup_dbops {
|
||||
'itemid' => $annotation->itemid))) {
|
||||
$DB->set_field('backup_ids_temp', 'itemname', $itemname . 'final', array('id' => $annotation->id));
|
||||
}
|
||||
$progress->progress();
|
||||
}
|
||||
$rs->close();
|
||||
// All the remaining $itemname annotations can be safely deleted
|
||||
$DB->delete_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => $itemname));
|
||||
$progress->end_progress();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -109,18 +109,34 @@ abstract class restore_dbops {
|
||||
|
||||
/**
|
||||
* Load one inforef.xml file to backup_ids table for future reference
|
||||
*
|
||||
* @param string $restoreid Restore id
|
||||
* @param string $inforeffile File path
|
||||
* @param core_backup_progress $progress Progress tracker
|
||||
*/
|
||||
public static function load_inforef_to_tempids($restoreid, $inforeffile) {
|
||||
public static function load_inforef_to_tempids($restoreid, $inforeffile,
|
||||
core_backup_progress $progress = null) {
|
||||
|
||||
if (!file_exists($inforeffile)) { // Shouldn't happen ever, but...
|
||||
throw new backup_helper_exception('missing_inforef_xml_file', $inforeffile);
|
||||
}
|
||||
|
||||
// Set up progress tracking (indeterminate).
|
||||
if (!$progress) {
|
||||
$progress = new core_backup_null_progress();
|
||||
}
|
||||
$progress->start_progress('Loading inforef.xml file');
|
||||
|
||||
// Let's parse, custom processor will do its work, sending info to DB
|
||||
$xmlparser = new progressive_parser();
|
||||
$xmlparser->set_file($inforeffile);
|
||||
$xmlprocessor = new restore_inforef_parser_processor($restoreid);
|
||||
$xmlparser->set_processor($xmlprocessor);
|
||||
$xmlparser->set_progress($progress);
|
||||
$xmlparser->process();
|
||||
|
||||
// Finish progress
|
||||
$progress->end_progress();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -400,18 +416,34 @@ abstract class restore_dbops {
|
||||
|
||||
/**
|
||||
* Load the needed users.xml file to backup_ids table for future reference
|
||||
*
|
||||
* @param string $restoreid Restore id
|
||||
* @param string $usersfile File path
|
||||
* @param core_backup_progress $progress Progress tracker
|
||||
*/
|
||||
public static function load_users_to_tempids($restoreid, $usersfile) {
|
||||
public static function load_users_to_tempids($restoreid, $usersfile,
|
||||
core_backup_progress $progress = null) {
|
||||
|
||||
if (!file_exists($usersfile)) { // Shouldn't happen ever, but...
|
||||
throw new backup_helper_exception('missing_users_xml_file', $usersfile);
|
||||
}
|
||||
|
||||
// Set up progress tracking (indeterminate).
|
||||
if (!$progress) {
|
||||
$progress = new core_backup_null_progress();
|
||||
}
|
||||
$progress->start_progress('Loading users into temporary table');
|
||||
|
||||
// Let's parse, custom processor will do its work, sending info to DB
|
||||
$xmlparser = new progressive_parser();
|
||||
$xmlparser->set_file($usersfile);
|
||||
$xmlprocessor = new restore_users_parser_processor($restoreid);
|
||||
$xmlparser->set_processor($xmlprocessor);
|
||||
$xmlparser->set_progress($progress);
|
||||
$xmlparser->process();
|
||||
|
||||
// Finish progress.
|
||||
$progress->end_progress();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1385,8 +1417,15 @@ abstract class restore_dbops {
|
||||
* for each one (mapping / creation) and returning one array
|
||||
* of problems in case something is wrong (lack of permissions,
|
||||
* conficts)
|
||||
*
|
||||
* @param string $restoreid Restore id
|
||||
* @param int $courseid Course id
|
||||
* @param int $userid User id
|
||||
* @param bool $samesite True if restore is to same site
|
||||
* @param core_backup_progress $progress Progress reporter
|
||||
*/
|
||||
public static function precheck_included_users($restoreid, $courseid, $userid, $samesite) {
|
||||
public static function precheck_included_users($restoreid, $courseid, $userid, $samesite,
|
||||
core_backup_progress $progress) {
|
||||
global $CFG, $DB;
|
||||
|
||||
// To return any problem found
|
||||
@@ -1409,8 +1448,14 @@ abstract class restore_dbops {
|
||||
$cancreateuser = true;
|
||||
}
|
||||
|
||||
// Prepare for reporting progress.
|
||||
$conditions = array('backupid' => $restoreid, 'itemname' => 'user');
|
||||
$max = $DB->count_records('backup_ids_temp', $conditions);
|
||||
$done = 0;
|
||||
$progress->start_progress('Checking users', $max);
|
||||
|
||||
// Iterate over all the included users
|
||||
$rs = $DB->get_recordset('backup_ids_temp', array('backupid' => $restoreid, 'itemname' => 'user'), '', 'itemid, info');
|
||||
$rs = $DB->get_recordset('backup_ids_temp', $conditions, '', 'itemid, info');
|
||||
foreach ($rs as $recuser) {
|
||||
$user = (object)backup_controller_dbops::decode_backup_temp_info($recuser->info);
|
||||
|
||||
@@ -1447,8 +1492,11 @@ abstract class restore_dbops {
|
||||
} else { // Shouldn't arrive here ever, something is for sure wrong. Exception
|
||||
throw new restore_dbops_exception('restore_error_processing_user', $user->username);
|
||||
}
|
||||
$done++;
|
||||
$progress->progress($done);
|
||||
}
|
||||
$rs->close();
|
||||
$progress->end_progress();
|
||||
return $problems;
|
||||
}
|
||||
|
||||
@@ -1458,12 +1506,19 @@ abstract class restore_dbops {
|
||||
*
|
||||
* Just wrap over precheck_included_users(), returning
|
||||
* exception if any problem is found
|
||||
*
|
||||
* @param string $restoreid Restore id
|
||||
* @param int $courseid Course id
|
||||
* @param int $userid User id
|
||||
* @param bool $samesite True if restore is to same site
|
||||
* @param core_backup_progress $progress Optional progress tracker
|
||||
*/
|
||||
public static function process_included_users($restoreid, $courseid, $userid, $samesite) {
|
||||
public static function process_included_users($restoreid, $courseid, $userid, $samesite,
|
||||
core_backup_progress $progress = null) {
|
||||
global $DB;
|
||||
|
||||
// Just let precheck_included_users() to do all the hard work
|
||||
$problems = self::precheck_included_users($restoreid, $courseid, $userid, $samesite);
|
||||
$problems = self::precheck_included_users($restoreid, $courseid, $userid, $samesite, $progress);
|
||||
|
||||
// With problems, throw exception, shouldn't happen if prechecks were originally
|
||||
// executed, so be radical here.
|
||||
|
||||
@@ -43,7 +43,7 @@ abstract class restore_prechecks_helper {
|
||||
*
|
||||
* Returns empty array or warnings/errors array
|
||||
*/
|
||||
public static function execute_prechecks($controller, $droptemptablesafter = false) {
|
||||
public static function execute_prechecks(restore_controller $controller, $droptemptablesafter = false) {
|
||||
global $CFG;
|
||||
|
||||
$errors = array();
|
||||
@@ -57,16 +57,31 @@ abstract class restore_prechecks_helper {
|
||||
$courseid = $controller->get_courseid();
|
||||
$userid = $controller->get_userid();
|
||||
$rolemappings = $controller->get_info()->role_mappings;
|
||||
$progress = $controller->get_progress();
|
||||
|
||||
// Start tracking progress. There are currently 8 major steps, corresponding
|
||||
// to $majorstep++ lines in this code; we keep track of the total so as to
|
||||
// verify that it's still correct. If you add a major step, you need to change
|
||||
// the total here.
|
||||
$majorstep = 1;
|
||||
$majorsteps = 8;
|
||||
$progress->start_progress('Carrying out pre-restore checks', $majorsteps);
|
||||
|
||||
// Load all the included tasks to look for inforef.xml files
|
||||
$inforeffiles = array();
|
||||
$tasks = restore_dbops::get_included_tasks($restoreid);
|
||||
$progress->start_progress('Listing inforef files', count($tasks));
|
||||
$minorstep = 1;
|
||||
foreach ($tasks as $task) {
|
||||
// Add the inforef.xml file if exists
|
||||
$inforefpath = $task->get_taskbasepath() . '/inforef.xml';
|
||||
if (file_exists($inforefpath)) {
|
||||
$inforeffiles[] = $inforefpath;
|
||||
}
|
||||
$progress->progress($minorstep++);
|
||||
}
|
||||
$progress->end_progress();
|
||||
$progress->progress($majorstep++);
|
||||
|
||||
// Create temp tables
|
||||
restore_controller_dbops::create_restore_temp_tables($controller->get_restoreid());
|
||||
@@ -108,18 +123,31 @@ abstract class restore_prechecks_helper {
|
||||
}
|
||||
|
||||
// Load all the inforef files, we are going to need them
|
||||
$progress->start_progress('Loading temporary IDs', count($inforeffiles));
|
||||
$minorstep = 1;
|
||||
foreach ($inforeffiles as $inforeffile) {
|
||||
restore_dbops::load_inforef_to_tempids($restoreid, $inforeffile); // Load each inforef file to temp_ids
|
||||
// Load each inforef file to temp_ids.
|
||||
restore_dbops::load_inforef_to_tempids($restoreid, $inforeffile, $progress);
|
||||
$progress->progress($minorstep++);
|
||||
}
|
||||
$progress->end_progress();
|
||||
$progress->progress($majorstep++);
|
||||
|
||||
// If restoring users, check we are able to create all them
|
||||
if ($restoreusers) {
|
||||
$file = $controller->get_plan()->get_basepath() . '/users.xml';
|
||||
restore_dbops::load_users_to_tempids($restoreid, $file); // Load needed users to temp_ids
|
||||
if ($problems = restore_dbops::precheck_included_users($restoreid, $courseid, $userid, $samesite)) {
|
||||
// Load needed users to temp_ids.
|
||||
restore_dbops::load_users_to_tempids($restoreid, $file, $progress);
|
||||
$progress->progress($majorstep++);
|
||||
if ($problems = restore_dbops::precheck_included_users($restoreid, $courseid, $userid, $samesite, $progress)) {
|
||||
$errors = array_merge($errors, $problems);
|
||||
}
|
||||
} else {
|
||||
// To ensure consistent number of steps in progress tracking,
|
||||
// mark progress even though we didn't do anything.
|
||||
$progress->progress($majorstep++);
|
||||
}
|
||||
$progress->progress($majorstep++);
|
||||
|
||||
// Note: restore won't create roles at all. Only mapping/skip!
|
||||
$file = $controller->get_plan()->get_basepath() . '/roles.xml';
|
||||
@@ -128,6 +156,7 @@ abstract class restore_prechecks_helper {
|
||||
$errors = array_key_exists('errors', $problems) ? array_merge($errors, $problems['errors']) : $errors;
|
||||
$warnings = array_key_exists('warnings', $problems) ? array_merge($warnings, $problems['warnings']) : $warnings;
|
||||
}
|
||||
$progress->progress($majorstep++);
|
||||
|
||||
// Check we are able to restore and the categories and questions
|
||||
$file = $controller->get_plan()->get_basepath() . '/questions.xml';
|
||||
@@ -136,8 +165,9 @@ abstract class restore_prechecks_helper {
|
||||
$errors = array_key_exists('errors', $problems) ? array_merge($errors, $problems['errors']) : $errors;
|
||||
$warnings = array_key_exists('warnings', $problems) ? array_merge($warnings, $problems['warnings']) : $warnings;
|
||||
}
|
||||
$progress->progress($majorstep++);
|
||||
|
||||
// Prepare results and return
|
||||
// Prepare results.
|
||||
$results = array();
|
||||
if (!empty($errors)) {
|
||||
$results['errors'] = $errors;
|
||||
@@ -149,6 +179,14 @@ abstract class restore_prechecks_helper {
|
||||
if (!empty($results) || $droptemptablesafter) {
|
||||
restore_controller_dbops::drop_restore_temp_tables($controller->get_restoreid());
|
||||
}
|
||||
|
||||
// Finish progress and check we got the initial number of steps right.
|
||||
$progress->progress($majorstep++);
|
||||
if ($majorstep != $majorsteps) {
|
||||
throw new coding_exception('Progress step count wrong: ' . $majorstep);
|
||||
}
|
||||
$progress->end_progress();
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,9 @@ abstract class backup_structure_step extends backup_step {
|
||||
// from xml_writer (blame serialized data!)
|
||||
}
|
||||
$xw = new xml_writer($xo, $xt);
|
||||
$pr = new backup_structure_processor($xw);
|
||||
$progress = $this->task->get_progress();
|
||||
$progress->start_progress($this->get_name());
|
||||
$pr = new backup_structure_processor($xw, $progress);
|
||||
|
||||
// Set processor variables from settings
|
||||
foreach ($this->get_settings() as $setting) {
|
||||
@@ -105,6 +107,7 @@ abstract class backup_structure_step extends backup_step {
|
||||
|
||||
// Close everything
|
||||
$xw->stop();
|
||||
$progress->end_progress();
|
||||
|
||||
// Destroy the structure. It helps PHP 5.2 memory a lot!
|
||||
$structure->destroy();
|
||||
|
||||
@@ -101,8 +101,14 @@ abstract class restore_structure_step extends restore_step {
|
||||
$xmlprocessor->add_path($element->get_path(), $element->is_grouped());
|
||||
}
|
||||
|
||||
// Set up progress tracking.
|
||||
$progress = $this->get_task()->get_progress();
|
||||
$progress->start_progress($this->get_name(), core_backup_progress::INDETERMINATE);
|
||||
$xmlparser->set_progress($progress);
|
||||
|
||||
// And process it, dispatch to target methods in step will start automatically
|
||||
$xmlparser->process();
|
||||
$progress->end_progress();
|
||||
|
||||
// Have finished, launch the after_execute method of all the processing objects
|
||||
$this->launch_after_execute_methods();
|
||||
|
||||
@@ -132,6 +132,9 @@ class backup_step_testcase extends advanced_testcase {
|
||||
|
||||
// Remove the test dir and any content
|
||||
@remove_dir(dirname($file));
|
||||
|
||||
// Clear the time limit, otherwise PHPUnit complains.
|
||||
set_time_limit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,6 +43,11 @@ class core_backup_display_progress_if_slow extends core_backup_display_progress
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @var string Text to display in heading if bar appears
|
||||
*/
|
||||
protected $heading;
|
||||
|
||||
/**
|
||||
* @var int Time at which the progress bar should display (if it isn't yet)
|
||||
*/
|
||||
@@ -52,23 +57,38 @@ class core_backup_display_progress_if_slow extends core_backup_display_progress
|
||||
* Constructs the progress reporter. This will not output HTML just yet,
|
||||
* until the required delay time expires.
|
||||
*
|
||||
* @param string $heading Text to display above bar (if it appears); '' for none
|
||||
* @param int $delay Delay time (default 5 seconds)
|
||||
*/
|
||||
public function __construct($delay = self::DEFAULT_DISPLAY_DELAY) {
|
||||
public function __construct($heading, $delay = self::DEFAULT_DISPLAY_DELAY) {
|
||||
// Set start time based on delay.
|
||||
$this->starttime = time() + $delay;
|
||||
$this->heading = $heading;
|
||||
parent::__construct(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a div around the parent display so it can be hidden.
|
||||
* Starts displaying the progress bar, with optional heading and a special
|
||||
* div so it can be hidden later.
|
||||
*
|
||||
* @see core_backup_display_progress::start_html()
|
||||
*/
|
||||
public function start_html() {
|
||||
global $OUTPUT;
|
||||
$this->id = 'core_backup_display_progress_if_slow' . self::$nextid;
|
||||
self::$nextid++;
|
||||
echo html_writer::start_div('', array('id' => $this->id));
|
||||
|
||||
// Containing div includes a CSS class so that it can be themed if required,
|
||||
// and an id so it can be automatically hidden at end.
|
||||
echo html_writer::start_div('core_backup_display_progress_if_slow',
|
||||
array('id' => $this->id));
|
||||
|
||||
// Display optional heading.
|
||||
if ($this->heading !== '') {
|
||||
echo $OUTPUT->heading($this->heading, 3);
|
||||
}
|
||||
|
||||
// Use base class to display progress bar.
|
||||
parent::start_html();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,21 @@ class backup_structure_processor extends base_processor {
|
||||
protected $writer; // xml_writer where the processor is going to output data
|
||||
protected $vars; // array of backup::VAR_XXX => helper value pairs to be used by source specifications
|
||||
|
||||
public function __construct(xml_writer $writer) {
|
||||
/**
|
||||
* @var core_backup_progress Progress tracker (null if none)
|
||||
*/
|
||||
protected $progress;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param xml_writer $writer XML writer to save data
|
||||
* @param core_backup_progress $progress Progress tracker (optional)
|
||||
*/
|
||||
public function __construct(xml_writer $writer, core_backup_progress $progress = null) {
|
||||
$this->writer = $writer;
|
||||
$this->vars = array();
|
||||
$this->progress = $progress;
|
||||
$this->vars = array();
|
||||
}
|
||||
|
||||
public function set_var($key, $value) {
|
||||
@@ -83,6 +95,9 @@ class backup_structure_processor extends base_processor {
|
||||
public function post_process_nested_element(base_nested_element $nested) {
|
||||
// Send close tag to xml_writer
|
||||
$this->writer->end_tag($nested->get_name());
|
||||
if ($this->progress) {
|
||||
$this->progress->progress();
|
||||
}
|
||||
}
|
||||
|
||||
public function process_final_element(base_final_element $final) {
|
||||
@@ -93,6 +108,9 @@ class backup_structure_processor extends base_processor {
|
||||
$attrarr[$attribute->get_name()] = $attribute->get_value();
|
||||
}
|
||||
$this->writer->full_tag($final->get_name(), $final->get_value(), $attrarr);
|
||||
if ($this->progress) {
|
||||
$this->progress->progress();
|
||||
}
|
||||
// Annotate current value if configured to do so
|
||||
$final->annotate($this->get_var(backup::VAR_BACKUPID));
|
||||
}
|
||||
|
||||
@@ -330,7 +330,7 @@ abstract class base_moodleform extends moodleform {
|
||||
* Displays the form
|
||||
*/
|
||||
public function display() {
|
||||
global $PAGE;
|
||||
global $PAGE, $COURSE;
|
||||
|
||||
$this->require_definition_after_data();
|
||||
|
||||
@@ -342,8 +342,13 @@ abstract class base_moodleform extends moodleform {
|
||||
$config->closeButtonTitle = get_string('close', 'editor');
|
||||
$PAGE->requires->yui_module('moodle-backup-confirmcancel', 'M.core_backup.watch_cancel_buttons', array($config));
|
||||
|
||||
// Get list of module types on course.
|
||||
$modinfo = get_fast_modinfo($COURSE);
|
||||
$modnames = $modinfo->get_used_module_names(true);
|
||||
$PAGE->requires->yui_module('moodle-backup-backupselectall', 'M.core_backup.select_all_init',
|
||||
array(array('select' => get_string('select'), 'all' => get_string('all'), 'none' => get_string('none'))));
|
||||
array($modnames));
|
||||
$PAGE->requires->strings_for_js(array('select', 'all', 'none'), 'moodle');
|
||||
$PAGE->requires->strings_for_js(array('showtypes', 'hidetypes'), 'backup');
|
||||
|
||||
parent::display();
|
||||
}
|
||||
|
||||
+89
-10
@@ -6,15 +6,23 @@ M.core_backup = M.core_backup || {};
|
||||
/**
|
||||
* Adds select all/none links to the top of the backup/restore/import schema page.
|
||||
*/
|
||||
M.core_backup.select_all_init = function(str) {
|
||||
M.core_backup.select_all_init = function(modnames) {
|
||||
var formid = null;
|
||||
|
||||
var helper = function(e, check, type) {
|
||||
var helper = function(e, check, type, mod) {
|
||||
e.preventDefault();
|
||||
var prefix = '';
|
||||
if (typeof mod !== 'undefined') {
|
||||
prefix = 'setting_activity_' + mod + '_';
|
||||
}
|
||||
|
||||
var len = type.length;
|
||||
Y.all('input[type="checkbox"]').each(function(checkbox) {
|
||||
var name = checkbox.get('name');
|
||||
// If a prefix has been set, ignore checkboxes which don't have that prefix.
|
||||
if (prefix && name.substring(0, prefix.length) !== prefix) {
|
||||
return;
|
||||
}
|
||||
if (name.substring(name.length - len) == type) {
|
||||
checkbox.set('checked', check);
|
||||
}
|
||||
@@ -28,13 +36,17 @@ M.core_backup.select_all_init = function(str) {
|
||||
}
|
||||
};
|
||||
|
||||
var html_generator = function(classname, idtype) {
|
||||
var html_generator = function(classname, idtype, heading, extra) {
|
||||
if (typeof extra === 'undefined') {
|
||||
extra = '';
|
||||
}
|
||||
return '<div class="' + classname + '">' +
|
||||
'<div class="fitem fitem_fcheckbox">' +
|
||||
'<div class="fitemtitle">' + str.select + '</div>' +
|
||||
'<div class="fitem fitem_fcheckbox backup_selector">' +
|
||||
'<div class="fitemtitle">' + heading + '</div>' +
|
||||
'<div class="felement">' +
|
||||
'<a id="backup-all-' + idtype + '" href="#">' + str.all + '</a> / ' +
|
||||
'<a id="backup-none-' + idtype + '" href="#">' + str.none + '</a>' +
|
||||
'<a id="backup-all-' + idtype + '" href="#">' + M.util.get_string('all', 'moodle') + '</a> / ' +
|
||||
'<a id="backup-none-' + idtype + '" href="#">' + M.util.get_string('none', 'moodle') + '</a>' +
|
||||
extra +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
@@ -62,13 +74,80 @@ M.core_backup.select_all_init = function(str) {
|
||||
}
|
||||
});
|
||||
|
||||
var html = html_generator('include_setting section_level', 'included');
|
||||
// Add global select all/none options.
|
||||
var html = html_generator('include_setting section_level', 'included', M.util.get_string('select', 'moodle'),
|
||||
' (<a id="backup-bytype" href="#">' + M.util.get_string('showtypes', 'backup') + '</a>)');
|
||||
if (withuserdata) {
|
||||
html += html_generator('normal_setting', 'userdata');
|
||||
html += html_generator('normal_setting', 'userdata', M.util.get_string('select', 'moodle'));
|
||||
}
|
||||
var links = Y.Node.create('<div class="grouped_settings section_level">' + html + '</div>');
|
||||
firstsection.insert(links, 'before');
|
||||
|
||||
// Add select all/none for each module type.
|
||||
var initlinks = function(links, mod) {
|
||||
Y.one('#backup-all-mod_' + mod).on('click', function(e) { helper(e, true, '_included', mod); });
|
||||
Y.one('#backup-none-mod_' + mod).on('click', function(e) { helper(e, false, '_included', mod); });
|
||||
if (withuserdata) {
|
||||
Y.one('#backup-all-userdata-mod_' + mod).on('click', function(e) { helper(e, true, withuserdata, mod); });
|
||||
Y.one('#backup-none-userdata-mod_' + mod).on('click', function(e) { helper(e, false, withuserdata, mod); });
|
||||
}
|
||||
};
|
||||
|
||||
// For each module type on the course, add hidden select all/none options.
|
||||
var modlist = Y.Node.create('<div id="mod_select_links">');
|
||||
modlist.hide();
|
||||
modlist.currentlyshown = false;
|
||||
links.appendChild(modlist);
|
||||
for (var mod in modnames) {
|
||||
// Only include actual values from the list.
|
||||
if (!modnames.hasOwnProperty(mod)) {
|
||||
continue;
|
||||
}
|
||||
var html = html_generator('include_setting section_level', 'mod_' + mod, modnames[mod]);
|
||||
if (withuserdata) {
|
||||
html += html_generator('normal_setting', 'userdata-mod_' + mod, modnames[mod]);
|
||||
}
|
||||
var modlinks = Y.Node.create(
|
||||
'<div class="grouped_settings section_level">' + html + '</div>');
|
||||
modlist.appendChild(modlinks);
|
||||
initlinks(modlinks, mod);
|
||||
}
|
||||
|
||||
// Toggles the display of the hidden module select all/none links.
|
||||
var toggletypes = function() {
|
||||
// Change text of type toggle link.
|
||||
var link = Y.one('#backup-bytype');
|
||||
if (modlist.currentlyshown) {
|
||||
link.setHTML(M.util.get_string('showtypes', 'backup'));
|
||||
} else {
|
||||
link.setHTML(M.util.get_string('hidetypes', 'backup'));
|
||||
}
|
||||
|
||||
// The link has now been toggled (from show to hide, or vice-versa).
|
||||
modlist.currentlyshown = !modlist.currentlyshown;
|
||||
|
||||
// Either hide or show the links.
|
||||
var animcfg = { node: modlist, duration: 0.2 };
|
||||
if (modlist.currentlyshown) {
|
||||
// Animate reveal of the module links.
|
||||
modlist.show();
|
||||
animcfg.to = { maxHeight: modlist.get('clientHeight') + 'px' };
|
||||
modlist.setStyle('maxHeight', '0px');
|
||||
var anim = new Y.Anim(animcfg);
|
||||
anim.on('end', function() { modlist.setStyle('maxHeight', 'none'); });
|
||||
anim.run();
|
||||
} else {
|
||||
// Animate hide of the module links.
|
||||
animcfg.to = { maxHeight: '0px' };
|
||||
modlist.setStyle('maxHeight', modlist.get('clientHeight') + 'px');
|
||||
var anim = new Y.Anim(animcfg);
|
||||
anim.on('end', function() { modlist.hide(); modlist.setStyle('maxHeight', 'none'); });
|
||||
anim.run();
|
||||
}
|
||||
|
||||
};
|
||||
Y.one('#backup-bytype').on('click', function(e) { toggletypes(); });
|
||||
|
||||
Y.one('#backup-all-included').on('click', function(e) { helper(e, true, '_included'); });
|
||||
Y.one('#backup-none-included').on('click', function(e) { helper(e, false, '_included'); });
|
||||
if (withuserdata) {
|
||||
@@ -77,4 +156,4 @@ M.core_backup.select_all_init = function(str) {
|
||||
}
|
||||
}
|
||||
|
||||
}, '@VERSION@', {'requires':['base','node','event', 'node-event-simulate']});
|
||||
}, '@VERSION@', {'requires':['base', 'node', 'event', 'node-event-simulate', 'anim']});
|
||||
|
||||
@@ -67,6 +67,11 @@ class progressive_parser {
|
||||
protected $prevlevel; // level of the previous tag processed - to detect pushing places
|
||||
protected $currtag; // name/value/attributes of the tag being processed
|
||||
|
||||
/**
|
||||
* @var core_backup_progress Progress tracker called for each action
|
||||
*/
|
||||
protected $progress;
|
||||
|
||||
public function __construct($case_folding = false) {
|
||||
$this->xml_parser = xml_parser_create('UTF-8');
|
||||
xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, $case_folding);
|
||||
@@ -118,6 +123,18 @@ class progressive_parser {
|
||||
$this->processor = $processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress tracker for the parser. If set, the tracker will be
|
||||
* called to report indeterminate progress for each chunk of XML.
|
||||
*
|
||||
* The caller should have already called start_progress on the progress tracker.
|
||||
*
|
||||
* @param core_backup_progress $progress Progress tracker
|
||||
*/
|
||||
public function set_progress(core_backup_progress $progress) {
|
||||
$this->progress = $progress;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the XML, delegating found chunks to the @progressive_parser_processor
|
||||
*/
|
||||
@@ -167,6 +184,10 @@ class progressive_parser {
|
||||
|
||||
protected function publish($data) {
|
||||
$this->processor->receive_chunk($data);
|
||||
if (!empty($this->progress)) {
|
||||
// Report indeterminate progress.
|
||||
$this->progress->progress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -110,6 +110,7 @@ if ($activate) {
|
||||
if ($confirm == 1) {
|
||||
require_sesskey();
|
||||
$badge->set_status($status);
|
||||
$returnurl->param('msg', 'activatesuccess');
|
||||
|
||||
if ($badge->type == BADGE_TYPE_SITE) {
|
||||
// Review on cron if there are more than 1000 users who can earn a site-level badge.
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ $PAGE->set_url('/badges/ajax.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
// Unlock session during potentially long curl request.
|
||||
session_get_instance()->write_close();
|
||||
\core\session\manager::write_close();
|
||||
|
||||
$result = badges_check_backpack_accessibility();
|
||||
|
||||
|
||||
+84
-1
@@ -43,4 +43,87 @@ function check_site_access() {
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the status indicator to show connection progress.
|
||||
*/
|
||||
function badges_set_connection_progress(status) {
|
||||
switch (status) {
|
||||
case 'connecting':
|
||||
var connecting = M.util.get_string('connecting', 'badges');
|
||||
var imageurl = M.util.image_url('i/loading_small', 'moodle');
|
||||
var loading = Y.Node.create(connecting + ' <img src="'+imageurl+'" width="16" height="16" alt="'+connecting+'"/>');
|
||||
Y.one('#connection-status').removeClass('notconnected').addClass('connecting').setHTML(loading);
|
||||
break;
|
||||
case 'notconnected':
|
||||
var notconnected = M.util.get_string('notconnected', 'badges');;
|
||||
Y.one('#connection-status').removeClass('connecting').addClass('notconnected').setHTML(notconnected);
|
||||
break;
|
||||
default:
|
||||
// Unknown status, do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an error message at the top of the page.
|
||||
*/
|
||||
function badges_set_error_message(messagekey, param) {
|
||||
var errortext = M.util.get_string(messagekey, 'badges', param);
|
||||
Y.one('#connection-error').setHTML(errortext);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the assertion generated by the Persona dialog.
|
||||
*/
|
||||
function badges_handle_assertion(assertion) {
|
||||
|
||||
if (!assertion) {
|
||||
var noassertionstr = M.util.get_string('error:noassertion', 'badges');
|
||||
badges_set_error_message('error:backpackloginfailed', noassertionstr);
|
||||
return;
|
||||
}
|
||||
|
||||
badges_set_connection_progress('connecting');
|
||||
|
||||
Y.io("backpackconnect.php", {
|
||||
method: "POST",
|
||||
data: "assertion="+assertion+"&sesskey="+M.cfg.sesskey,
|
||||
on: {
|
||||
success: function (id, result) {
|
||||
// Reload page to display connected email address.
|
||||
window.location.href = "mybackpack.php";
|
||||
},
|
||||
failure: function (id, result) {
|
||||
try {
|
||||
var parsedResponse = Y.JSON.parse(result.response);
|
||||
} catch (e) {
|
||||
badges_set_connection_progress('notconnected');
|
||||
var badjsonstr = M.util.get_string('error:badjson', 'badges');
|
||||
badges_set_error_message('error:backpackloginfailed', badjsonstr);
|
||||
return;
|
||||
}
|
||||
badges_set_connection_progress('notconnected');
|
||||
badges_set_error_message('error:backpackloginfailed', parsedResponse.reason);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and bind the persona login button.
|
||||
*/
|
||||
function badges_init_persona_login_button() {
|
||||
// Create the login button and add to the page via Javascript.
|
||||
var imageurl = M.util.image_url('i/persona_sign_in_black', 'moodle');
|
||||
var imagealt = M.util.get_string('signinwithyouremail', 'badges');
|
||||
var button = Y.Node.create('<img id="persona_signin" src="'+imageurl+'" width="202" height="25" alt="'+imagealt+'"/>');
|
||||
Y.one('#persona-container').append(button);
|
||||
|
||||
// Bind a click event to trigger login when clicked.
|
||||
button.on('click', function() {
|
||||
Y.one('#connection-error').empty();
|
||||
navigator.id.get(badges_handle_assertion);
|
||||
});
|
||||
}
|
||||
|
||||
+27
-22
@@ -39,28 +39,37 @@ class edit_backpack_form extends moodleform {
|
||||
* Defines the form
|
||||
*/
|
||||
public function definition() {
|
||||
global $USER;
|
||||
global $USER, $PAGE, $OUTPUT;
|
||||
$mform = $this->_form;
|
||||
|
||||
$mform->addElement('html', html_writer::tag('span', '', array('class' => 'notconnected', 'id' => 'connection-error')));
|
||||
$mform->addElement('header', 'backpackheader', get_string('backpackconnection', 'badges'));
|
||||
$mform->addHelpButton('backpackheader', 'backpackconnection', 'badges');
|
||||
$mform->addElement('static', 'url', get_string('url'), 'http://backpack.openbadges.org');
|
||||
$status = html_writer::tag('span', get_string('notconnected', 'badges'), array('class' => 'notconnected'));
|
||||
$mform->addElement('static', 'url', get_string('url'), BADGE_BACKPACKURL);
|
||||
$status = html_writer::tag('span', get_string('notconnected', 'badges'),
|
||||
array('class' => 'notconnected', 'id' => 'connection-status'));
|
||||
$mform->addElement('static', 'status', get_string('status'), $status);
|
||||
|
||||
$mform->addElement('text', 'email', get_string('email'), array('size' => '50'));
|
||||
$mform->setDefault('email', $USER->email);
|
||||
$mform->setType('email', PARAM_RAW);
|
||||
$mform->addRule('email', get_string('required'), 'required', null , 'client');
|
||||
$mform->addHelpButton('email', 'backpackemail', 'badges');
|
||||
$nojs = html_writer::tag('noscript', get_string('error:personaneedsjs', 'badges'),
|
||||
array('class' => 'notconnected'));
|
||||
$personadiv = $OUTPUT->container($nojs, null, 'persona-container');
|
||||
|
||||
$mform->addElement('static', 'persona', '', $personadiv);
|
||||
$mform->addHelpButton('persona', 'personaconnection', 'badges');
|
||||
|
||||
$PAGE->requires->js(new moodle_url('https://login.persona.org/include.js'));
|
||||
$PAGE->requires->js('/badges/backpack.js');
|
||||
$PAGE->requires->js_init_call('badges_init_persona_login_button', null, false);
|
||||
$PAGE->requires->strings_for_js(array('error:backpackloginfailed', 'signinwithyouremail',
|
||||
'error:noassertion', 'error:connectionunknownreason', 'error:badjson', 'connecting',
|
||||
'notconnected'), 'badges');
|
||||
|
||||
$mform->addElement('hidden', 'userid', $USER->id);
|
||||
$mform->setType('userid', PARAM_INT);
|
||||
|
||||
$mform->addElement('hidden', 'backpackurl', 'http://backpack.openbadges.org');
|
||||
$mform->addElement('hidden', 'backpackurl', BADGE_BACKPACKURL);
|
||||
$mform->setType('backpackurl', PARAM_URL);
|
||||
|
||||
$this->add_action_buttons(true, get_string('connect', 'badges'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,18 +79,14 @@ class edit_backpack_form extends moodleform {
|
||||
global $DB;
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
if (!validate_email($data['email'])) {
|
||||
$errors['email'] = get_string('invalidemail');
|
||||
} else {
|
||||
$check = new stdClass();
|
||||
$check->backpackurl = $data['backpackurl'];
|
||||
$check->email = $data['email'];
|
||||
$check = new stdClass();
|
||||
$check->backpackurl = $data['backpackurl'];
|
||||
$check->email = $data['email'];
|
||||
|
||||
$bp = new OpenBadgesBackpackHandler($check);
|
||||
$request = $bp->curl_request('user');
|
||||
if (isset($request->status) && $request->status == 'missing') {
|
||||
$errors['email'] = get_string('error:nosuchuser', 'badges');
|
||||
}
|
||||
$bp = new OpenBadgesBackpackHandler($check);
|
||||
$request = $bp->curl_request('user');
|
||||
if (isset($request->status) && $request->status == 'missing') {
|
||||
$errors['email'] = get_string('error:nosuchuser', 'badges');
|
||||
}
|
||||
return $errors;
|
||||
}
|
||||
@@ -113,7 +118,7 @@ class edit_collections_form extends moodleform {
|
||||
|
||||
$mform->addElement('header', 'backpackheader', get_string('backpackconnection', 'badges'));
|
||||
$mform->addHelpButton('backpackheader', 'backpackconnection', 'badges');
|
||||
$mform->addElement('static', 'url', get_string('url'), 'http://backpack.openbadges.org');
|
||||
$mform->addElement('static', 'url', get_string('url'), BADGE_BACKPACKURL);
|
||||
|
||||
$status = html_writer::tag('span', get_string('connected', 'badges'), array('class' => 'connected'));
|
||||
$mform->addElement('static', 'status', get_string('status'), $status);
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* AJAX script for validating backpack connection.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage badges
|
||||
* @copyright 2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @author Simon Coggins <[email protected]>
|
||||
*/
|
||||
|
||||
define('AJAX_SCRIPT', true);
|
||||
|
||||
require_once(dirname(dirname(__FILE__)) . '/config.php');
|
||||
require_once($CFG->dirroot . '/badges/lib/backpacklib.php');
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
require_sesskey();
|
||||
require_login();
|
||||
$PAGE->set_url('/badges/backpackconnect.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
// Use PHP input filtering as there is no PARAM type for
|
||||
// the type of cleaning that is required (ASCII chars 32-127 only).
|
||||
$assertion = filter_input(
|
||||
INPUT_POST,
|
||||
'assertion',
|
||||
FILTER_UNSAFE_RAW,
|
||||
FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH
|
||||
);
|
||||
|
||||
// Audience is the site url scheme + host + port only.
|
||||
$wwwparts = parse_url($CFG->wwwroot);
|
||||
$audience = $wwwparts['scheme'] . '://' . $wwwparts['host'];
|
||||
$audience .= isset($wwwparts['port']) ? $wwwparts['port'] : '';
|
||||
$params = 'assertion=' . urlencode($assertion) . '&audience=' .
|
||||
urlencode($audience);
|
||||
|
||||
$curl = new curl();
|
||||
$url = 'https://verifier.login.persona.org/verify';
|
||||
$options = array(
|
||||
'FRESH_CONNECT' => true,
|
||||
'RETURNTRANSFER' => true,
|
||||
'FORBID_REUSE' => true,
|
||||
'SSL_VERIFYPEER' => true,
|
||||
'SSL_VERIFYHOST' => 2,
|
||||
'HEADER' => 0,
|
||||
'HTTPHEADER' => array('Content-type: application/x-www-form-urlencoded'),
|
||||
'CONNECTTIMEOUT' => 0,
|
||||
'TIMEOUT' => 10, // Fail if data not returned within 10 seconds.
|
||||
);
|
||||
$result = $curl->post($url, $params, $options);
|
||||
|
||||
// Handle time-out and failed request.
|
||||
if ($curl->errno != 0) {
|
||||
if ($curl->errno == CURLE_OPERATION_TIMEOUTED) {
|
||||
$reason = get_string('error:requesttimeout', 'badges');
|
||||
} else {
|
||||
$reason = get_string('error:requesterror', 'badges', $curl->errno);
|
||||
}
|
||||
badges_send_response('failure', $reason);
|
||||
}
|
||||
|
||||
$data = json_decode($result);
|
||||
|
||||
if (!isset($data->status) || $data->status != 'okay') {
|
||||
$reason = isset($data->reason) ? $data->reason : get_string('error:connectionunknownreason', 'badges');
|
||||
badges_send_response('failure', $reason);
|
||||
}
|
||||
|
||||
// Make sure email matches a backpack.
|
||||
$check = new stdClass();
|
||||
$check->backpackurl = BADGE_BACKPACKURL;
|
||||
$check->email = $data->email;
|
||||
|
||||
$bp = new OpenBadgesBackpackHandler($check);
|
||||
$request = $bp->curl_request('user');
|
||||
if (isset($request->status) && $request->status == 'missing') {
|
||||
$reason = get_string('error:backpackemailnotfound', 'badges', $data->email);
|
||||
badges_send_response('failure', $reason);
|
||||
} else if (empty($request->userId)) {
|
||||
$reason = get_string('error:backpackdatainvalid', 'badges');
|
||||
badges_send_response('failure', $reason);
|
||||
} else {
|
||||
$backpackuid = $request->userId;
|
||||
}
|
||||
|
||||
// Insert record.
|
||||
$obj = new stdClass();
|
||||
$obj->userid = $USER->id;
|
||||
$obj->email = $data->email;
|
||||
$obj->backpackurl = BADGE_BACKPACKURL;
|
||||
$obj->backpackuid = $backpackuid;
|
||||
$obj->autosync = 0;
|
||||
$obj->password = '';
|
||||
$DB->insert_record('badge_backpack', $obj);
|
||||
|
||||
// Return success indicator and email address.
|
||||
badges_send_response('success', $data->email);
|
||||
|
||||
|
||||
/**
|
||||
* Return a JSON response containing the response provided.
|
||||
*
|
||||
* @param string $status Status of the response, typically 'success' or 'failure'.
|
||||
* @param string $responsetext On success, the email address of the user,
|
||||
* otherwise a reason for the failure.
|
||||
* @return void Outputs the JSON and terminates the script.
|
||||
*/
|
||||
function badges_send_response($status, $responsetext) {
|
||||
$out = new stdClass();
|
||||
$out->status = $status;
|
||||
if ($status == 'success') {
|
||||
$out->email = $responsetext;
|
||||
} else {
|
||||
$out->reason = $responsetext;
|
||||
send_header_404();
|
||||
}
|
||||
echo json_encode($out);
|
||||
exit;
|
||||
}
|
||||
+2
-2
@@ -72,7 +72,7 @@ if ((($update == BADGE_CRITERIA_AGGREGATION_ALL) || ($update == BADGE_CRITERIA_A
|
||||
$obj->id = $badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->id;
|
||||
$obj->method = $update;
|
||||
if ($DB->update_record('badge_criteria', $obj)) {
|
||||
$msg = get_string('changessaved');
|
||||
$msg = 'criteriaupdated';
|
||||
} else {
|
||||
$emsg = get_string('error:save', 'badges');
|
||||
}
|
||||
@@ -84,7 +84,7 @@ echo $OUTPUT->heading(print_badge_image($badge, $context, 'small') . ' ' . $badg
|
||||
if ($emsg !== '') {
|
||||
echo $OUTPUT->notification($emsg);
|
||||
} else if ($msg !== '') {
|
||||
echo $OUTPUT->notification($msg, 'notifysuccess');
|
||||
echo $OUTPUT->notification(get_string($msg, 'badges'), 'notifysuccess');
|
||||
}
|
||||
|
||||
echo $output->print_badge_status_box($badge);
|
||||
|
||||
@@ -80,6 +80,7 @@ if ($delete && has_capability('moodle/badges:configurecriteria', $context)) {
|
||||
} else {
|
||||
$badge->criteria[$type]->delete();
|
||||
}
|
||||
$return->param('msg', 'criteriadeleted');
|
||||
redirect($return);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,10 @@ $PAGE->navbar->add($badge->name, new moodle_url('overview.php', array('id' => $b
|
||||
$cparams = array('criteriatype' => $type, 'badgeid' => $badge->id);
|
||||
if ($edit) {
|
||||
$criteria = $badge->criteria[$type];
|
||||
$msg = 'criteriaupdated';
|
||||
} else {
|
||||
$criteria = award_criteria::build($cparams);
|
||||
$msg = 'criteriacreated';
|
||||
}
|
||||
|
||||
$mform = new edit_criteria_form($FULLME, array('criteria' => $criteria, 'addcourse' => $addcourse, 'course' => $badge->courseid));
|
||||
@@ -96,7 +98,7 @@ if (!empty($addcourse)) {
|
||||
$criteria_overall->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ALL));
|
||||
}
|
||||
$criteria->save($data);
|
||||
$return->param('msg', get_string('changessaved'));
|
||||
$return->param('msg', $msg);
|
||||
redirect($return);
|
||||
}
|
||||
|
||||
|
||||
+4
-22
@@ -124,33 +124,15 @@ if ($delete && has_capability('moodle/badges:deletebadge', $PAGE->context)) {
|
||||
}
|
||||
}
|
||||
|
||||
if ($activate && has_capability('moodle/badges:configuredetails', $PAGE->context)) {
|
||||
$badge = new badge($activate);
|
||||
|
||||
if (!$badge->has_criteria()) {
|
||||
$err = get_string('error:cannotact', 'badges') . get_string('nocriteria', 'badges');
|
||||
} else {
|
||||
if ($badge->is_locked()) {
|
||||
$badge->set_status(BADGE_STATUS_ACTIVE_LOCKED);
|
||||
$msg = get_string('activatesuccess', 'badges');
|
||||
} else {
|
||||
require_sesskey();
|
||||
$badge->set_status(BADGE_STATUS_ACTIVE);
|
||||
$msg = get_string('activatesuccess', 'badges');
|
||||
}
|
||||
$returnurl->param('msg', $msg);
|
||||
redirect($returnurl);
|
||||
}
|
||||
} else if ($deactivate && has_capability('moodle/badges:configuredetails', $PAGE->context)) {
|
||||
if ($deactivate && has_capability('moodle/badges:configuredetails', $PAGE->context)) {
|
||||
require_sesskey();
|
||||
$badge = new badge($deactivate);
|
||||
if ($badge->is_locked()) {
|
||||
$badge->set_status(BADGE_STATUS_INACTIVE_LOCKED);
|
||||
$msg = get_string('deactivatesuccess', 'badges');
|
||||
} else {
|
||||
require_sesskey();
|
||||
$badge->set_status(BADGE_STATUS_INACTIVE);
|
||||
$msg = get_string('deactivatesuccess', 'badges');
|
||||
}
|
||||
$msg = 'deactivatesuccess';
|
||||
$returnurl->param('msg', $msg);
|
||||
redirect($returnurl);
|
||||
}
|
||||
@@ -178,7 +160,7 @@ if ($totalcount) {
|
||||
}
|
||||
|
||||
if ($msg !== '') {
|
||||
echo $OUTPUT->notification($msg, 'notifysuccess');
|
||||
echo $OUTPUT->notification(get_string($msg, 'badges'), 'notifysuccess');
|
||||
}
|
||||
|
||||
$badges = new badge_management($records);
|
||||
|
||||
@@ -26,6 +26,12 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/*
|
||||
* URL of backpack. Currently only the Open Badges backpack
|
||||
* is supported.
|
||||
*/
|
||||
define('BADGE_BACKPACKURL', 'http://backpack.openbadges.org');
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ $badgeid = required_param('id', PARAM_INT);
|
||||
$sortby = optional_param('sort', 'dateissued', PARAM_ALPHA);
|
||||
$sorthow = optional_param('dir', 'DESC', PARAM_ALPHA);
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
$updatepref = optional_param('updatepref', false, PARAM_BOOL);
|
||||
|
||||
require_login();
|
||||
|
||||
|
||||
+7
-3
@@ -228,12 +228,16 @@ class core_badges_renderer extends plugin_renderer_base {
|
||||
public function print_badge_table_actions($badge, $context) {
|
||||
$actions = "";
|
||||
|
||||
if (has_capability('moodle/badges:configuredetails', $context)) {
|
||||
if (has_capability('moodle/badges:configuredetails', $context) && $badge->has_criteria()) {
|
||||
// Activate/deactivate badge.
|
||||
if ($badge->status == BADGE_STATUS_INACTIVE || $badge->status == BADGE_STATUS_INACTIVE_LOCKED) {
|
||||
$url = new moodle_url(qualified_me());
|
||||
$url->param('activate', $badge->id);
|
||||
// "Activate" will go to another page and ask for confirmation.
|
||||
$url = new moodle_url('/badges/action.php');
|
||||
$url->param('id', $badge->id);
|
||||
$url->param('activate', true);
|
||||
$url->param('sesskey', sesskey());
|
||||
$return = new moodle_url(qualified_me());
|
||||
$url->param('return', $return->out_as_local_url(false));
|
||||
$actions .= $this->output->action_icon($url, new pix_icon('t/show', get_string('activate', 'badges'))) . " ";
|
||||
} else {
|
||||
$url = new moodle_url(qualified_me());
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $a
|
||||
$forcedownload = true;
|
||||
}
|
||||
|
||||
session_get_instance()->write_close();
|
||||
\core\session\manager::write_close();
|
||||
send_stored_file($file, 60*60, 0, $forcedownload, $options);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class block_mnet_hosts extends block_list {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (session_is_loggedinas()) {
|
||||
if (\core\session\manager::is_loggedinas()) {
|
||||
$this->content = new stdClass();
|
||||
$this->content->footer = html_writer::tag('span',
|
||||
get_string('notpermittedtojumpas', 'mnet'));
|
||||
|
||||
@@ -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
|
||||
|
||||
Vendored
+6
-7
@@ -24,8 +24,8 @@ A definition:
|
||||
'overrideclassfile' => null, // Optional
|
||||
'datasource' => null, // Optional
|
||||
'datasourcefile' => null, // Optional
|
||||
'persistent' => false, // Optional
|
||||
'persistentmaxsize' => false, // Optional
|
||||
'staticacceleration' => false, // Optional
|
||||
'staticaccelerationsize' => false, // Optional
|
||||
'ttl' => 0, // Optional
|
||||
'mappingsonly' => false // Optional
|
||||
'invalidationevents' => array( // Optional
|
||||
@@ -144,8 +144,8 @@ The following optional settings can also be defined:
|
||||
* overrideclassfile - Included if required when using the overrideclass param.
|
||||
* datasource - If provided this class will be used as a data source for the definition. It must implement the cache_data_source interface.
|
||||
* datasourcefile - Included if required when using the datasource param.
|
||||
* persistent - If set to true the loader will be stored when first created and provided to subsequent requests. More on this later.
|
||||
* persistentmaxsize - If set to an int this will be the maximum number of items stored in the persistent cache.
|
||||
* staticacceleration - Any data passing through the cache will be held onto to make subsequent requests for it faster.
|
||||
* staticaccelerationsize - If set to an int this will be the maximum number of items stored in the static acceleration array.
|
||||
* ttl - Can be used to set a ttl value for data being set for this cache.
|
||||
* mappingsonly - This definition can only be used if there is a store mapping for it. More on this later.
|
||||
* invalidationevents - An array of events that should trigger this cache to invalidate.
|
||||
@@ -154,11 +154,10 @@ The following optional settings can also be defined:
|
||||
|
||||
It's important to note that internally the definition is also aware of the component. This is picked up when the definition is read, based upon the location of the caches.php file.
|
||||
|
||||
The persistent option.
|
||||
As noted the persistent option causes the loader generated for this definition to be stored when first created. Subsequent requests for this definition will be given the original loader instance.
|
||||
The staticacceleration option.
|
||||
Data passed to or retrieved from the loader and its chained loaders gets cached by the instance.
|
||||
This option should be used when you know you will require the loader several times and perhaps in different areas of code.
|
||||
Because it caches key=>value data it avoids the need to re-fetch things from stores after the first request. Its good for performance, bad for memory.
|
||||
Memory use can be controlled by setting the staticaccelerationsize option.
|
||||
It should be used sparingly.
|
||||
|
||||
The mappingsonly option.
|
||||
|
||||
Vendored
+75
-28
@@ -75,19 +75,14 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* [string] A class to use as the data loader for this definition.
|
||||
* Any class used here must inherit the cache_data_loader interface.
|
||||
* + datasourcefile
|
||||
* [string] Suplements the above setting indicated the file containing the class to be used. This file is included when
|
||||
* [string] Supplements the above setting indicating the file containing the class to be used. This file is included when
|
||||
* required.
|
||||
* + persistent
|
||||
* [bool] This setting does two important things. First it tells the cache API to only instantiate the cache structure for
|
||||
* this definition once, further requests will be given the original instance.
|
||||
* Second the cache loader will keep an array of the items set and retrieved to the cache during the request.
|
||||
* This has several advantages including better performance without needing to start passing the cache instance between
|
||||
* function calls, the downside is that the cache instance + the items used stay within memory.
|
||||
* Consider using this setting when you know that there are going to be many calls to the cache for the same information
|
||||
* or when you are converting existing code to the cache and need to access the cache within functions but don't want
|
||||
* to add it as an argument to the function.
|
||||
* + persistentmaxsize
|
||||
* [int] This supplements the above setting by limiting the number of items in the caches persistent array of items.
|
||||
* + staticacceleration
|
||||
* The cache loader will keep an array of the items set and retrieved to the cache during the request.
|
||||
* Consider using this setting when you know that there are going to be many calls to the cache for the same information.
|
||||
* Requests for data in this array will be ultra fast, but it will cost memory.
|
||||
* + staticaccelerationsize
|
||||
* [int] This supplements the above setting by limiting the number of items in the static acceleration array.
|
||||
* Tweaking this setting lower will allow you to minimise the memory implications above while hopefully still managing to
|
||||
* offset calls to the cache store.
|
||||
* + ttl
|
||||
@@ -253,16 +248,16 @@ class cache_definition {
|
||||
protected $datasourceaggregate = null;
|
||||
|
||||
/**
|
||||
* Set to true if the definitions cache should be persistent
|
||||
* Set to true if the cache should hold onto items passing through it to speed up subsequent requests.
|
||||
* @var bool
|
||||
*/
|
||||
protected $persistent = false;
|
||||
protected $staticacceleration = false;
|
||||
|
||||
/**
|
||||
* The persistent item array max size.
|
||||
* The maximum number of items that static acceleration cache should hold onto.
|
||||
* @var int
|
||||
*/
|
||||
protected $persistentmaxsize = false;
|
||||
protected $staticaccelerationsize = false;
|
||||
|
||||
/**
|
||||
* The TTL for data in this cache. Please don't use this, instead use event driven invalidation.
|
||||
@@ -363,8 +358,8 @@ class cache_definition {
|
||||
$overrideclassfile = null;
|
||||
$datasource = null;
|
||||
$datasourcefile = null;
|
||||
$persistent = false;
|
||||
$persistentmaxsize = false;
|
||||
$staticacceleration = false;
|
||||
$staticaccelerationsize = false;
|
||||
$ttl = 0;
|
||||
$mappingsonly = false;
|
||||
$invalidationevents = array();
|
||||
@@ -419,10 +414,18 @@ class cache_definition {
|
||||
}
|
||||
|
||||
if (array_key_exists('persistent', $definition)) {
|
||||
$persistent = (bool)$definition['persistent'];
|
||||
// Ahhh this is the legacy persistent option.
|
||||
$staticacceleration = (bool)$definition['persistent'];
|
||||
}
|
||||
if (array_key_exists('staticacceleration', $definition)) {
|
||||
$staticacceleration = (bool)$definition['staticacceleration'];
|
||||
}
|
||||
if (array_key_exists('persistentmaxsize', $definition)) {
|
||||
$persistentmaxsize = (int)$definition['persistentmaxsize'];
|
||||
// Ahhh this is the legacy persistentmaxsize option.
|
||||
$staticaccelerationsize = (int)$definition['persistentmaxsize'];
|
||||
}
|
||||
if (array_key_exists('staticaccelerationsize', $definition)) {
|
||||
$staticaccelerationsize = (int)$definition['staticaccelerationsize'];
|
||||
}
|
||||
if (array_key_exists('ttl', $definition)) {
|
||||
$ttl = (int)$definition['ttl'];
|
||||
@@ -518,8 +521,8 @@ class cache_definition {
|
||||
$cachedefinition->datasource = $datasource;
|
||||
$cachedefinition->datasourcefile = $datasourcefile;
|
||||
$cachedefinition->datasourceaggregate = $datasourceaggregate;
|
||||
$cachedefinition->persistent = $persistent;
|
||||
$cachedefinition->persistentmaxsize = $persistentmaxsize;
|
||||
$cachedefinition->staticacceleration = $staticacceleration;
|
||||
$cachedefinition->staticaccelerationsize = $staticaccelerationsize;
|
||||
$cachedefinition->ttl = $ttl;
|
||||
$cachedefinition->mappingsonly = $mappingsonly;
|
||||
$cachedefinition->invalidationevents = $invalidationevents;
|
||||
@@ -543,7 +546,8 @@ class cache_definition {
|
||||
* - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
|
||||
* - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
|
||||
* - overrideclass : The class to use as the loader.
|
||||
* - persistent : If set to true the cache will persist construction requests.
|
||||
* - staticacceleration : If set to true the cache will hold onto data passing through it.
|
||||
* - staticaccelerationsize : Set it to an int to limit the size of the staticacceleration cache.
|
||||
* @return cache_application|cache_session|cache_request
|
||||
*/
|
||||
public static function load_adhoc($mode, $component, $area, array $options = array()) {
|
||||
@@ -560,7 +564,14 @@ class cache_definition {
|
||||
$definition['simpledata'] = $options['simpledata'];
|
||||
}
|
||||
if (!empty($options['persistent'])) {
|
||||
$definition['persistent'] = $options['persistent'];
|
||||
// Ahhh this is the legacy persistent option.
|
||||
$definition['staticacceleration'] = (bool)$options['persistent'];
|
||||
}
|
||||
if (!empty($options['staticacceleration'])) {
|
||||
$definition['staticacceleration'] = (bool)$options['staticacceleration'];
|
||||
}
|
||||
if (!empty($options['staticaccelerationsize'])) {
|
||||
$definition['staticaccelerationsize'] = (int)$options['staticaccelerationsize'];
|
||||
}
|
||||
if (!empty($options['overrideclass'])) {
|
||||
$definition['overrideclass'] = $options['overrideclass'];
|
||||
@@ -788,18 +799,54 @@ class cache_definition {
|
||||
|
||||
/**
|
||||
* Returns true if this definitions cache should be made persistent.
|
||||
*
|
||||
* Please call {@link cache_definition::use_static_acceleration()} instead.
|
||||
*
|
||||
* @see cache_definition::use_static_acceleration()
|
||||
* @deprecated since 2.6
|
||||
* @return bool
|
||||
*/
|
||||
public function should_be_persistent() {
|
||||
return $this->persistent || $this->mode === cache_store::MODE_SESSION;
|
||||
debugging('Please upgrade your code to use cache_definition::use_static_acceleration', DEBUG_DEVELOPER);
|
||||
return $this->use_static_acceleration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the max size for the persistent item array in the cache.
|
||||
* Returns true if we should hold onto the data flowing through the cache.
|
||||
*
|
||||
* If set to true data flowing through the cache will be stored in a static variable
|
||||
* to make subsequent requests for the data much faster.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function use_static_acceleration() {
|
||||
if ($this->mode === cache_store::MODE_REQUEST) {
|
||||
// Request caches should never use static acceleration - it just doesn't make sense.
|
||||
return false;
|
||||
}
|
||||
return $this->staticacceleration || $this->mode === cache_store::MODE_SESSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the max size for the static acceleration array.
|
||||
*
|
||||
* Please call {@link cache_definition::get_static_acceleration_size()} instead.
|
||||
*
|
||||
* @see cache_definition::get_static_acceleration_size()
|
||||
* @deprecated since 2.6
|
||||
* @return int
|
||||
*/
|
||||
public function get_persistent_max_size() {
|
||||
return $this->persistentmaxsize;
|
||||
debugging('Please upgrade your code to call cache_definition::get_static_acceleration_size', DEBUG_DEVELOPER);
|
||||
return $this->get_static_acceleration_size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the max size for the static acceleration array.
|
||||
* @return int
|
||||
*/
|
||||
public function get_static_acceleration_size() {
|
||||
return $this->staticaccelerationsize;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -916,4 +963,4 @@ class cache_definition {
|
||||
public function has_required_identifiers() {
|
||||
return (count($this->requireidentifiers) > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+9
-8
@@ -46,14 +46,15 @@ class cachestore_dummy extends cache_store {
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Gets set to true if this store is going to persist data.
|
||||
* This happens when the definition doesn't require it as the loader will not be persisting information and something has to.
|
||||
* Gets set to true if this store is going to store data.
|
||||
* This happens when the definition doesn't require static acceleration as the loader will not be storing information and
|
||||
* something has to.
|
||||
* @var bool
|
||||
*/
|
||||
protected $persist = false;
|
||||
|
||||
/**
|
||||
* The persistent store array
|
||||
* The stored data array
|
||||
* @var array
|
||||
*/
|
||||
protected $store = array();
|
||||
@@ -106,13 +107,13 @@ class cachestore_dummy extends cache_store {
|
||||
* @param cache_definition $definition
|
||||
*/
|
||||
public function initialise(cache_definition $definition) {
|
||||
// If the definition isn't persistent then we need to be persistent here.
|
||||
// If the definition isn't using static acceleration then we need to be store data here.
|
||||
// The reasoning behind this is that:
|
||||
// - If the definition is persistent then the cache loader is going to
|
||||
// store things in its persistent cache.
|
||||
// - If the definition is not persistent then the cache loader won't try to store anything
|
||||
// - If the definition is using static acceleration then the cache loader is going to
|
||||
// store things in its static array.
|
||||
// - If the definition is not using static acceleration then the cache loader won't try to store anything
|
||||
// and we will need to store it here in order to make sure it is accessible.
|
||||
$this->persist = !$definition->should_be_persistent();
|
||||
$this->persist = !$definition->use_static_acceleration();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+29
-10
@@ -150,9 +150,7 @@ class cache_factory {
|
||||
*/
|
||||
public static function reset() {
|
||||
$factory = self::instance();
|
||||
$factory->cachesfromdefinitions = array();
|
||||
$factory->cachesfromparams = array();
|
||||
$factory->stores = array();
|
||||
$factory->reset_cache_instances();
|
||||
$factory->configs = array();
|
||||
$factory->definitions = array();
|
||||
$factory->lockplugins = array(); // MUST be null in order to force its regeneration.
|
||||
@@ -160,6 +158,18 @@ class cache_factory {
|
||||
$factory->state = self::STATE_UNINITIALISED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the stores, clearing the array of created stores.
|
||||
*
|
||||
* Cache objects still held onto by the code that initialised them will remain as is
|
||||
* however all future requests for a cache/store will lead to a new instance being re-initialised.
|
||||
*/
|
||||
public function reset_cache_instances() {
|
||||
$this->cachesfromdefinitions = array();
|
||||
$this->cachesfromparams = array();
|
||||
$this->stores = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a cache object given the parameters for a definition.
|
||||
*
|
||||
@@ -181,9 +191,8 @@ class cache_factory {
|
||||
$definition = $this->create_definition($component, $area, $aggregate);
|
||||
$definition->set_identifiers($identifiers);
|
||||
$cache = $this->create_cache($definition, $identifiers);
|
||||
if ($definition->should_be_persistent()) {
|
||||
$this->cachesfromdefinitions[$definitionname] = $cache;
|
||||
}
|
||||
// Loaders are always held onto to speed up subsequent requests.
|
||||
$this->cachesfromdefinitions[$definitionname] = $cache;
|
||||
return $cache;
|
||||
}
|
||||
|
||||
@@ -199,7 +208,8 @@ class cache_factory {
|
||||
* @param array $options An array of options, available options are:
|
||||
* - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
|
||||
* - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
|
||||
* - persistent : If set to true the cache will persist construction requests.
|
||||
* - staticacceleration : If set to true the cache will hold onto data passing through it.
|
||||
* - staticaccelerationsize : The maximum number of items to hold onto for acceleration purposes.
|
||||
* @return cache_application|cache_session|cache_request
|
||||
*/
|
||||
public function create_cache_from_params($mode, $component, $area, array $identifiers = array(), array $options = array()) {
|
||||
@@ -210,9 +220,7 @@ class cache_factory {
|
||||
$definition = cache_definition::load_adhoc($mode, $component, $area, $options);
|
||||
$definition->set_identifiers($identifiers);
|
||||
$cache = $this->create_cache($definition, $identifiers);
|
||||
if ($definition->should_be_persistent()) {
|
||||
$this->cachesfromparams[$key] = $cache;
|
||||
}
|
||||
$this->cachesfromparams[$key] = $cache;
|
||||
return $cache;
|
||||
}
|
||||
|
||||
@@ -297,6 +305,15 @@ class cache_factory {
|
||||
return $this->definitionstores[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache instances that have been used within this request.
|
||||
* @since 2.6
|
||||
* @return array
|
||||
*/
|
||||
public function get_caches_in_use() {
|
||||
return $this->cachesfromdefinitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a cache config instance with the ability to write if required.
|
||||
*
|
||||
@@ -585,7 +602,9 @@ class cache_factory {
|
||||
* </code>
|
||||
*/
|
||||
public static function disable_stores() {
|
||||
// First reset to clear any static acceleration array.
|
||||
$factory = self::instance();
|
||||
$factory->reset_cache_instances();
|
||||
$factory->set_state(self::STATE_STORES_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+27
-20
@@ -238,19 +238,24 @@ class cache_helper {
|
||||
$instance = cache_config::instance();
|
||||
$invalidationeventset = false;
|
||||
$factory = cache_factory::instance();
|
||||
$inuse = $factory->get_caches_in_use();
|
||||
foreach ($instance->get_definitions() as $name => $definitionarr) {
|
||||
$definition = cache_definition::load($name, $definitionarr);
|
||||
if ($definition->invalidates_on_event($event)) {
|
||||
// OK at this point we know that the definition has information to invalidate on the event.
|
||||
// There are two routes, either its an application cache in which case we can invalidate it now.
|
||||
// or it is a persistent cache that also needs to be invalidated now.
|
||||
if ($definition->get_mode() === cache_store::MODE_APPLICATION || $definition->should_be_persistent()) {
|
||||
$cache = $factory->create_cache_from_definition($definition->get_component(), $definition->get_area());
|
||||
$cache->delete_many($keys);
|
||||
// First up check if there is a cache loader for this definition already.
|
||||
// If there is we need to invalidate the keys from there.
|
||||
$definitionkey = $definition->get_component().'/'.$definition->get_area();
|
||||
if (isset($inuse[$definitionkey])) {
|
||||
$inuse[$definitionkey]->delete_many($keys);
|
||||
}
|
||||
|
||||
// We need to flag the event in the "Event invalidation" cache if it hasn't already happened.
|
||||
if ($invalidationeventset === false) {
|
||||
// We should only log events for application and session caches.
|
||||
// Request caches shouldn't have events as all data is lost at the end of the request.
|
||||
// Events should only be logged once of course and likely several definitions are watching so we
|
||||
// track its logging with $invalidationeventset.
|
||||
$logevent = ($invalidationeventset === false && $definition->get_mode() !== cache_store::MODE_REQUEST);
|
||||
|
||||
if ($logevent) {
|
||||
// Get the event invalidation cache.
|
||||
$cache = cache::make('core', 'eventinvalidation');
|
||||
// Get any existing invalidated keys for this cache.
|
||||
@@ -312,23 +317,25 @@ class cache_helper {
|
||||
$instance = cache_config::instance();
|
||||
$invalidationeventset = false;
|
||||
$factory = cache_factory::instance();
|
||||
$inuse = $factory->get_caches_in_use();
|
||||
foreach ($instance->get_definitions() as $name => $definitionarr) {
|
||||
$definition = cache_definition::load($name, $definitionarr);
|
||||
if ($definition->invalidates_on_event($event)) {
|
||||
// Check if this definition would result in a persistent loader being in use.
|
||||
if ($definition->should_be_persistent()) {
|
||||
// There may be a persistent cache loader. Lets purge that first so that any persistent data is removed.
|
||||
$cache = $factory->create_cache_from_definition($definition->get_component(), $definition->get_area());
|
||||
$cache->purge();
|
||||
}
|
||||
// Get all of the store instances that are in use for this store.
|
||||
$stores = $factory->get_store_instances_in_use($definition);
|
||||
foreach ($stores as $store) {
|
||||
// Purge each store individually.
|
||||
$store->purge();
|
||||
// First up check if there is a cache loader for this definition already.
|
||||
// If there is we need to invalidate the keys from there.
|
||||
$definitionkey = $definition->get_component().'/'.$definition->get_area();
|
||||
if (isset($inuse[$definitionkey])) {
|
||||
$inuse[$definitionkey]->purge();
|
||||
}
|
||||
|
||||
// We should only log events for application and session caches.
|
||||
// Request caches shouldn't have events as all data is lost at the end of the request.
|
||||
// Events should only be logged once of course and likely several definitions are watching so we
|
||||
// track its logging with $invalidationeventset.
|
||||
$logevent = ($invalidationeventset === false && $definition->get_mode() !== cache_store::MODE_REQUEST);
|
||||
|
||||
// We need to flag the event in the "Event invalidation" cache if it hasn't already happened.
|
||||
if ($invalidationeventset === false) {
|
||||
if ($logevent && $invalidationeventset === false) {
|
||||
// Get the event invalidation cache.
|
||||
$cache = cache::make('core', 'eventinvalidation');
|
||||
// Create a key to invalidate all.
|
||||
|
||||
Vendored
+165
-85
@@ -93,43 +93,46 @@ class cache implements cache_loader {
|
||||
private $supportsnativettl = null;
|
||||
|
||||
/**
|
||||
* Gets set to true if the cache is going to be using the build in static "persist" cache.
|
||||
* The persist cache statically caches items used during the lifetime of the request. This greatly speeds up interaction
|
||||
* Gets set to true if the cache is going to be using a static array for acceleration.
|
||||
* The array statically caches items used during the lifetime of the request. This greatly speeds up interaction
|
||||
* with the cache in areas where it will be repetitively hit for the same information such as with strings.
|
||||
* There are several other variables to control how this persist cache works.
|
||||
* There are several other variables to control how this static acceleration array works.
|
||||
* @var bool
|
||||
*/
|
||||
private $persist = false;
|
||||
private $staticacceleration = false;
|
||||
|
||||
/**
|
||||
* The persist cache itself.
|
||||
* The static acceleration array.
|
||||
* Items will be stored in this cache as they were provided. This ensure there is no unnecessary processing taking place.
|
||||
* @var array
|
||||
*/
|
||||
private $persistcache = array();
|
||||
private $staticaccelerationarray = array();
|
||||
|
||||
/**
|
||||
* The number of items in the persist cache. Avoids count calls like you wouldn't believe.
|
||||
* The number of items in the static acceleration array. Avoids count calls like you wouldn't believe.
|
||||
* @var int
|
||||
*/
|
||||
private $persistcount = 0;
|
||||
private $staticaccelerationcount = 0;
|
||||
|
||||
/**
|
||||
* An array containing just the keys being used in the persist cache.
|
||||
* This seems redundant perhaps but is used when managing the size of the persist cache.
|
||||
* An array containing just the keys being used in the static acceleration array.
|
||||
* This seems redundant perhaps but is used when managing the size of the static acceleration array.
|
||||
* Items are added to the end of the array and the when we need to reduce the size of the cache we use the
|
||||
* key that is first on this array.
|
||||
* @var array
|
||||
*/
|
||||
private $persistkeys = array();
|
||||
private $staticaccelerationkeys = array();
|
||||
|
||||
/**
|
||||
* The maximum size of the persist cache. If set to false there is no max size.
|
||||
* Caches that make use of the persist cache should seriously consider setting this to something reasonably small, but
|
||||
* The maximum size of the static acceleration array.
|
||||
*
|
||||
* If set to false there is no max size.
|
||||
* Caches that make use of static acceleration should seriously consider setting this to something reasonably small, but
|
||||
* still large enough to offset repetitive calls.
|
||||
*
|
||||
* @var int|false
|
||||
*/
|
||||
private $persistmaxsize = false;
|
||||
private $staticaccelerationsize = false;
|
||||
|
||||
/**
|
||||
* Gets set to true during initialisation if the definition is making use of a ttl.
|
||||
@@ -181,7 +184,8 @@ class cache implements cache_loader {
|
||||
* @param array $options An array of options, available options are:
|
||||
* - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
|
||||
* - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
|
||||
* - persistent : If set to true the cache will persist construction requests.
|
||||
* - staticacceleration : If set to true the cache will hold onto data passing through it.
|
||||
* - staticaccelerationsize : The max size for the static acceleration array.
|
||||
* @return cache_application|cache_session|cache_store
|
||||
*/
|
||||
public static function make_from_params($mode, $component, $area, array $identifiers = array(), array $options = array()) {
|
||||
@@ -218,9 +222,9 @@ class cache implements cache_loader {
|
||||
$this->datasource = $loader;
|
||||
}
|
||||
$this->definition->generate_definition_hash();
|
||||
$this->persist = $this->definition->should_be_persistent();
|
||||
if ($this->persist) {
|
||||
$this->persistmaxsize = $this->definition->get_persistent_max_size();
|
||||
$this->staticacceleration = $this->definition->use_static_acceleration();
|
||||
if ($this->staticacceleration) {
|
||||
$this->staticaccelerationsize = $this->definition->get_static_acceleration_size();
|
||||
}
|
||||
$this->hasattl = ($this->definition->get_ttl() > 0);
|
||||
}
|
||||
@@ -228,7 +232,7 @@ class cache implements cache_loader {
|
||||
/**
|
||||
* Used to inform the loader of its state as a sub loader, or as the top of the chain.
|
||||
*
|
||||
* This is important as it ensures that we do not have more than one loader keeping persistent data.
|
||||
* This is important as it ensures that we do not have more than one loader keeping static acceleration data.
|
||||
* Subloaders need to be "pure" loaders in the sense that they are used to store and retrieve information from stores or the
|
||||
* next loader/data source in the chain.
|
||||
* Nothing fancy, nothing flash.
|
||||
@@ -238,14 +242,14 @@ class cache implements cache_loader {
|
||||
protected function set_is_sub_loader($setting = true) {
|
||||
if ($setting) {
|
||||
$this->subloader = true;
|
||||
// Subloaders should not keep persistent data.
|
||||
$this->persist = false;
|
||||
$this->persistmaxsize = false;
|
||||
// Subloaders should not keep static acceleration data.
|
||||
$this->staticacceleration = false;
|
||||
$this->staticaccelerationsize = false;
|
||||
} else {
|
||||
$this->subloader = true;
|
||||
$this->persist = $this->definition->should_be_persistent();
|
||||
if ($this->persist) {
|
||||
$this->persistmaxsize = $this->definition->get_persistent_max_size();
|
||||
$this->staticacceleration = $this->definition->use_static_acceleration();
|
||||
if ($this->staticacceleration) {
|
||||
$this->staticaccelerationsize = $this->definition->get_static_acceleration_size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,10 +280,10 @@ class cache implements cache_loader {
|
||||
public function get($key, $strictness = IGNORE_MISSING) {
|
||||
// 1. Parse the key.
|
||||
$parsedkey = $this->parse_key($key);
|
||||
// 2. Get it from the persist cache if we can (only when persist is enabled and it has already been requested/set).
|
||||
// 2. Get it from the static acceleration array if we can (only when it is enabled and it has already been requested/set).
|
||||
$result = false;
|
||||
if ($this->is_using_persist_cache()) {
|
||||
$result = $this->get_from_persist_cache($parsedkey);
|
||||
if ($this->use_static_acceleration()) {
|
||||
$result = $this->static_acceleration_get($parsedkey);
|
||||
}
|
||||
if ($result !== false) {
|
||||
if (!is_scalar($result)) {
|
||||
@@ -291,7 +295,7 @@ class cache implements cache_loader {
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
// 3. Get it from the store. Obviously wasn't in the persist cache.
|
||||
// 3. Get it from the store. Obviously wasn't in the static acceleration array.
|
||||
$result = $this->store->get($parsedkey);
|
||||
if ($result !== false) {
|
||||
if ($result instanceof cache_ttl_wrapper) {
|
||||
@@ -305,8 +309,8 @@ class cache implements cache_loader {
|
||||
if ($result instanceof cache_cached_object) {
|
||||
$result = $result->restore_object();
|
||||
}
|
||||
if ($this->is_using_persist_cache()) {
|
||||
$this->set_in_persist_cache($parsedkey, $result);
|
||||
if ($this->use_static_acceleration()) {
|
||||
$this->static_acceleration_set($parsedkey, $result);
|
||||
}
|
||||
}
|
||||
// 4. Load if from the loader/datasource if we don't already have it.
|
||||
@@ -374,14 +378,14 @@ class cache implements cache_loader {
|
||||
$keystofind = array();
|
||||
|
||||
// First up check the persist cache for each key.
|
||||
$isusingpersist = $this->is_using_persist_cache();
|
||||
$isusingpersist = $this->use_static_acceleration();
|
||||
foreach ($keys as $key) {
|
||||
$pkey = $this->parse_key($key);
|
||||
$keysparsed[$key] = $pkey;
|
||||
$parsedkeys[$pkey] = $key;
|
||||
$keystofind[$pkey] = $key;
|
||||
if ($isusingpersist) {
|
||||
$value = $this->get_from_persist_cache($pkey);
|
||||
$value = $this->static_acceleration_get($pkey);
|
||||
if ($value !== false) {
|
||||
$resultpersist[$pkey] = $value;
|
||||
unset($keystofind[$pkey]);
|
||||
@@ -404,6 +408,9 @@ class cache implements cache_loader {
|
||||
if ($value instanceof cache_cached_object) {
|
||||
$value = $value->restore_object();
|
||||
}
|
||||
if ($value !== false && $this->use_static_acceleration()) {
|
||||
$this->static_acceleration_set($key, $value);
|
||||
}
|
||||
$resultstore[$key] = $value;
|
||||
}
|
||||
}
|
||||
@@ -499,8 +506,8 @@ class cache implements cache_loader {
|
||||
$data = new cache_ttl_wrapper($data, $this->definition->get_ttl());
|
||||
}
|
||||
$parsedkey = $this->parse_key($key);
|
||||
if ($this->is_using_persist_cache()) {
|
||||
$this->set_in_persist_cache($parsedkey, $data);
|
||||
if ($this->use_static_acceleration()) {
|
||||
$this->static_acceleration_set($parsedkey, $data);
|
||||
}
|
||||
return $this->store->set($parsedkey, $data);
|
||||
}
|
||||
@@ -604,7 +611,7 @@ class cache implements cache_loader {
|
||||
}
|
||||
$data = array();
|
||||
$simulatettl = $this->has_a_ttl() && !$this->store_supports_native_ttl();
|
||||
$usepersistcache = $this->is_using_persist_cache();
|
||||
$usestaticaccelerationarray = $this->use_static_acceleration();
|
||||
foreach ($keyvaluearray as $key => $value) {
|
||||
if (is_object($value) && $value instanceof cacheable_object) {
|
||||
$value = new cache_cached_object($value);
|
||||
@@ -622,8 +629,8 @@ class cache implements cache_loader {
|
||||
'key' => $this->parse_key($key),
|
||||
'value' => $value
|
||||
);
|
||||
if ($usepersistcache) {
|
||||
$this->set_in_persist_cache($data[$key]['key'], $value);
|
||||
if ($usestaticaccelerationarray) {
|
||||
$this->static_acceleration_set($data[$key]['key'], $value);
|
||||
}
|
||||
}
|
||||
if ($this->perfdebug) {
|
||||
@@ -655,8 +662,8 @@ class cache implements cache_loader {
|
||||
*/
|
||||
public function has($key, $tryloadifpossible = false) {
|
||||
$parsedkey = $this->parse_key($key);
|
||||
if ($this->is_in_persist_cache($parsedkey)) {
|
||||
// Hoorah, that was easy. It exists in the persist cache so we definitely have it.
|
||||
if ($this->static_acceleration_has($parsedkey)) {
|
||||
// Hoorah, that was easy. It exists in the static acceleration array so we definitely have it.
|
||||
return true;
|
||||
}
|
||||
if ($this->has_a_ttl() && !$this->store_supports_native_ttl()) {
|
||||
@@ -737,11 +744,11 @@ class cache implements cache_loader {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->is_using_persist_cache()) {
|
||||
if ($this->use_static_acceleration()) {
|
||||
$parsedkeys = array();
|
||||
foreach ($keys as $id => $key) {
|
||||
$parsedkey = $this->parse_key($key);
|
||||
if ($this->is_in_persist_cache($parsedkey)) {
|
||||
if ($this->static_acceleration_has($parsedkey)) {
|
||||
return true;
|
||||
}
|
||||
$parsedkeys[] = $parsedkey;
|
||||
@@ -762,7 +769,7 @@ class cache implements cache_loader {
|
||||
*/
|
||||
public function delete($key, $recurse = true) {
|
||||
$parsedkey = $this->parse_key($key);
|
||||
$this->delete_from_persist_cache($parsedkey);
|
||||
$this->static_acceleration_delete($parsedkey);
|
||||
if ($recurse && $this->loader !== false) {
|
||||
// Delete from the bottom of the stack first.
|
||||
$this->loader->delete($key, $recurse);
|
||||
@@ -780,9 +787,9 @@ class cache implements cache_loader {
|
||||
*/
|
||||
public function delete_many(array $keys, $recurse = true) {
|
||||
$parsedkeys = array_map(array($this, 'parse_key'), $keys);
|
||||
if ($this->is_using_persist_cache()) {
|
||||
if ($this->use_static_acceleration()) {
|
||||
foreach ($parsedkeys as $parsedkey) {
|
||||
$this->delete_from_persist_cache($parsedkey);
|
||||
$this->static_acceleration_delete($parsedkey);
|
||||
}
|
||||
}
|
||||
if ($recurse && $this->loader !== false) {
|
||||
@@ -798,8 +805,12 @@ class cache implements cache_loader {
|
||||
* @return bool True on success, false otherwise
|
||||
*/
|
||||
public function purge() {
|
||||
// 1. Purge the persist cache.
|
||||
$this->persistcache = array();
|
||||
// 1. Purge the static acceleration array.
|
||||
$this->staticaccelerationarray = array();
|
||||
if ($this->staticaccelerationsize !== false) {
|
||||
$this->staticaccelerationkeys = array();
|
||||
$this->staticaccelerationcount = 0;
|
||||
}
|
||||
// 2. Purge the store.
|
||||
$this->store->purge();
|
||||
// 3. Optionally pruge any stacked loaders.
|
||||
@@ -908,62 +919,101 @@ class cache implements cache_loader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this cache is making use of the persist cache.
|
||||
* Returns true if this cache is making use of the static acceleration array.
|
||||
*
|
||||
* @deprecated since 2.6
|
||||
* @see cache::use_static_acceleration()
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_using_persist_cache() {
|
||||
return $this->persist;
|
||||
debugging('This function has been deprecated. Please call use_static_acceleration instead', DEBUG_DEVELOPER);
|
||||
return $this->use_static_acceleration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the requested key exists within the persist cache.
|
||||
* Returns true if this cache is making use of the static acceleration array.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function use_static_acceleration() {
|
||||
return $this->staticacceleration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the requested key exists within the static acceleration array.
|
||||
*
|
||||
* @see cache::static_acceleration_has
|
||||
* @deprecated since 2.6
|
||||
* @param string $key The parsed key
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_in_persist_cache($key) {
|
||||
debugging('This function has been deprecated. Please call static_acceleration_has instead', DEBUG_DEVELOPER);
|
||||
return $this->static_acceleration_has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the requested key exists within the static acceleration array.
|
||||
*
|
||||
* @param string $key The parsed key
|
||||
* @return bool
|
||||
*/
|
||||
protected function static_acceleration_has($key) {
|
||||
// This method of checking if an array was supplied is faster than is_array.
|
||||
if ($key === (array)$key) {
|
||||
$key = $key['key'];
|
||||
}
|
||||
// This could be written as a single line, however it has been split because the ttl check is faster than the instanceof
|
||||
// and has_expired calls.
|
||||
if (!$this->persist || !array_key_exists($key, $this->persistcache)) {
|
||||
if (!$this->staticacceleration || !array_key_exists($key, $this->staticaccelerationarray)) {
|
||||
return false;
|
||||
}
|
||||
if ($this->has_a_ttl() && $this->store_supports_native_ttl()) {
|
||||
return !($this->persistcache[$key] instanceof cache_ttl_wrapper && $this->persistcache[$key]->has_expired());
|
||||
return !($this->staticaccelerationarray[$key] instanceof cache_ttl_wrapper &&
|
||||
$this->staticaccelerationarray[$key]->has_expired());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item from the persist cache if it exists there.
|
||||
* Returns the item from the static acceleration array if it exists there.
|
||||
*
|
||||
* @deprecated since 2.6
|
||||
* @see cache::static_acceleration_get
|
||||
* @param string $key The parsed key
|
||||
* @return mixed|false The data from the persist cache or false if it wasn't there.
|
||||
* @return mixed|false The data from the static acceleration array or false if it wasn't there.
|
||||
*/
|
||||
protected function get_from_persist_cache($key) {
|
||||
debugging('This function has been deprecated. Please call static_acceleration_get instead', DEBUG_DEVELOPER);
|
||||
return $this->static_acceleration_get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item from the static acceleration array if it exists there.
|
||||
*
|
||||
* @param string $key The parsed key
|
||||
* @return mixed|false The data from the static acceleration array or false if it wasn't there.
|
||||
*/
|
||||
protected function static_acceleration_get($key) {
|
||||
// This method of checking if an array was supplied is faster than is_array.
|
||||
if ($key === (array)$key) {
|
||||
$key = $key['key'];
|
||||
}
|
||||
// This isset check is faster than array_key_exists but will return false
|
||||
// for null values, meaning null values will come from backing store not
|
||||
// the persist cache. We think this okay because null usage should be
|
||||
// the static acceleration array. We think this okay because null usage should be
|
||||
// very rare (see comment in MDL-39472).
|
||||
if (!$this->persist || !isset($this->persistcache[$key])) {
|
||||
if (!$this->staticacceleration || !isset($this->staticaccelerationarray[$key])) {
|
||||
$result = false;
|
||||
} else {
|
||||
$data = $this->persistcache[$key];
|
||||
$data = $this->staticaccelerationarray[$key];
|
||||
if (!$this->has_a_ttl() || !$data instanceof cache_ttl_wrapper) {
|
||||
if ($data instanceof cache_cached_object) {
|
||||
$data = $data->restore_object();
|
||||
}
|
||||
$result = $data;
|
||||
} else if ($data->has_expired()) {
|
||||
$this->delete_from_persist_cache($key);
|
||||
$this->static_acceleration_delete($key);
|
||||
$result = false;
|
||||
} else {
|
||||
if ($data instanceof cache_cached_object) {
|
||||
@@ -974,64 +1024,95 @@ class cache implements cache_loader {
|
||||
}
|
||||
if ($result) {
|
||||
if ($this->perfdebug) {
|
||||
cache_helper::record_cache_hit('** static persist **', $this->definition->get_id());
|
||||
cache_helper::record_cache_hit('** static acceleration **', $this->definition->get_id());
|
||||
}
|
||||
if ($this->persistmaxsize > 1 && $this->persistcount > 1) {
|
||||
// Check to see if this is the last item on the persist keys array.
|
||||
if (end($this->persistkeys) !== $key) {
|
||||
if ($this->staticaccelerationsize > 1 && $this->staticaccelerationcount > 1) {
|
||||
// Check to see if this is the last item on the static acceleration keys array.
|
||||
if (end($this->staticaccelerationkeys) !== $key) {
|
||||
// It isn't the last item.
|
||||
// Move the item to the end of the array so that it is last to be removed.
|
||||
unset($this->persistkeys[$key]);
|
||||
$this->persistkeys[$key] = $key;
|
||||
unset($this->staticaccelerationkeys[$key]);
|
||||
$this->staticaccelerationkeys[$key] = $key;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
} else {
|
||||
if ($this->perfdebug) {
|
||||
cache_helper::record_cache_miss('** static persist **', $this->definition->get_id());
|
||||
cache_helper::record_cache_miss('** static acceleration **', $this->definition->get_id());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a key value pair into the persist cache.
|
||||
* Sets a key value pair into the static acceleration array.
|
||||
*
|
||||
* @deprecated since 2.6
|
||||
* @see cache::static_acceleration_set
|
||||
* @param string $key The parsed key
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
protected function set_in_persist_cache($key, $data) {
|
||||
debugging('This function has been deprecated. Please call static_acceleration_set instead', DEBUG_DEVELOPER);
|
||||
return $this->static_acceleration_set($key, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a key value pair into the static acceleration array.
|
||||
*
|
||||
* @param string $key The parsed key
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
protected function static_acceleration_set($key, $data) {
|
||||
// This method of checking if an array was supplied is faster than is_array.
|
||||
if ($key === (array)$key) {
|
||||
$key = $key['key'];
|
||||
}
|
||||
$this->persistcache[$key] = $data;
|
||||
if ($this->persistmaxsize !== false) {
|
||||
$this->persistcount++;
|
||||
$this->persistkeys[$key] = $key;
|
||||
if ($this->persistcount > $this->persistmaxsize) {
|
||||
$dropkey = array_shift($this->persistkeys);
|
||||
unset($this->persistcache[$dropkey]);
|
||||
$this->persistcount--;
|
||||
if ($this->staticaccelerationsize !== false && isset($this->staticaccelerationkeys[$key])) {
|
||||
$this->staticaccelerationcount--;
|
||||
unset($this->staticaccelerationkeys[$key]);
|
||||
}
|
||||
$this->staticaccelerationarray[$key] = $data;
|
||||
if ($this->staticaccelerationsize !== false) {
|
||||
$this->staticaccelerationcount++;
|
||||
$this->staticaccelerationkeys[$key] = $key;
|
||||
if ($this->staticaccelerationcount > $this->staticaccelerationsize) {
|
||||
$dropkey = array_shift($this->staticaccelerationkeys);
|
||||
unset($this->staticaccelerationarray[$dropkey]);
|
||||
$this->staticaccelerationcount--;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an item from the persist cache.
|
||||
* Deletes an item from the static acceleration array.
|
||||
*
|
||||
* @deprecated since 2.6
|
||||
* @see cache::static_acceleration_delete()
|
||||
* @param string|int $key As given to get|set|delete
|
||||
* @return bool True on success, false otherwise.
|
||||
*/
|
||||
protected function delete_from_persist_cache($key) {
|
||||
unset($this->persistcache[$key]);
|
||||
if ($this->persistmaxsize !== false) {
|
||||
$dropkey = array_search($key, $this->persistkeys);
|
||||
debugging('This function has been deprecated. Please call static_acceleration_delete instead', DEBUG_DEVELOPER);
|
||||
return $this->static_acceleration_delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an item from the static acceleration array.
|
||||
*
|
||||
* @param string|int $key As given to get|set|delete
|
||||
* @return bool True on success, false otherwise.
|
||||
*/
|
||||
protected function static_acceleration_delete($key) {
|
||||
unset($this->staticaccelerationarray[$key]);
|
||||
if ($this->staticaccelerationsize !== false) {
|
||||
$dropkey = array_search($key, $this->staticaccelerationkeys);
|
||||
if ($dropkey) {
|
||||
unset($this->persistkeys[$dropkey]);
|
||||
$this->persistcount--;
|
||||
unset($this->staticaccelerationkeys[$dropkey]);
|
||||
$this->staticaccelerationcount--;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1448,9 +1529,8 @@ class cache_application extends cache implements cache_loader_with_locking {
|
||||
* This class is used for session caches returned by the cache::make methods.
|
||||
*
|
||||
* It differs from the application loader in a couple of noteable ways:
|
||||
* 1. Sessions are always expected to be persistent.
|
||||
* Because of this we don't ever use the persist cache and instead a session array
|
||||
* containing all of the data is maintained by this object.
|
||||
* 1. Sessions are always expected to exist.
|
||||
* Because of this we don't ever use the static acceleration array.
|
||||
* 2. Session data for a loader instance (store + definition) is consolidate into a
|
||||
* single array for storage within the store.
|
||||
* Along with this we embed a lastaccessed time with the data. This way we can
|
||||
@@ -2063,12 +2143,12 @@ class cache_session extends cache {
|
||||
}
|
||||
|
||||
/**
|
||||
* The session loader never uses the persist cache.
|
||||
* The session loader never uses static acceleration.
|
||||
* Instead it stores things in the static $session variable. Shared between all session loaders.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_using_persist_cache() {
|
||||
protected function use_static_acceleration() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+3
-3
@@ -49,8 +49,7 @@ class cache_disabled extends cache {
|
||||
* @param null $loader Unused.
|
||||
*/
|
||||
public function __construct(cache_definition $definition, cache_store $store, $loader = null) {
|
||||
$this->definition = $definition;
|
||||
$this->store = $store;
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,7 +227,8 @@ class cache_factory_disabled extends cache_factory {
|
||||
* @param array $options An array of options, available options are:
|
||||
* - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
|
||||
* - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
|
||||
* - persistent : If set to true the cache will persist construction requests.
|
||||
* - staticacceleration : If set to true the cache will hold onto all data passing through it.
|
||||
* - staticaccelerationsize : Sets the max size of the static acceleration array.
|
||||
* @return cache_application|cache_session|cache_request
|
||||
*/
|
||||
public function create_cache_from_params($mode, $component, $area, array $identifiers = array(), array $options = array()) {
|
||||
|
||||
Vendored
+30
@@ -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)
|
||||
Vendored
+174
-16
@@ -149,8 +149,8 @@ class core_cache_testcase extends advanced_testcase {
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'component' => 'phpunit',
|
||||
'area' => 'test_default_application_cache',
|
||||
'persistent' => true,
|
||||
'persistentmaxsize' => 1
|
||||
'staticacceleration' => true,
|
||||
'staticaccelerationsize' => 1
|
||||
));
|
||||
$cache = cache::make('phpunit', 'test_default_application_cache');
|
||||
$this->assertInstanceOf('cache_application', $cache);
|
||||
@@ -189,7 +189,7 @@ class core_cache_testcase extends advanced_testcase {
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'component' => 'phpunit',
|
||||
'area' => 'nostoretest2',
|
||||
'persistent' => true
|
||||
'staticacceleration' => true
|
||||
));
|
||||
$instance->phpunit_remove_stores();
|
||||
|
||||
@@ -924,11 +924,11 @@ class core_cache_testcase extends advanced_testcase {
|
||||
'crazyevent'
|
||||
)
|
||||
));
|
||||
$instance->phpunit_add_definition('phpunit/eventpurgetestpersistent', array(
|
||||
$instance->phpunit_add_definition('phpunit/eventpurgetestaccelerated', array(
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'component' => 'phpunit',
|
||||
'area' => 'eventpurgetestpersistent',
|
||||
'persistent' => true,
|
||||
'area' => 'eventpurgetestaccelerated',
|
||||
'staticacceleration' => true,
|
||||
'invalidationevents' => array(
|
||||
'crazyevent'
|
||||
)
|
||||
@@ -947,8 +947,8 @@ class core_cache_testcase extends advanced_testcase {
|
||||
$this->assertFalse($cache->get('testkey1'));
|
||||
$this->assertFalse($cache->get('testkey2'));
|
||||
|
||||
// Now test the persistent cache.
|
||||
$cache = cache::make('phpunit', 'eventpurgetestpersistent');
|
||||
// Now test the static acceleration array.
|
||||
$cache = cache::make('phpunit', 'eventpurgetestaccelerated');
|
||||
$this->assertTrue($cache->set('testkey1', 'test data 1'));
|
||||
$this->assertEquals('test data 1', $cache->get('testkey1'));
|
||||
$this->assertTrue($cache->set('testkey2', 'test data 2'));
|
||||
@@ -975,11 +975,11 @@ class core_cache_testcase extends advanced_testcase {
|
||||
'crazyevent'
|
||||
)
|
||||
));
|
||||
$instance->phpunit_add_definition('phpunit/eventpurgetestpersistent', array(
|
||||
$instance->phpunit_add_definition('phpunit/eventpurgetestaccelerated', array(
|
||||
'mode' => cache_store::MODE_SESSION,
|
||||
'component' => 'phpunit',
|
||||
'area' => 'eventpurgetestpersistent',
|
||||
'persistent' => true,
|
||||
'area' => 'eventpurgetestaccelerated',
|
||||
'staticacceleration' => true,
|
||||
'invalidationevents' => array(
|
||||
'crazyevent'
|
||||
)
|
||||
@@ -998,8 +998,8 @@ class core_cache_testcase extends advanced_testcase {
|
||||
$this->assertFalse($cache->get('testkey1'));
|
||||
$this->assertFalse($cache->get('testkey2'));
|
||||
|
||||
// Now test the persistent cache.
|
||||
$cache = cache::make('phpunit', 'eventpurgetestpersistent');
|
||||
// Now test the static acceleration array.
|
||||
$cache = cache::make('phpunit', 'eventpurgetestaccelerated');
|
||||
$this->assertTrue($cache->set('testkey1', 'test data 1'));
|
||||
$this->assertEquals('test data 1', $cache->get('testkey1'));
|
||||
$this->assertTrue($cache->set('testkey2', 'test data 2'));
|
||||
@@ -1400,8 +1400,8 @@ class core_cache_testcase extends advanced_testcase {
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'component' => 'phpunit',
|
||||
'area' => 'test_application_locking',
|
||||
'persistent' => true,
|
||||
'persistentmaxsize' => 1,
|
||||
'staticacceleration' => true,
|
||||
'staticaccelerationsize' => 1,
|
||||
'requirelockingread' => true,
|
||||
'requirelockingwrite' => true
|
||||
));
|
||||
@@ -1535,4 +1535,162 @@ class core_cache_testcase extends advanced_testcase {
|
||||
$this->assertInstanceOf('cache_request', $cache);
|
||||
$this->assertArrayHasKey('cache_is_searchable', $cache->phpunit_get_store_implements());
|
||||
}
|
||||
}
|
||||
|
||||
public function test_static_acceleration() {
|
||||
$instance = cache_config_phpunittest::instance();
|
||||
$instance->phpunit_add_definition('phpunit/accelerated', array(
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'component' => 'phpunit',
|
||||
'area' => 'accelerated',
|
||||
'staticacceleration' => true,
|
||||
'staticaccelerationsize' => 3,
|
||||
));
|
||||
$instance->phpunit_add_definition('phpunit/accelerated2', array(
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'component' => 'phpunit',
|
||||
'area' => 'accelerated2',
|
||||
'staticacceleration' => true,
|
||||
'staticaccelerationsize' => 3,
|
||||
));
|
||||
$instance->phpunit_add_definition('phpunit/accelerated3', array(
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'component' => 'phpunit',
|
||||
'area' => 'accelerated3',
|
||||
'staticacceleration' => true,
|
||||
'staticaccelerationsize' => 3,
|
||||
));
|
||||
$instance->phpunit_add_definition('phpunit/accelerated4', array(
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'component' => 'phpunit',
|
||||
'area' => 'accelerated4',
|
||||
'staticacceleration' => true,
|
||||
'staticaccelerationsize' => 4,
|
||||
));
|
||||
$cache = cache::make('phpunit', 'accelerated');
|
||||
$this->assertInstanceOf('cache_phpunit_application', $cache);
|
||||
|
||||
// Set and get three elements.
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('b', 'B'));
|
||||
$this->assertTrue($cache->set('c', 'C'));
|
||||
$this->assertEquals('A', $cache->get('a'));
|
||||
$this->assertEquals(array('b' => 'B', 'c' => 'C'), $cache->get_many(array('b', 'c')));
|
||||
|
||||
// Make sure all items are in static acceleration array.
|
||||
$this->assertEquals('A', $cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertEquals('B', $cache->phpunit_static_acceleration_get('b'));
|
||||
$this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
|
||||
|
||||
// Add new value and make sure it is in cache and it is in array.
|
||||
$this->assertTrue($cache->set('d', 'D'));
|
||||
$this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
|
||||
$this->assertEquals('D', $cache->get('d'));
|
||||
|
||||
// Now the least recent accessed item (a) is no longer in acceleration array.
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertEquals('B', $cache->phpunit_static_acceleration_get('b'));
|
||||
$this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
|
||||
|
||||
// Adding and deleting element.
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->delete('a'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertFalse($cache->has('a'));
|
||||
|
||||
// Make sure "purge" deletes from the array as well.
|
||||
$cache->purge();
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('b'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('c'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('d'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('e'));
|
||||
|
||||
// Check that the array holds the last accessed items by get/set.
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('b', 'B'));
|
||||
$this->assertTrue($cache->set('c', 'C'));
|
||||
$this->assertTrue($cache->set('d', 'D'));
|
||||
$this->assertTrue($cache->set('e', 'E'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('b'));
|
||||
$this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
|
||||
$this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
|
||||
$this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
|
||||
|
||||
/** @var cache_phpunit_application $cache */
|
||||
$cache = cache::make('phpunit', 'accelerated2');
|
||||
$this->assertInstanceOf('cache_phpunit_application', $cache);
|
||||
|
||||
// Check that the array holds the last accessed items by get/set.
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('b', 'B'));
|
||||
$this->assertTrue($cache->set('c', 'C'));
|
||||
$this->assertTrue($cache->set('d', 'D'));
|
||||
$this->assertTrue($cache->set('e', 'E'));
|
||||
// Current keys in the array: c, d, e.
|
||||
$this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
|
||||
$this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
|
||||
$this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('b'));
|
||||
|
||||
$this->assertEquals('A', $cache->get('a'));
|
||||
// Current keys in the array: d, e, a.
|
||||
$this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
|
||||
$this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
|
||||
$this->assertEquals('A', $cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('b'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('c'));
|
||||
|
||||
// Current keys in the array: d, e, a.
|
||||
$this->assertEquals(array('c' => 'C'), $cache->get_many(array('c')));
|
||||
// Current keys in the array: e, a, c.
|
||||
$this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
|
||||
$this->assertEquals('A', $cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('b'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('d'));
|
||||
|
||||
|
||||
$cache = cache::make('phpunit', 'accelerated3');
|
||||
$this->assertInstanceOf('cache_phpunit_application', $cache);
|
||||
|
||||
// Check that the array holds the last accessed items by get/set.
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('b', 'B'));
|
||||
$this->assertTrue($cache->set('c', 'C'));
|
||||
$this->assertTrue($cache->set('d', 'D'));
|
||||
$this->assertTrue($cache->set('e', 'E'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('b'));
|
||||
$this->assertEquals('C', $cache->phpunit_static_acceleration_get('c'));
|
||||
$this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
|
||||
$this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
|
||||
|
||||
$this->assertTrue($cache->set('b', 'B2'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertEquals('B2', $cache->phpunit_static_acceleration_get('b'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('c'));
|
||||
$this->assertEquals('D', $cache->phpunit_static_acceleration_get('d'));
|
||||
$this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
|
||||
|
||||
$this->assertEquals(2, $cache->set_many(array('b' => 'B3', 'c' => 'C3')));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertEquals('B3', $cache->phpunit_static_acceleration_get('b'));
|
||||
$this->assertEquals('C3', $cache->phpunit_static_acceleration_get('c'));
|
||||
$this->assertFalse($cache->phpunit_static_acceleration_get('d'));
|
||||
$this->assertEquals('E', $cache->phpunit_static_acceleration_get('e'));
|
||||
|
||||
$cache = cache::make('phpunit', 'accelerated4');
|
||||
$this->assertInstanceOf('cache_phpunit_application', $cache);
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertTrue($cache->set('a', 'A'));
|
||||
$this->assertEquals('A', $cache->phpunit_static_acceleration_get('a'));
|
||||
$this->assertEquals('A', $cache->get('a'));
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+11
@@ -251,6 +251,17 @@ class cache_phpunit_application extends cache_application {
|
||||
public function phpunit_get_store_implements() {
|
||||
return class_implements($this->get_store());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given key directly from the static acceleration array.
|
||||
*
|
||||
* @param string $key
|
||||
* @return false|mixed
|
||||
*/
|
||||
public function phpunit_static_acceleration_get($key) {
|
||||
$key = $this->parse_key($key);
|
||||
return $this->static_acceleration_get($key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+14
@@ -1,6 +1,20 @@
|
||||
This files describes API changes in /cache/stores/* - cache store plugins.
|
||||
Information provided here is intended especially for developers.
|
||||
|
||||
=== 2.6 ===
|
||||
* All cache instances are recorded and subsequent requests are given a reference to the original instance.
|
||||
* The persistent option for the cache definition has been deprecated. Please use the staticacceleration option instead.
|
||||
* There is a new static acceleration option. If enabled data passing through the cache is held onto.
|
||||
* The persistentmaxsize option has been renamed to staticaccelerationsize. It does the same thing.
|
||||
* cache_definition::should_be_persistent has been deprecated. Please call cache_definition::use_static_acceleration instead.
|
||||
* cache_definition::get_persistent_max_size has been deprecated. Please call cache_definition::get_static_acceleration_size instead.
|
||||
* cache::is_using_persist_cache() has been deprecated. Please call cache::use_static_acceleration()
|
||||
* cache::is_in_persist_cache() has been deprecated. Please call cache::static_acceleration_has()
|
||||
* cache::get_from_persist_cache() has been deprecated. Please call cache::static_acceleration_get()
|
||||
* cache::set_in_persist_cache() has been deprecated. Please call cache::static_acceleration_set()
|
||||
* cache::delete_from_persist_cache() has been deprecated. Please call cache::static_acceleration_delete()
|
||||
* If you have any custom cache loaders you will need to rename these methods if you have overriden them and adjust any calls you may have made to them.
|
||||
|
||||
=== 2.5 ===
|
||||
* cleanup method renamed to instance_deleted.
|
||||
It is now called when the store is deleted as all comments suggested anyway.
|
||||
|
||||
@@ -277,6 +277,6 @@ class core_calendar_type_testcase extends advanced_testcase {
|
||||
*/
|
||||
private function set_calendar_type($type) {
|
||||
$this->user->calendartype = $type;
|
||||
session_set_user($this->user);
|
||||
\core\session\manager::set_user($this->user);
|
||||
}
|
||||
}
|
||||
|
||||
+30
-4
@@ -224,10 +224,22 @@ $CFG->admin = 'admin';
|
||||
// RewriteRule (^.*/theme/yui_combo\.php)(/.*) $1?file=$2
|
||||
//
|
||||
//
|
||||
// By default all user sessions should be using locking, uncomment
|
||||
// the following setting to prevent locking for guests and not-logged-in
|
||||
// accounts. This may improve performance significantly.
|
||||
// $CFG->sessionlockloggedinonly = 1;
|
||||
// Following settings may be used to select session driver, uncomment only one of the handlers.
|
||||
// Database session handler (not compatible with MyISAM):
|
||||
// $CFG->session_handler_class = '\core\session\database';
|
||||
// $CFG->session_database_acquire_lock_timeout = 120;
|
||||
//
|
||||
// File session handler (file system locking required):
|
||||
// $CFG->session_handler_class = '\core\session\file';
|
||||
// $CFG->session_file_save_path = $CFG->dataroot.'/sessions';
|
||||
//
|
||||
// Memcached session handler (requires memcached server and extension):
|
||||
// $CFG->session_handler_class = '\core\session\memcached';
|
||||
// $CFG->session_memcached_save_path = '127.0.0.1:11211';
|
||||
// $CFG->session_memcached_prefix = 'memc.sess.key.';
|
||||
//
|
||||
// Following setting allows you to alter how frequently is timemodified updated in sessions table.
|
||||
// $CFG->session_update_timemodified_frequency = 20; // In seconds.
|
||||
//
|
||||
// If this setting is set to true, then Moodle will track the IP of the
|
||||
// current user to make sure it hasn't changed during a session. This
|
||||
@@ -628,6 +640,20 @@ $CFG->admin = 'admin';
|
||||
// used to expand the default white list with an array of extra settings.
|
||||
// Example:
|
||||
// $CFG->behat_extraallowedsettings = array('logsql', 'dblogerror');
|
||||
//
|
||||
//=========================================================================
|
||||
// 12. DEVELOPER DATA GENERATOR
|
||||
//=========================================================================
|
||||
//
|
||||
// The developer data generator tool is intended to be used only in development or testing sites and
|
||||
// it's usage in production environments is not recommended; if it is used to create JMeter test plans
|
||||
// is even less recommended as JMeter needs to log in as site course users. JMeter needs to know the
|
||||
// users passwords but would be dangerous to have a default password as everybody would know it, which would
|
||||
// be specially dangerouse if somebody uses this tool in a production site, so in order to prevent unintended
|
||||
// uses of the tool and undesired accesses as well, is compulsory to set a password for the users
|
||||
// generated by this tool, but only in case you want to generate a JMeter test. The value should be a string.
|
||||
// Example:
|
||||
// $CFG->tool_generator_users_password = 'examplepassword';
|
||||
|
||||
//=========================================================================
|
||||
// ALL DONE! To continue installation, visit your main page with a browser
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ $url = new moodle_url('/course/loginas.php', array('id'=>$id));
|
||||
$PAGE->set_url($url);
|
||||
|
||||
// Reset user back to their real self if needed, for security reasons you need to log out and log in again.
|
||||
if (session_is_loggedinas()) {
|
||||
if (\core\session\manager::is_loggedinas()) {
|
||||
require_sesskey();
|
||||
require_logout();
|
||||
|
||||
@@ -61,7 +61,7 @@ if (has_capability('moodle/user:loginas', $systemcontext)) {
|
||||
}
|
||||
|
||||
// Login as this user and return to course home page.
|
||||
session_loginas($userid, $context);
|
||||
\core\session\manager::loginas($userid, $context);
|
||||
$newfullname = fullname($USER, true);
|
||||
|
||||
$strloginas = get_string('loginas');
|
||||
|
||||
@@ -650,12 +650,16 @@ abstract class moodleform_mod extends moodleform {
|
||||
$mform->addElement('hidden', 'completionunlocked', 0);
|
||||
$mform->setType('completionunlocked', PARAM_INT);
|
||||
|
||||
$trackingdefault = COMPLETION_TRACKING_NONE;
|
||||
// If system and activity default is on, set it.
|
||||
if ($CFG->completiondefault && $this->_features->defaultcompletion) {
|
||||
$trackingdefault = COMPLETION_TRACKING_MANUAL;
|
||||
}
|
||||
|
||||
$mform->addElement('select', 'completion', get_string('completion', 'completion'),
|
||||
array(COMPLETION_TRACKING_NONE=>get_string('completion_none', 'completion'),
|
||||
COMPLETION_TRACKING_MANUAL=>get_string('completion_manual', 'completion')));
|
||||
$mform->setDefault('completion', $this->_features->defaultcompletion
|
||||
? COMPLETION_TRACKING_MANUAL
|
||||
: COMPLETION_TRACKING_NONE);
|
||||
$mform->setDefault('completion', $trackingdefault);
|
||||
$mform->addHelpButton('completion', 'completion', 'completion');
|
||||
|
||||
// Automatic completion once you view it
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user