Compare commits

..

21 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) 296b602f2c Moodle release 2.8.1 2014-11-13 12:22:51 +01:00
Eloy Lafuente (stronk7) 76db660264 Merge branch 'MDL-48214-28-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_28_STABLE 2014-11-13 12:05:17 +01:00
Helen Foster e5381b67e9 MDL-48214 Merge English strings from the en_fix language pack 2014-11-13 11:32:24 +01:00
Eugene Venter 8d4e07d86d MDL-48204 mod_wiki: admin.php - fix syntax error 2014-11-13 00:47:16 +01:00
Dan Poltawski b37f9889d0 weekly release 2.8+ 2014-11-12 11:33:31 +00:00
Dan Poltawski c8900a5152 MDL-48174 tool_langimport: info about skipped update
So admins can work out why the task might not be having an effect.
2014-11-12 11:22:45 +00:00
Rajesh Taneja 4c4d53ebaf MDL-48174 core_lang: support for ->skiplangupgrade in lang cron task
Similar to upgrade_language_pack(), update_langpacks_task should
respect skiplangupgrade config. Also, this should be added to behat
whitelist, so it can be disabled during on-sync period, when lang
pack for master is not available.
2014-11-12 11:03:55 +00:00
David Monllao a26ce935c7 MDL-30968 mod_forum: No picture link to group when no groups mode 2014-11-12 07:43:08 +00:00
James Ballard 0df5893423 MDL-47391 Update pagelayout for default profile configuration 2014-11-12 12:34:27 +13:00
Frederic Massart dd818fdb44 MDL-39692 grade: Little code clean up of letter boundary deletion 2014-11-12 12:19:31 +13:00
Huy Hoang 1fd2bc4810 MDL-39692 grade: Ability to delete letter boundary 2014-11-12 12:19:31 +13:00
Amanda Doughty 088c4fb280 MDL-30968 mod/forum Fixed group link 2014-11-12 09:00:16 +13:00
Dan Poltawski 0ed92e6a37 MDL-47502 statslib tests: improve test
While integrating I noticed some problems which already existed in this
test:
* The enrolment data generator was not used
* The student roleid was hardocded
* The role assignment was at site level..
2014-11-11 19:26:03 +00:00
Eugene Venter afc8bd9672 MDL-47502 test_statslib_cron_daily: fix provider
Fiddling with the database in the data provider causes "out of sync"
errors when running suite tests.
2014-11-11 19:12:46 +00:00
Damyon Wiese c2dd91bfef MDL-47975 assign: Stop gap fix for random time fails. 2014-11-11 19:06:38 +00:00
sam marshall b0ac83b82b MDL-48093 HTML 5 video: Firefox now supports .mp4 2014-11-11 19:00:12 +00:00
Dan Poltawski 272ad5b577 Merge branch 'MDL-48168_28' of git://github.com/timhunt/moodle into MOODLE_28_STABLE 2014-11-11 18:48:36 +00:00
Darko Miletic 928497310e MDL-39376 enrol: Optimized setting for ldap and database 2014-11-11 17:23:01 +00:00
David Mudrák 5755d70f2e MDL-48156 task: Skip the scheduled task only for really disabled plugins 2014-11-11 17:18:03 +00:00
Tim Hunt 21c633a8c6 MDL-48168 quiz editing: max grade should be editable after attempts
Note that there was a lot of legacy code left from Moodle 2.7 which is
no longer required, and I took this opportunity to delete it.
2014-11-10 19:00:33 +00:00
Eloy Lafuente (stronk7) 25fe23f5f5 MDL-48144 upgrade: add v2.8.0 sep lines 2014-11-10 18:09:20 +01:00
3221 changed files with 74249 additions and 149424 deletions
-3
View File
@@ -1,3 +0,0 @@
--errors=errors,duplicate-properties
--warnings=known-properties,display-property-grouping,empty-rules,important
--exclude-list=vendor/,lib/editor/tinymce/,lib/yuilib/,theme/bootstrapbase/style/
+2 -2
View File
@@ -26,8 +26,9 @@ CVS
/.buildpath
/.cache
phpunit.xml
# Composer support. Do not ignore composer.json, or composer.lock. These should be shipped by us.
# Composer support - only composer.json is to be in git, the rest is installed in each checkout.
composer.phar
composer.lock
/vendor/
/behat.yml
*/yui/build/*/*-coverage.js
@@ -35,4 +36,3 @@ composer.phar
# lib/yuilib/version/module/module-coverage.js
/lib/yuilib/*/*/*-coverage.js
atlassian-ide-plugin.xml
/node_modules/
+22 -28
View File
@@ -1,54 +1,48 @@
{
"asi": false,
"bitwise": true,
"boss": false,
"browser": true,
"yui": true,
"bitwise": true,
"curly": true,
"eqeqeq": true,
"forin": false,
"immed": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nomen": false,
"onevar": false,
"plusplus": false,
"regexp": false,
"strict": false,
"trailing": true,
"unused": true,
"white": false,
"asi": false,
"boss": false,
"debug": false,
"eqeqeq": false,
"eqnull": false,
"es5": false,
"esnext": false,
"evil": false,
"expr": false,
"forin": false,
"funcscope": false,
"globalstrict": false,
"immed": true,
"indent": 4,
"iterator": false,
"lastsemic": false,
"latedef": true,
"laxbreak": true,
"laxcomma": false,
"loopfunc": false,
"maxerr": 500,
"maxlen": 132,
"multistr": false,
"newcap": true,
"noarg": true,
"noempty": true,
"nomen": false,
"onecase": false,
"onevar": false,
"passfail": false,
"plusplus": false,
"predef": [
"M",
"define"
],
"proto": false,
"regexdash": false,
"regexp": false,
"scripturl": false,
"shadow": false,
"smarttabs": false,
"strict": false,
"sub": false,
"supernew": false,
"trailing": true,
"undef": true,
"unused": true,
"white": false,
"yui": true
"maxerr": 500,
"maxlen": 180,
"passfail": false,
"latedef": true
}
-152
View File
@@ -1,152 +0,0 @@
// 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/>.
/**
* @copyright 2014 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Grunt configuration
*/
module.exports = function(grunt) {
var path = require('path'),
tasks = {},
cwd = process.env.PWD || process.cwd();
// Project configuration.
grunt.initConfig({
jshint: {
options: {jshintrc: '.jshintrc'},
files: ['**/amd/src/*.js']
},
uglify: {
dynamic_mappings: {
files: grunt.file.expandMapping(
['**/src/*.js', '!**/node_modules/**'],
'',
{
cwd: cwd,
rename: function(destBase, destPath) {
destPath = destPath.replace('src', 'build');
destPath = destPath.replace('.js', '.min.js');
destPath = path.resolve(cwd, destPath);
return destPath;
}
}
)
}
}
});
tasks.shifter = function() {
var exec = require('child_process').spawn,
done = this.async(),
args = [],
options = {
recursive: true,
watch: false,
walk: false,
module: false
},
shifter;
args.push( path.normalize(__dirname + '/node_modules/shifter/bin/shifter'));
// Determine the most appropriate options to run with based upon the current location.
if (path.basename(cwd) === 'src') {
// Detect whether we're in a src directory.
grunt.log.debug('In a src directory');
args.push('--walk');
options.walk = true;
} else if (path.basename(path.dirname(cwd)) === 'src') {
// Detect whether we're in a module directory.
grunt.log.debug('In a module directory');
options.module = true;
}
if (grunt.option('watch')) {
if (!options.walk && !options.module) {
grunt.fail.fatal('Unable to watch unless in a src or module directory');
}
// It is not advisable to run with recursivity and watch - this
// leads to building the build directory in a race-like fashion.
grunt.log.debug('Detected a watch - disabling recursivity');
options.recursive = false;
args.push('--watch');
}
if (options.recursive) {
args.push('--recursive');
}
// Always ignore the node_modules directory.
args.push('--excludes', 'node_modules');
// Add the stderr option if appropriate
if (grunt.option('verbose')) {
args.push('--lint-stderr');
}
// Actually run shifter.
shifter = exec("node", args, {
cwd: cwd,
stdio: 'inherit',
env: process.env
});
// Tidy up after exec.
shifter.on('exit', function (code) {
if (code) {
grunt.fail.fatal('Shifter failed with code: ' + code);
} else {
grunt.log.ok('Shifter build complete.');
done();
}
});
};
tasks.startup = function() {
// Are we in a YUI directory?
if (path.basename(path.resolve(cwd, '../../')) == 'yui') {
grunt.task.run('shifter');
// Are we in an AMD directory?
} else if (path.basename(cwd) == 'amd') {
grunt.task.run('jshint');
grunt.task.run('uglify');
} else {
// Run them all!.
grunt.task.run('shifter');
grunt.task.run('jshint');
grunt.task.run('uglify');
}
};
// Register NPM tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
// Register the shifter task.
grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter);
// Register the startup task.
grunt.registerTask('startup', 'Run the correct tasks for the current directory', tasks.startup);
// Register the default task.
grunt.registerTask('default', ['startup']);
};
+2 -1
View File
@@ -67,6 +67,7 @@ if ($data = data_submitted() and confirm_sesskey()) {
$errormsg = get_string('errorwithsettings', 'admin');
$firsterror = reset($adminroot->errors);
}
$adminroot = admin_get_root(true); //reload tree
$settingspage = $adminroot->locate($category, true);
}
@@ -155,4 +156,4 @@ echo $outputhtml;
echo html_writer::end_tag('fieldset');
echo html_writer::end_tag('form');
echo $OUTPUT->footer();
echo $OUTPUT->footer();
+3 -22
View File
@@ -69,11 +69,9 @@ Options:
--prefix=STRING Table prefix for above database tables. Default is mdl_
--fullname=STRING The fullname of the site
--shortname=STRING The shortname of the site
--summary=STRING The summary to be displayed on the front page
--adminuser=USERNAME Username for the moodle admin account. Default is admin
--adminpass=PASSWORD Password for the moodle admin account,
required in non-interactive mode.
--adminemail=STRING Email address for the moodle admin account.
--non-interactive No interactive questions, installation fails if any
problem encountered.
--agree-license Indicates agreement with software license,
@@ -122,11 +120,10 @@ $olddir = getcwd();
chdir(dirname($_SERVER['argv'][0]));
// Servers should define a default timezone in php.ini, but if they don't then make sure something is defined.
if (!function_exists('date_default_timezone_set') or !function_exists('date_default_timezone_get')) {
fwrite(STDERR, "Timezone functions are not available.\n");
exit(1);
// This is a quick hack. Ideally we should ask the admin for a value. See MDL-22625 for more on this.
if (function_exists('date_default_timezone_set') and function_exists('date_default_timezone_get')) {
@date_default_timezone_set(@date_default_timezone_get());
}
date_default_timezone_set(@date_default_timezone_get());
// make sure PHP errors are displayed - helps with diagnosing of problems
@error_reporting(E_ALL);
@@ -253,10 +250,8 @@ list($options, $unrecognized) = cli_get_params(
'prefix' => 'mdl_',
'fullname' => '',
'shortname' => '',
'summary' => '',
'adminuser' => 'admin',
'adminpass' => '',
'adminemail' => '',
'non-interactive' => false,
'agree-license' => false,
'allow-unstable' => false,
@@ -692,20 +687,6 @@ if ($interactive) {
}
}
// Ask for the admin email address.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
$options['adminemail'] = cli_input($prompt);
}
// Validate that the address provided was an e-mail address.
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
$a = (object) array('option' => 'adminemail', 'value' => $options['adminemail']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
if ($interactive) {
if (!$options['agree-license']) {
cli_separator();
-8
View File
@@ -52,7 +52,6 @@ Options:
--lang=CODE Installation and default site language. Default is en.
--adminuser=USERNAME Username for the moodle admin account. Default is admin.
--adminpass=PASSWORD Password for the moodle admin account.
--adminemail=STRING Email address for the moodle admin account.
--agree-license Indicates agreement with software license.
--fullname=STRING Name of the site
--shortname=STRING Name of the site
@@ -103,7 +102,6 @@ list($options, $unrecognized) = cli_get_params(
'lang' => 'en',
'adminuser' => 'admin',
'adminpass' => '',
'adminemail' => '',
'fullname' => '',
'shortname' => '',
'agree-license' => false,
@@ -128,12 +126,6 @@ if ($options['adminpass'] === true or $options['adminpass'] === '') {
cli_error('You have to specify admin password. --help prints out the help'); // TODO: localize
}
// Validate that the address provided was an e-mail address.
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
$a = (object) array('option' => 'adminemail', 'value' => $options['adminemail']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
$options['lang'] = clean_param($options['lang'], PARAM_SAFEDIR);
if (!file_exists($CFG->dirroot.'/install/lang/'.$options['lang'])) {
$options['lang'] = 'en';
+3 -3
View File
@@ -90,7 +90,7 @@ if (!empty($options['info'])) {
$problem = false;
foreach ($DB->get_tables(false) as $table) {
$columns = $DB->get_columns($table, false);
$size = $generator->guess_antelope_row_size($columns);
$size = $generator->guess_antolope_row_size($columns);
$format = $DB->get_row_format($table);
if ($size <= $generator::ANTELOPE_MAX_ROW_SIZE) {
continue;
@@ -120,7 +120,7 @@ if (!empty($options['info'])) {
$fixtables = array();
foreach ($DB->get_tables(false) as $table) {
$columns = $DB->get_columns($table, false);
$size = $generator->guess_antelope_row_size($columns);
$size = $generator->guess_antolope_row_size($columns);
$format = $DB->get_row_format($table);
if ($size <= $generator::ANTELOPE_MAX_ROW_SIZE) {
continue;
@@ -169,7 +169,7 @@ if (!empty($options['info'])) {
foreach ($DB->get_tables(false) as $table) {
$columns = $DB->get_columns($table, false);
$size = $generator->guess_antelope_row_size($columns);
$size = $generator->guess_antolope_row_size($columns);
$format = $DB->get_row_format($table);
if ($size <= $generator::ANTELOPE_MAX_ROW_SIZE) {
continue;
-138
View File
@@ -1259,142 +1259,4 @@
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="2.9" requires="2.2">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="5.5.31" />
<VENDOR name="mysql" version="5.5.31" />
<VENDOR name="postgres" version="9.1" />
<VENDOR name="mssql" version="10.0" />
<VENDOR name="oracle" version="10.2" />
</DATABASE>
<PHP version="5.4.4" level="required">
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="optional">
<FEEDBACK>
<ON_CHECK message="mbstringrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="optional">
<FEEDBACK>
<ON_CHECK message="opensslrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlrpc" level="optional">
<FEEDBACK>
<ON_CHECK message="xmlrpcrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="optional">
<FEEDBACK>
<ON_CHECK message="intlrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+22 -22
View File
@@ -88,6 +88,7 @@ core_component::get_core_subsystems();
require_once($CFG->libdir.'/adminlib.php'); // various admin-only functions
require_once($CFG->libdir.'/upgradelib.php'); // general upgrade/install related functions
$id = optional_param('id', '', PARAM_TEXT);
$confirmupgrade = optional_param('confirmupgrade', 0, PARAM_BOOL);
$confirmrelease = optional_param('confirmrelease', 0, PARAM_BOOL);
$confirmplugins = optional_param('confirmplugincheck', 0, PARAM_BOOL);
@@ -521,10 +522,14 @@ if (empty($site->shortname)) {
// probably new installation - lets return to frontpage after this step
// remove settings that we want uninitialised
unset_config('registerauth');
unset_config('timezone'); // Force admin to select timezone!
redirect('upgradesettings.php?return=site');
}
// Check if we are returning from moodle.org registration and if so, we mark that fact to remove reminders
if (!empty($id) and $id == $CFG->siteidentifier) {
set_config('registered', time());
}
// setup critical warnings before printing admin tree block
$insecuredataroot = is_dataroot_insecure(true);
$SESSION->admin_critical_warning = ($insecuredataroot==INSECURE_DATAROOT_ERROR);
@@ -556,37 +561,32 @@ $cronoverdue = ($lastcron < time() - 3600 * 24);
$dbproblems = $DB->diagnose();
$maintenancemode = !empty($CFG->maintenance_enabled);
// Available updates for Moodle core.
// Available updates for Moodle core
$updateschecker = \core\update\checker::instance();
$availableupdates = array();
$availableupdatesfetch = null;
$availableupdates['core'] = $updateschecker->get_update_info('core',
array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
if (empty($CFG->disableupdatenotifications)) {
// Only compute the update information when it is going to be displayed to the user.
$availableupdates['core'] = $updateschecker->get_update_info('core',
array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
// Available updates for contributed plugins
$pluginman = core_plugin_manager::instance();
foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) {
foreach ($plugintypeinstances as $pluginname => $plugininfo) {
if (!empty($plugininfo->availableupdates)) {
foreach ($plugininfo->availableupdates as $pluginavailableupdate) {
if ($pluginavailableupdate->version > $plugininfo->versiondisk) {
if (!isset($availableupdates[$plugintype.'_'.$pluginname])) {
$availableupdates[$plugintype.'_'.$pluginname] = array();
}
$availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate;
// Available updates for contributed plugins
$pluginman = core_plugin_manager::instance();
foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) {
foreach ($plugintypeinstances as $pluginname => $plugininfo) {
if (!empty($plugininfo->availableupdates)) {
foreach ($plugininfo->availableupdates as $pluginavailableupdate) {
if ($pluginavailableupdate->version > $plugininfo->versiondisk) {
if (!isset($availableupdates[$plugintype.'_'.$pluginname])) {
$availableupdates[$plugintype.'_'.$pluginname] = array();
}
$availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate;
}
}
}
}
// The timestamp of the most recent check for available updates
$availableupdatesfetch = $updateschecker->get_last_timefetched();
}
// The timestamp of the most recent check for available updates
$availableupdatesfetch = $updateschecker->get_last_timefetched();
$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
//check if the site is registered on Moodle.org
$registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
-9
View File
@@ -94,15 +94,6 @@ class mnet_review_host_form extends moodleform {
$mform->setType('wwwroot', PARAM_URL);
$mform->addRule('wwwroot', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
$options = array(
mnet_peer::SSL_NONE => get_string('none'),
mnet_peer::SSL_HOST => get_string('verifyhostonly', 'core_mnet'),
mnet_peer::SSL_HOST_AND_PEER => get_string('verifyhostandpeer', 'core_mnet')
);
$mform->addElement('select', 'sslverification', get_string('sslverification', 'core_mnet'), $options);
$mform->setDefault('sslverification', mnet_peer::SSL_HOST_AND_PEER);
$mform->addHelpButton('sslverification', 'sslverification', 'core_mnet');
$themes = array('' => get_string('forceno'));
foreach (array_keys(core_component::get_plugin_list('theme')) as $themename) {
$themes[$themename] = get_string('pluginname', 'theme_'.$themename);
-1
View File
@@ -172,7 +172,6 @@ if ($formdata = $reviewform->get_data()) {
$mnet_peer->public_key = $formdata->public_key;
$credentials = $mnet_peer->check_credentials($mnet_peer->public_key);
$mnet_peer->public_key_expires = $credentials['validTo_time_t'];
$mnet_peer->sslverification = $formdata->sslverification;
if ($mnet_peer->commit()) {
redirect(new moodle_url('/admin/mnet/peers.php', array('hostid' => $mnet_peer->id)), get_string('changessaved'));
-19
View File
@@ -66,19 +66,12 @@ if (!empty($hostid) && array_key_exists($hostid, $hosts)) {
$mnet_request->set_method('system/listServices');
$mnet_request->send($mnet_peer);
$services = $mnet_request->response;
$yesno = array('No', 'Yes');
$servicenames = array();
echo $OUTPUT->heading(get_string('servicesavailableonhost', 'mnet', $host->wwwroot));
if (!empty($mnet_request->error)) {
echo $OUTPUT->heading(get_string('error'), 3);
echo html_writer::alist($mnet_request->error);
$services = array();
}
$table = new html_table();
$table->head = array(
get_string('serviceid', 'mnet'),
@@ -134,7 +127,6 @@ if (!empty($hostid) && array_key_exists($hostid, $hosts)) {
echo html_writer::table($table);
$mnet_request = new mnet_xmlrpc_client();
$mnet_request->set_method('system/listMethods');
if (isset($servicename) && array_key_exists($servicename, $serviceinfo)) {
echo $OUTPUT->heading(get_string('methodsavailableonhostinservice', 'mnet', (object)array('host' => $host->wwwroot, 'service' => $servicename)));
@@ -147,11 +139,6 @@ if (!empty($hostid) && array_key_exists($hostid, $hosts)) {
$mnet_request->send($mnet_peer);
$methods = $mnet_request->response;
if (!empty($mnet_request->error)) {
echo $OUTPUT->heading(get_string('error'), 3);
echo html_writer::alist($mnet_request->error);
$methods = array();
}
$table = new html_table();
$table->head = array(
@@ -184,12 +171,6 @@ if (!empty($hostid) && array_key_exists($hostid, $hosts)) {
echo $OUTPUT->heading(get_string('methodsignature', 'mnet', $method));
if (!empty($mnet_request->error)) {
echo $OUTPUT->heading(get_string('error'), 3);
echo html_writer::alist($mnet_request->error);
$signature = array();
}
$table = new html_table();
$table->head = array(
get_string('position', 'mnet'),
+5 -2
View File
@@ -58,14 +58,17 @@ if (!empty($registeredhub) and $registeredhub->token == $token) {
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('registrationconfirmed', 'hub'), 3, 'main');
$hublink = html_writer::tag('a', $hubname, array('href' => $url));
$registeredhub->token = $newtoken;
$registeredhub->confirmed = 1;
$registeredhub->hubname = $hubname;
$registrationmanager->update_registeredhub($registeredhub);
// Display notification message.
echo $OUTPUT->notification(get_string('registrationconfirmedon', 'hub'), 'notifysuccess');
//display notficiation message
$notificationmessage = $OUTPUT->notification(
get_string('registrationconfirmedon', 'hub', $hublink), 'notifysuccess');
echo $notificationmessage;
//display continue button
$registrationpage = new moodle_url('/admin/registration/index.php');
+3 -3
View File
@@ -22,9 +22,9 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com
*
* On this page the administrator selects which hub he wants to register (except for moodle.net)
* Admins can register with moodle.net via the site admin menu "Registration" link.
* On this page the administrator can also unregister from any hubs including moodle.net.
* On this page the administrator selects which hub he wants to register,
* except for MOOCH. Admins can register with MOOCH with the top admin menu "Registration" link.
* On this page the administrator can also unregister from any hubs, including MOOCH.
*/
require('../../config.php');
+27 -28
View File
@@ -53,30 +53,31 @@ class registration_manager {
public function cron() {
global $CFG;
if (extension_loaded('xmlrpc')) {
$function = 'hub_update_site_info';
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
//check if the last registration cron update was less than a week ago
$lastcron = get_config('registration', 'crontime');
if ($lastcron === false or $lastcron < strtotime("-7 day")) { //set to a week, see MDL-23704
$function = 'hub_update_site_info';
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
// Update all hubs where the site is registered.
$hubs = $this->get_registered_on_hubs();
if (empty($hubs)) {
mtrace(get_string('registrationwarning', 'admin'));
}
foreach ($hubs as $hub) {
// Update the registration.
$siteinfo = $this->get_site_info($hub->huburl);
$params = array('siteinfo' => $siteinfo);
$serverurl = $hub->huburl . "/local/hub/webservice/webservices.php";
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
try {
$result = $xmlrpcclient->call($function, $params);
$this->update_registeredhub($hub); // To update timemodified.
mtrace(get_string('siteupdatedcron', 'hub', $hub->hubname));
} catch (Exception $e) {
$errorparam = new stdClass();
$errorparam->errormessage = $e->getMessage();
$errorparam->hubname = $hub->hubname;
mtrace(get_string('errorcron', 'hub', $errorparam));
//update all hub where the site is registered on
$hubs = $this->get_registered_on_hubs();
foreach ($hubs as $hub) {
//update the registration
$siteinfo = $this->get_site_info($hub->huburl);
$params = array('siteinfo' => $siteinfo);
$serverurl = $hub->huburl . "/local/hub/webservice/webservices.php";
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
try {
$result = $xmlrpcclient->call($function, $params);
mtrace(get_string('siteupdatedcron', 'hub', $hub->hubname));
} catch (Exception $e) {
$errorparam = new stdClass();
$errorparam->errormessage = $e->getMessage();
$errorparam->hubname = $hub->hubname;
mtrace(get_string('errorcron', 'hub', $errorparam));
}
}
set_config('crontime', time(), 'registration');
}
} else {
mtrace(get_string('errorcronnoxmlrpc', 'hub'));
@@ -117,7 +118,6 @@ class registration_manager {
*/
public function add_registeredhub($hub) {
global $DB;
$hub->timemodified = time();
$id = $DB->insert_record('registration_hubs', $hub);
return $id;
}
@@ -171,16 +171,15 @@ class registration_manager {
/**
* Update a registered hub (mostly use to update the confirmation status)
* @param object $hub the hub
* @param object $communication the hub
*/
public function update_registeredhub($hub) {
public function update_registeredhub($communication) {
global $DB;
$hub->timemodified = time();
$DB->update_record('registration_hubs', $hub);
$DB->update_record('registration_hubs', $communication);
}
/**
* Return all hubs where the site is registered
* Return all hubs where the site is registered on
*/
public function get_registered_on_hubs() {
global $DB;
+1 -14
View File
@@ -116,7 +116,6 @@ if ($update and confirm_sesskey()) {
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $registeredhub->token);
try {
$result = $xmlrpcclient->call($function, $params);
$registrationmanager->update_registeredhub($registeredhub); // To update timemodified.
} catch (Exception $e) {
$error = $OUTPUT->notification(get_string('errorregistration', 'hub', $e->getMessage()));
}
@@ -176,20 +175,8 @@ if (!empty($error)) {
echo $error;
}
// Some Moodle.org registration explanation.
//some Moodle.org resitration explanation
if ($huburl == HUB_MOODLEORGHUBURL) {
if (!empty($registeredhub->token)) {
if ($registeredhub->timemodified == 0) {
$registrationmessage = get_string('pleaserefreshregistrationunknown', 'admin');
} else {
$lastupdated = userdate($registeredhub->timemodified, get_string('strftimedate', 'langconfig'));
$registrationmessage = get_string('pleaserefreshregistration', 'admin', $lastupdated);
}
} else {
$registrationmessage = get_string('registrationwarning', 'admin');
}
echo $OUTPUT->notification($registrationmessage);
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
$renderer = $PAGE->get_renderer('core', 'register');
echo $renderer->moodleorg_registration_message();
+7 -7
View File
@@ -31,18 +31,18 @@
class core_register_renderer extends plugin_renderer_base {
/**
* Display message about the benefits of registering on Moodle.org
* Display Moodle.org registration message about benefit to register on Moodle.org
*
* @return string
*/
public function moodleorg_registration_message() {
$moodleorgstatslink = html_writer::link('http://moodle.net/stats',
get_string('statsmoodleorg', 'admin'),
array('target' => '_blank'));
$moodleorgregmsg = get_string('registermoodleorg', 'admin');
$moodleorgurl = html_writer::link('http://moodle.org', 'Moodle.org');
$moodleorgstatsurl = html_writer::link('http://moodle.org/stats', get_string('statsmoodleorg', 'admin'));
$moochurl = html_writer::link(HUB_MOODLEORGHUBURL, get_string('moodleorghubname', 'admin'));
$moodleorgregmsg = get_string('registermoodleorg', 'admin', $moodleorgurl);
$items = array(get_string('registermoodleorgli1', 'admin'),
get_string('registermoodleorgli2', 'admin', $moodleorgstatslink));
get_string('registermoodleorgli2', 'admin', $moodleorgstatsurl),
get_string('registermoodleorgli3', 'admin', $moochurl));
$moodleorgregmsg .= html_writer::alist($items);
return $moodleorgregmsg;
}
-2
View File
@@ -721,8 +721,6 @@ class core_admin_renderer extends plugin_renderer_base {
foreach ($updates['core'] as $update) {
$updateinfo .= $this->moodle_available_update_info($update);
}
$updateinfo .= html_writer::tag('p', get_string('updateavailablerecommendation', 'core_admin'),
array('class' => 'updateavailablerecommendation'));
}
unset($updates['core']);
// If something has left in the $updates array now, it is updates for plugins.
+4 -14
View File
@@ -264,7 +264,6 @@ if (($action == 'edit') || ($action == 'new')) {
$strshow = get_string('on', 'repository');
$strhide = get_string('off', 'repository');
$strdelete = get_string('disabled', 'repository');
$struninstall = get_string('uninstallplugin', 'core_admin');
$actionchoicesforexisting = array(
'show' => $strshow,
@@ -287,9 +286,9 @@ if (($action == 'edit') || ($action == 'new')) {
// Table to list plug-ins
$table = new html_table();
$table->head = array(get_string('name'), get_string('isactive', 'repository'), get_string('order'), $settingsstr, $struninstall);
$table->head = array(get_string('name'), get_string('isactive', 'repository'), get_string('order'), $settingsstr);
$table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
$table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
$table->id = 'repositoriessetting';
$table->data = array();
$table->attributes['class'] = 'admintable generaltable';
@@ -385,12 +384,7 @@ if (($action == 'edit') || ($action == 'new')) {
$updowncount++;
$uninstall = '';
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('repository_' . $typename, 'manage')) {
$uninstall = html_writer::link($uninstallurl, $struninstall);
}
$table->data[] = array($i->get_readablename(), $OUTPUT->render($select), $updown, $settings, $uninstall);
$table->data[] = array($i->get_readablename(), $OUTPUT->render($select), $updown, $settings);
if (!in_array($typename, $alreadyplugins)) {
$alreadyplugins[] = $typename;
@@ -406,11 +400,7 @@ if (($action == 'edit') || ($action == 'new')) {
if (!in_array($plugin, $alreadyplugins)) {
$select = new single_select(repository_action_url($plugin, 'repos'), 'action', $actionchoicesfornew, 'delete', null, 'applyto' . basename($plugin));
$select->set_label(get_string('action'), array('class' => 'accesshide'));
$uninstall = '';
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('repository_' . $plugin, 'manage')) {
$uninstall = html_writer::link($uninstallurl, $struninstall);
}
$table->data[] = array(get_string('pluginname', 'repository_'.$plugin), $OUTPUT->render($select), '', '', $uninstall);
$table->data[] = array(get_string('pluginname', 'repository_'.$plugin), $OUTPUT->render($select), '', '');
}
}
}
-5
View File
@@ -135,11 +135,6 @@ if ($roleid) {
}
}
if (!empty($user) && ($user->id != $USER->id)) {
$PAGE->navigation->extend_for_user($user);
$PAGE->navbar->includesettingsbase = true;
}
$PAGE->set_pagelayout('admin');
$PAGE->set_title($title);
-1
View File
@@ -52,7 +52,6 @@ if (!has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride',
$PAGE->set_url($url);
if ($context->contextlevel == CONTEXT_USER and $USER->id != $context->instanceid) {
$PAGE->navbar->includesettingsbase = true;
$PAGE->navigation->extend_for_user($user);
$PAGE->set_context(context_course::instance($course->id));
} else {
+5 -14
View File
@@ -41,24 +41,15 @@ class core_role_existing_role_holders extends core_role_assign_user_selector_bas
list($sort, $sortparams) = users_order_by_sql('u', $search, $this->accesscontext);
$params = array_merge($params, $sortparams);
$fields = "SELECT ra.id AS raid," . $this->required_fields_sql('u') . ",ra.contextid,ra.component ";
$countfields = "SELECT COUNT(1) ";
$sql = "FROM {role_assignments} ra
$sql = "SELECT ra.id AS raid," . $this->required_fields_sql('u') . ",ra.contextid,ra.component
FROM {role_assignments} ra
JOIN {user} u ON u.id = ra.userid
JOIN {context} ctx ON ra.contextid = ctx.id
WHERE $wherecondition
AND ctx.id $ctxcondition
AND ra.roleid = :roleid";
$order = " ORDER BY ctx.depth DESC, ra.component, $sort";
if (!$this->is_validating()) {
$existinguserscount = $DB->count_records_sql($countfields . $sql, $params);
if ($existinguserscount > $this->maxusersperpage) {
return $this->too_many_results($search, $existinguserscount);
}
}
$contextusers = $DB->get_records_sql($fields . $sql . $order, $params);
AND ra.roleid = :roleid
ORDER BY ctx.depth DESC, ra.component, $sort";
$contextusers = $DB->get_records_sql($sql, $params);
// No users at all.
if (empty($contextusers)) {
+2 -2
View File
@@ -53,9 +53,9 @@ M.core_role.init_cap_table_filter = function(Y, tableid, contextid) {
// Create the capability search input.
this.input = Y.Node.create('<input type="text" id="'+this.table.get('id')+'capabilitysearch" value="'+Y.Escape.html(filtervalue)+'" />');
// Create a label for the search input.
this.label = Y.Node.create('<label for="'+this.input.get('id')+'">'+M.util.get_string('filter', 'moodle')+' </label>');
this.label = Y.Node.create('<label for="'+this.input.get('id')+'">'+M.str.moodle.filter+' </label>');
// Create a clear button to clear the input.
this.button = Y.Node.create('<input type="button" value="'+M.util.get_string('clear', 'moodle')+'" />').set('disabled', filtervalue=='');
this.button = Y.Node.create('<input type="button" value="'+M.str.moodle.clear+'" />').set('disabled', filtervalue=='');
// Tie it all together
this.div.append(this.label).append(this.input).append(this.button);
+1 -2
View File
@@ -59,9 +59,8 @@ require_capability('moodle/role:review', $context);
$PAGE->set_url($url);
if ($context->contextlevel == CONTEXT_USER and $USER->id != $context->instanceid) {
$PAGE->navbar->includesettingsbase = true;
$PAGE->navigation->extend_for_user($user);
$PAGE->set_context(context_user::instance($user->id));
$PAGE->set_context(context_course::instance($course->id));
} else {
$PAGE->set_context($context);
}
+1 -1
View File
@@ -132,7 +132,7 @@ if ($courseid == SITEID) {
$PAGE->set_heading($course->fullname.': '.$fullname);
}
echo $OUTPUT->header();
echo $OUTPUT->heading($title);
echo $OUTPUT->heading($title, 3);
echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthnormal');
// Display them.
+3 -1
View File
@@ -22,6 +22,7 @@ if ($data = data_submitted() and confirm_sesskey()) {
if (admin_write_settings($data)) {
$statusmsg = get_string('changessaved');
}
$adminroot = admin_get_root(true); //reload tree
if (!empty($adminroot->errors)) {
$errormsg = get_string('errorwithsettings', 'admin');
@@ -43,9 +44,10 @@ if ($errormsg !== '') {
$resultshtml = admin_search_settings_html($query); // case insensitive search only
echo '<form action="' . $PAGE->url->out(true) . '" method="post" id="adminsettings">';
echo '<form action="search.php" method="post" id="adminsettings">';
echo '<div>';
echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
echo '<input type="hidden" name="query" value="'.s($query).'" />';
echo '</div>';
echo '<fieldset>';
echo '<div class="clearer"><!-- --></div>';
+1
View File
@@ -48,6 +48,7 @@ if ($data = data_submitted() and confirm_sesskey()) {
$errormsg = get_string('errorwithsettings', 'admin');
$firsterror = reset($adminroot->errors);
}
$adminroot = admin_get_root(true); //reload tree
$settingspage = $adminroot->locate($section, true);
}
+9 -24
View File
@@ -27,9 +27,9 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { // sp
'customusermenuitems',
new lang_string('customusermenuitems', 'admin'),
new lang_string('configcustomusermenuitems', 'admin'),
'grades,grades|/grade/report/mygrades.php|grades
messages,message|/message/index.php|message
preferences,moodle|/user/preferences.php|preferences',
'messages,message|/message/index.php|message
myfiles,moodle|/user/files.php|download
mybadges,badges|/badges/mybadges.php|award',
PARAM_TEXT,
'50',
'10'
@@ -75,24 +75,11 @@ preferences,moodle|/user/preferences.php|preferences',
6 => new lang_string('saturday', 'calendar')
)));
$temp->add(new admin_setting_special_calendar_weekend());
$options = array(365 => new lang_string('numyear', '', 1),
270 => new lang_string('nummonths', '', 9),
180 => new lang_string('nummonths', '', 6),
150 => new lang_string('nummonths', '', 5),
120 => new lang_string('nummonths', '', 4),
90 => new lang_string('nummonths', '', 3),
60 => new lang_string('nummonths', '', 2),
30 => new lang_string('nummonth', '', 1),
21 => new lang_string('numweeks', '', 3),
14 => new lang_string('numweeks', '', 2),
7 => new lang_string('numweek', '', 1),
6 => new lang_string('numdays', '', 6),
5 => new lang_string('numdays', '', 5),
4 => new lang_string('numdays', '', 4),
3 => new lang_string('numdays', '', 3),
2 => new lang_string('numdays', '', 2),
1 => new lang_string('numday', '', 1));
$temp->add(new admin_setting_configselect('calendar_lookahead', new lang_string('configlookahead', 'admin'), new lang_string('helpupcominglookahead', 'admin'), 21, $options));
$options = array();
for ($i=1; $i<=99; $i++) {
$options[$i] = $i;
}
$temp->add(new admin_setting_configselect('calendar_lookahead',new lang_string('configlookahead','admin'),new lang_string('helpupcominglookahead', 'admin'),21,$options));
$options = array();
for ($i=1; $i<=20; $i++) {
$options[$i] = $i;
@@ -140,8 +127,7 @@ preferences,moodle|/user/preferences.php|preferences',
HOMEPAGE_MY => new lang_string('mymoodle', 'admin'),
HOMEPAGE_USER => new lang_string('userpreference', 'admin')
);
$temp->add(new admin_setting_configselect('defaulthomepage', new lang_string('defaulthomepage', 'admin'),
new lang_string('configdefaulthomepage', 'admin'), HOMEPAGE_MY, $choices));
$temp->add(new admin_setting_configselect('defaulthomepage', new lang_string('defaulthomepage', 'admin'), new lang_string('configdefaulthomepage', 'admin'), HOMEPAGE_SITE, $choices));
$temp->add(new admin_setting_configcheckbox('allowguestmymoodle', new lang_string('allowguestmymoodle', 'admin'), new lang_string('configallowguestmymoodle', 'admin'), 1));
$temp->add(new admin_setting_configcheckbox('navshowfullcoursenames', new lang_string('navshowfullcoursenames', 'admin'), new lang_string('navshowfullcoursenames_help', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('navshowcategories', new lang_string('navshowcategories', 'admin'), new lang_string('confignavshowcategories', 'admin'), 1));
@@ -158,7 +144,6 @@ preferences,moodle|/user/preferences.php|preferences',
$temp->add(new admin_setting_configtext('navcourselimit',new lang_string('navcourselimit','admin'),new lang_string('confignavcourselimit', 'admin'),20,PARAM_INT));
$temp->add(new admin_setting_configcheckbox('usesitenameforsitepages', new lang_string('usesitenameforsitepages', 'admin'), new lang_string('configusesitenameforsitepages', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('linkadmincategories', new lang_string('linkadmincategories', 'admin'), new lang_string('linkadmincategories_help', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('linkcoursesections', new lang_string('linkcoursesections', 'admin'), new lang_string('linkcoursesections_help', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('navshowfrontpagemods', new lang_string('navshowfrontpagemods', 'admin'), new lang_string('navshowfrontpagemods_help', 'admin'), 1));
$temp->add(new admin_setting_configcheckbox('navadduserpostslinks', new lang_string('navadduserpostslinks', 'admin'), new lang_string('navadduserpostslinks_help', 'admin'), 1));
+1 -7
View File
@@ -196,10 +196,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_logs', new lang_string('generallogs','backup'), new lang_string('configgenerallogs','backup'), array('value'=>0, 'locked'=>0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_histories', new lang_string('generalhistories','backup'), new lang_string('configgeneralhistories','backup'), array('value'=>0, 'locked'=>0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_questionbank', new lang_string('generalquestionbank','backup'), new lang_string('configgeneralquestionbank','backup'), array('value'=>1, 'locked'=>0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_groups',
new lang_string('generalgroups', 'backup'), new lang_string('configgeneralgroups', 'backup'),
array('value' => 1, 'locked' => 0)));
$ADMIN->add('backups', $temp);
// Create a page for general import configuration and defaults.
@@ -225,7 +221,7 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
2 => new lang_string('storagecourseandexternal', 'backup')
);
$temp->add(new admin_setting_configselect('backup/backup_auto_storage', new lang_string('automatedstorage', 'backup'), new lang_string('automatedstoragehelp', 'backup'), 0, $storageoptions));
$temp->add(new admin_setting_special_backup_auto_destination());
$temp->add(new admin_setting_configdirectory('backup/backup_auto_destination', new lang_string('saveto'), new lang_string('backupsavetohelp'), ''));
$keepoptoins = array(
0 => new lang_string('all'), 1 => '1',
2 => '2',
@@ -275,8 +271,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_logs', new lang_string('generallogs', 'backup'), new lang_string('configgenerallogs', 'backup'), 0));
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_histories', new lang_string('generalhistories','backup'), new lang_string('configgeneralhistories','backup'), 0));
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_questionbank', new lang_string('generalquestionbank','backup'), new lang_string('configgeneralquestionbank','backup'), 1));
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_groups', new lang_string('generalgroups', 'backup'),
new lang_string('configgeneralgroups', 'backup'), 1));
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_messages', new lang_string('messages', 'message'), new lang_string('backupmessageshelp','message'), 0));
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_blogs', new lang_string('blogs', 'blog'), new lang_string('backupblogshelp','blog'), 0));
+9
View File
@@ -18,6 +18,15 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$enablecssoptimiser->set_updatedcallback('theme_reset_all_caches');
$temp->add($enablecssoptimiser);
// Backup archive .mbz format: switching to .tar.gz enables larger files, better
// progress reporting and possibly better performance. This is an experimental
// setting but if successful, should be removed and enabled by default in a future
// version. Note: this setting controls newly-created backups only; restore always
// supports both formats.
$temp->add(new admin_setting_configcheckbox('enabletgzbackups',
new lang_string('enabletgzbackups', 'admin'),
new lang_string('enabletgzbackups_desc', 'admin'), 0));
$ADMIN->add('experimental', $temp);
// "debugging" settingpage
-5
View File
@@ -75,11 +75,6 @@ if (has_capability('moodle/grade:manage', $systemcontext)
$temp->add(new admin_setting_special_gradepointmax());
$temp->add(new admin_setting_special_gradepointdefault());
$temp->add(new admin_setting_my_grades_report());
$temp->add(new admin_setting_configtext('gradereport_mygradeurl', new lang_string('externalurl', 'grades'),
new lang_string('externalurl_desc', 'grades'), ''));
}
$ADMIN->add('grades', $temp);
+5 -2
View File
@@ -4,8 +4,11 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
// "locations" settingpage
$temp = new admin_settingpage('locationsettings', new lang_string('locationsettings', 'admin'));
$temp->add(new admin_setting_servertimezone());
$temp->add(new admin_setting_forcetimezone());
$options = get_list_of_timezones();
$options[99] = new lang_string('serverlocaltime');
$temp->add(new admin_setting_configselect('timezone', new lang_string('timezone','admin'), new lang_string('configtimezone', 'admin'), 99, $options));
$options[99] = new lang_string('timezonenotforced', 'admin');
$temp->add(new admin_setting_configselect('forcetimezone', new lang_string('forcetimezone', 'admin'), new lang_string('helpforcetimezone', 'admin'), 99, $options));
$temp->add(new admin_settings_country_select('country', new lang_string('country', 'admin'), new lang_string('configcountry', 'admin'), 0));
$temp->add(new admin_setting_configtext('defaultcity', new lang_string('defaultcity', 'admin'), new lang_string('defaultcity_help', 'admin'), ''));
+3 -11
View File
@@ -32,13 +32,6 @@ if ($hassiteconfig) {
// activity modules
$ADMIN->add('modules', new admin_category('modsettings', new lang_string('activitymodules')));
$temp = new admin_settingpage('managemodulescommon', new lang_string('commonsettings', 'admin'));
$temp->add(new admin_setting_configcheckbox('requiremodintro',
get_string('requiremodintro', 'admin'), get_string('requiremodintro_desc', 'admin'), 0));
$ADMIN->add('modsettings', $temp);
$ADMIN->add('modsettings', new admin_page_managemods());
foreach (core_plugin_manager::instance()->get_plugins_of_type('mod') as $plugin) {
/** @var \core\plugininfo\mod $plugin */
@@ -84,10 +77,6 @@ if ($hassiteconfig) {
$temp->add(new admin_setting_configcheckbox('loginpageautofocus', new lang_string('loginpageautofocus', 'admin'), new lang_string('loginpageautofocus_help', 'admin'), 0));
$temp->add(new admin_setting_configselect('guestloginbutton', new lang_string('guestloginbutton', 'auth'),
new lang_string('showguestlogin', 'auth'), '1', array('0'=>new lang_string('hide'), '1'=>new lang_string('show'))));
$options = array(0 => get_string('no'), 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 10 => 10, 20 => 20, 50 => 50);
$temp->add(new admin_setting_configselect('limitconcurrentlogins',
new lang_string('limitconcurrentlogins', 'core_auth'),
new lang_string('limitconcurrentlogins_desc', 'core_auth'), 0, $options));
$temp->add(new admin_setting_configtext('alternateloginurl', new lang_string('alternateloginurl', 'auth'),
new lang_string('alternatelogin', 'auth', htmlspecialchars(get_login_url())), ''));
$temp->add(new admin_setting_configtext('forgottenpasswordurl', new lang_string('forgottenpasswordurl', 'auth'),
@@ -289,6 +278,9 @@ if ($hassiteconfig) {
$ADMIN->add('webservicesettings', new admin_externalpage('webservicedocumentation', new lang_string('wsdocapi', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/documentation.php", 'moodle/site:config', false));
/// manage service
$temp = new admin_settingpage('externalservices', new lang_string('externalservices', 'webservice'));
$temp->add(new admin_setting_enablemobileservice('enablemobilewebservice',
new lang_string('enablemobilewebservice', 'admin'),
new lang_string('configenablemobilewebservice', 'admin', $enablemobiledoclink), 0));
$temp->add(new admin_setting_heading('manageserviceshelpexplaination', new lang_string('information', 'webservice'), new lang_string('servicehelpexplanation', 'webservice')));
$temp->add(new admin_setting_manageexternalservices());
$ADMIN->add('webservicesettings', $temp);
+1 -10
View File
@@ -55,8 +55,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp->add(new admin_setting_configcheckbox('profilesforenrolledusersonly', new lang_string('profilesforenrolledusersonly','admin'),new lang_string('configprofilesforenrolledusersonly', 'admin'),'1'));
$temp->add(new admin_setting_configcheckbox('cronclionly', new lang_string('cronclionly', 'admin'), new lang_string
('configcronclionly', 'admin'), 1));
$temp->add(new admin_setting_configcheckbox('cronclionly', new lang_string('cronclionly', 'admin'), new lang_string('configcronclionly', 'admin'), 0));
$temp->add(new admin_setting_configpasswordunmask('cronremotepassword', new lang_string('cronremotepassword', 'admin'), new lang_string('configcronremotepassword', 'admin'), ''));
$options = array(0=>get_string('no'), 3=>3, 5=>5, 7=>7, 10=>10, 20=>20, 30=>30, 50=>50, 100=>100);
@@ -71,11 +70,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp->add(new admin_setting_configtext('minpasswordupper', new lang_string('minpasswordupper', 'admin'), new lang_string('configminpasswordupper', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_configtext('minpasswordnonalphanum', new lang_string('minpasswordnonalphanum', 'admin'), new lang_string('configminpasswordnonalphanum', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_configtext('maxconsecutiveidentchars', new lang_string('maxconsecutiveidentchars', 'admin'), new lang_string('configmaxconsecutiveidentchars', 'admin'), 0, PARAM_INT));
$temp->add(new admin_setting_configtext('passwordreuselimit',
new lang_string('passwordreuselimit', 'admin'),
new lang_string('passwordreuselimit_desc', 'admin'), 0, PARAM_INT));
$pwresetoptions = array(
300 => new lang_string('numminutes', '', 5),
900 => new lang_string('numminutes', '', 15),
@@ -92,9 +86,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
1800,
$pwresetoptions);
$temp->add($adminsetting);
$temp->add(new admin_setting_configcheckbox('passwordchangelogout',
new lang_string('passwordchangelogout', 'admin'),
new lang_string('passwordchangelogout_desc', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('groupenrolmentkeypolicy', new lang_string('groupenrolmentkeypolicy', 'admin'), new lang_string('groupenrolmentkeypolicy_desc', 'admin'), 1));
$temp->add(new admin_setting_configcheckbox('disableuserimages', new lang_string('disableuserimages', 'admin'), new lang_string('configdisableuserimages', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('emailchangeconfirmation', new lang_string('emailchangeconfirmation', 'admin'), new lang_string('configemailchangeconfirmation', 'admin'), 1));
-13
View File
@@ -153,19 +153,6 @@ $temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_strin
60 => new lang_string('numdays', '', 60),
30 => new lang_string('numdays', '', 30))));
$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'),
new lang_string('configtempdatafoldercleanup', 'admin'), 168, array(
1 => new lang_string('numhours', '', 1),
3 => new lang_string('numhours', '', 3),
6 => new lang_string('numhours', '', 6),
9 => new lang_string('numhours', '', 9),
12 => new lang_string('numhours', '', 12),
18 => new lang_string('numhours', '', 18),
24 => new lang_string('numhours', '', 24),
48 => new lang_string('numdays', '', 2),
168 => new lang_string('numdays', '', 7),
)));
$ADMIN->add('server', $temp);
-1
View File
@@ -157,7 +157,6 @@ if ($hassiteconfig
array('description' => new lang_string('description'),
'city' => new lang_string('city'),
'country' => new lang_string('country'),
'timezone' => new lang_string('timezone'),
'webpage' => new lang_string('webpage'),
'icqnumber' => new lang_string('icqnumber'),
'skypeid' => new lang_string('skypeid'),
-24
View File
@@ -114,30 +114,6 @@ class behat_admin extends behat_base {
}
}
/**
* Sets the specified site settings. A table with | config | value | (optional)plugin | is expected.
*
* @Given /^the following config values are set as admin:$/
* @param TableNode $table
*/
public function the_following_config_values_are_set_as_admin(TableNode $table) {
if (!$data = $table->getRowsHash()) {
return;
}
foreach ($data as $config => $value) {
// Default plugin value is null.
$plugin = null;
if (is_array($value)) {
$plugin = $value[1];
$value = $value[0];
}
set_config($config, $value, $plugin);
}
}
/**
* Waits with the provided params if we are running a JS session.
*
@@ -9,7 +9,6 @@ Feature: Display extended course names
| fullname | shortname | category |
| Course fullname | C_shortname | 0 |
And I log in as "admin"
And I am on site homepage
Scenario: Courses list without extended course names (default value)
Then I should see "Course fullname"
@@ -20,5 +19,5 @@ Feature: Display extended course names
And I click on "Courses" "link" in the "//div[@id='settingsnav']/descendant::li[contains(concat(' ', normalize-space(@class), ' '), ' type_setting ')][contains(., 'Appearance')]" "xpath_element"
And I set the field "Display extended course names" to "1"
When I press "Save changes"
And I am on site homepage
And I am on homepage
Then I should see "C_shortname Course fullname"
+6 -6
View File
@@ -7,10 +7,10 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
Background:
Given the following "users" exist:
| username | firstname | lastname | email | auth | confirmed |
| user1 | User | One | one@example.com | manual | 0 |
| user2 | User | Two | two@example.com | ldap | 1 |
| user3 | User | Three | three@example.com | manual | 1 |
| user4 | User | Four | four@example.com | ldap | 0 |
| user1 | User | One | one@asd.com | manual | 0 |
| user2 | User | Two | two@asd.com | ldap | 1 |
| user3 | User | Three | three@asd.com | manual | 1 |
| user4 | User | Four | four@asd.com | ldap | 0 |
And the following "cohorts" exist:
| name | idnumber |
| Cohort 1 | CH1 |
@@ -23,8 +23,8 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
| user2 | C1 | student |
| user3 | C1 | student |
And I log in as "admin"
And I add "User Two (two@example.com)" user to "CH1" cohort members
And I add "User Three (three@example.com)" user to "CH1" cohort members
And I add "User Two (two@asd.com)" user to "CH1" cohort members
And I add "User Three (three@asd.com)" user to "CH1" cohort members
And I follow "Browse list of users"
@javascript
@@ -9,18 +9,19 @@ Feature: Set admin settings value
| fullname | shortname | category |
| Course fullname | C_shortname | 0 |
And I log in as "admin"
And I am on site homepage
And I should see "Course fullname"
And I should not see "C_shortname Course fullname"
Scenario: set admin value with full name
Given the following config values are set as admin:
| courselistshortnames | 1 |
And I am on site homepage
Given I set the following administration settings values:
| Display extended course names | 1 |
When I press "Save changes"
And I am on homepage
Then I should see "C_shortname Course fullname"
Scenario: set admin value with short name
Given the following config values are set as admin:
Given I set the following administration settings values:
| courselistshortnames | 1 |
And I am on site homepage
Then I should see "C_shortname Course fullname"
When I press "Save changes"
And I am on homepage
Then I should see "C_shortname Course fullname"
+3 -3
View File
@@ -21,7 +21,7 @@ Feature: Upload users
And I should see "Tom"
And I should see "Jones"
And I should see "verysecret"
And I should see "jonest@example.com"
And I should see "jonest@someplace.edu"
And I should see "Reznor"
And I should see "course1"
And I should see "math102"
@@ -32,8 +32,8 @@ Feature: Upload users
And I follow "Browse list of users"
And I should see "Tom Jones"
And I should see "Trent Reznor"
And I should see "reznor@example.com"
And I am on site homepage
And I should see "reznor@someplace.edu"
And I am on homepage
And I follow "Maths"
And I expand "Users" node
And I follow "Groups"
+2 -2
View File
@@ -41,11 +41,11 @@
}
require_once($CFG->dirroot.'/calendar/lib.php');
$timezones = core_date::get_list_of_timezones(null, true);
$timezones = get_list_of_timezones();
echo '<center><form action="timezone.php" method="post">';
echo html_writer::label($strusers . ' (' . $strall . '): ', 'menuzone');
echo html_writer::select($timezones, "zone", $current);
echo html_writer::select($timezones, "zone", $current, array('99'=>get_string("serverlocaltime")));
echo "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />";
echo '<input type="submit" value="'.s($strsavechanges).'" />';
echo "</form></center>";
+1 -1
View File
@@ -55,7 +55,7 @@ M.tool_assignmentupgrade = {
assignmentsinput = Y.one('input.selectedassignments');
assignmentsinput.set('value', selectedassignments.join(','));
if (selectedassignments.length == 0) {
alert(M.util.get_string('noassignmentsselected', 'tool_assignmentupgrade'));
alert(M.str.tool_assignmentupgrade.noassignmentsselected);
e.preventDefault();
}
});
+3 -3
View File
@@ -24,7 +24,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100;
$plugin->requires = 2015050500;
$plugin->version = 2014111000;
$plugin->requires = 2014110400;
$plugin->component = 'tool_assignmentupgrade';
$plugin->dependencies = array('mod_assign' => 2015050500);
$plugin->dependencies = array('mod_assign' => 2014110400);
@@ -13,8 +13,8 @@ Feature: Manage availability conditions
Then I should not see "Availability restrictions"
# Enable it and check I can now see and click on it.
And the following config values are set as admin:
| enableavailability | 1 |
And I set the following administration settings values:
| Enable conditional access | 1 |
And I am on homepage
And I navigate to "Manage restrictions" node in "Site administration > Plugins > Availability restrictions"
@@ -28,10 +28,10 @@ Feature: Manage availability conditions
Given the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
And the following config values are set as admin:
| enableavailability | 1 |
And I log in as "admin"
And I am on site homepage
And I set the following administration settings values:
| Enable conditional access | 1 |
And I am on homepage
When I navigate to "Manage restrictions" node in "Site administration > Plugins > Availability restrictions"
# Check the icon is there (it should be a Hide icon, meaning is currently visible).
@@ -47,7 +47,7 @@ Feature: Manage availability conditions
# OK, toggling works. Set the grade one to Hide and we'll go see if it actually worked.
And I click on "input[title=Hide]" "css_element" in the "Restriction by grade" "table_row"
And I am on site homepage
And I am on homepage
And I follow "Course 1"
And I turn editing mode on
And I add a "Page" to section "1"
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100;
$plugin->requires = 2015050500;
$plugin->version = 2014111000;
$plugin->requires = 2014110400;
$plugin->component = 'tool_availabilityconditions';
+24 -76
View File
@@ -40,113 +40,61 @@ define('CACHE_DISABLE_ALL', true);
require_once(__DIR__ . '/../../../../lib/clilib.php');
require_once(__DIR__ . '/../../../../lib/behat/lib.php');
list($options, $unrecognized) = cli_get_params(
array(
'parallel' => 0,
'maxruns' => false,
'help' => false,
'fromrun' => 1,
'torun' => 0,
),
array(
'j' => 'parallel',
'm' => 'maxruns',
'h' => 'help',
)
);
// Checking run.php CLI script usage.
$help = "
Behat utilities to initialise behat tests
Usage:
php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]] [--help]
Options:
-j, --parallel Number of parallel behat run to initialise
-m, --maxruns Max parallel processes to be executed at one time.
--fromrun Execute run starting from (Used for parallel runs on different vms)
--torun Execute run till (Used for parallel runs on different vms)
-h, --help Print out this help
Example from Moodle root directory:
\$ php admin/tool/behat/cli/init.php --parallel=2
More info in http://docs.moodle.org/dev/Acceptance_testing#Running_tests
";
if (!empty($options['help'])) {
echo $help;
exit(0);
}
// Check which util file to call.
$utilfile = 'util_single_run.php';
$paralleloption = "";
// If parallel run then use utilparallel.
if ($options['parallel'] && $options['parallel'] > 1) {
$utilfile = 'util.php';
$paralleloption = "";
foreach ($options as $option => $value) {
if ($value) {
$paralleloption .= " --$option=\"$value\"";
}
}
}
// Changing the cwd to admin/tool/behat/cli.
$cwd = getcwd();
$output = null;
// If behat dependencies not downloaded then do it first, else symfony/process can't be used.
testing_update_composer_dependencies();
// Check whether the behat test environment needs to be updated.
chdir(__DIR__);
exec("php $utilfile --diag $paralleloption", $output, $code);
$output = null;
exec("php util.php --diag", $output, $code);
if ($code == 0) {
echo "Behat test environment already installed\n";
} else if ($code == BEHAT_EXITCODE_INSTALL) {
testing_update_composer_dependencies();
// Behat and dependencies are installed and we need to install the test site.
chdir(__DIR__);
passthru("php $utilfile --install $paralleloption", $code);
passthru("php util.php --install", $code);
if ($code != 0) {
chdir($cwd);
exit($code);
}
} else if ($code == BEHAT_EXITCODE_REINSTALL) {
testing_update_composer_dependencies();
// Test site data is outdated.
chdir(__DIR__);
passthru("php $utilfile --drop $paralleloption", $code);
passthru("php util.php --drop", $code);
if ($code != 0) {
chdir($cwd);
exit($code);
}
chdir(__DIR__);
passthru("php $utilfile --install $paralleloption", $code);
passthru("php util.php --install", $code);
if ($code != 0) {
exit($code);
}
} else if ($code == BEHAT_EXITCODE_COMPOSER) {
// Missing Behat dependencies.
testing_update_composer_dependencies();
// Returning to admin/tool/behat/cli.
chdir(__DIR__);
passthru("php util.php --install", $code);
if ($code != 0) {
chdir($cwd);
exit($code);
}
} else {
// Generic error, we just output it.
echo implode("\n", $output)."\n";
chdir($cwd);
exit($code);
}
// Enable editing mode according to config.php vars.
chdir(__DIR__);
passthru("php $utilfile --enable $paralleloption", $code);
passthru("php util.php --enable", $code);
if ($code != 0) {
echo "Error enabling site" . PHP_EOL;
chdir($cwd);
exit($code);
}
-398
View File
@@ -1,398 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Wrapper to run previously set-up behat tests in parallel.
*
* @package tool_behat
* @copyright 2014 NetSpot Pty Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if (isset($_SERVER['REMOTE_ADDR'])) {
die(); // No access from web!
}
define('BEHAT_UTIL', true);
define('CLI_SCRIPT', true);
define('ABORT_AFTER_CONFIG', true);
define('CACHE_DISABLE_ALL', true);
define('NO_OUTPUT_BUFFERING', true);
require_once(__DIR__ .'/../../../../config.php');
require_once(__DIR__.'/../../../../lib/clilib.php');
require_once(__DIR__.'/../../../../lib/behat/lib.php');
require_once(__DIR__.'/../../../../lib/behat/classes/behat_command.php');
require_once(__DIR__.'/../../../../lib/behat/classes/behat_config_manager.php');
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', '1');
ini_set('log_errors', '1');
list($options, $unrecognised) = cli_get_params(
array(
'stop-on-failure' => 0,
'verbose' => false,
'replace' => false,
'help' => false,
'tags' => '',
'profile' => '',
'feature' => '',
'fromrun' => 1,
'torun' => 0,
'single-run' => false,
),
array(
'h' => 'help',
't' => 'tags',
'p' => 'profile',
's' => 'single-run',
)
);
// Checking run.php CLI script usage.
$help = "
Behat utilities to run behat tests in parallel
Usage:
php run.php [--BEHAT_OPTION=\"value\"] [--feature=\"value\"] [--replace] [--fromrun=value --torun=value] [--help]
Options:
--BEHAT_OPTION Any combination of behat option specified in http://behat.readthedocs.org/en/v2.5/guides/6.cli.html
--feature Only execute specified feature file (Absolute path of feature file).
--replace Replace args string with run process number, useful for output.
--fromrun Execute run starting from (Used for parallel runs on different vms)
--torun Execute run till (Used for parallel runs on different vms)
-h, --help Print out this help
Example from Moodle root directory:
\$ php admin/tool/behat/cli/run.php --tags=\"@javascript\"
More info in http://docs.moodle.org/dev/Acceptance_testing#Running_tests
";
if (!empty($options['help'])) {
echo $help;
exit(0);
}
$parallelrun = behat_config_manager::get_parallel_test_runs($options['fromrun']);
// Default torun is maximum parallel runs.
if (empty($options['torun'])) {
$options['torun'] = $parallelrun;
}
// Capture signals and ensure we clean symlinks.
if (extension_loaded('pcntl')) {
$disabled = explode(',', ini_get('disable_functions'));
if (!in_array('pcntl_signal', $disabled)) {
pcntl_signal(SIGTERM, "signal_handler");
pcntl_signal(SIGINT, "signal_handler");
}
}
$time = microtime(true);
array_walk($unrecognised, function (&$v) {
if ($x = preg_filter("#^(-+\w+)=(.+)#", "\$1=\"\$2\"", $v)) {
$v = $x;
} else if (!preg_match("#^-#", $v)) {
$v = escapeshellarg($v);
}
});
$extraopts = $unrecognised;
$tags = '';
if ($options['profile']) {
$profile = $options['profile'];
if (!isset($CFG->behat_config[$profile])) {
echo "Invalid profile passed: " . $profile;
exit(1);
}
$extraopts[] = '--profile="' . $profile . '"';
// By default, profile tags will be used.
if (!empty($CFG->behat_config[$profile]['filters']['tags'])) {
$tags = $CFG->behat_config[$profile]['filters']['tags'];
}
}
// Command line tags have precedence (std behat behavior).
if ($options['tags']) {
$tags = $options['tags'];
$extraopts[] = '--tags="' . $tags . '"';
}
// Feature should be added to last, for behat command.
if ($options['feature']) {
$extraopts[] = $options['feature'];
// Only run 1 process as process.
// Feature file is picked from absolute path provided, so no need to check for behat.yml.
$options['torun'] = $options['fromrun'];
}
// Set of options to pass to behat.
$extraopts = implode(' ', $extraopts);
// If empty parallelrun then just check with user if it's a run single behat test.
if (empty($parallelrun)) {
$cwd = getcwd();
chdir(__DIR__);
$runtestscommand = behat_command::get_behat_command(false, false, true);
$runtestscommand .= ' --config ' . behat_config_manager::get_behat_cli_config_filepath();
$runtestscommand .= ' ' . $extraopts;
echo "Running single behat site:" . PHP_EOL;
passthru("php $runtestscommand", $code);
chdir($cwd);
exit($code);
}
// Update config file if tags defined.
if ($tags) {
// Hack to set proper dataroot and wwwroot.
$behatdataroot = $CFG->behat_dataroot;
$behatwwwroot = $CFG->behat_wwwroot;
for ($i = 1; $i <= $parallelrun; $i++) {
$CFG->behatrunprocess = $i;
if (!empty($CFG->behat_parallel_run[$i - 1]['behat_wwwroot'])) {
$CFG->behat_wwwroot = $CFG->behat_parallel_run[$i - 1]['behat_wwwroot'];
} else {
$CFG->behat_wwwroot = $behatwwwroot . "/" . BEHAT_PARALLEL_SITE_NAME . $i;
}
if (!empty($CFG->behat_parallel_run[$i - 1]['behat_dataroot'])) {
$CFG->behat_dataroot = $CFG->behat_parallel_run[$i - 1]['behat_dataroot'];
} else {
$CFG->behat_dataroot = $behatdataroot . $i;
}
behat_config_manager::update_config_file('', true, $tags);
}
$CFG->behat_dataroot = $behatdataroot;
$CFG->behat_wwwroot = $behatwwwroot;
unset($CFG->behatrunprocess);
}
$cmds = array();
echo "Running " . ($options['torun'] - $options['fromrun'] + 1) . " parallel behat sites:" . PHP_EOL;
for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
$CFG->behatrunprocess = $i;
// Options parameters to be added to each run.
$myopts = !empty($options['replace']) ? str_replace($options['replace'], $i, $extraopts) : $extraopts;
$behatcommand = behat_command::get_behat_command(false, false, true);
$behatconfigpath = behat_config_manager::get_behat_cli_config_filepath($i);
// Command to execute behat run.
$cmds[BEHAT_PARALLEL_SITE_NAME . $i] = $behatcommand . ' --config ' . $behatconfigpath . " " . $myopts;
echo "[" . BEHAT_PARALLEL_SITE_NAME . $i . "] " . $cmds[BEHAT_PARALLEL_SITE_NAME . $i] . PHP_EOL;
}
if (empty($cmds)) {
echo "No commands to execute " . PHP_EOL;
exit(1);
}
// Create site symlink if necessary.
if (!behat_config_manager::create_parallel_site_links($options['fromrun'], $options['torun'])) {
echo "Check permissions. If on windows, make sure you are running this command as admin" . PHP_EOL;
exit(1);
}
// Execute all commands.
$processes = cli_execute_parallel($cmds, __DIR__);
$stoponfail = empty($options['stop-on-failure']) ? false : true;
// Print header.
print_process_start_info($processes);
// Print combined run o/p from processes.
$exitcodes = print_combined_run_output($processes, $stoponfail);
$time = round(microtime(true) - $time, 1);
echo "Finished in " . gmdate("G\h i\m s\s", $time) . PHP_EOL . PHP_EOL;
// Print exit info from each run.
$status = false;
foreach ($exitcodes as $exitcode) {
$status = (bool)$status || (bool)$exitcode;
}
// Run finished. Show exit code and output from individual process.
$verbose = empty($options['verbose']) ? false : true;
$verbose = $verbose || $status;
// Show exit code from each process, if any process failed.
if ($verbose) {
// Echo exit codes.
echo "Exit codes for each behat run: " . PHP_EOL;
ksort($exitcodes);
foreach ($exitcodes as $run => $exitcode) {
echo $run . ": " . $exitcode . PHP_EOL;
}
// Show failed re-run commands.
if ($status) {
echo "To re-run failed processes, you can use following commands:" . PHP_EOL;
foreach ($cmds as $name => $cmd) {
if (!empty($exitcodes[$name])) {
echo "[" . $name . "] " . $cmd . PHP_EOL;
}
}
}
echo PHP_EOL;
}
print_each_process_info($processes, $verbose);
// Remove site symlink if necessary.
behat_config_manager::drop_parallel_site_links();
exit((int) $status);
/**
* Signal handler for terminal exit.
*
* @param int $signal signal number.
*/
function signal_handler($signal) {
switch ($signal) {
case SIGTERM:
case SIGKILL:
case SIGINT:
// Remove site symlink if necessary.
behat_config_manager::drop_parallel_site_links();
exit(1);
}
}
/**
* Prints header from the first process.
*
* @param array $processes list of processes to loop though.
*/
function print_process_start_info($processes) {
$printed = false;
// Keep looping though processes, till we get first process o/p.
while (!$printed) {
usleep(10000);
foreach ($processes as $name => $process) {
// Exit if any process has stopped.
if (!$process->isRunning()) {
$printed = true;
break;
}
$op = explode(PHP_EOL, $process->getOutput());
if (count($op) >= 3) {
foreach ($op as $line) {
if (trim($line) && (strpos($line, '.') !== 0)) {
echo $line . PHP_EOL;
}
}
$printed = true;
}
}
}
}
/**
* Loop though all processes and print combined o/p
*
* @param array $processes list of processes to loop though.
* @param bool $stoponfail Stop all processes and exit if failed.
* @return array list of exit codes from all processes.
*/
function print_combined_run_output($processes, $stoponfail = false) {
$exitcodes = array();
$maxdotsonline = 70;
$remainingprintlen = $maxdotsonline;
$progresscount = 0;
while (count($exitcodes) != count($processes)) {
usleep(10000);
foreach ($processes as $name => $process) {
if ($process->isRunning()) {
$op = $process->getIncrementalOutput();
if (trim($op)) {
$update = preg_filter('#^\s*([FS\.\-]+)(?:\s+\d+)?\s*$#', '$1', $op);
// Exit process if anything fails.
if ($stoponfail && (strpos($update, 'F') !== false)) {
$process->stop(0);
}
$strlentoprint = strlen($update);
// If not enough dots printed on line then just print.
if ($strlentoprint < $remainingprintlen) {
echo $update;
$remainingprintlen = $remainingprintlen - $strlentoprint;
} else if ($strlentoprint == $remainingprintlen) {
$progresscount += $maxdotsonline;
echo $update ." " . $progresscount . PHP_EOL;
$remainingprintlen = $maxdotsonline;
} else {
while ($part = substr($update, 0, $remainingprintlen) > 0) {
$progresscount += $maxdotsonline;
echo $part . " " . $progresscount . PHP_EOL;
$update = substr($update, $remainingprintlen);
$remainingprintlen = $maxdotsonline;
}
}
}
} else {
$exitcodes[$name] = $process->getExitCode();
if ($stoponfail && ($exitcodes[$name] != 0)) {
foreach ($processes as $l => $p) {
$exitcodes[$l] = -1;
$process->stop(0);
}
}
}
}
}
echo PHP_EOL;
return $exitcodes;
}
/**
* Loop though all processes and print combined o/p
*
* @param array $processes list of processes to loop though.
* @param bool $verbose Show verbose output for each process.
*/
function print_each_process_info($processes, $verbose = false) {
foreach ($processes as $name => $process) {
echo "**************** [" . $name . "] ****************" . PHP_EOL;
if ($verbose) {
echo $process->getOutput();
echo $process->getErrorOutput();
} else {
$op = explode(PHP_EOL, $process->getOutput());
foreach ($op as $line) {
// Don't print progress .
if (trim($line) && (strpos($line, '.') !== 0) && (strpos($line, 'Moodle ') !== 0) &&
(strpos($line, 'Server OS ') !== 0) && (strpos($line, 'Started at ') !== 0) &&
(strpos($line, 'Browser specific fixes ') !== 0)) {
echo $line . PHP_EOL;
}
}
}
echo PHP_EOL;
}
}
+69 -347
View File
@@ -15,7 +15,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI tool with utilities to manage parallel Behat integration in Moodle
* CLI tool with utilities to manage Behat integration in Moodle
*
* All CLI utilities uses $CFG->behat_dataroot and $CFG->prefix_dataroot as
* $CFG->dataroot and $CFG->prefix
@@ -30,61 +30,45 @@ if (isset($_SERVER['REMOTE_ADDR'])) {
die(); // No access from web!.
}
define('BEHAT_UTIL', true);
define('CLI_SCRIPT', true);
define('NO_OUTPUT_BUFFERING', true);
define('IGNORE_COMPONENT_CACHE', true);
define('ABORT_AFTER_CONFIG', true);
require_once(__DIR__ . '/../../../../config.php');
// Basic functions.
require_once(__DIR__ . '/../../../../lib/clilib.php');
require_once(__DIR__ . '/../../../../lib/behat/lib.php');
require_once(__DIR__ . '/../../../../lib/behat/classes/behat_command.php');
require_once(__DIR__ . '/../../../../lib/behat/classes/behat_config_manager.php');
// CLI options.
list($options, $unrecognized) = cli_get_params(
array(
'help' => false,
'install' => false,
'drop' => false,
'enable' => false,
'disable' => false,
'diag' => false,
'parallel' => 0,
'maxruns' => false,
'updatesteps' => false,
'fromrun' => 1,
'torun' => 0,
'help' => false,
'install' => false,
'drop' => false,
'enable' => false,
'disable' => false,
'diag' => false
),
array(
'h' => 'help',
'j' => 'parallel',
'm' => 'maxruns'
'h' => 'help'
)
);
if ($options['install'] or $options['drop']) {
define('CACHE_DISABLE_ALL', true);
}
// Checking util.php CLI script usage.
$help = "
Behat utilities to manage the test environment
Usage:
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--help] [--parallel=value [--maxruns=value]]
Options:
--install Installs the test environment for acceptance tests
--drop Drops the database tables and the dataroot contents
--enable Enables test environment and updates tests list
--disable Disables test environment
--diag Get behat test environment status code
--updatesteps Update feature step file.
-j, --parallel Number of parallel behat run operation
-m, --maxruns Max parallel processes to be executed at one time.
--install Installs the test environment for acceptance tests
--drop Drops the database tables and the dataroot contents
--enable Enables test environment and updates tests list
--disable Disables test environment
--diag Get behat test environment status code
-h, --help Print out this help
Example from Moodle root directory:
\$ php admin/tool/behat/cli/util.php --enable --parallel=4
\$ php admin/tool/behat/cli/util.php --enable
More info in http://docs.moodle.org/dev/Acceptance_testing#Running_tests
";
@@ -94,328 +78,66 @@ if (!empty($options['help'])) {
exit(0);
}
$cwd = getcwd();
// Describe this script.
define('BEHAT_UTIL', true);
define('CLI_SCRIPT', true);
define('NO_OUTPUT_BUFFERING', true);
define('IGNORE_COMPONENT_CACHE', true);
// For drop option check if parallel site.
if ((empty($options['parallel'])) && $options['drop']) {
// Get parallel run info from first run.
$options['parallel'] = behat_config_manager::get_parallel_test_runs($options['fromrun']);
// Only load CFG from config.php, stop ASAP in lib/setup.php.
define('ABORT_AFTER_CONFIG', true);
require_once(__DIR__ . '/../../../../config.php');
// Remove error handling overrides done in config.php.
$CFG->debug = (E_ALL | E_STRICT);
$CFG->debugdisplay = 1;
error_reporting($CFG->debug);
ini_set('display_errors', '1');
ini_set('log_errors', '1');
// Finish moodle init.
define('ABORT_AFTER_CONFIG_CANCEL', true);
require("$CFG->dirroot/lib/setup.php");
raise_memory_limit(MEMORY_HUGE);
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/upgradelib.php');
require_once($CFG->libdir.'/clilib.php');
require_once($CFG->libdir.'/installlib.php');
require_once($CFG->libdir.'/testing/classes/test_lock.php');
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
// If not a parallel site then open single run.
if (empty($options['parallel'])) {
chdir(__DIR__);
// Check if behat is initialised, if not exit.
passthru("php util_single_run.php --diag", $status);
if ($status) {
exit ($status);
}
$cmd = commands_to_execute($options);
$processes = cli_execute_parallel(array($cmd), __DIR__);
$status = print_sequential_output($processes, false);
chdir($cwd);
exit($status);
}
// Behat utilities.
require_once($CFG->libdir . '/behat/classes/util.php');
require_once($CFG->libdir . '/behat/classes/behat_command.php');
// Default torun is maximum parallel runs.
if (empty($options['torun'])) {
$options['torun'] = $options['parallel'];
}
$status = false;
$cmds = commands_to_execute($options);
// Start executing commands either sequential/parallel for options provided.
if ($options['diag'] || $options['enable'] || $options['disable']) {
// Do it sequentially as it's fast and need to be displayed nicely.
foreach (array_chunk($cmds, 1, true) as $cmd) {
$processes = cli_execute_parallel($cmd, __DIR__);
print_sequential_output($processes);
}
} else if ($options['drop']) {
$processes = cli_execute_parallel($cmds, __DIR__);
$exitcodes = print_combined_drop_output($processes);
foreach ($exitcodes as $exitcode) {
$status = (bool)$status || (bool)$exitcode;
}
} else if ($options['install']) {
// This is intensive compared to behat itself so run them in chunk if option maxruns not set.
if ($options['maxruns']) {
foreach (array_chunk($cmds, $options['maxruns'], true) as $chunk) {
$processes = cli_execute_parallel($chunk, __DIR__);
$exitcodes = print_combined_install_output($processes);
foreach ($exitcodes as $name => $exitcode) {
if ($exitcode != 0) {
echo "Failed process [[$name]]" . PHP_EOL;
echo $processes[$name]->getOutput();
echo PHP_EOL;
echo $processes[$name]->getErrorOutput();
echo PHP_EOL . PHP_EOL;
}
$status = (bool)$status || (bool)$exitcode;
}
}
} else {
$processes = cli_execute_parallel($cmds, __DIR__);
$exitcodes = print_combined_install_output($processes);
foreach ($exitcodes as $name => $exitcode) {
if ($exitcode != 0) {
echo "Failed process [[$name]]" . PHP_EOL;
echo $processes[$name]->getOutput();
echo PHP_EOL;
echo $processes[$name]->getErrorOutput();
echo PHP_EOL . PHP_EOL;
}
$status = (bool)$status || (bool)$exitcode;
}
}
} else {
// We should never reach here.
echo $help;
exit(1);
}
// Ensure we have success status to show following information.
if ($status) {
echo "Unknown failure $status" . PHP_EOL;
exit((int)$status);
}
// Show command o/p (only one per time).
// Run command (only one per time).
if ($options['install']) {
echo "Acceptance tests site installed for sites:".PHP_EOL;
// Display all sites which are installed/drop/diabled.
for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
if (empty($CFG->behat_parallel_run[$i - 1]['behat_wwwroot'])) {
echo $CFG->behat_wwwroot . "/" . BEHAT_PARALLEL_SITE_NAME . $i . PHP_EOL;
} else {
echo $CFG->behat_parallel_run[$i - 1]['behat_wwwroot'] . PHP_EOL;
}
}
behat_util::install_site();
mtrace("Acceptance tests site installed");
} else if ($options['drop']) {
echo "Acceptance tests site dropped for " . $options['parallel'] . " parallel sites" . PHP_EOL;
// Ensure no tests are running.
test_lock::acquire('behat');
behat_util::drop_site();
mtrace("Acceptance tests site dropped");
} else if ($options['enable']) {
echo "Acceptance tests environment enabled on $CFG->behat_wwwroot, to run the tests use:" . PHP_EOL;
echo behat_command::get_behat_command(true, true);
echo PHP_EOL;
behat_util::start_test_mode();
$runtestscommand = behat_command::get_behat_command(true) .
' --config ' . behat_config_manager::get_behat_cli_config_filepath();
mtrace("Acceptance tests environment enabled on $CFG->behat_wwwroot, to run the tests use:\n " . $runtestscommand);
} else if ($options['disable']) {
echo "Acceptance tests environment disabled for " . $options['parallel'] . " parallel sites" . PHP_EOL;
behat_util::stop_test_mode();
mtrace("Acceptance tests environment disabled");
} else if ($options['diag']) {
// Valid option, so nothing to do.
$code = behat_util::get_behat_status();
exit($code);
} else {
echo $help;
chdir($cwd);
exit(1);
}
chdir($cwd);
exit(0);
/**
* Create commands to be executed for parallel run.
*
* @param array $options options provided by user.
* @return array commands to be executed.
*/
function commands_to_execute($options) {
$removeoptions = array('maxruns', 'fromrun', 'torun');
$cmds = array();
$extraoptions = $options;
$extra = "";
// Remove extra options not in util_single_run.php.
foreach ($removeoptions as $ro) {
$extraoptions[$ro] = null;
unset($extraoptions[$ro]);
}
foreach ($extraoptions as $option => $value) {
if ($options[$option]) {
$extra .= " --$option";
if ($value) {
$extra .= "=$value";
}
}
}
if (empty($options['parallel'])) {
$cmds = "php util_single_run.php " . $extra;
} else {
// Create commands which has to be executed for parallel site.
for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
$prefix = BEHAT_PARALLEL_SITE_NAME . $i;
$cmds[$prefix] = "php util_single_run.php " . $extra . " --run=" . $i . " 2>&1";
}
}
return $cmds;
}
/**
* Print drop output merging each run.
*
* @param array $processes list of processes.
* @return array exit codes of each process.
*/
function print_combined_drop_output($processes) {
$exitcodes = array();
$maxdotsonline = 70;
$remainingprintlen = $maxdotsonline;
$progresscount = 0;
echo "Dropping tables:" . PHP_EOL;
while (count($exitcodes) != count($processes)) {
usleep(10000);
foreach ($processes as $name => $process) {
if ($process->isRunning()) {
$op = $process->getIncrementalOutput();
if (trim($op)) {
$update = preg_filter('#^\s*([FS\.\-]+)(?:\s+\d+)?\s*$#', '$1', $op);
$strlentoprint = strlen($update);
// If not enough dots printed on line then just print.
if ($strlentoprint < $remainingprintlen) {
echo $update;
$remainingprintlen = $remainingprintlen - $strlentoprint;
} else if ($strlentoprint == $remainingprintlen) {
$progresscount += $maxdotsonline;
echo $update . " " . $progresscount . PHP_EOL;
$remainingprintlen = $maxdotsonline;
} else {
while ($part = substr($update, 0, $remainingprintlen) > 0) {
$progresscount += $maxdotsonline;
echo $part . " " . $progresscount . PHP_EOL;
$update = substr($update, $remainingprintlen);
$remainingprintlen = $maxdotsonline;
}
}
}
} else {
// Process exited.
$process->clearOutput();
$exitcodes[$name] = $process->getExitCode();
}
}
}
echo PHP_EOL;
return $exitcodes;
}
/**
* Print install output merging each run.
*
* @param array $processes list of processes.
* @return array exit codes of each process.
*/
function print_combined_install_output($processes) {
$exitcodes = array();
$line = array();
// Check what best we can do to accommodate all parallel run o/p on single line.
// Windows command line has length of 80 chars, so default we will try fit o/p in 80 chars.
if (defined('BEHAT_MAX_CMD_LINE_OUTPUT') && BEHAT_MAX_CMD_LINE_OUTPUT) {
$lengthofprocessline = (int)max(10, BEHAT_MAX_CMD_LINE_OUTPUT / count($processes));
} else {
$lengthofprocessline = (int)max(10, 80 / count($processes));
}
echo "Installing behat site for " . count($processes) . " parallel behat run" . PHP_EOL;
// Show process name in first row.
foreach ($processes as $name => $process) {
// If we don't have enough space to show full run name then show runX.
if ($lengthofprocessline < strlen($name + 2)) {
$name = substr($name, -5);
}
// One extra padding as we are adding | separator for rest of the data.
$line[$name] = str_pad('[' . $name . '] ', $lengthofprocessline + 1);
}
ksort($line);
$tableheader = array_keys($line);
echo implode("", $line) . PHP_EOL;
// Now print o/p from each process.
while (count($exitcodes) != count($processes)) {
usleep(50000);
$poutput = array();
// Create child process.
foreach ($processes as $name => $process) {
if ($process->isRunning()) {
$output = $process->getIncrementalOutput();
if (trim($output)) {
$poutput[$name] = explode(PHP_EOL, $output);
}
} else {
// Process exited.
$exitcodes[$name] = $process->getExitCode();
}
}
ksort($poutput);
// Get max depth of o/p before displaying.
$maxdepth = 0;
foreach ($poutput as $pout) {
$pdepth = count($pout);
$maxdepth = $pdepth >= $maxdepth ? $pdepth : $maxdepth;
}
// Iterate over each process to get line to print.
for ($i = 0; $i <= $maxdepth; $i++) {
$pline = "";
foreach ($tableheader as $name) {
$po = empty($poutput[$name][$i]) ? "" : substr($poutput[$name][$i], 0, $lengthofprocessline - 1);
$po = str_pad($po, $lengthofprocessline);
$pline .= "|". $po;
}
if (trim(str_replace("|", "", $pline))) {
echo $pline . PHP_EOL;
}
}
unset($poutput);
$poutput = null;
}
echo PHP_EOL;
return $exitcodes;
}
/**
* Print install output merging showing one run at a time.
* If any process fail then exit.
*
* @param array $processes list of processes.
* @param bool $showprefix show prefix.
* @return bool exitcode.
*/
function print_sequential_output($processes, $showprefix = true) {
$status = false;
foreach ($processes as $name => $process) {
$shownname = false;
while ($process->isRunning()) {
$op = $process->getIncrementalOutput();
if (trim($op)) {
// Show name of the run once for sequential.
if ($showprefix && !$shownname) {
echo '[' . $name . '] ';
$shownname = true;
}
echo $op;
}
}
// If any error then exit.
$exitcode = $process->getExitCode();
if ($exitcode != 0) {
exit($exitcode);
}
$status = $status || (bool)$exitcode;
}
return $status;
}
-276
View File
@@ -1,276 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI tool with utilities to manage Behat integration in Moodle
*
* All CLI utilities uses $CFG->behat_dataroot and $CFG->prefix_dataroot as
* $CFG->dataroot and $CFG->prefix
*
* @package tool_behat
* @copyright 2012 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if (isset($_SERVER['REMOTE_ADDR'])) {
die(); // No access from web!.
}
// Basic functions.
require_once(__DIR__ . '/../../../../lib/clilib.php');
require_once(__DIR__ . '/../../../../lib/behat/lib.php');
// CLI options.
list($options, $unrecognized) = cli_get_params(
array(
'help' => false,
'install' => false,
'parallel' => 0,
'run' => '',
'drop' => false,
'enable' => false,
'disable' => false,
'diag' => false,
'tags' => '',
'updatesteps' => false,
),
array(
'h' => 'help'
)
);
if ($options['install'] or $options['drop']) {
define('CACHE_DISABLE_ALL', true);
}
// Checking util_single_run.php CLI script usage.
$help = "
Behat utilities to manage the test environment
Usage:
php util_single_run.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--help]
Options:
--install Installs the test environment for acceptance tests
--drop Drops the database tables and the dataroot contents
--enable Enables test environment and updates tests list
--disable Disables test environment
--diag Get behat test environment status code
--updatesteps Update feature step file.
-h, --help Print out this help
Example from Moodle root directory:
\$ php admin/tool/behat/cli/util_single_run.php --enable
More info in http://docs.moodle.org/dev/Acceptance_testing#Running_tests
";
if (!empty($options['help'])) {
echo $help;
exit(0);
}
// Describe this script.
define('BEHAT_UTIL', true);
define('CLI_SCRIPT', true);
define('NO_OUTPUT_BUFFERING', true);
define('IGNORE_COMPONENT_CACHE', true);
// Set run value, to be used by setup for configuring proper CFG variables.
if ($options['run']) {
define('BEHAT_CURRENT_RUN', $options['run']);
}
// Only load CFG from config.php, stop ASAP in lib/setup.php.
define('ABORT_AFTER_CONFIG', true);
require_once(__DIR__ . '/../../../../config.php');
// Remove error handling overrides done in config.php.
$CFG->debug = (E_ALL | E_STRICT);
$CFG->debugdisplay = 1;
error_reporting($CFG->debug);
ini_set('display_errors', '1');
ini_set('log_errors', '1');
// Finish moodle init.
define('ABORT_AFTER_CONFIG_CANCEL', true);
require("$CFG->dirroot/lib/setup.php");
raise_memory_limit(MEMORY_HUGE);
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/upgradelib.php');
require_once($CFG->libdir.'/clilib.php');
require_once($CFG->libdir.'/installlib.php');
require_once($CFG->libdir.'/testing/classes/test_lock.php');
if ($unrecognized) {
$unrecognized = implode(PHP_EOL . " ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
// Behat utilities.
require_once($CFG->libdir . '/behat/classes/util.php');
require_once($CFG->libdir . '/behat/classes/behat_command.php');
require_once($CFG->libdir . '/behat/classes/behat_config_manager.php');
// Ensure run option is <= parallel run installed.
if ($options['run']) {
if (!$options['parallel']) {
$options['parallel'] = behat_config_manager::get_parallel_test_runs();
}
if (empty($options['parallel']) || $options['run'] > $options['parallel']) {
echo "Parallel runs can't be more then ".$options['parallel'].PHP_EOL;
exit(1);
}
$CFG->behatrunprocess = $options['run'];
}
// Run command (only one per time).
if ($options['install']) {
behat_util::install_site();
// This is only displayed once for parallel install.
if (empty($options['run'])) {
mtrace("Acceptance tests site installed");
}
} else if ($options['drop']) {
// Ensure no tests are running.
test_lock::acquire('behat');
behat_util::drop_site();
// This is only displayed once for parallel install.
if (empty($options['run'])) {
mtrace("Acceptance tests site dropped");
}
} else if ($options['enable']) {
if (!empty($options['parallel'])) {
// Save parallel site info for enable and install options.
$filepath = behat_config_manager::get_parallel_test_file_path();
if (!file_put_contents($filepath, $options['parallel'])) {
behat_error(BEHAT_EXITCODE_PERMISSIONS, 'File ' . $filepath . ' can not be created');
}
}
// Enable test mode.
behat_util::start_test_mode();
// This is only displayed once for parallel install.
if (empty($options['run'])) {
$runtestscommand = behat_command::get_behat_command(true, !empty($options['run']));
$runtestscommand .= ' --config ' . behat_config_manager::get_behat_cli_config_filepath();
mtrace("Acceptance tests environment enabled on $CFG->behat_wwwroot, to run the tests use: " . PHP_EOL .
$runtestscommand);
}
} else if ($options['disable']) {
behat_util::stop_test_mode();
// This is only displayed once for parallel install.
if (empty($options['run'])) {
mtrace("Acceptance tests environment disabled");
}
} else if ($options['diag']) {
$code = behat_util::get_behat_status();
exit($code);
} else if ($options['updatesteps']) {
if (defined('BEHAT_FEATURE_STEP_FILE') && BEHAT_FEATURE_STEP_FILE) {
$behatstepfile = BEHAT_FEATURE_STEP_FILE;
} else {
echo "BEHAT_FEATURE_STEP_FILE is not set, please ensure you set this to writable file" . PHP_EOL;
exit(1);
}
// Rewrite config file to ensure we have all the features covered.
behat_config_manager::update_config_file();
// Run behat command to get steps in feature files.
$featurestepscmd = behat_command::get_behat_command(true);
$featurestepscmd .= ' --config ' . behat_config_manager::get_behat_cli_config_filepath();
$featurestepscmd .= ' --dry-run --format=moodle_step_count';
$processes = cli_execute_parallel(array($featurestepscmd), __DIR__ . "/../../../../");
$status = print_update_step_output(array_pop($processes), $behatstepfile);
exit($status);
} else {
echo $help;
exit(1);
}
exit(0);
/**
* Print update progress as dots for updating feature file step list.
*
* @param Process $process process executing update step command.
* @param string $featurestepfile feature step file in which steps will be saved.
* @return int exitcode.
*/
function print_update_step_output($process, $featurestepfile) {
$printedlength = 0;
echo "Updating steps feature file for parallel behat runs" . PHP_EOL;
// Show progress while running command.
while ($process->isRunning()) {
usleep(10000);
$op = $process->getIncrementalOutput();
if (trim($op)) {
echo ".";
$printedlength++;
if ($printedlength > 70) {
$printedlength = 0;
echo PHP_EOL;
}
}
}
// If any error then exit.
$exitcode = $process->getExitCode();
// Output err.
if ($exitcode != 0) {
echo $process->getErrorOutput();
exit($exitcode);
}
// Extract features with step info and save it in file.
$featuresteps = $process->getOutput();
$featuresteps = explode(PHP_EOL, $featuresteps);
$realroot = realpath(__DIR__.'/../../../../').'/';
foreach ($featuresteps as $featurestep) {
if (trim($featurestep)) {
$step = explode("::", $featurestep);
$step[0] = str_replace($realroot, '', $step[0]);
$steps[$step[0]] = $step[1];
}
}
arsort($steps);
if (!@file_put_contents($featurestepfile, json_encode($steps, JSON_PRETTY_PRINT))) {
behat_error(BEHAT_EXITCODE_PERMISSIONS, 'File ' . $featurestepfile . ' can not be created');
$exitcode = -1;
}
echo PHP_EOL. "Updated step count in " . $featurestepfile . PHP_EOL;
return $exitcode;
}
+1 -1
View File
@@ -165,7 +165,7 @@ class tool_behat_renderer extends plugin_renderer_base {
// Info.
$installurl = behat_command::DOCS_URL . '#Installation';
$installlink = html_writer::tag('a', $installurl, array('href' => $installurl, 'target' => '_blank'));
$writetestsurl = behat_command::DOCS_URL . '#Writing_features';
$writetestsurl = behat_command::DOCS_URL . '#Writting_features';
$writetestslink = html_writer::tag('a', $writetestsurl, array('href' => $writetestsurl, 'target' => '_blank'));
$writestepsurl = behat_command::DOCS_URL . '#Adding_steps_definitions';
$writestepslink = html_writer::tag('a', $writestepsurl, array('href' => $writestepsurl, 'target' => '_blank'));
@@ -7,7 +7,7 @@ Feature: Page contents assertions
@javascript
Scenario: Basic contents assertions
Given I log in as "admin"
And I am on site homepage
And I am on homepage
And I expand "Users" node
And I follow "Groups"
And I press "Create group"
@@ -22,8 +22,8 @@ Feature: Page contents assertions
Then I should see "I'm the description"
And "Grouping" "select" in the "region-main" "region" should be visible
And "Group" "select" should be visible
And "Activity report" "link" in the "Administration" "block" should not be visible
And "Event monitoring rules" "link" should not be visible
And "Messaging" "link" in the "Administration" "block" should not be visible
And "Change password" "link" should not be visible
And I should see "Filter groups by"
And I should not see "Filter groupssss by"
And I should see "Group members" in the "#region-main table th.c1" "css_element"
@@ -38,7 +38,6 @@ Feature: Page contents assertions
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And I log in as "admin"
And I am on site homepage
And I follow "Course 1"
When I dock "Administration" block
Then I should not see "Question bank" in the ".block-region" "css_element"
@@ -27,7 +27,6 @@ Feature: Set up contextual data for tests
| Course 2 | COURSE2 | CAT3 |
| Course 3 | COURSE3 | 0 |
When I log in as "admin"
And I am on site homepage
Then I should see "Course 1"
And I should see "Course 2"
And I should see "Course 3"
@@ -57,7 +56,6 @@ Feature: Set up contextual data for tests
| Grouping 1 | C1 | GG1 |
| Grouping 2 | C1 | GG2 |
When I log in as "admin"
And I am on site homepage
And I follow "Course 1"
And I expand "Users" node
And I follow "Groups"
@@ -71,8 +69,8 @@ Feature: Set up contextual data for tests
Scenario: Role overrides
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| teacher1 | Teacher | 1 | teacher1@asd.com |
| student1 | Student | 1 | student1@asd.com |
And the following "categories" exist:
| name | category | idnumber |
| Cat 1 | 0 | CAT1 |
@@ -88,7 +86,6 @@ Feature: Set up contextual data for tests
| mod/forum:editanypost | Allow | student | Course | C1 |
| mod/forum:replynews | Prevent | editingteacher | Course | C1 |
When I log in as "admin"
And I am on site homepage
And I follow "Course 1"
And I expand "Users" node
And I follow "Permissions"
@@ -102,7 +99,7 @@ Feature: Set up contextual data for tests
Scenario: Add course enrolments
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| student1 | Student | 1 | student1@asd.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
@@ -120,11 +117,11 @@ Feature: Set up contextual data for tests
| Custom student | custom2 | | |
And the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | 1 | user1@example.com |
| user2 | User | 2 | user2@example.com |
| user3 | User | 3 | user3@example.com |
| user4 | User | 4 | user4@example.com |
| user5 | User | 5 | user5@example.com |
| user1 | User | 1 | user1@moodlemoodle.com |
| user2 | User | 2 | user2@moodlemoodle.com |
| user3 | User | 3 | user3@moodlemoodle.com |
| user4 | User | 4 | user4@moodlemoodle.com |
| user5 | User | 5 | user5@moodlemoodle.com |
And the following "categories" exist:
| name | category | idnumber |
| Cat 1 | 0 | CAT1 |
@@ -141,27 +138,22 @@ Feature: Set up contextual data for tests
| user3 | editingteacher | Course | C1 |
| user5 | custom2 | System | |
When I log in as "user1"
And I am on site homepage
Then I should see "Front page settings"
And I log out
And I log in as "user2"
And I am on site homepage
And I follow "Course 1"
And I should see "Turn editing on"
And I log out
And I log in as "user3"
And I am on site homepage
And I follow "Course 1"
And I should see "Turn editing on"
And I log out
And I log in as "user4"
And I am on site homepage
And I follow "Course 1"
And I should see "Turn editing on"
And I log out
And I log in as "user5"
And I should see "You are logged in as"
And I am on site homepage
And I follow "Course 1"
And I should see "You can not enrol yourself in this course."
@@ -200,7 +192,6 @@ Feature: Set up contextual data for tests
| activity | name | intro | course | idnumber | grade |
| assign | Test assignment name with scale | Test assignment description | C1 | assign1 | Test Scale 1 |
When I log in as "admin"
And I am on site homepage
And I follow "Course 1"
Then I should see "Test assignment name"
# Assignment 2.2 module type is disabled by default
@@ -238,8 +229,8 @@ Feature: Set up contextual data for tests
Scenario: Add relations between users and groups
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student1 | Student | 1 | student1@asd.com |
| student2 | Student | 2 | student2@asd.com |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
@@ -262,7 +253,6 @@ Feature: Set up contextual data for tests
| grouping | group |
| GG1 | G1 |
When I log in as "admin"
And I am on site homepage
And I follow "Course 1"
And I expand "Users" node
And I follow "Groups"
@@ -279,8 +269,8 @@ Feature: Set up contextual data for tests
| Cat 1 | 0 | CAT1 |
And the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
| student1 | Student | 1 | student1@asd.com |
| student2 | Student | 2 | student2@asd.com |
And the following "cohorts" exist:
| name | idnumber |
| System cohort A | CHSA |
@@ -322,7 +312,6 @@ Feature: Set up contextual data for tests
| fullname | course | gradecategory |
| Grade sub category 2 | C1 | Grade category 1 |
When I log in as "admin"
And I am on site homepage
And I follow "Courses"
And I follow "Course 1"
And I navigate to "Grades" node in "Course administration"
@@ -347,9 +336,8 @@ Feature: Set up contextual data for tests
| Test Grade Item 2 | C1 | Grade category 1 |
| Test Grade Item 3 | C1 | Grade sub category 2 |
When I log in as "admin"
And I am on site homepage
And I follow "Course 1"
And I navigate to "Grades" node in "Course administration"
And I follow "Grades"
And I expand "Setup" node
And I follow "Categories and items"
Then I should see "Test Grade Item 1"
@@ -378,9 +366,8 @@ Feature: Set up contextual data for tests
| name | scale |
| Test Scale 1 | Disappointing, Good, Very good, Excellent |
When I log in as "admin"
And I am on site homepage
And I follow "Course 1"
And I navigate to "Grades" node in "Course administration"
And I follow "Grades"
And I follow "Scales"
Then I should see "Test Scale 1"
And I should see "Disappointing, Good, Very good, Excellent"
@@ -398,10 +385,10 @@ Feature: Set up contextual data for tests
And the following "grade outcomes" exist:
| fullname | shortname | course | scale |
| Grade outcome 2 | OT2 | C1 | Test Scale 1 |
And the following config values are set as admin:
| enableoutcomes | 1 |
When I log in as "admin"
And I am on site homepage
And I set the following administration settings values:
| Enable outcomes | 1 |
And I follow "Home"
And I follow "Course 1"
And I follow "Outcomes"
Then I should see "Grade outcome 1" in the "#addoutcomes" "css_element"
@@ -427,12 +414,12 @@ Feature: Set up contextual data for tests
And the following "grade items" exist:
| itemname | course | outcome | gradecategory |
| Test Outcome Grade Item 1 | C1 | OT1 | Grade category 1 |
And the following config values are set as admin:
| enableoutcomes | 1 |
When I log in as "admin"
And I am on site homepage
And I set the following administration settings values:
| Enable outcomes | 1 |
And I follow "Home"
And I follow "Course 1"
And I navigate to "Grades" node in "Course administration"
And I follow "Grades"
And I expand "Setup" node
And I follow "Categories and items"
Then I should see "Test Outcome Grade Item 1"
@@ -7,7 +7,7 @@ Feature: Edit capabilities
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| teacher1 | Teacher | 1 | teacher1@asd.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
@@ -10,9 +10,9 @@ Feature: Verify that all form fields values can be get and set
| Course 1 | C1 | 0 |
And the following "users" exist:
| username | email | firstname | lastname |
| student1 | s1@example.com | Student | 1 |
| student2 | s2@example.com | Student | 2 |
| student3 | s3@example.com | Student | 3 |
| student1 | s1@asd.com | Student | 1 |
| student2 | s2@asd.com | Student | 2 |
| student3 | s3@asd.com | Student | 3 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
@@ -39,7 +39,7 @@ Feature: Verify that all form fields values can be get and set
# Select (multi-select) - We will check "I set the field...".
And I set the field "otagsadd" to "OT1, OT2, OT3, OT4, OT5"
And I press "Add official tags"
And I am on site homepage
And I am on homepage
And I follow "Course 1"
And I turn editing mode on
And I follow "Test this one"
@@ -7,14 +7,13 @@ Feature: Forms manipulation
@javascript
Scenario: Basic forms manipulation
Given I log in as "admin"
And I follow "Preferences" in the user menu
And I follow "Edit profile"
And I navigate to "Edit profile" node in "My profile settings"
When I set the field "First name" to "Field value"
And I set the field "Select a country" to "Japan"
And I set the field "Text editor" to "Plain text area"
And I set the field "Unmask" to "1"
And I expand all fieldsets
Then the field "First name" matches value "Field value"
And the "Select a country" select box should contain "Japan"
And the "Text editor" select box should contain "Plain text area"
And the field "Unmask" matches value "1"
And I set the field "Unmask" to ""
And the field "Unmask" matches value ""
@@ -26,7 +25,6 @@ Feature: Forms manipulation
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And I log in as "admin"
And I am on site homepage
And I follow "Course 1"
And I turn editing mode on
And I add a "Quiz" to section "1"
@@ -5,15 +5,13 @@ Feature: Transform steps arguments
I need to apply some transformations to the steps arguments
Background:
Given I am on site homepage
Given I am on homepage
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And I log in as "admin"
And I follow "Preferences" in the user menu
And I follow "Edit profile"
And I navigate to "Edit profile" node in "My profile settings"
@javascript
Scenario: Use nasty strings on steps arguments
When I set the field "Surname" to "$NASTYSTRING1"
And I set the field "Description" to "$NASTYSTRING2"
@@ -24,7 +22,6 @@ Feature: Transform steps arguments
And the field "Surname" matches value "$NASTYSTRING1"
And the field "City/town" matches value "$NASTYSTRING3"
@javascript
Scenario: Use nasty strings on table nodes
When I set the following fields to these values:
| Surname | $NASTYSTRING1 |
@@ -36,7 +33,6 @@ Feature: Transform steps arguments
And the field "Surname" matches value "$NASTYSTRING1"
And the field "City/town" matches value "$NASTYSTRING3"
@javascript
Scenario: Use double quotes
When I set the following fields to these values:
| First name | va"lue1 |
@@ -5,5 +5,5 @@ Feature: Set up the testing environment
I need to use the test environment instead of the regular environment
Scenario: Accessing the site
When I am on site homepage
When I am on homepage
Then I should see "Acceptance test site"
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2014110400; // Requires this Moodle version
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2014110400; // Requires this Moodle version.
$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
+2 -2
View File
@@ -25,6 +25,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100;
$plugin->requires = 2015050500;
$plugin->version = 2014111000;
$plugin->requires = 2014110400;
$plugin->component = 'tool_customlang'; // Full name of the plugin (used for diagnostics)
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2015050500; // Requires this Moodle version.
$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2014110400; // Requires this Moodle version.
$plugin->component = 'tool_dbtransfer'; // Full name of the plugin (used for diagnostics).
-122
View File
@@ -1,122 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Class with static back-end methods used by the file type tool.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_filetypes;
defined('MOODLE_INTERNAL') || die();
/**
* Class with static back-end methods used by the file type tool.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class utils {
/**
* Checks if the given file type extension is invalid.
* The added file type extension must be unique and must not begin with a dot.
*
* @param string $extension Extension of the file type to add
* @param string $oldextension Extension prior to update (empty string if adding new type)
* @return bool True if it the file type trying to add already exists
*/
public static function is_extension_invalid($extension, $oldextension = '') {
$extension = trim($extension);
if ($extension === '' || $extension[0] === '.') {
return true;
}
$mimeinfo = get_mimetypes_array();
if ($oldextension !== '') {
unset($mimeinfo[$oldextension]);
}
return array_key_exists($extension, $mimeinfo);
}
/**
* Checks if we are allowed to turn on the 'default icon' option. You can
* only have one of these for a given MIME type.
*
* @param string $mimetype MIME type
* @param string $oldextension File extension name (before any change)
*/
public static function is_defaulticon_allowed($mimetype, $oldextension = '') {
$mimeinfo = get_mimetypes_array();
if ($oldextension !== '') {
unset($mimeinfo[$oldextension]);
}
foreach ($mimeinfo as $extension => $values) {
if ($values['type'] !== $mimetype) {
continue;
}
if (!empty($values['defaulticon'])) {
return false;
}
}
return true;
}
/**
* Gets all unique file type icons from a specific path, not including
* sub-directories.
*
* Icon files such as pdf.png, pdf-24.png and pdf-36.png etc. are counted as
* the same icon type.
*
* The resultant array has both key and value set to the icon name prefix,
* such as 'pdf' => 'pdf'.
*
* @param string $path The path of the icon path
* @return array An array of unique file icons within the given path
*/
public static function get_icons_from_path($path) {
$icons = array();
if ($handle = @opendir($path)) {
while (($file = readdir($handle)) !== false) {
$matches = array();
if (preg_match('~(.+?)(?:-24|-32|-48|-64|-72|-80|-96|-128|-256)?\.(?:gif|png)$~',
$file, $matches)) {
$key = $matches[1];
$icons[$key] = $key;
}
}
closedir($handle);
}
ksort($icons);
return $icons;
}
/**
* Gets unique file type icons from pix/f folder.
*
* @return array An array of unique file type icons e.g. 'pdf' => 'pdf'
*/
public static function get_file_icons() {
global $CFG;
$path = $CFG->dirroot . '/pix/f';
return self::get_icons_from_path($path);
}
}
-60
View File
@@ -1,60 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Delete a file type with a confirmation box.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__ . '/../../../config.php');
require_once($CFG->libdir . '/adminlib.php');
admin_externalpage_setup('tool_filetypes');
$extension = required_param('extension', PARAM_ALPHANUMEXT);
$redirecturl = new \moodle_url('/admin/tool/filetypes/index.php');
if (optional_param('delete', 0, PARAM_INT)) {
require_sesskey();
// Delete the file type from the config.
core_filetypes::delete_type($extension);
redirect($redirecturl);
}
// Page settings.
$title = get_string('deletefiletypes', 'tool_filetypes');
$context = context_system::instance();
$PAGE->set_url(new \moodle_url('/admin/tool/filetypes/delete.php', array('extension' => $extension)));
$PAGE->navbar->add($title);
$PAGE->set_context($context);
$PAGE->set_pagelayout('admin');
$PAGE->set_title($SITE->fullname. ': ' . $title);
// Display the page.
echo $OUTPUT->header();
$message = get_string('delete_confirmation', 'tool_filetypes', $extension);
$deleteurl = new \moodle_url('delete.php', array('extension' => $extension, 'delete' => 1));
$yesbutton = new single_button($deleteurl, get_string('yes'));
$nobutton = new single_button($redirecturl, get_string('no'), 'get');
echo $OUTPUT->confirm($message, $yesbutton, $nobutton);
echo $OUTPUT->footer();
-111
View File
@@ -1,111 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Display the file type updating page.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__ . '/../../../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once('edit_form.php');
admin_externalpage_setup('tool_filetypes');
$oldextension = optional_param('oldextension', '', PARAM_ALPHANUMEXT);
$mform = new tool_filetypes_form('edit.php', array('oldextension' => $oldextension));
$title = get_string('addfiletypes', 'tool_filetypes');
if ($oldextension) {
// This is editing an existing filetype, load data to the form.
$mimetypes = get_mimetypes_array();
if (!array_key_exists($oldextension, $mimetypes)) {
throw new moodle_exception('error_notfound', 'tool_filetypes');
}
$typeinfo = $mimetypes[$oldextension];
$formdata = array(
'extension' => $oldextension,
'mimetype' => $typeinfo['type'],
'icon' => $typeinfo['icon'],
'oldextension' => $oldextension,
'description' => '',
'groups' => '',
'corestring' => '',
'defaulticon' => 0
);
if (!empty($typeinfo['customdescription'])) {
$formdata['description'] = $typeinfo['customdescription'];
}
if (!empty($typeinfo['groups'])) {
$formdata['groups'] = implode(', ', $typeinfo['groups']);
}
if (!empty($typeinfo['string'])) {
$formdata['corestring'] = $typeinfo['string'];
}
if (!empty($typeinfo['defaulticon'])) {
$formdata['defaulticon'] = 1;
}
$mform->set_data($formdata);
$title = get_string('editfiletypes', 'tool_filetypes');
}
$backurl = new \moodle_url('/admin/tool/filetypes/index.php');
if ($mform->is_cancelled()) {
redirect($backurl);
} else if ($data = $mform->get_data()) {
// Convert the groups value back into an array.
$data->groups = trim($data->groups);
if ($data->groups) {
$data->groups = preg_split('~,\s*~', $data->groups);
} else {
$data->groups = array();
}
if (empty($data->defaulticon)) {
$data->defaulticon = 0;
}
if (empty($data->corestring)) {
$data->corestring = '';
}
if (empty($data->description)) {
$data->description = '';
}
if ($data->oldextension) {
// Update an existing file type.
core_filetypes::update_type($data->oldextension, $data->extension, $data->mimetype, $data->icon,
$data->groups, $data->corestring, $data->description, (bool)$data->defaulticon);
} else {
// Add a new file type entry.
core_filetypes::add_type($data->extension, $data->mimetype, $data->icon,
$data->groups, $data->corestring, $data->description, (bool)$data->defaulticon);
}
redirect($backurl);
}
// Page settings.
$context = context_system::instance();
$PAGE->set_url(new \moodle_url('/admin/tool/filetypes/edit.php', array('oldextension' => $oldextension)));
$PAGE->navbar->add($oldextension ? s($oldextension) : $title);
$PAGE->set_context($context);
$PAGE->set_pagelayout('admin');
$PAGE->set_title($SITE->fullname. ': ' . $title);
// Display the page.
echo $OUTPUT->header();
$mform->display();
echo $OUTPUT->footer();
-152
View File
@@ -1,152 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Customised file types editing form.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once($CFG->dirroot . '/lib/formslib.php');
/**
* Form for adding a new custom file type or updating an existing custom file type.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_filetypes_form extends moodleform {
public function definition() {
global $CFG;
$mform = $this->_form;
$oldextension = $this->_customdata['oldextension'];
$mform->addElement('text', 'extension', get_string('extension', 'tool_filetypes'));
$mform->setType('extension', PARAM_ALPHANUMEXT);
$mform->addRule('extension', null, 'required', null, 'client');
$mform->addHelpButton('extension', 'extension', 'tool_filetypes');
$mform->addElement('text', 'mimetype', get_string('mimetype', 'tool_filetypes'));
$mform->setType('mimetype', PARAM_RAW);
$mform->addRule('mimetype', null, 'required', null, 'client');
$mform->addHelpButton('mimetype', 'mimetype', 'tool_filetypes');
$fileicons = \tool_filetypes\utils::get_file_icons();
$mform->addElement('select', 'icon',
get_string('icon', 'tool_filetypes'), $fileicons);
$mform->addHelpButton('icon', 'icon', 'tool_filetypes');
$mform->addElement('text', 'groups', get_string('groups', 'tool_filetypes'));
$mform->setType('groups', PARAM_RAW);
$mform->addHelpButton('groups', 'groups', 'tool_filetypes');
$mform->addElement('select', 'descriptiontype', get_string('descriptiontype', 'tool_filetypes'),
array('' => get_string('descriptiontype_default', 'tool_filetypes'),
'custom' => get_string('descriptiontype_custom', 'tool_filetypes'),
'lang' => get_string('descriptiontype_lang', 'tool_filetypes')));
$mform->addElement('text', 'description', get_string('description', 'tool_filetypes'));
$mform->setType('description', PARAM_TEXT);
$mform->addHelpButton('description', 'description', 'tool_filetypes');
$mform->disabledIf('description', 'descriptiontype', 'ne', 'custom');
$mform->addElement('text', 'corestring', get_string('corestring', 'tool_filetypes'));
$mform->setType('corestring', PARAM_ALPHANUMEXT);
$mform->addHelpButton('corestring', 'corestring', 'tool_filetypes');
$mform->disabledIf('corestring', 'descriptiontype', 'ne', 'lang');
$mform->addElement('checkbox', 'defaulticon', get_string('defaulticon', 'tool_filetypes'));
$mform->addHelpButton('defaulticon', 'defaulticon', 'tool_filetypes');
$mform->addElement('hidden', 'oldextension', $oldextension);
$mform->setType('oldextension', PARAM_RAW);
$this->add_action_buttons(true, get_string('savechanges'));
}
public function set_data($data) {
// Set up the description type.
if (!empty($data['corestring'])) {
$data['descriptiontype'] = 'lang';
} else if (!empty($data['description'])) {
$data['descriptiontype'] = 'custom';
} else {
$data['descriptiontype'] = '';
}
// Call parent.
parent::set_data($data);
}
public function get_data() {
$data = parent::get_data();
// Update the data to handle the descriptiontype dropdown. (The type
// is not explicitly stored, we just set or unset relevant fields.)
if ($data) {
switch ($data->descriptiontype) {
case 'lang' :
unset($data->description);
break;
case 'custom' :
unset($data->corestring);
break;
default:
unset($data->description);
unset($data->corestring);
break;
}
unset($data->descriptiontype);
}
return $data;
}
public function validation($data, $files) {
$errors = parent::validation($data, $files);
// Check the extension isn't already in use.
$oldextension = $data['oldextension'];
$extension = trim($data['extension']);
if (\tool_filetypes\utils::is_extension_invalid($extension, $oldextension)) {
$errors['extension'] = get_string('error_extension', 'tool_filetypes', $extension);
}
// Check the 'default icon' setting doesn't conflict with an existing one.
if (!empty($data['defaulticon']) && !\tool_filetypes\utils::is_defaulticon_allowed(
$data['mimetype'], $oldextension)) {
$errors['defaulticon'] = get_string('error_defaulticon', 'tool_filetypes', $extension);
}
// If you choose 'lang' or 'custom' descriptiontype, you must fill something in the field.
switch ($data['descriptiontype']) {
case 'lang' :
if (!trim($data['corestring'])) {
$errors['corestring'] = get_string('required');
}
break;
case 'custom' :
if (!trim($data['description'])) {
$errors['description'] = get_string('required');
}
break;
}
return $errors;
}
}
-48
View File
@@ -1,48 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Display the custom file type settings page.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__ . '/../../../config.php');
require_once($CFG->libdir . '/adminlib.php');
admin_externalpage_setup('tool_filetypes');
// Page settings.
$title = get_string('pluginname', 'tool_filetypes');
$context = context_system::instance();
$PAGE->set_url(new \moodle_url('/admin/tool/filetypes/index.php'));
$PAGE->set_context($context);
$PAGE->set_pagelayout('admin');
$PAGE->set_title($SITE->fullname. ': ' . $title);
$renderer = $PAGE->get_renderer('tool_filetypes');
// Is it restricted because set in config.php?
$restricted = array_key_exists('customfiletypes', $CFG->config_php_settings);
// Display the page.
echo $renderer->header();
echo $renderer->edit_table(get_mimetypes_array(), core_filetypes::get_deleted_types(),
$restricted);
echo $renderer->footer();
@@ -1,69 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for custom file types.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['addfiletypes'] = 'Add a new file type';
$string['corestring'] = 'Alternative language string';
$string['corestring_help'] = 'This setting can be used to select a different language string from the core mimetypes.php language file. Generally it should be left blank. For custom types, use the description field.';
$string['defaulticon'] = 'Default icon for MIME type';
$string['defaulticon_help'] = 'If there are multiple file extensions with the same MIME type, select this option for one of the extensions so that its icon will be used when determining an icon from the MIME type.';
$string['delete_confirmation'] = 'Are you absolutely sure you want to remove <strong>.{$a}</strong>?';
$string['deletea'] = 'Delete {$a}';
$string['deletefiletypes'] = 'Delete a file type';
$string['description'] = 'Custom description';
$string['description_help'] = 'Simple file type description, e.g. &lsquo;Kindle ebook&rsquo;. If your site supports multiple languages and uses the multi-language filter, you can enter multi-language tags in this field to supply a description in different languages.';
$string['descriptiontype'] = 'Description type';
$string['descriptiontype_help'] = 'There are three possible ways to specify a description.
* Default behaviour uses the MIME type. If there is a language string in mimetypes.php corresponding to that MIME type, it will be used; otherwise the MIME type itself will be displayed to users.
* You can specify a custom description on this form.
* You can specify the name of a languge string in mimetypes.php to use instead of the MIME type.';
$string['descriptiontype_default'] = 'Default (MIME type or corresponding language string if available)';
$string['descriptiontype_custom'] = 'Custom description specified in this form';
$string['descriptiontype_lang'] = 'Alternative language string (from mimetypes.php)';
$string['displaydescription'] = 'Description';
$string['editfiletypes'] = 'Edit an existing file type';
$string['emptylist'] = 'There are no file types defined.';
$string['error_addentry'] = 'The file type extension, description, MIME type, and icon must not contain line feed and semicolon characters.';
$string['error_defaulticon'] = 'Another file extension with the same MIME type is already marked as the default icon.';
$string['error_extension'] = 'The file type extension <strong>{$a}</strong> already exists or is invalid. File extensions must be unique and must not contain special characters.';
$string['error_notfound'] = 'The file type with extension {$a} cannot be found.';
$string['extension'] = 'Extension';
$string['extension_help'] = 'File name extension without the dot, e.g. &lsquo;mobi&rsquo;';
$string['groups'] = 'Type groups';
$string['groups_help'] = 'Optional list of file type groups that this type belongs to. These are generic categories such as &lsquo;document&rsquo; and &lsquo;image&rsquo;.';
$string['icon'] = 'File icon';
$string['icon_help'] = 'Icon filename.
The list of icons is taken from the /pix/f directory inside your Moodle installation. You can add custom icons to this folder if required.';
$string['mimetype'] = 'MIME type';
$string['mimetype_help'] = 'MIME type associated with this file type, e.g. &lsquo;application/x-mobipocket-ebook&rsquo;';
$string['pluginname'] = 'File types';
$string['revert'] = 'Restore {$a} to Moodle defaults';
$string['revert_confirmation'] = 'Are you sure you want to restore <strong>.{$a}</strong> to Moodle defaults, discarding your changes?';
$string['revertfiletype'] = 'Restore a file type';
$string['source'] = 'Type';
$string['source_custom'] = 'Custom';
$string['source_deleted'] = 'Deleted';
$string['source_modified'] = 'Modified';
$string['source_standard'] = 'Standard';
-179
View File
@@ -1,179 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Renderer.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Class containing the renderer functions for displaying file types.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_filetypes_renderer extends plugin_renderer_base {
/**
* Renderer for displaying the file type edit table.
*
* @param array $filetypes An array of file type objects (from get_mimetypes_array)
* @param array $deleted An array of deleted file types
* @param bool $restricted If true, cannot be edited because set in config.php.
* @return string HTML code
*/
public function edit_table(array $filetypes, array $deleted, $restricted) {
// Get combined array of all types, with deleted marker.
$combined = array_merge($filetypes, $deleted);
foreach ($deleted as $ext => $value) {
$combined[$ext]['deleted'] = true;
}
ksort($combined);
$out = $this->heading(get_string('pluginname', 'tool_filetypes'));
if ($restricted) {
$out .= html_writer::div(
html_writer::div(get_string('configoverride', 'admin'), 'form-overridden'),
'', array('id' => 'adminsettings'));
}
if (count($combined) > 1) {
// Display the file type table if any file types exist (other than 'xxx').
$table = new html_table();
$headings = new html_table_row();
$headings->cells = array();
$headings->cells[] = new html_table_cell(get_string('extension', 'tool_filetypes'));
if (!$restricted) {
$headings->cells[] =
new html_table_cell(html_writer::span(get_string('edit'), 'accesshide'));
}
$headings->cells[] = new html_table_cell(get_string('source', 'tool_filetypes'));
$headings->cells[] = new html_table_cell(get_string('mimetype', 'tool_filetypes'));
$headings->cells[] = new html_table_cell(get_string('groups', 'tool_filetypes'));
$headings->cells[] = new html_table_cell(get_string('displaydescription', 'tool_filetypes'));
foreach ($headings->cells as $cell) {
$cell->header = true;
}
$table->data = array($headings);
foreach ($combined as $extension => $filetype) {
if ($extension === 'xxx') {
continue;
}
$row = new html_table_row();
$row->cells = array();
// First cell has icon and extension.
$icon = $this->pix_icon('f/' . $filetype['icon'], '');
$row->cells[] = new html_table_cell($icon . ' ' . html_writer::span(s($extension)));
// Reset URL and button if needed.
$reverturl = new \moodle_url('/admin/tool/filetypes/revert.php',
array('extension' => $extension));
$revertbutton = html_writer::link($reverturl, $this->pix_icon('t/restore',
get_string('revert', 'tool_filetypes', s($extension))));
if ($restricted) {
$revertbutton = '';
}
// Rest is different for deleted items.
if (!empty($filetype['deleted'])) {
// Show deleted standard types differently.
if (!$restricted) {
$row->cells[] = new html_table_cell('');
}
$source = new html_table_cell(get_string('source_deleted', 'tool_filetypes') .
' ' . $revertbutton);
$source->attributes = array('class' => 'nonstandard');
$row->cells[] = $source;
// Other cells are blank.
$row->cells[] = new html_table_cell('');
$row->cells[] = new html_table_cell('');
$row->cells[] = new html_table_cell('');
$row->attributes = array('class' => 'deleted');
} else {
if (!$restricted) {
// Edit icons. For accessibility, the name of these links should
// be different for each row, so we have to include the extension.
$editurl = new \moodle_url('/admin/tool/filetypes/edit.php',
array('oldextension' => $extension));
$editbutton = html_writer::link($editurl, $this->pix_icon('t/edit',
get_string('edita', '', s($extension))));
$deleteurl = new \moodle_url('/admin/tool/filetypes/delete.php',
array('extension' => $extension));
$deletebutton = html_writer::link($deleteurl, $this->pix_icon('t/delete',
get_string('deletea', 'tool_filetypes', s($extension))));
$row->cells[] = new html_table_cell($editbutton . '&nbsp;' . $deletebutton);
}
// Source.
$sourcestring = 'source_';
if (!empty($filetype['custom'])) {
$sourcestring .= 'custom';
} else if (!empty($filetype['modified'])) {
$sourcestring .= 'modified';
} else {
$sourcestring .= 'standard';
}
$source = new html_table_cell(get_string($sourcestring, 'tool_filetypes') .
($sourcestring === 'source_modified' ? ' ' . $revertbutton : ''));
if ($sourcestring !== 'source_standard') {
$source->attributes = array('class' => 'nonstandard');
}
$row->cells[] = $source;
// MIME type.
$mimetype = html_writer::div(s($filetype['type']), 'mimetype');
if (!empty($filetype['defaulticon'])) {
// Include the 'default for MIME type' info in the MIME type cell.
$mimetype .= html_writer::div(html_writer::tag('i',
get_string('defaulticon', 'tool_filetypes')));
}
$row->cells[] = new html_table_cell($mimetype);
// Groups.
$groups = !empty($filetype['groups']) ? implode(', ', $filetype['groups']) : '';
$row->cells[] = new html_table_cell(s($groups));
// Description.
$description = get_mimetype_description(array('filename' => 'a.' . $extension));
// Don't show the description if it's just a copy of the MIME type,
// it makes the table ugly with the long duplicate text; leave blank instead.
if ($description === $filetype['type']) {
$description = '';
}
$row->cells[] = new html_table_cell($description);
}
$table->data[] = $row;
}
$out .= html_writer::table($table);
} else {
$out .= html_writer::tag('div', get_string('emptylist', 'tool_filetypes'));
}
// Displaying the 'Add' button.
if (!$restricted) {
$out .= $this->single_button(new moodle_url('/admin/tool/filetypes/edit.php',
array('name' => 'add')), get_string('addfiletypes', 'tool_filetypes'), 'get');
}
return $out;
}
}
-60
View File
@@ -1,60 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Resets a file type to the default Moodle values.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__ . '/../../../config.php');
require_once($CFG->libdir . '/adminlib.php');
admin_externalpage_setup('tool_filetypes');
$extension = required_param('extension', PARAM_RAW);
$redirecturl = new \moodle_url('/admin/tool/filetypes/index.php');
if (optional_param('revert', 0, PARAM_INT)) {
require_sesskey();
// Reset the file type in config.
core_filetypes::revert_type_to_default($extension);
redirect($redirecturl);
}
// Page settings.
$title = get_string('revertfiletype', 'tool_filetypes');
$context = context_system::instance();
$PAGE->set_url(new \moodle_url('/admin/tool/filetypes/revert.php', array('extension' => $extension)));
$PAGE->navbar->add($title);
$PAGE->set_context($context);
$PAGE->set_pagelayout('admin');
$PAGE->set_title($SITE->fullname. ': ' . $title);
// Display the page.
echo $OUTPUT->header();
$message = get_string('revert_confirmation', 'tool_filetypes', $extension);
$reverturl = new \moodle_url('revert.php', array('extension' => $extension, 'revert' => 1));
$yesbutton = new single_button($reverturl, get_string('yes'));
$nobutton = new single_button($redirecturl, get_string('no'), 'get');
echo $OUTPUT->confirm($message, $yesbutton, $nobutton);
echo $OUTPUT->footer();
-31
View File
@@ -1,31 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Configure the setting page of the custom file type as an external page.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
if ($hassiteconfig) {
$ADMIN->add('server', new admin_externalpage('tool_filetypes',
new lang_string('pluginname', 'tool_filetypes'),
$CFG->wwwroot . '/admin/tool/filetypes/index.php'));
}
-32
View File
@@ -1,32 +0,0 @@
/**
* Styles for admin tool page.
*/
/* Fix bad default table wrap (caused by the long mimetype field). */
.path-admin-tool-filetypes .generaltable .c0,
.path-admin-tool-filetypes .generaltable .c1,
.path-admin-tool-filetypes .generaltable .c2,
.path-admin-tool-filetypes .generaltable th {
white-space: nowrap;
}
/* Formatting for deleted lines. */
.path-admin-tool-filetypes .generaltable .deleted .c0 img {
opacity: 0.2;
}
.path-admin-tool-filetypes .generaltable .deleted .c0 span {
text-decoration: line-through;
}
/* Custom types show bold */
.path-admin-tool-filetypes .generaltable .nonstandard {
font-weight: bold;
}
/* Spacing around the 'Defined in config.php' stripe */
.path-admin-tool-filetypes .form-overridden {
display: inline-block;
margin-bottom: 1em;
padding: 4px 6px;
}
@@ -1,136 +0,0 @@
@tool @tool_filetypes
Feature: Add customised file types
In order to support a file mime type which doesn't exist in Moodle
As an administrator
I need to add a new customised file type
Scenario: Add a new file type
Given I log in as "admin"
And I navigate to "File types" node in "Site administration > Server"
And I press "Add"
# Try setting all the form fields, not just the optional ones.
And I set the following fields to these values:
| Extension | frog |
| MIME type | application/x-frog |
| File icon | archive |
| Type groups | document |
| Description type | Custom description specified in this form |
| Custom description | Froggy file |
| Default icon for MIME type | 1 |
When I press "Save changes"
Then I should see "Froggy file" in the "application/x-frog" "table_row"
And I should see "document" in the "application/x-frog" "table_row"
And I should see "frog" in the "application/x-frog" "table_row"
And "//img[contains(@src, 'archive')]" "xpath_element" should exist in the "application/x-frog" "table_row"
Scenario: Update an existing file type
Given I log in as "admin"
And I navigate to "File types" node in "Site administration > Server"
When I click on "Edit 7z" "link"
And I set the following fields to these values:
| Extension | doc |
And I press "Save changes"
Then I should see "File extensions must be unique"
And I set the following fields to these values:
| Extension | frog |
And I press "Save changes"
And I should see "frog" in the "application/x-7z-compressed" "table_row"
Scenario: Change the text option (was buggy)
Given I log in as "admin"
And I navigate to "File types" node in "Site administration > Server"
When I click on "Edit 7z" "link"
And I set the following fields to these values:
| Description type | Custom description specified in this form |
| Custom description | New description for 7z |
And I press "Save changes"
Then I should see "New description" in the "application/x-7z-compressed" "table_row"
And I click on "Edit 7z" "link"
And I set the field "Description type" to "Default"
And I press "Save changes"
And I should not see "New description" in the "application/x-7z-compressed" "table_row"
Scenario: Try to select a text option without entering a value.
Given I log in as "admin"
And I navigate to "File types" node in "Site administration > Server"
When I click on "Edit dmg" "link"
And I set the field "Description type" to "Custom description"
And I press "Save changes"
Then I should see "Required"
And I set the field "Description type" to "Alternative language string"
And I press "Save changes"
And I should see "Required"
And I set the field "Description type" to "Default"
And I press "Save changes"
# Check we're back on the main page now.
And "dmg" "table_row" should exist
Scenario: Delete an existing file type
Given I log in as "admin"
And I navigate to "File types" node in "Site administration > Server"
When I click on "Delete 7z" "link"
Then I should see "Are you absolutely sure you want to remove .7z?"
And I press "Yes"
And I should see "Deleted" in the "7z" "table_row"
Scenario: Delete a custom file type
Given I log in as "admin"
And I navigate to "File types" node in "Site administration > Server"
And I press "Add"
And I set the following fields to these values:
| Extension | frog |
| MIME type | application/x-frog |
And I press "Save changes"
When I click on "Delete frog" "link"
And I press "Yes"
Then I should not see "frog"
Scenario: Revert changes to deleted file type
Given I log in as "admin"
And I navigate to "File types" node in "Site administration > Server"
When I click on "Delete 7z" "link"
And I press "Yes"
And I follow "Restore 7z to Moodle defaults"
And I press "Yes"
Then I should not see "Deleted" in the "7z" "table_row"
Scenario: Revert changes to updated file type
Given I log in as "admin"
And I navigate to "File types" node in "Site administration > Server"
And I click on "Edit 7z" "link"
And I set the following fields to these values:
| File icon | document |
And I press "Save changes"
When I follow "Restore 7z to Moodle defaults"
And I press "Yes"
Then "//img[contains(@src, 'archive')]" "xpath_element" should exist in the "7z" "table_row"
@javascript @_file_upload
Scenario: Create a resource activity which contains a customised file type
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And I log in as "admin"
And I navigate to "File types" node in "Site administration > Server"
And I press "Add"
And I set the following fields to these values:
| Extension | frog |
| MIME type | application/x-frog |
| File icon | archive |
| Description type | Custom description specified in this form |
| Custom description | Froggy file |
And I press "Save changes"
# Create a resource activity and add it to a course
And I am on site homepage
And I follow "Course 1"
And I turn editing mode on
When I add a "File" to section "1"
And I set the following fields to these values:
| Name | An example of customised file type |
| Description | File description |
And I upload "admin/tool/filetypes/tests/fixtures/test.frog" file to "Select files" filemanager
And I expand all fieldsets
And I set the field "Show type" to "1"
And I press "Save and return to course"
Then I should see "Froggy file"
And the "src" attribute of ".modtype_resource a img" "css_element" should contain "archive"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 B

-1
View File
@@ -1 +0,0 @@
This is not a real file format.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 B

@@ -1,86 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the custom file types.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
use tool_filetypes\utils;
/**
* Unit tests for the custom file types.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_filetypes_test extends advanced_testcase {
/**
* Tests is_extension_invalid() function.
*/
public function test_is_extension_invalid() {
// The pdf file extension already exists in default moodle minetypes.
$this->assertTrue(utils::is_extension_invalid('pdf'));
// The frog extension does not.
$this->assertFalse(utils::is_extension_invalid('frog'));
// However you could use the pdf extension when editing the pdf extension.
$this->assertFalse(utils::is_extension_invalid('pdf', 'pdf'));
// Blank extension is invalid.
$this->assertTrue(utils::is_extension_invalid(''));
// Extensions with dot are invalid.
$this->assertTrue(utils::is_extension_invalid('.frog'));
}
/**
* Tests is_defaulticon_allowed() function.
*/
public function test_is_defaulticon_allowed() {
// You ARE allowed to set a default icon for a MIME type that hasn't
// been used yet.
$this->assertTrue(utils::is_defaulticon_allowed('application/x-frog'));
// You AREN'T allowed to set default icon for text/plain as there is
// already a type that has that set.
$this->assertFalse(utils::is_defaulticon_allowed('text/plain'));
// But you ARE still allowed to set it when actually editing txt, which
// is the default.
$this->assertTrue(utils::is_defaulticon_allowed('text/plain', 'txt'));
}
/**
* Tests get_icons_from_path() function.
*/
public function test_get_icons_from_path() {
// Get icons from the fixtures folder.
$icons = utils::get_icons_from_path(__DIR__ . '/fixtures');
// The icons are returned alphabetically and with keys === values.
// For the icon with numbers after the name, only the base name is
// returned and only one of it.
$this->assertEquals(array('frog' => 'frog', 'zombie' => 'zombie'), $icons);
}
}
-29
View File
@@ -1,29 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Version details.
*
* @package tool_filetypes
* @copyright 2014 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100;
$plugin->requires = 2015050500;
$plugin->component = 'tool_filetypes';
@@ -83,21 +83,6 @@ class tool_generator_course_backend extends tool_generator_backend {
*/
private $shortname;
/**
* @var string Course fullname.
*/
private $fullname = "";
/**
* @var string Course summary.
*/
private $summary = "";
/**
* @var string Course summary format, defaults to FORMAT_HTML.
*/
private $summaryformat = FORMAT_HTML;
/**
* @var testing_data_generator Data generator
*/
@@ -122,38 +107,11 @@ class tool_generator_course_backend extends tool_generator_backend {
* @param int|bool $filesizelimit The max number of bytes for a generated file
* @param bool $progress True if progress information should be displayed
*/
public function __construct(
$shortname,
$size,
$fixeddataset = false,
$filesizelimit = false,
$progress = true,
$fullname = null,
$summary = null,
$summaryformat = FORMAT_HTML) {
public function __construct($shortname, $size, $fixeddataset = false, $filesizelimit = false, $progress = true) {
// Set parameters.
$this->shortname = $shortname;
// We can't allow fullname to be set to an empty string.
if (empty($fullname)) {
$this->fullname = get_string(
'fullname',
'tool_generator',
array(
'size' => get_string('shortsize_' . $size, 'tool_generator')
)
);
} else {
$this->fullname = $fullname;
}
// Summary, on the other hand, should be empty-able.
if (!is_null($summary)) {
$this->summary = $summary;
$this->summaryformat = $summaryformat;
}
parent::__construct($size, $fixeddataset, $filesizelimit, $progress);
}
@@ -250,16 +208,10 @@ class tool_generator_course_backend extends tool_generator_backend {
*/
private function create_course() {
$this->log('createcourse', $this->shortname);
$courserecord = array(
'shortname' => $this->shortname,
'fullname' => $this->fullname,
'numsections' => self::$paramsections[$this->size]
);
if (strlen($this->summary) > 0) {
$courserecord['summary'] = $this->summary;
$courserecord['summary_format'] = $this->summaryformat;
}
$courserecord = array('shortname' => $this->shortname,
'fullname' => get_string('fullname', 'tool_generator',
array('size' => get_string('shortsize_' . $this->size, 'tool_generator'))),
'numsections' => self::$paramsections[$this->size]);
return $this->generator->create_course($courserecord, array('createsections' => true));
}
@@ -356,7 +308,8 @@ class tool_generator_course_backend extends tool_generator_backend {
$username = 'tool_generator_' . $textnumber;
// Create user account.
$record = array('username' => $username, 'idnumber' => $number);
$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)) {
@@ -51,12 +51,6 @@ class tool_generator_make_course_form extends moodleform {
$mform->addRule('shortname', get_string('missingshortname'), 'required', null, 'client');
$mform->setType('shortname', PARAM_TEXT);
$mform->addElement('text', 'fullname', get_string('fullnamecourse'));
$mform->setType('fullname', PARAM_TEXT);
$mform->addElement('editor', 'summary', get_string('coursesummary'));
$mform->setType('summary', PARAM_RAW);
$mform->addElement('submit', 'submit', get_string('createcourse', 'tool_generator'));
}
+1 -16
View File
@@ -33,8 +33,6 @@ list($options, $unrecognized) = cli_get_params(
array(
'help' => false,
'shortname' => false,
'fullname' => false,
'summary' => false,
'size' => false,
'fixeddataset' => false,
'filesizelimit' => false,
@@ -56,8 +54,6 @@ level.
Options:
--shortname Shortname of course to create (required)
--fullname Fullname of course to create (optional)
--summary Course summary, in double quotes (optional)
--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
@@ -80,8 +76,6 @@ if (empty($options['bypasscheck']) && !debugging('', DEBUG_DEVELOPER)) {
// Get options.
$shortname = $options['shortname'];
$fullname = $options['fullname'];
$summary = $options['summary'];
$sizename = $options['size'];
$fixeddataset = $options['fixeddataset'];
$filesizelimit = $options['filesizelimit'];
@@ -102,14 +96,5 @@ if ($error = tool_generator_course_backend::check_shortname_available($shortname
\core\session\manager::set_user(get_admin());
// Do backend code to generate course.
$backend = new tool_generator_course_backend(
$shortname,
$size,
$fixeddataset,
$filesizelimit,
empty($options['quiet']),
$fullname,
$summary,
FORMAT_HTML
);
$backend = new tool_generator_course_backend($shortname, $size, $fixeddataset, $filesizelimit, empty($options['quiet']));
$id = $backend->make();
@@ -62,6 +62,7 @@ $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';
+1 -10
View File
@@ -54,16 +54,7 @@ $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'));
$backend = new tool_generator_course_backend(
$data->shortname,
$data->size,
false,
false,
true,
$data->fullname,
$data->summary['text'],
$data->summary['format']
);
$backend = new tool_generator_course_backend($data->shortname, $data->size);
$id = $backend->make();
echo html_writer::div(
@@ -34,20 +34,8 @@ class tool_generator_maketestcourse_testcase extends advanced_testcase {
$this->resetAfterTest();
$this->setAdminUser();
$expectedshortname = 'TOOL_MAKELARGECOURSE_XS';
$expectedfullname = 'Ridiculous fullname';
$expectedsummary = 'who even knows what this is about';
// Create the XS course.
$backend = new tool_generator_course_backend(
$expectedshortname,
0,
false,
false,
false,
$expectedfullname,
$expectedsummary
);
$backend = new tool_generator_course_backend('TOOL_MAKELARGECOURSE_XS', 0, false, false, false);
$courseid = $backend->make();
// Get course details.
@@ -55,13 +43,6 @@ class tool_generator_maketestcourse_testcase extends advanced_testcase {
$context = context_course::instance($courseid);
$modinfo = get_fast_modinfo($course);
// Check course names.
$this->assertEquals($expectedshortname, $course->shortname);
$this->assertEquals($expectedfullname, $course->fullname);
// Check course summary.
$this->assertEquals($expectedsummary, $course->summary);
// Check sections (just section 0 plus one other).
$this->assertEquals(2, count($modinfo->get_section_info_all()));
@@ -155,7 +136,7 @@ class tool_generator_maketestcourse_testcase extends advanced_testcase {
$lastusernumber = 0;
$discussionstarters = array();
foreach ($discussions as $discussion) {
$usernumber = core_user::get_user($discussion->userid, 'id, idnumber')->idnumber;
$usernumber = intval($discussion->lastname);
// Checks that the users are odd numbers.
$this->assertEquals(1, $usernumber % 2);
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100;
$plugin->requires = 2015050500;
$plugin->version = 2014111000;
$plugin->requires = 2014110400;
$plugin->component = 'tool_generator';
+46 -120
View File
@@ -28,7 +28,6 @@
$extraws = ob_get_clean();
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/health/locallib.php');
admin_externalpage_setup('toolhealth');
@@ -604,10 +603,34 @@ class problem_000017 extends problem_base {
$categories = $DB->get_records('question_categories', array(), 'id');
// Look for missing parents.
$missingparent = tool_health_category_find_missing_parents($categories);
$missingparent = array();
foreach ($categories as $category) {
if ($category->parent != 0 && !array_key_exists($category->parent, $categories)) {
$missingparent[$category->id] = $category;
}
}
// Look for loops.
$loops = tool_health_category_find_loops($categories);
$loops = array();
while (!empty($categories)) {
$current = array_pop($categories);
$thisloop = array($current->id => $current);
while (true) {
if (isset($thisloop[$current->parent])) {
// Loop detected
$loops[$current->id] = $thisloop;
break;
} else if (!isset($categories[$current->parent])) {
// Got to the top level, or a category we already know is OK.
break;
} else {
// Continue following the path.
$current = $categories[$current->parent];
$thisloop[$current->id] = $current;
unset($categories[$current->id]);
}
}
}
$answer = array($missingparent, $loops);
}
@@ -628,19 +651,29 @@ class problem_000017 extends problem_base {
' structures by the question_categories.parent field. Sometimes ' .
' this tree structure gets messed up.</p>';
$description .= tool_health_category_list_missing_parents($missingparent);
$description .= tool_health_category_list_loops($loops);
if (!empty($missingparent)) {
$description .= '<p>The following categories are missing their parents:</p><ul>';
foreach ($missingparent as $cat) {
$description .= "<li>Category $cat->id: " . s($cat->name) . "</li>\n";
}
$description .= "</ul>\n";
}
if (!empty($loops)) {
$description .= '<p>The following categories form a loop of parents:</p><ul>';
foreach ($loops as $loop) {
$description .= "<li><ul>\n";
foreach ($loop as $cat) {
$description .= "<li>Category $cat->id: " . s($cat->name) . " has parent $cat->parent</li>\n";
}
$description .= "</ul></li>\n";
}
$description .= "</ul>\n";
}
return $description;
}
/**
* Outputs resolutions to problems outlined in MDL-34684 with items having themselves as parent
*
* @link https://tracker.moodle.org/browse/MDL-34684
* @return string Formatted html to be output to the browser with instructions and sql statements to run
*/
public function solution() {
function solution() {
global $CFG;
list($missingparent, $loops) = $this->find_problems();
@@ -663,113 +696,6 @@ class problem_000017 extends problem_base {
}
}
/**
* Check course categories tree structure for problems.
*
* @copyright 2013 Marko Vidberg
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class problem_000018 extends problem_base {
/**
* Generate title for this problem.
*
* @return string Title of problem.
*/
public function title() {
return 'Course categories tree structure';
}
/**
* Search for problems in the course categories.
*
* @uses $DB
* @return array List of categories that contain missing parents or loops.
*/
public function find_problems() {
global $DB;
static $answer = null;
if (is_null($answer)) {
$categories = $DB->get_records('course_categories', array(), 'id');
// Look for missing parents.
$missingparent = tool_health_category_find_missing_parents($categories);
// Look for loops.
$loops = tool_health_category_find_loops($categories);
$answer = array($missingparent, $loops);
}
return $answer;
}
/**
* Check if the problem exists.
*
* @return boolean True if either missing parents or loops found
*/
public function exists() {
list($missingparent, $loops) = $this->find_problems();
return !empty($missingparent) || !empty($loops);
}
/**
* Set problem severity.
*
* @return constant Problem severity.
*/
public function severity() {
return SEVERITY_SIGNIFICANT;
}
/**
* Generate problem description.
*
* @return string HTML containing details of the problem.
*/
public function description() {
list($missingparent, $loops) = $this->find_problems();
$description = '<p>The course categories should be arranged into tree ' .
' structures by the course_categories.parent field. Sometimes ' .
' this tree structure gets messed up.</p>';
$description .= tool_health_category_list_missing_parents($missingparent);
$description .= tool_health_category_list_loops($loops);
return $description;
}
/**
* Generate solution text.
*
* @uses $CFG
* @return string HTML containing the suggested solution.
*/
public function solution() {
global $CFG;
list($missingparent, $loops) = $this->find_problems();
$solution = '<p>Consider executing the following SQL queries. These fix ' .
'the problem by moving some categories to the top level.</p>';
if (!empty($missingparent)) {
$solution .= "<pre>UPDATE " . $CFG->prefix . "course_categories\n" .
" SET parent = 0, depth = 1, path = CONCAT('/', id)\n" .
" WHERE id IN (" . implode(',', array_keys($missingparent)) . ");</pre>\n";
}
if (!empty($loops)) {
$solution .= "<pre>UPDATE " . $CFG->prefix . "course_categories\n" .
" SET parent = 0, depth = 1, path = CONCAT('/', id)\n" .
" WHERE id IN (" . implode(',', array_keys($loops)) . ");</pre>\n";
}
return $solution;
}
}
class problem_00000x extends problem_base {
function title() {
return '';
-128
View File
@@ -1,128 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Functions used by the health tool.
*
* @package tool_health
* @copyright 2013 Marko Vidberg
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Given a list of categories, this function searches for ones
* that have a missing parent category.
*
* @param array $categories List of categories.
* @return array List of categories with missing parents.
*/
function tool_health_category_find_missing_parents($categories) {
$missingparent = array();
foreach ($categories as $category) {
if ($category->parent != 0 && !array_key_exists($category->parent, $categories)) {
$missingparent[$category->id] = $category;
}
}
return $missingparent;
}
/**
* Generates a list of categories with missing parents.
*
* @param array $missingparent List of categories with missing parents.
* @return string Bullet point list of categories with missing parents.
*/
function tool_health_category_list_missing_parents($missingparent) {
$description = '';
if (!empty($missingparent)) {
$description .= '<p>The following categories are missing their parents:</p><ul>';
foreach ($missingparent as $cat) {
$description .= "<li>Category $cat->id: " . s($cat->name) . "</li>\n";
}
$description .= "</ul>\n";
}
return $description;
}
/**
* Given a list of categories, this function searches for ones
* that have loops to previous parent categories.
*
* @param array $categories List of categories.
* @return array List of categories with loops.
*/
function tool_health_category_find_loops($categories) {
$loops = array();
while (!empty($categories)) {
$current = array_pop($categories);
$thisloop = array($current->id => $current);
while (true) {
if (isset($thisloop[$current->parent])) {
// Loop detected.
$loops = $loops + $thisloop;
break;
} else if ($current->parent === 0) {
// Top level.
break;
} else if (isset($loops[$current->parent])) {
// If the parent is in a loop we should also update this category.
$loops = $loops + $thisloop;
break;
} else if (!isset($categories[$current->parent])) {
// We already checked this category and is correct.
break;
} else {
// Continue following the path.
$current = $categories[$current->parent];
$thisloop[$current->id] = $current;
unset($categories[$current->id]);
}
}
}
return $loops;
}
/**
* Generates a list of categories with loops.
*
* @param array $loops List of categories with loops.
* @return string Bullet point list of categories with loops.
*/
function tool_health_category_list_loops($loops) {
$description = '';
if (!empty($loops)) {
$description .= '<p>The following categories form a loop of parents:</p><ul>';
foreach ($loops as $loop) {
$description .= "<li>\n";
$description .= "Category $loop->id: " . s($loop->name) . " has parent $loop->parent\n";
$description .= "</li>\n";
}
$description .= "</ul>\n";
}
return $description;
}
-218
View File
@@ -1,218 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for tool_health.
*
* @package tool_health
* @copyright 2013 Marko Vidberg
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/health/locallib.php');
/**
* Health lib testcase.
*
* @package tool_health
* @copyright 2013 Marko Vidberg
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class healthlib_testcase extends advanced_testcase {
/**
* Data provider for test_tool_health_category_find_loops.
*/
public static function provider_loop_categories() {
return array(
// One item loop including root.
0 => array(
array(
'1' => (object) array('id' => 1, 'parent' => 1)
),
array(
'1' => (object) array('id' => 1, 'parent' => 1)
),
),
// One item loop not including root.
1 => array(
array(
'1' => (object) array('id' => 1, 'parent' => 0),
'2' => (object) array('id' => 2, 'parent' => 2)
),
array(
'2' => (object) array('id' => 2, 'parent' => 2)
),
),
// Two item loop including root.
2 => array(
array(
'1' => (object) array('id' => 1, 'parent' => 2),
'2' => (object) array('id' => 2, 'parent' => 1)
),
array(
'2' => (object) array('id' => 2, 'parent' => 1),
'1' => (object) array('id' => 1, 'parent' => 2),
)
),
// Two item loop not including root.
3 => array(
array(
'1' => (object) array('id' => 1, 'parent' => 0),
'2' => (object) array('id' => 2, 'parent' => 3),
'3' => (object) array('id' => 3, 'parent' => 2),
),
array(
'3' => (object) array('id' => 3, 'parent' => 2),
'2' => (object) array('id' => 2, 'parent' => 3),
)
),
// Three item loop including root.
4 => array(
array(
'1' => (object) array('id' => 1, 'parent' => 2),
'2' => (object) array('id' => 2, 'parent' => 3),
'3' => (object) array('id' => 3, 'parent' => 1),
),
array(
'3' => (object) array('id' => 3, 'parent' => 1),
'1' => (object) array('id' => 1, 'parent' => 2),
'2' => (object) array('id' => 2, 'parent' => 3),
)
),
// Three item loop not including root.
5 => array(
array(
'1' => (object) array('id' => 1, 'parent' => 0),
'2' => (object) array('id' => 2, 'parent' => 3),
'3' => (object) array('id' => 3, 'parent' => 4),
'4' => (object) array('id' => 4, 'parent' => 2)
),
array(
'4' => (object) array('id' => 4, 'parent' => 2),
'2' => (object) array('id' => 2, 'parent' => 3),
'3' => (object) array('id' => 3, 'parent' => 4),
)
),
// Multi-loop.
6 => array(
array(
'1' => (object) array('id' => 1, 'parent' => 2),
'2' => (object) array('id' => 2, 'parent' => 1),
'3' => (object) array('id' => 3, 'parent' => 4),
'4' => (object) array('id' => 4, 'parent' => 5),
'5' => (object) array('id' => 5, 'parent' => 3),
'6' => (object) array('id' => 6, 'parent' => 6),
'7' => (object) array('id' => 7, 'parent' => 1),
'8' => (object) array('id' => 8, 'parent' => 7),
),
array(
'1' => (object) array('id' => 1, 'parent' => 2),
'2' => (object) array('id' => 2, 'parent' => 1),
'8' => (object) array('id' => 8, 'parent' => 7),
'7' => (object) array('id' => 7, 'parent' => 1),
'6' => (object) array('id' => 6, 'parent' => 6),
'5' => (object) array('id' => 5, 'parent' => 3),
'3' => (object) array('id' => 3, 'parent' => 4),
'4' => (object) array('id' => 4, 'parent' => 5),
)
),
// Double-loop
7 => array(
array(
'1' => (object) array('id' => 1, 'parent' => 2),
'2' => (object) array('id' => 2, 'parent' => 1),
'3' => (object) array('id' => 3, 'parent' => 2),
'4' => (object) array('id' => 4, 'parent' => 2),
),
array(
'4' => (object) array('id' => 4, 'parent' => 2),
'3' => (object) array('id' => 3, 'parent' => 2),
'2' => (object) array('id' => 2, 'parent' => 1),
'1' => (object) array('id' => 1, 'parent' => 2),
)
)
);
}
/**
* Data provider for test_tool_health_category_find_missing_parents.
*/
public static function provider_missing_parent_categories() {
return array(
// Test for two items, both with direct ancestor (parent) missing.
0 => array(
array(
'1' => (object) array('id' => 1, 'parent' => 0),
'2' => (object) array('id' => 2, 'parent' => 3),
'4' => (object) array('id' => 4, 'parent' => 5),
'6' => (object) array('id' => 6, 'parent' => 2)
),
array(
'4' => (object) array('id' => 4, 'parent' => 5),
'2' => (object) array('id' => 2, 'parent' => 3)
),
)
);
}
/**
* Test finding loops between two items referring to each other.
*
* @param array $categories
* @param array $expected
* @dataProvider provider_loop_categories
*/
public function test_tool_health_category_find_loops($categories, $expected) {
$loops = tool_health_category_find_loops($categories);
$this->assertEquals($expected, $loops);
}
/**
* Test finding missing parent categories.
*
* @param array $categories
* @param array $expected
* @dataProvider provider_missing_parent_categories
*/
public function test_tool_health_category_find_missing_parents($categories, $expected) {
$missingparent = tool_health_category_find_missing_parents($categories);
$this->assertEquals($expected, $missingparent);
}
/**
* Test listing missing parent categories.
*/
public function test_tool_health_category_list_missing_parents() {
$missingparent = array((object) array('id' => 2, 'parent' => 3, 'name' => 'test'),
(object) array('id' => 4, 'parent' => 5, 'name' => 'test2'));
$result = tool_health_category_list_missing_parents($missingparent);
$this->assertRegExp('/Category 2: test/', $result);
$this->assertRegExp('/Category 4: test2/', $result);
}
/**
* Test listing loop categories.
*/
public function test_tool_health_category_list_loops() {
$loops = array((object) array('id' => 2, 'parent' => 3, 'name' => 'test'));
$result = tool_health_category_list_loops($loops);
$this->assertRegExp('/Category 2: test/', $result);
}
}
+2 -2
View File
@@ -25,8 +25,8 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2014110400; // Requires this Moodle version
$plugin->component = 'tool_health'; // Full name of the plugin (used for diagnostics)
$plugin->maturity = MATURITY_ALPHA; // this version's maturity level
+2 -2
View File
@@ -25,6 +25,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2015051100; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2015050500; // Requires this Moodle version
$plugin->version = 2014111000; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2014110400; // Requires this Moodle version
$plugin->component = 'tool_innodb'; // Full name of the plugin (used for diagnostics)
@@ -459,27 +459,6 @@ class tool_installaddon_installer {
clearstatcache();
}
/**
* Detect the given plugin's component name
*
* Only plugins that declare valid $plugin->component value in the version.php
* are supported.
*
* @param string $zipfilepath full path to the saved ZIP file
* @param string $workdir full path to the directory we can use for extracting required bits from the archive
* @return string|bool declared component name or false if unable to detect
*/
public function detect_plugin_component($zipfilepath, $workdir) {
$versionphp = $this->extract_versionphp_file($zipfilepath, $workdir);
if (empty($versionphp)) {
return false;
}
return $this->detect_plugin_component_from_versionphp(file_get_contents($workdir.'/'.$versionphp));
}
//// End of external API ///////////////////////////////////////////////////
/**
@@ -647,86 +626,6 @@ class tool_installaddon_installer {
return $data;
}
/**
* Extracts the version.php from the given plugin ZIP file into the target directory
*
* @param string $zipfilepath full path to the saved ZIP file
* @param string $targetdir full path to extract the file to
* @return string|bool path to the version.php within the $targetpath; false on error (e.g. not found)
*/
protected function extract_versionphp_file($zipfilepath, $targetdir) {
global $CFG;
require_once($CFG->libdir.'/filelib.php');
$fp = get_file_packer('application/zip');
$files = $fp->list_files($zipfilepath);
if (empty($files)) {
return false;
}
$rootdirname = null;
$found = null;
foreach ($files as $file) {
// Valid plugin ZIP package has just one root directory with all
// files in it.
$pathnameitems = explode('/', $file->pathname);
if (empty($pathnameitems)) {
return false;
}
// Set the expected name of the root directory in the first
// iteration of the loop.
if ($rootdirname === null) {
$rootdirname = $pathnameitems[0];
}
// Require the same root directory for all files in the ZIP
// package.
if ($rootdirname !== $pathnameitems[0]) {
return false;
}
// If we reached the valid version.php file, remember it.
if ($pathnameitems[1] === 'version.php' and !$file->is_directory and $file->size > 0) {
$found = $file->pathname;
}
}
if (empty($found)) {
return false;
}
$extracted = $fp->extract_to_pathname($zipfilepath, $targetdir, array($found));
if (empty($extracted)) {
return false;
}
// The following syntax uses function array dereferencing, added in PHP 5.4.0.
return array_keys($extracted)[0];
}
/**
* Return the plugin component declared in its version.php file
*
* @param string $code the contents of the version.php file
* @return string|bool declared plugin component or false if unable to detect
*/
protected function detect_plugin_component_from_versionphp($code) {
$result = preg_match_all('#^\s*\$plugin\->component\s*=\s*([\'"])(.+?_.+?)\1\s*;#m', $code, $matches);
// Return if and only if the single match was detected.
if ($result === 1 and !empty($matches[2][0])) {
return $matches[2][0];
}
return false;
}
}
@@ -46,46 +46,33 @@ class tool_installaddon_installfromzip_form extends moodleform {
$mform->addElement('header', 'general', get_string('installfromzip', 'tool_installaddon'));
$mform->addHelpButton('general', 'installfromzip', 'tool_installaddon');
$mform->addElement('filepicker', 'zipfile', get_string('installfromzipfile', 'tool_installaddon'),
null, array('accepted_types' => '.zip'));
$mform->addHelpButton('zipfile', 'installfromzipfile', 'tool_installaddon');
$mform->addRule('zipfile', null, 'required', null, 'client');
$options = $installer->get_plugin_types_menu();
$mform->addElement('select', 'plugintype', get_string('installfromziptype', 'tool_installaddon'), $options,
array('id' => 'tool_installaddon_installfromzip_plugintype'));
$mform->addHelpButton('plugintype', 'installfromziptype', 'tool_installaddon');
$mform->setAdvanced('plugintype');
$mform->addRule('plugintype', null, 'required', null, 'client');
$mform->addElement('static', 'permcheck', '',
html_writer::span(get_string('permcheck', 'tool_installaddon'), '',
array('id' => 'tool_installaddon_installfromzip_permcheck')));
$mform->setAdvanced('permcheck');
$mform->addElement('filepicker', 'zipfile', get_string('installfromzipfile', 'tool_installaddon'),
null, array('accepted_types' => '.zip'));
$mform->addHelpButton('zipfile', 'installfromzipfile', 'tool_installaddon');
$mform->addRule('zipfile', null, 'required', null, 'client');
$mform->addElement('text', 'rootdir', get_string('installfromziprootdir', 'tool_installaddon'));
$mform->addHelpButton('rootdir', 'installfromziprootdir', 'tool_installaddon');
$mform->setType('rootdir', PARAM_PLUGIN);
$mform->setAdvanced('rootdir');
$mform->addElement('checkbox', 'acknowledgement', get_string('acknowledgement', 'tool_installaddon'),
' '.get_string('acknowledgementtext', 'tool_installaddon'));
$mform->addRule('acknowledgement', get_string('acknowledgementmust', 'tool_installaddon'), 'required', null, 'client');
$this->add_action_buttons(false, get_string('installfromzipsubmit', 'tool_installaddon'));
}
/**
* Switch the form to a mode that requires manual selection of the plugin type
*/
public function require_explicit_plugintype() {
$mform = $this->_form;
$mform->addRule('plugintype', get_string('required'), 'required', null, 'client');
$mform->setAdvanced('plugintype', false);
$mform->setAdvanced('permcheck', false);
$typedetectionfailed = $mform->createElement('static', 'typedetectionfailed', '',
html_writer::span(get_string('typedetectionfailed', 'tool_installaddon'), 'error'));
$mform->insertElementBefore($typedetectionfailed, 'permcheck');
}
/**
* Validate the form fields
*
@@ -98,11 +85,9 @@ class tool_installaddon_installfromzip_form extends moodleform {
$installer = $this->_customdata['installer'];
$errors = parent::validation($data, $files);
if (!empty($data['plugintype'])) {
if (!$installer->is_plugintype_writable($data['plugintype'])) {
$path = $installer->get_plugintype_root($data['plugintype']);
$errors['plugintype'] = get_string('permcheckresultno', 'tool_installaddon', array('path' => $path));
}
if (!$installer->is_plugintype_writable($data['plugintype'])) {
$path = $installer->get_plugintype_root($data['plugintype']);
$errors['plugintype'] = get_string('permcheckresultno', 'tool_installaddon', array('path' => $path));
}
return $errors;
+7 -23
View File
@@ -52,30 +52,14 @@ if ($form->is_cancelled()) {
$jobid = md5(rand().uniqid('', true));
$sourcedir = make_temp_directory('tool_installaddon/'.$jobid.'/source');
$zipfilename = $installer->save_installfromzip_file($form, $sourcedir);
if (empty($data->plugintype)) {
$versiondir = make_temp_directory('tool_installaddon/'.$jobid.'/version');
$detected = $installer->detect_plugin_component($sourcedir.'/'.$zipfilename, $versiondir);
if (empty($detected)) {
$form->require_explicit_plugintype();
} else {
list($detectedtype, $detectedname) = core_component::normalize_component($detected);
if ($detectedtype and $detectedname and $detectedtype !== 'core') {
$data->plugintype = $detectedtype;
} else {
$form->require_explicit_plugintype();
}
}
}
// Redirect to the validation page.
if (!empty($data->plugintype)) {
$nexturl = new moodle_url('/admin/tool/installaddon/validate.php', array(
'sesskey' => sesskey(),
'jobid' => $jobid,
'zip' => $zipfilename,
'type' => $data->plugintype,
'rootdir' => $data->rootdir));
redirect($nexturl);
}
$nexturl = new moodle_url('/admin/tool/installaddon/validate.php', array(
'sesskey' => sesskey(),
'jobid' => $jobid,
'zip' => $zipfilename,
'type' => $data->plugintype,
'rootdir' => $data->rootdir));
redirect($nexturl);
}
// Output starts here.
@@ -27,6 +27,7 @@
defined('MOODLE_INTERNAL') || die();
$string['acknowledgement'] = 'Acknowledgement';
$string['acknowledgementmust'] = 'You must acknowledge this';
$string['acknowledgementtext'] = 'I understand that it is my responsibility to have full backups of this site prior to installing additional plugins. I accept and understand that plugins (especially but not only those originating in unofficial sources) may contain security holes, can make the site unavailable, or cause private data leaks or loss.';
$string['featuredisabled'] = 'The plugin installer is disabled on this site.';
$string['installaddon'] = 'Install plugin!';
@@ -42,28 +43,25 @@ $string['installfromziprootdir'] = 'Rename the root directory';
$string['installfromziprootdir_help'] = 'Some ZIP packages, such as those generated by Github, may contain an incorrect root directory name. If so, the correct name may be entered here.';
$string['installfromzipsubmit'] = 'Install plugin from the ZIP file';
$string['installfromziptype'] = 'Plugin type';
$string['installfromziptype_help'] = 'For plugins that correctly declare their component name, the installer is able to detect the plugin type automatically. If the auto-detection fails, choose the correct type of plugin manually. Warning: The installation procedure can fail badly if an incorrect plugin type is specified.';
$string['installfromziptype_link'] = 'Development:Plugins';
$string['installfromziptype_help'] = 'Choose the correct type of plugin you are about to install. Warning: The installation procedure can fail badly if an incorrect plugin type is specified.';
$string['permcheck'] = 'Make sure the plugin type root location is writable by the web server process.';
$string['permcheckerror'] = 'Error while checking for write permission';
$string['permcheckprogress'] = 'Checking for write permission ...';
$string['permcheckresultno'] = 'Plugin type location <em>{$a->path}</em> is not writable';
$string['permcheckresultyes'] = 'Plugin type location <em>{$a->path}</em> is writable';
$string['permcheckrepeat'] = 'Check again';
$string['pluginname'] = 'Plugin installer';
$string['remoterequestalreadyinstalled'] = 'There is a request to install plugin {$a->name} ({$a->component}) version {$a->version} from the Moodle plugins directory on this site. However, this plugin is <strong>already installed</strong> on the site.';
$string['remoterequestconfirm'] = 'There is a request to install plugin <strong>{$a->name}</strong> ({$a->component}) version {$a->version} from the Moodle plugins directory on this site. If you continue, the plugin ZIP package will be downloaded for validation. Nothing will be installed yet.';
$string['remoterequestinvalid'] = 'There is a request to install a plugin from the Moodle plugins directory on this site. Unfortunately the request is not valid and so the plugin cannot be installed.';
$string['remoterequestpermcheck'] = 'There is a request to install plugin {$a->name} ({$a->component}) version {$a->version} from the Moodle plugins directory on this site. However, the location <strong>{$a->typepath}</strong> is <strong>not writable</strong>. You need to give write access for the web server user to the location, then press the continue button to repeat the check.';
$string['remoterequestpluginfoexception'] = 'Oops... An error occurred while trying to obtain information about the plugin {$a->name} ({$a->component}) version {$a->version}. The plugin cannot be installed. Turn debugging mode on to see details of the error.';
$string['typedetectionfailed'] = 'Unable to detect the plugin type. Please choose the plugin type manually.';
$string['validation'] = 'Plugin package validation';
$string['validationmsg_componentmatch'] = 'Full component name';
$string['validationmsg_componentmismatchname'] = 'Plugin name mismatch';
$string['validationmsg_componentmismatchname_help'] = 'Some ZIP packages, such as those generated by Github, may contain an incorrect root directory name. You need to fix the name of the root directory to match the declared plugin name.';
$string['validationmsg_componentmismatchname_info'] = 'The plugin declares its name is \'{$a}\' but that does not match the name of the root directory.';
$string['validationmsg_componentmismatchtype'] = 'Plugin type mismatch';
$string['validationmsg_componentmismatchtype_info'] = 'Expected type \'{$a->expected}\' but the plugin declares its type is \'{$a->found}\'.';
$string['validationmsg_componentmismatchtype_info'] = 'You have selected the type \'{$a->expected}\' but the plugin declares its type is \'{$a->found}\'.';
$string['validationmsg_filenotexists'] = 'Extracted file not found';
$string['validationmsg_filesnumber'] = 'Not enough files found in the package';
$string['validationmsg_filestatus'] = 'Unable to extract all files';
+2 -10
View File
@@ -83,8 +83,7 @@ class tool_installaddon_renderer extends plugin_renderer_base {
$this->page->requires->yui_module('moodle-tool_installaddon-permcheck', 'M.tool_installaddon.permcheck.init',
array(array('permcheckurl' => $permcheckurl->out())));
$this->page->requires->strings_for_js(
array('permcheckprogress', 'permcheckresultno', 'permcheckresultyes', 'permcheckerror', 'permcheckrepeat'),
'tool_installaddon');
array('permcheckprogress', 'permcheckresultno', 'permcheckresultyes', 'permcheckerror'), 'tool_installaddon');
$out = $this->output->header();
$out .= $this->index_page_heading();
@@ -381,26 +380,19 @@ class tool_installaddon_renderer extends plugin_renderer_base {
*/
protected function validation_page_continue() {
$output = '';
$conturl = $this->validator->get_continue_url();
if (is_null($conturl)) {
$contbutton = '';
} else {
$contbutton = $this->output->single_button(
$conturl, get_string('installaddon', 'tool_installaddon'), 'post',
array('class' => 'singlebutton continuebutton'));
$output .= $this->output->heading(get_string('acknowledgement', 'tool_installaddon'), 3);
$output .= $this->output->container(get_string('acknowledgementtext', 'tool_installaddon'));
}
$cancelbutton = $this->output->single_button(
new moodle_url('/admin/tool/installaddon/index.php'), get_string('cancel', 'core'), 'get',
array('class' => 'singlebutton cancelbutton'));
$output .= $this->output->container($cancelbutton.$contbutton, 'postvalidationbuttons');
return $output;
return $this->output->container($cancelbutton.$contbutton, 'postvalidationbuttons');
}
}
Binary file not shown.
@@ -143,21 +143,6 @@ class tool_installaddon_installer_testcase extends advanced_testcase {
$this->assertTrue(is_file($jobroot.'/moved/sub/folder/readme.txt'));
$this->assertSame('Hello world!', file_get_contents($jobroot.'/moved/sub/folder/readme.txt'));
}
public function test_detect_plugin_component() {
$jobid = md5(rand().uniqid('test_', true));
$workdir = make_temp_directory('tool_installaddon/'.$jobid.'/version');
$zipfile = __DIR__.'/fixtures/zips/bar.zip';
$installer = tool_installaddon_installer::instance();
$this->assertEquals('foo_bar', $installer->detect_plugin_component($zipfile, $workdir));
}
public function test_detect_plugin_component_from_versionphp() {
$installer = testable_tool_installaddon_installer::instance();
$this->assertEquals('bar_bar_conan', $installer->detect_plugin_component_from_versionphp('
$plugin->version = 2014121300;
$plugin->component= "bar_bar_conan" ; // Go Arnie go!'));
}
}
@@ -188,8 +173,4 @@ class testable_tool_installaddon_installer extends tool_installaddon_installer {
protected function should_send_site_info() {
return true;
}
public function detect_plugin_component_from_versionphp($code) {
return parent::detect_plugin_component_from_versionphp($code);
}
}
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'tool_installaddon';
$plugin->version = 2015051100;
$plugin->requires = 2015050500;
$plugin->version = 2014111000;
$plugin->requires = 2014110400;
$plugin->maturity = MATURITY_STABLE;

Some files were not shown because too many files have changed in this diff Show More