Compare commits
313 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3e90b10ad8 | |||
| 8a646b55f7 | |||
| 72cece6ff4 | |||
| 9b7b6fa33c | |||
| 43bfcff941 | |||
| a4611b9d02 | |||
| 5be009245b | |||
| a50bf852e4 | |||
| 9c3ef35763 | |||
| 562782a48d | |||
| b56324b829 | |||
| 47ee76344e | |||
| 844cb63fed | |||
| a668f57e75 | |||
| 543fc34ed9 | |||
| 0a32dca4bb | |||
| 65a550c484 | |||
| 0f83a143b0 | |||
| 793c431543 | |||
| 2e25f806fb | |||
| f923f7aefe | |||
| cb838a36b2 | |||
| 56f4d0ed80 | |||
| 6c806e8384 | |||
| 5b6e74c85f | |||
| c33a96f676 | |||
| 9910a5d7eb | |||
| 7c8fb69b1c | |||
| ef42830b87 | |||
| 05f8741cee | |||
| 9a1ac11640 | |||
| 04ab55dd4f | |||
| b2e3fb3dc9 | |||
| d72a0aa2c8 | |||
| 2be82d5e13 | |||
| 019cc4eae4 | |||
| 2726d2a6a4 | |||
| 0c49b6c445 | |||
| 83a23ea878 | |||
| f849d1f6fc | |||
| 2e8da707a0 | |||
| f4537d5676 | |||
| 850aa189e4 | |||
| c5e96ad32f | |||
| 9acc49eb93 | |||
| d389a2f7f4 | |||
| 321554d35f | |||
| 102903f7ab | |||
| 181b7f5fea | |||
| e04f57c95b | |||
| b9639c524d | |||
| 56003ca491 | |||
| 192cb8f894 | |||
| 2d7c42275f | |||
| ac41913cea | |||
| 359c790b1c | |||
| 49a66d4b68 | |||
| 1a5a5f8e9c | |||
| 3735e3d289 | |||
| 2c6b79365b | |||
| 1565171e07 | |||
| 0c1be2af21 | |||
| e5d70123c9 | |||
| 3d6b1bf4e3 | |||
| b164a8904a | |||
| 78ac8558e0 | |||
| 363ed37e76 | |||
| 3b800be056 | |||
| ef227f1e0f | |||
| 6606784c3f | |||
| a17b3a200e | |||
| d63a406b02 | |||
| e6a3c6e1a1 | |||
| 356513cc80 | |||
| b1dc798512 | |||
| 697871ddcf | |||
| 602150068a | |||
| eeeac779c8 | |||
| c0333c98ea | |||
| d59467dfc9 | |||
| c731018d50 | |||
| e17644cca3 | |||
| d71b142446 | |||
| b61dd8b299 | |||
| 41bbc35471 | |||
| 0af4bf40ee | |||
| b09c5ac837 | |||
| 3f897939b2 | |||
| 3124654247 | |||
| 9a57563b9f | |||
| 190b5e7cbe | |||
| a8f8537965 | |||
| f938b1a89b | |||
| 2a39a4e01c | |||
| ab7d4ea7ba | |||
| ac4404e0cc | |||
| 0fe16db123 | |||
| 5c0dd1fadd | |||
| a7eec81ec6 | |||
| e03782efdd | |||
| eb2d6a23ab | |||
| a48b376978 | |||
| 544f0f9b11 | |||
| 322af447f5 | |||
| ec39bd51dd | |||
| bbb750e1ba | |||
| 73dd2ee2d5 | |||
| a1ccc146ac | |||
| 7a6f073415 | |||
| 76fa287781 | |||
| 94c5a8fe82 | |||
| d3fdafc358 | |||
| 606c07ae3e | |||
| c6b458edce | |||
| a8ccdd2880 | |||
| 656581fa2c | |||
| 785a713b82 | |||
| cf04387947 | |||
| eddec24752 | |||
| f454c9884f | |||
| 53f7c0c641 | |||
| 2de5b09d84 | |||
| 70c31beef7 | |||
| 901dd625f8 | |||
| 7d3341b000 | |||
| 1f60fe8a23 | |||
| 730271af49 | |||
| 8a35efacd7 | |||
| cfa9c7e1d0 | |||
| acb011dc20 | |||
| a7a1adf4e0 | |||
| e60bae3575 | |||
| ddb5fb5980 | |||
| b70a545c88 | |||
| c383f33bbf | |||
| 13683200d6 | |||
| 7be97bd89d | |||
| cd281ce1b4 | |||
| adc1d7b2a5 | |||
| b4454b133f | |||
| 520a601f14 | |||
| 0409483d5f | |||
| 2d07933c17 | |||
| 6eabdb6d8c | |||
| 291455cecd | |||
| b76204d589 | |||
| e8e9393e76 | |||
| 231f758404 | |||
| e92d664dd2 | |||
| 973fe984cd | |||
| 4548df3155 | |||
| c874cee03a | |||
| caeb7f90b0 | |||
| da264959f2 | |||
| 41e1109c5f | |||
| 209b2f7b3e | |||
| 503325ddcb | |||
| 41575c5571 | |||
| 73f60c1886 | |||
| dc7c91ae67 | |||
| 15dbd27efa | |||
| 9a05bd0f8f | |||
| 524e1ce789 | |||
| 3d4de0bc4e | |||
| 1264dd11a0 | |||
| 599e7fe006 | |||
| b768c6f77a | |||
| 4651e4e464 | |||
| 4c7e6ea021 | |||
| 46b0673732 | |||
| 9c2d41fce2 | |||
| c5148e0ab6 | |||
| 8bd65e7aaa | |||
| 4dbdc18fd8 | |||
| 9789d825c2 | |||
| 8f0019214e | |||
| 45cff73a1b | |||
| aa0cd4a7ef | |||
| 785e3deb4d | |||
| 7a4b7c5e18 | |||
| dc5c56e90c | |||
| 26679bee33 | |||
| 1076d79905 | |||
| 0034f04164 | |||
| 1ff2b56319 | |||
| 4d9b4e9782 | |||
| f51fdc9bb7 | |||
| f1c403dcec | |||
| ab1f9aa3a4 | |||
| 1ce6bdd1dd | |||
| e20e67161c | |||
| c545dcad4f | |||
| 9e9dd64c35 | |||
| c6c7a7be8c | |||
| e958133ca6 | |||
| 9261144beb | |||
| 71cc181bac | |||
| cf617e112f | |||
| 865485fc54 | |||
| a595b4dacb | |||
| 7c431a345f | |||
| 4dbc9b0a64 | |||
| 9242214612 | |||
| 4832c70022 | |||
| 54fdd4c0e9 | |||
| 0324045e4f | |||
| fac9ba991b | |||
| ae5ecea065 | |||
| 6357dd08b6 | |||
| c15b286f88 | |||
| 4afa0b50c7 | |||
| b90b9b83bd | |||
| 79bf1e37ca | |||
| 95ae9d9e5e | |||
| 7027fe4538 | |||
| 50f3d7b5ea | |||
| 22fc0c5e9b | |||
| 6ff1745873 | |||
| 505530eaf5 | |||
| a2630c08ae | |||
| fddbdb79db | |||
| 1c90b9976d | |||
| 35cb0e4a4c | |||
| ada098890b | |||
| 2e8b836243 | |||
| b004c163ee | |||
| 6d0c04c208 | |||
| 29a7d7a1c1 | |||
| eda1d3f37a | |||
| 6466396f38 | |||
| 5b2313c26c | |||
| 473eadfe10 | |||
| 52d4168038 | |||
| c6bd16545e | |||
| 517a2dbe84 | |||
| 88d48cd51f | |||
| a5ff28cc9f | |||
| 1b2cf98bb0 | |||
| 86e28894f4 | |||
| c125bb553d | |||
| 4ac455d9a4 | |||
| 3b7a18f2e5 | |||
| a13a1707bc | |||
| 6812769f8f | |||
| 2f860b4ded | |||
| d84c21dfcc | |||
| 0e3c1231da | |||
| 71e8ee1c33 | |||
| 8938f0848e | |||
| 0e73e16460 | |||
| 9321379b10 | |||
| c91c7fcded | |||
| 0663096dc6 | |||
| 7a9e253405 | |||
| 5e6b64571c | |||
| c446a0fca2 | |||
| 07f89a017c | |||
| b8b1926e2f | |||
| 4d5970ea63 | |||
| 656cea20a6 | |||
| e9f8261131 | |||
| d87a55fc2b | |||
| b0c87306a6 | |||
| 38ab68e6ab | |||
| 0e7cadca03 | |||
| efd08cdc2b | |||
| 7e61737f3d | |||
| 138025470f | |||
| 8b72167d0e | |||
| f92305bfa9 | |||
| 0b4767ca50 | |||
| 1c50e53a05 | |||
| a3301036d6 | |||
| c7a34ab704 | |||
| 1b696de61b | |||
| f4d4c73899 | |||
| da0cf7f883 | |||
| 7c3f70812e | |||
| f5eabd12db | |||
| db1dd3e550 | |||
| f48902e139 | |||
| 7b03292e24 | |||
| 2a6e3435d0 | |||
| 0411eed2cb | |||
| 365ef195b5 | |||
| 8c3547554b | |||
| 324efa55e3 | |||
| 0b7c52dd4c | |||
| cf31390c6f | |||
| 5af62aa90a | |||
| cf839b4396 | |||
| 257a5d1299 | |||
| e6d4708fcf | |||
| f9870842bd | |||
| 2d7173d0c7 | |||
| 4682fc7c38 | |||
| 15a77653e4 | |||
| 9b1f784178 | |||
| 44bfbe1e15 | |||
| 0c767bf6cc | |||
| 81c89dd705 | |||
| b46ee168ef | |||
| e399d32694 | |||
| 606e2c8ebe | |||
| c6e0d385c3 | |||
| 31a3bcc933 | |||
| acade5443f | |||
| 113105bf9c | |||
| dd9f2b1cca | |||
| 90d740364b | |||
| 89bc7e7b6e | |||
| 5c58a540ea | |||
| 325e266e95 |
@@ -30,4 +30,3 @@ phpunit.xml
|
||||
composer.phar
|
||||
composer.lock
|
||||
/vendor/
|
||||
/behat.yml
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"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,
|
||||
"eqnull": false,
|
||||
"es5": false,
|
||||
"esnext": false,
|
||||
"evil": false,
|
||||
"expr": false,
|
||||
"funcscope": false,
|
||||
"globalstrict": false,
|
||||
"iterator": false,
|
||||
"lastsemic": false,
|
||||
"laxbreak": true,
|
||||
"laxcomma": false,
|
||||
"loopfunc": false,
|
||||
"multistr": false,
|
||||
"onecase": false,
|
||||
"proto": false,
|
||||
"regexdash": false,
|
||||
"scripturl": false,
|
||||
"shadow": false,
|
||||
"smarttabs": false,
|
||||
"sub": false,
|
||||
"supernew": false,
|
||||
"maxerr": 500,
|
||||
"maxlen": 150,
|
||||
"passfail": false,
|
||||
"latedef": true
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ a few minutes:
|
||||
1) Move the Moodle files into your web directory.
|
||||
|
||||
2) Create a single database for Moodle to store all
|
||||
its tables in (or choose an existing database).
|
||||
it's tables in (or choose an existing database).
|
||||
|
||||
3) Visit your Moodle site with a browser, you should
|
||||
be taken to the install.php script, which will lead
|
||||
|
||||
+1
-5
@@ -30,9 +30,6 @@
|
||||
$strprotect = get_string('blockprotect', 'admin');
|
||||
$strunprotect = get_string('blockunprotect', 'admin');
|
||||
|
||||
// Purge all caches related to blocks administration.
|
||||
cache::make('core', 'plugininfo_block')->purge();
|
||||
|
||||
/// If data submitted, then process and store.
|
||||
|
||||
if (!empty($hide) && confirm_sesskey()) {
|
||||
@@ -130,8 +127,7 @@
|
||||
$table->define_columns(array('name', 'instances', 'version', 'hideshow', 'undeletable', 'delete', 'settings'));
|
||||
$table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strprotecthdr, $strdelete, $strsettings));
|
||||
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
|
||||
$table->set_attribute('class', 'admintable blockstable generaltable');
|
||||
$table->set_attribute('id', 'compatibleblockstable');
|
||||
$table->set_attribute('class', 'compatibleblockstable blockstable generaltable');
|
||||
$table->setup();
|
||||
$tablerows = array();
|
||||
|
||||
|
||||
+10
-46
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
@@ -15,7 +16,7 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Enable or disable maintenance mode.
|
||||
* Enable or disable maintenance mode
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
@@ -25,13 +26,12 @@
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once("$CFG->libdir/clilib.php");
|
||||
require_once("$CFG->libdir/adminlib.php");
|
||||
require(dirname(dirname(dirname(__FILE__))).'/config.php');
|
||||
require_once($CFG->libdir.'/clilib.php'); // cli only functions
|
||||
|
||||
|
||||
// Now get cli options.
|
||||
list($options, $unrecognized) = cli_get_params(array('enable'=>false, 'enablelater'=>0, 'enableold'=>false, 'disable'=>false, 'help'=>false),
|
||||
// now get cli options
|
||||
list($options, $unrecognized) = cli_get_params(array('enable'=>false, 'disable'=>false, 'help'=>false),
|
||||
array('h'=>'help'));
|
||||
|
||||
if ($unrecognized) {
|
||||
@@ -45,14 +45,12 @@ if ($options['help']) {
|
||||
Current status displayed if not option specified.
|
||||
|
||||
Options:
|
||||
--enable Enable CLI maintenance mode
|
||||
--enablelater=MINUTES Number of minutes before entering CLI maintenance mode
|
||||
--enableold Enable legacy half-maintenance mode
|
||||
--enable Enable maintenance mode
|
||||
--disable Disable maintenance mode
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$ sudo -u www-data /usr/bin/php admin/cli/maintenance.php
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/maintenance.php
|
||||
"; //TODO: localize - to be translated later when everything is finished
|
||||
|
||||
echo $help;
|
||||
@@ -61,52 +59,18 @@ Example:
|
||||
|
||||
cli_heading(get_string('sitemaintenancemode', 'admin')." ($CFG->wwwroot)");
|
||||
|
||||
if ($options['enablelater']) {
|
||||
if (file_exists("$CFG->dataroot/climaintenance.html")) {
|
||||
// Already enabled, sorry.
|
||||
echo get_string('clistatusenabled', 'admin')."\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
$time = time() + ($options['enablelater']*60);
|
||||
set_config('maintenance_later', $time);
|
||||
|
||||
echo get_string('clistatusenabledlater', 'admin', userdate($time))."\n";
|
||||
return 0;
|
||||
|
||||
} else if ($options['enable']) {
|
||||
if (file_exists("$CFG->dataroot/climaintenance.html")) {
|
||||
// The maintenance is already enabled, nothing to do.
|
||||
} else {
|
||||
enable_cli_maintenance_mode();
|
||||
}
|
||||
set_config('maintenance_enabled', 0);
|
||||
unset_config('maintenance_later');
|
||||
echo get_string('sitemaintenanceoncli', 'admin')."\n";
|
||||
exit(0);
|
||||
|
||||
} else if ($options['enableold']) {
|
||||
if ($options['enable']) {
|
||||
set_config('maintenance_enabled', 1);
|
||||
unset_config('maintenance_later');
|
||||
echo get_string('sitemaintenanceon', 'admin')."\n";
|
||||
exit(0);
|
||||
|
||||
} else if ($options['disable']) {
|
||||
set_config('maintenance_enabled', 0);
|
||||
unset_config('maintenance_later');
|
||||
if (file_exists("$CFG->dataroot/climaintenance.html")) {
|
||||
unlink("$CFG->dataroot/climaintenance.html");
|
||||
}
|
||||
echo get_string('sitemaintenanceoff', 'admin')."\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!empty($CFG->maintenance_enabled) or file_exists("$CFG->dataroot/climaintenance.html")) {
|
||||
if (!empty($CFG->maintenance_enabled)) {
|
||||
echo get_string('clistatusenabled', 'admin')."\n";
|
||||
|
||||
} else if (isset($CFG->maintenance_later)) {
|
||||
echo get_string('clistatusenabledlater', 'admin', userdate($CFG->maintenance_later))."\n";
|
||||
|
||||
} else {
|
||||
echo get_string('clistatusdisabled', 'admin')."\n";
|
||||
}
|
||||
|
||||
+20
-136
@@ -227,7 +227,7 @@
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
<ON_CHECK message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="optional">
|
||||
@@ -237,7 +237,7 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
<ON_CHECK message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="optional">
|
||||
@@ -277,12 +277,12 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
<ON_CHECK message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
<ON_CHECK message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
@@ -344,7 +344,7 @@
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
<ON_CHECK message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="optional">
|
||||
@@ -354,7 +354,7 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
<ON_CHECK message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="optional">
|
||||
@@ -394,12 +394,12 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
<ON_CHECK message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
<ON_CHECK message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
@@ -454,7 +454,7 @@
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
<ON_CHECK message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="optional">
|
||||
@@ -464,7 +464,7 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
<ON_CHECK message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="optional">
|
||||
@@ -504,12 +504,12 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
<ON_CHECK message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
<ON_CHECK message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
@@ -569,7 +569,7 @@
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
<ON_CHECK message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="optional">
|
||||
@@ -579,7 +579,7 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
<ON_CHECK message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="optional">
|
||||
@@ -619,12 +619,12 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
<ON_CHECK message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
<ON_CHECK message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
@@ -685,7 +685,7 @@
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
<ON_CHECK message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="optional">
|
||||
@@ -695,7 +695,7 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
<ON_CHECK message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="optional">
|
||||
@@ -735,128 +735,12 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
<ON_CHECK 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="40M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="safe_mode" value="0" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingsafemode" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
</MOODLE>
|
||||
<MOODLE version="2.5" requires="2.2">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mysql" version="5.1.33" />
|
||||
<VENDOR name="postgres" version="8.3" />
|
||||
<VENDOR name="mssql" version="9.0" />
|
||||
<VENDOR name="odbc_mssql" version="9.0" />
|
||||
<VENDOR name="mssql_n" version="9.0" />
|
||||
<VENDOR name="oracle" version="10.2" />
|
||||
<VENDOR name="sqlite" version="2.0" />
|
||||
</DATABASE>
|
||||
<PHP version="5.3.3" 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="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" />
|
||||
<ON_CHECK message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
|
||||
+36
-18
@@ -35,7 +35,7 @@
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
|
||||
$filterpath = optional_param('filterpath', '', PARAM_SAFEDIR);
|
||||
$filterpath = optional_param('filterpath', '', PARAM_PATH);
|
||||
|
||||
require_login();
|
||||
$systemcontext = context_system::instance();
|
||||
@@ -44,9 +44,6 @@
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/filters.php";
|
||||
admin_externalpage_setup('managefilters');
|
||||
|
||||
// Purge all caches related to filter administration.
|
||||
cache::make('core', 'plugininfo_filter')->purge();
|
||||
|
||||
$filters = filter_get_global_states();
|
||||
|
||||
// In case any new filters have been installed, but not put in the table yet.
|
||||
@@ -87,22 +84,39 @@
|
||||
|
||||
case 'down':
|
||||
if (isset($filters[$filterpath])) {
|
||||
filter_set_global_state($filterpath, $filters[$filterpath]->active, 1);
|
||||
$oldpos = $filters[$filterpath]->sortorder;
|
||||
if ($oldpos <= count($filters)) {
|
||||
filter_set_global_state($filterpath, $filters[$filterpath]->active, $oldpos + 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'up':
|
||||
if (isset($filters[$filterpath])) {
|
||||
$oldpos = $filters[$filterpath]->sortorder;
|
||||
filter_set_global_state($filterpath, $filters[$filterpath]->active, -1);
|
||||
if ($oldpos >= 1) {
|
||||
filter_set_global_state($filterpath, $filters[$filterpath]->active, $oldpos - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if (!empty($filternames[$filterpath])) {
|
||||
$filtername = $filternames[$filterpath];
|
||||
} else {
|
||||
$filtername = $filterpath;
|
||||
}
|
||||
|
||||
if (substr($filterpath, 0, 4) == 'mod/') {
|
||||
$mod = basename($filterpath);
|
||||
$a = new stdClass;
|
||||
$a->filter = $filtername;
|
||||
$a->module = get_string('modulename', $mod);
|
||||
print_error('cannotdeletemodfilter', 'admin', $returnurl, $a);
|
||||
}
|
||||
|
||||
// If not yet confirmed, display a confirmation message.
|
||||
if (!optional_param('confirm', '', PARAM_BOOL)) {
|
||||
$filtername = filter_get_name($filterpath);
|
||||
|
||||
$title = get_string('deletefilterareyousure', 'admin', $filtername);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($title);
|
||||
@@ -115,7 +129,7 @@
|
||||
}
|
||||
|
||||
// Do the deletion.
|
||||
$title = get_string('deletingfilter', 'admin', $filterpath);
|
||||
$title = get_string('deletingfilter', 'admin', $filtername);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($title);
|
||||
|
||||
@@ -123,8 +137,8 @@
|
||||
filter_delete_all_for_filter($filterpath);
|
||||
|
||||
$a = new stdClass;
|
||||
$a->filter = $filterpath;
|
||||
$a->directory = "$CFG->dirroot/filter/$filterpath";
|
||||
$a->filter = $filtername;
|
||||
$a->directory = $filterpath;
|
||||
echo $OUTPUT->box(get_string('deletefilterfiles', 'admin', $a), 'generalbox', 'notice');
|
||||
echo $OUTPUT->continue_button($returnurl);
|
||||
echo $OUTPUT->footer();
|
||||
@@ -171,9 +185,8 @@
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('filter'), get_string('isactive', 'filters'),
|
||||
get_string('order'), get_string('applyto', 'filters'), get_string('settings'), get_string('delete'));
|
||||
$table->colclasses = array ('leftalign', 'leftalign', 'centeralign', 'leftalign', 'leftalign', 'leftalign');
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$table->id = 'filterssetting';
|
||||
$table->align = array('left', 'left', 'center', 'left', 'left');
|
||||
$table->width = '100%';
|
||||
$table->data = array();
|
||||
|
||||
$lastactive = null;
|
||||
@@ -228,7 +241,7 @@ function get_table_row($filterinfo, $isfirstrow, $islastactive, $applytostrings)
|
||||
}
|
||||
|
||||
// Disable/off/on
|
||||
$select = new single_select(filters_action_url($filter, 'setstate'), 'newstate', $activechoices, $filterinfo->active, null, 'active' . $filter);
|
||||
$select = new single_select(filters_action_url($filter, 'setstate'), 'newstate', $activechoices, $filterinfo->active, null, 'active' . basename($filter));
|
||||
$select->set_label(get_string('isactive', 'filters'), array('class' => 'accesshide'));
|
||||
$row[] = $OUTPUT->render($select);
|
||||
|
||||
@@ -250,20 +263,25 @@ function get_table_row($filterinfo, $isfirstrow, $islastactive, $applytostrings)
|
||||
$row[] = $updown;
|
||||
|
||||
// Apply to strings.
|
||||
$select = new single_select(filters_action_url($filter, 'setapplyto'), 'stringstoo', $applytochoices, $applytostrings, null, 'applyto' . $filter);
|
||||
$select = new single_select(filters_action_url($filter, 'setapplyto'), 'stringstoo', $applytochoices, $applytostrings, null, 'applyto' . basename($filter));
|
||||
$select->set_label(get_string('applyto', 'filters'), array('class' => 'accesshide'));
|
||||
$select->disabled = $filterinfo->active == TEXTFILTER_DISABLED;
|
||||
$row[] = $OUTPUT->render($select);
|
||||
|
||||
// Settings link, if required
|
||||
if (filter_has_global_settings($filter)) {
|
||||
$row[] = '<a href="' . $CFG->wwwroot . '/' . $CFG->admin . '/settings.php?section=filtersetting' . $filter . '">' . get_string('settings') . '</a>';
|
||||
$row[] = '<a href="' . $CFG->wwwroot . '/' . $CFG->admin . '/settings.php?section=filtersetting' .
|
||||
str_replace('/', '',$filter) . '">' . get_string('settings') . '</a>';
|
||||
} else {
|
||||
$row[] = '';
|
||||
}
|
||||
|
||||
// Delete
|
||||
$row[] = '<a href="' . filters_action_url($filter, 'delete') . '">' . get_string('delete') . '</a>';
|
||||
if (substr($filter, 0, 4) != 'mod/') {
|
||||
$row[] = '<a href="' . filters_action_url($filter, 'delete') . '">' . get_string('delete') . '</a>';
|
||||
} else {
|
||||
$row[] = '';
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
+3
-22
@@ -59,18 +59,10 @@ $confirmplugins = optional_param('confirmplugincheck', 0, PARAM_BOOL);
|
||||
$showallplugins = optional_param('showallplugins', 0, PARAM_BOOL);
|
||||
$agreelicense = optional_param('agreelicense', 0, PARAM_BOOL);
|
||||
$fetchupdates = optional_param('fetchupdates', 0, PARAM_BOOL);
|
||||
$newaddonreq = optional_param('installaddonrequest', null, PARAM_RAW);
|
||||
|
||||
// Check some PHP server settings
|
||||
|
||||
if (is_null($newaddonreq)) {
|
||||
$PAGE->set_url('/admin/index.php');
|
||||
} else {
|
||||
// We need to set the eventual add-on installation request in the $PAGE's URL
|
||||
// so that it is stored in $SESSION->wantsurl and the admin is redirected
|
||||
// correctly once they are logged-in.
|
||||
$PAGE->set_url('/admin/index.php', array('installaddonrequest' => $newaddonreq));
|
||||
}
|
||||
$PAGE->set_url('/admin/index.php');
|
||||
$PAGE->set_pagelayout('admin'); // Set a default pagelayout
|
||||
|
||||
$documentationlink = '<a href="http://docs.moodle.org/en/Installation">Installation docs</a>';
|
||||
@@ -216,8 +208,8 @@ if ($version > $CFG->version) { // upgrade
|
||||
|
||||
if (empty($confirmupgrade)) {
|
||||
$a = new stdClass();
|
||||
$a->oldversion = "$CFG->release (".sprintf('%.2f', $CFG->version).")";
|
||||
$a->newversion = "$release (".sprintf('%.2f', $version).")";
|
||||
$a->oldversion = "$CFG->release ($CFG->version)";
|
||||
$a->newversion = "$release ($version)";
|
||||
$strdatabasechecking = get_string('databasechecking', '', $a);
|
||||
|
||||
$PAGE->set_title($stradministration);
|
||||
@@ -431,17 +423,6 @@ if (!empty($id) and $id == $CFG->siteidentifier) {
|
||||
set_config('registered', time());
|
||||
}
|
||||
|
||||
// Check if we are returning from an add-on installation request at moodle.org/plugins
|
||||
if (!is_null($newaddonreq)) {
|
||||
if (!empty($CFG->disableonclickaddoninstall)) {
|
||||
// The feature is disabled in config.php, ignore the request.
|
||||
} else {
|
||||
redirect(new moodle_url('/admin/tool/installaddon/index.php', array(
|
||||
'installaddonrequest' => $newaddonreq,
|
||||
'confirm' => 0)));
|
||||
}
|
||||
}
|
||||
|
||||
// setup critical warnings before printing admin tree block
|
||||
$insecuredataroot = is_dataroot_insecure(true);
|
||||
$SESSION->admin_critical_warning = ($insecuredataroot==INSECURE_DATAROOT_ERROR);
|
||||
|
||||
@@ -77,7 +77,7 @@ $table->define_columns(array('name', 'version', 'delete'));
|
||||
$table->define_headers(array(get_string('plugin'), get_string('version'), get_string('delete')));
|
||||
$table->define_baseurl($PAGE->url);
|
||||
$table->set_attribute('id', 'localplugins');
|
||||
$table->set_attribute('class', 'admintable generaltable');
|
||||
$table->set_attribute('class', 'generaltable generalbox boxaligncenter boxwidthwide');
|
||||
$table->setup();
|
||||
|
||||
$plugins = array();
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
echo $OUTPUT->header();
|
||||
?>
|
||||
<form method="post" action="index.php">
|
||||
<table align="center" width="635" class="generaltable" border="0" cellpadding="5" cellspacing="0">
|
||||
<table align="center" width="635" class="generalbox" border="0" cellpadding="5" cellspacing="0">
|
||||
<tr>
|
||||
<td class="generalboxcontent">
|
||||
<table cellpadding="9" cellspacing="0" >
|
||||
@@ -106,7 +106,7 @@
|
||||
</table>
|
||||
</form>
|
||||
<form method="post" action="index.php">
|
||||
<table align="center" width="635" class="generaltable" border="0" cellpadding="5" cellspacing="0">
|
||||
<table align="center" width="635" class="generalbox" border="0" cellpadding="5" cellspacing="0">
|
||||
<tr>
|
||||
<td class="generalboxcontent">
|
||||
<table cellpadding="9" cellspacing="0" >
|
||||
|
||||
@@ -29,9 +29,6 @@
|
||||
$stractivitymodule = get_string("activitymodule");
|
||||
$strshowmodulecourse = get_string('showmodulecourse');
|
||||
|
||||
// Purge all caches related to activity modules administration.
|
||||
cache::make('core', 'plugininfo_mod')->purge();
|
||||
|
||||
/// If data submitted, then process and store.
|
||||
|
||||
if (!empty($hide) and confirm_sesskey()) {
|
||||
|
||||
+1
-1
@@ -28,8 +28,8 @@ require_once(dirname(dirname(__FILE__)) . '/config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/pluginlib.php');
|
||||
|
||||
admin_externalpage_setup('pluginsoverview');
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
admin_externalpage_setup('pluginsoverview');
|
||||
|
||||
$fetchremote = optional_param('fetchremote', false, PARAM_BOOL);
|
||||
$updatesonly = optional_param('updatesonly', false, PARAM_BOOL);
|
||||
|
||||
@@ -43,9 +43,6 @@ $configstr = get_string('manageportfolios', 'portfolio');
|
||||
|
||||
$return = true; // direct back to the main page
|
||||
|
||||
// Purge all caches related to portfolio administration.
|
||||
cache::make('core', 'plugininfo_portfolio')->purge();
|
||||
|
||||
/**
|
||||
* Helper function that generates a moodle_url object
|
||||
* relevant to the portfolio
|
||||
|
||||
+1
-1
@@ -195,7 +195,7 @@ $table->define_headers(array(get_string('questiontype', 'question'), get_string(
|
||||
get_string('version'), get_string('requires', 'admin'), get_string('availableq', 'question'),
|
||||
get_string('delete'), get_string('settings')));
|
||||
$table->set_attribute('id', 'qtypes');
|
||||
$table->set_attribute('class', 'admintable generaltable');
|
||||
$table->set_attribute('class', 'generaltable generalbox boxaligncenter boxwidthwide');
|
||||
$table->setup();
|
||||
|
||||
// Add a row for each question type.
|
||||
|
||||
@@ -243,8 +243,6 @@ class site_registration_form extends moodleform {
|
||||
$postsnumber = get_config('hub', 'site_postsnumber_' . $cleanhuburl);
|
||||
$questionsnumber = get_config('hub', 'site_questionsnumber_' . $cleanhuburl);
|
||||
$resourcesnumber = get_config('hub', 'site_resourcesnumber_' . $cleanhuburl);
|
||||
$badges = get_config('hub', 'site_badges_' . $cleanhuburl);
|
||||
$issuedbadges = get_config('hub', 'site_issuedbadges_' . $cleanhuburl);
|
||||
$mediancoursesize = get_config('hub', 'site_mediancoursesize_' . $cleanhuburl);
|
||||
|
||||
//hidden parameters
|
||||
@@ -374,9 +372,6 @@ class site_registration_form extends moodleform {
|
||||
require_once($CFG->dirroot . "/course/lib.php");
|
||||
$participantnumberaverage = number_format(average_number_of_participants(), 2);
|
||||
$modulenumberaverage = number_format(average_number_of_courses_modules(), 2);
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
$badges = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
|
||||
$issuedbadges = $DB->count_records('badge_issued');
|
||||
|
||||
if (HUB_MOODLEORGHUBURL != $huburl) {
|
||||
$mform->addElement('checkbox', 'courses', get_string('sendfollowinginfo', 'hub'),
|
||||
@@ -404,14 +399,6 @@ class site_registration_form extends moodleform {
|
||||
" " . get_string('resourcesnumber', 'hub', $resourcecount));
|
||||
$mform->setDefault('resources', true);
|
||||
|
||||
$mform->addElement('checkbox', 'badges', '',
|
||||
" " . get_string('badgesnumber', 'hub', $badges));
|
||||
$mform->setDefault('badges', true);
|
||||
|
||||
$mform->addElement('checkbox', 'issuedbadges', '',
|
||||
" " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
|
||||
$mform->setDefault('issuedbadges', true);
|
||||
|
||||
$mform->addElement('checkbox', 'participantnumberaverage', '',
|
||||
" " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
|
||||
$mform->setDefault('participantnumberaverage', true);
|
||||
@@ -451,16 +438,6 @@ class site_registration_form extends moodleform {
|
||||
$mform->addElement('hidden', 'resources', true);
|
||||
$mform->setType('resources', PARAM_FLOAT);
|
||||
|
||||
$mform->addElement('static', 'badgeslabel', '',
|
||||
" " . get_string('badgesnumber', 'hub', $badges));
|
||||
$mform->addElement('hidden', 'badges', true);
|
||||
$mform->setType('badges', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'issuedbadgeslabel', '',
|
||||
" " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
|
||||
$mform->addElement('hidden', 'issuedbadges', true);
|
||||
$mform->setType('issuedbadges', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'participantnumberaveragelabel', '',
|
||||
" " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
|
||||
$mform->addElement('hidden', 'participantnumberaverage', true);
|
||||
|
||||
@@ -247,20 +247,6 @@ class registration_manager {
|
||||
$resourcecount = $DB->count_records('resource');
|
||||
}
|
||||
$siteinfo['resources'] = $resourcecount;
|
||||
// Badge statistics.
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
if (get_config('hub', 'site_badges_' . $cleanhuburl) == -1) {
|
||||
$badges = -1;
|
||||
} else {
|
||||
$badges = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
|
||||
}
|
||||
$siteinfo['badges'] = $badges;
|
||||
if (get_config('hub', 'site_issuedbadges_' . $cleanhuburl) == -1) {
|
||||
$issuedbadges = -1;
|
||||
} else {
|
||||
$issuedbadges = $DB->count_records('badge_issued');
|
||||
}
|
||||
$siteinfo['issuedbadges'] = $issuedbadges;
|
||||
//TODO
|
||||
require_once($CFG->dirroot . "/course/lib.php");
|
||||
if (get_config('hub', 'site_participantnumberaverage_' . $cleanhuburl) == -1) {
|
||||
|
||||
@@ -84,8 +84,6 @@ if (!empty($fromform) and confirm_sesskey()) {
|
||||
set_config('site_postsnumber_' . $cleanhuburl, $fromform->posts, 'hub');
|
||||
set_config('site_questionsnumber_' . $cleanhuburl, $fromform->questions, 'hub');
|
||||
set_config('site_resourcesnumber_' . $cleanhuburl, $fromform->resources, 'hub');
|
||||
set_config('site_badges_' . $cleanhuburl, $fromform->badges, 'hub');
|
||||
set_config('site_issuedbadges_' . $cleanhuburl, $fromform->issuedbadges, 'hub');
|
||||
set_config('site_modulenumberaverage_' . $cleanhuburl, $fromform->modulenumberaverage, 'hub');
|
||||
set_config('site_participantnumberaverage_' . $cleanhuburl, $fromform->participantnumberaverage, 'hub');
|
||||
}
|
||||
|
||||
+8
-6
@@ -1245,9 +1245,10 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
get_string('report'),
|
||||
get_string('status'),
|
||||
);
|
||||
$servertable->colclasses = array('centeralign name', 'centeralign status', 'leftalign report', 'centeralign info');
|
||||
$servertable->attributes['class'] = 'admintable environmenttable generaltable';
|
||||
$servertable->id = 'serverstatus';
|
||||
$servertable->align = array('center', 'center', 'left', 'center');
|
||||
$servertable->wrap = array('nowrap', '', '', 'nowrap');
|
||||
$servertable->size = array('10', 10, '100%', '10');
|
||||
$servertable->attributes['class'] = 'environmenttable generaltable';
|
||||
|
||||
$serverdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
|
||||
|
||||
@@ -1257,9 +1258,10 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
get_string('report'),
|
||||
get_string('status'),
|
||||
);
|
||||
$othertable->colclasses = array('aligncenter info', 'alignleft report', 'aligncenter status');
|
||||
$othertable->attributes['class'] = 'admintable environmenttable generaltable';
|
||||
$othertable->id = 'otherserverstatus';
|
||||
$othertable->align = array('center', 'left', 'center');
|
||||
$othertable->wrap = array('', '', 'nowrap');
|
||||
$othertable->size = array(10, '100%', '10');
|
||||
$othertable->attributes['class'] = 'environmenttable generaltable';
|
||||
|
||||
$otherdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
|
||||
|
||||
|
||||
@@ -61,9 +61,6 @@ if (!empty($action)) {
|
||||
require_sesskey();
|
||||
}
|
||||
|
||||
// Purge all caches related to repositories administration.
|
||||
cache::make('core', 'plugininfo_repository')->purge();
|
||||
|
||||
/**
|
||||
* Helper function that generates a moodle_url object
|
||||
* relevant to the repository
|
||||
@@ -284,11 +281,8 @@ 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);
|
||||
|
||||
$table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
|
||||
$table->id = 'repositoriessetting';
|
||||
$table->align = array('left', 'center', 'center', 'center', 'center');
|
||||
$table->data = array();
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
|
||||
// Get list of used plug-ins
|
||||
$instances = repository::get_types();
|
||||
|
||||
@@ -62,9 +62,6 @@ $return = true;
|
||||
if (!empty($edit) || !empty($new)) {
|
||||
if (!empty($edit)) {
|
||||
$instance = repository::get_instance($edit);
|
||||
if (!$instance->can_be_edited_by_user()) {
|
||||
throw new repository_exception('nopermissiontoaccess', 'repository');
|
||||
}
|
||||
$instancetype = repository::get_type_by_id($instance->options['typeid']);
|
||||
$classname = 'repository_' . $instancetype->get_typename();
|
||||
$configs = $instance->get_instance_option_names();
|
||||
@@ -121,12 +118,10 @@ if (!empty($edit) || !empty($new)) {
|
||||
$return = true;
|
||||
} else if (!empty($delete)) {
|
||||
$instance = repository::get_instance($delete);
|
||||
//if you try to delete an instance set as readonly, display an error message
|
||||
if ($instance->readonly) {
|
||||
// If you try to delete an instance set as readonly, display an error message.
|
||||
throw new repository_exception('readonlyinstance', 'repository');
|
||||
} else if (!$instance->can_be_edited_by_user()) {
|
||||
throw new repository_exception('nopermissiontoaccess', 'repository');
|
||||
}
|
||||
throw new repository_exception('readonlyinstance', 'repository');
|
||||
}
|
||||
if ($sure) {
|
||||
if ($instance->delete($downloadcontents)) {
|
||||
$deletedstr = get_string('instancedeleted', 'repository');
|
||||
|
||||
@@ -189,7 +189,7 @@ $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
|
||||
<form id="assignform" method="post" action="<?php echo $assignurl ?>"><div>
|
||||
<input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" />
|
||||
|
||||
<table id="assigningrole" summary="" class="admintable roleassigntable generaltable" cellspacing="0">
|
||||
<table summary="" class="roleassigntable generaltable generalbox boxaligncenter" cellspacing="0">
|
||||
<tr>
|
||||
<td id="existingcell">
|
||||
<p><label for="removeselect"><?php print_string('extusers', 'role'); ?></label></p>
|
||||
@@ -278,13 +278,15 @@ $assignurl = new moodle_url($PAGE->url, array('roleid'=>$roleid));
|
||||
|
||||
// Print overview table
|
||||
$table = new html_table();
|
||||
$table->id = 'assignrole';
|
||||
$table->tablealign = 'center';
|
||||
$table->width = '60%';
|
||||
$table->head = array(get_string('role'), get_string('description'), get_string('userswiththisrole', 'role'));
|
||||
$table->colclasses = array('leftalign role', 'leftalign', 'centeralign userrole');
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$table->wrap = array('nowrap', '', 'nowrap');
|
||||
$table->align = array('left', 'left', 'center');
|
||||
if ($showroleholders) {
|
||||
$table->headspan = array(1, 1, 2);
|
||||
$table->colclasses[] = 'leftalign roleholder';
|
||||
$table->wrap[] = 'nowrap';
|
||||
$table->align[] = 'left';
|
||||
}
|
||||
|
||||
foreach ($assignableroles as $roleid => $rolename) {
|
||||
|
||||
+11
-113
@@ -661,7 +661,7 @@ class define_role_table_advanced extends capability_table_with_risks {
|
||||
public function make_copy() {
|
||||
$this->roleid = 0;
|
||||
unset($this->role->id);
|
||||
$this->role->name = role_get_name($this->role, null, ROLENAME_ORIGINAL) . ' ' . get_string('copyasnoun');
|
||||
$this->role->name .= ' ' . get_string('copyasnoun');
|
||||
$this->role->shortname .= 'copy';
|
||||
}
|
||||
|
||||
@@ -738,56 +738,6 @@ class define_role_table_advanced extends capability_table_with_risks {
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of roles of the allowed type.
|
||||
*
|
||||
* @param string $type Must be one of: assign, switch, or override.
|
||||
* @return array
|
||||
*/
|
||||
protected function get_allow_roles_list($type) {
|
||||
global $DB;
|
||||
|
||||
if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') {
|
||||
debugging('Invalid role allowed type specified', DEBUG_DEVELOPER);
|
||||
return array();
|
||||
}
|
||||
|
||||
if (empty($this->roleid)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$sql = "SELECT r.*
|
||||
FROM {role} r
|
||||
JOIN {role_allow_{$type}} a ON a.allow{$type} = r.id
|
||||
WHERE a.roleid = :roleid
|
||||
ORDER BY r.sortorder ASC";
|
||||
return $DB->get_records_sql($sql, array('roleid'=>$this->roleid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of roles with the allowed type.
|
||||
*
|
||||
* @param string $type Must be one of: assign, switch, or override.
|
||||
* @return array Am array of role names with the allowed type
|
||||
*/
|
||||
protected function get_allow_role_control($type) {
|
||||
if ($roles = $this->get_allow_roles_list($type)) {
|
||||
$roles = role_fix_names($roles, null, ROLENAME_ORIGINAL, true);
|
||||
return implode(', ', $roles);
|
||||
} else {
|
||||
return get_string('none');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the risks associated with a role.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_role_risks_info() {
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function print_field($name, $caption, $field) {
|
||||
global $OUTPUT;
|
||||
// Attempt to generate HTML like formslib.
|
||||
@@ -831,12 +781,6 @@ class define_role_table_advanced extends capability_table_with_risks {
|
||||
$this->print_field('edit-description', get_string('customroledescription', 'role').' '.$OUTPUT->help_icon('customroledescription', 'role'), $this->get_description_field('description'));
|
||||
$this->print_field('menuarchetype', get_string('archetype', 'role').' '.$OUTPUT->help_icon('archetype', 'role'), $this->get_archetype_field('archetype'));
|
||||
$this->print_field('', get_string('maybeassignedin', 'role'), $this->get_assignable_levels_control());
|
||||
$this->print_field('', get_string('allowassign', 'role'), $this->get_allow_role_control('assign'));
|
||||
$this->print_field('', get_string('allowoverride', 'role'), $this->get_allow_role_control('override'));
|
||||
$this->print_field('', get_string('allowswitch', 'role'), $this->get_allow_role_control('switch'));
|
||||
if ($risks = $this->get_role_risks_info()) {
|
||||
$this->print_field('', get_string('rolerisks', 'role'), $risks);
|
||||
}
|
||||
echo "</div>";
|
||||
|
||||
$this->print_show_hide_advanced_button();
|
||||
@@ -938,57 +882,6 @@ class view_role_definition_table extends define_role_table_advanced {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML risk icons.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_role_risks_info() {
|
||||
global $OUTPUT;
|
||||
|
||||
if (empty($this->roleid)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$risks = array();
|
||||
$allrisks = get_all_risks();
|
||||
foreach ($this->capabilities as $capability) {
|
||||
$perm = $this->permissions[$capability->name];
|
||||
if ($perm != CAP_ALLOW) {
|
||||
continue;
|
||||
}
|
||||
foreach ($allrisks as $type=>$risk) {
|
||||
if ($risk & (int)$capability->riskbitmask) {
|
||||
$risks[$type] = $risk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$risksurl = new moodle_url(get_docs_url(s(get_string('risks', 'role'))));
|
||||
foreach ($risks as $type=>$risk) {
|
||||
$pixicon = new pix_icon('/i/' . str_replace('risk', 'risk_', $type), get_string($type . 'short', 'admin'));
|
||||
$risks[$type] = $OUTPUT->action_icon($risksurl, $pixicon, new popup_action('click', $risksurl));
|
||||
}
|
||||
|
||||
return implode(' ', $risks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the row should be skipped.
|
||||
*
|
||||
* @param string $capability
|
||||
* @return bool
|
||||
*/
|
||||
protected function skip_row($capability) {
|
||||
$perm = $this->permissions[$capability->name];
|
||||
if ($perm == CAP_INHERIT) {
|
||||
// Do not print empty rows in role overview, admins need to know quickly what is allowed and prohibited,
|
||||
// if they want to see the list of all capabilities they can go to edit role page.
|
||||
return true;
|
||||
}
|
||||
parent::skip_row($capability);
|
||||
}
|
||||
|
||||
protected function add_permission_cells($capability) {
|
||||
$perm = $this->permissions[$capability->name];
|
||||
$permname = $this->allpermissions[$perm];
|
||||
@@ -1089,6 +982,8 @@ class override_permissions_table_advanced extends capability_table_with_risks {
|
||||
* Base class to avoid duplicating code.
|
||||
*/
|
||||
abstract class role_assign_user_selector_base extends user_selector_base {
|
||||
const MAX_USERS_PER_PAGE = 100;
|
||||
|
||||
protected $roleid;
|
||||
protected $context;
|
||||
|
||||
@@ -1157,7 +1052,7 @@ class potential_assignees_below_course extends role_assign_user_selector_base {
|
||||
// Check to see if there are too many to show sensibly.
|
||||
if (!$this->is_validating()) {
|
||||
$potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
|
||||
if ($potentialmemberscount > $this->maxusersperpage) {
|
||||
if ($potentialmemberscount > role_assign_user_selector_base::MAX_USERS_PER_PAGE) {
|
||||
return $this->too_many_results($search, $potentialmemberscount);
|
||||
}
|
||||
}
|
||||
@@ -1185,6 +1080,9 @@ class potential_assignees_below_course extends role_assign_user_selector_base {
|
||||
* @copyright 2012 Petr Skoda {@link http://skodak.org}
|
||||
*/
|
||||
class role_check_users_selector extends user_selector_base {
|
||||
const MAX_ENROLLED_PER_PAGE = 100;
|
||||
const MAX_POTENTIAL_PER_PAGE = 100;
|
||||
|
||||
/** @var bool limit listing of users to enrolled only */
|
||||
var $onlyenrolled;
|
||||
|
||||
@@ -1265,7 +1163,7 @@ class role_check_users_selector extends user_selector_base {
|
||||
|
||||
if ($sql1) {
|
||||
$enrolleduserscount = $DB->count_records_sql($countfields . $sql1, $params);
|
||||
if (!$this->is_validating() and $enrolleduserscount > $this->maxusersperpage) {
|
||||
if (!$this->is_validating() and $enrolleduserscount > $this::MAX_ENROLLED_PER_PAGE) {
|
||||
$result[$groupname1] = array();
|
||||
$toomany = $this->too_many_results($search, $enrolleduserscount);
|
||||
$result[implode(' - ', array_keys($toomany))] = array();
|
||||
@@ -1282,7 +1180,7 @@ class role_check_users_selector extends user_selector_base {
|
||||
}
|
||||
if ($sql2) {
|
||||
$otheruserscount = $DB->count_records_sql($countfields . $sql2, $params);
|
||||
if (!$this->is_validating() and $otheruserscount > $this->maxusersperpage) {
|
||||
if (!$this->is_validating() and $otheruserscount > $this::MAX_POTENTIAL_PER_PAGE) {
|
||||
$result[$groupname2] = array();
|
||||
$toomany = $this->too_many_results($search, $otheruserscount);
|
||||
$result[implode(' - ', array_keys($toomany))] = array();
|
||||
@@ -1335,7 +1233,7 @@ class potential_assignees_course_and_above extends role_assign_user_selector_bas
|
||||
|
||||
if (!$this->is_validating()) {
|
||||
$potentialmemberscount = $DB->count_records_sql($countfields . $sql, $params);
|
||||
if ($potentialmemberscount > $this->maxusersperpage) {
|
||||
if ($potentialmemberscount > role_assign_user_selector_base::MAX_USERS_PER_PAGE) {
|
||||
return $this->too_many_results($search, $potentialmemberscount);
|
||||
}
|
||||
}
|
||||
@@ -1760,7 +1658,7 @@ class admins_potential_selector extends user_selector_base {
|
||||
// Check to see if there are too many to show sensibly.
|
||||
if (!$this->is_validating()) {
|
||||
$potentialcount = $DB->count_records_sql($countfields . $sql, $params);
|
||||
if ($potentialcount > $this->maxusersperpage) {
|
||||
if ($potentialcount > 100) {
|
||||
return $this->too_many_results($search, $potentialcount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,9 +186,10 @@
|
||||
|
||||
/// Initialise table.
|
||||
$table = new html_table();
|
||||
$table->colclasses = array('leftalign', 'leftalign', 'leftalign', 'leftalign');
|
||||
$table->id = 'roles';
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$table->tablealign = 'center';
|
||||
$table->align = array('left', 'left', 'left', 'left');
|
||||
$table->wrap = array('nowrap', '', 'nowrap','nowrap');
|
||||
$table->width = '90%';
|
||||
$table->head = array(
|
||||
get_string('role') . ' ' . $OUTPUT->help_icon('roles', 'role'),
|
||||
get_string('description'),
|
||||
|
||||
@@ -67,21 +67,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
}
|
||||
$temp->add(new admin_setting_configselect('calendar_maxevents',new lang_string('configmaxevents','admin'),new lang_string('helpupcomingmaxevents', 'admin'),10,$options));
|
||||
$temp->add(new admin_setting_configcheckbox('enablecalendarexport', new lang_string('enablecalendarexport', 'admin'), new lang_string('configenablecalendarexport','admin'), 1));
|
||||
|
||||
// Calendar custom export settings.
|
||||
$days = array(365 => new lang_string('numdays', '', 365),
|
||||
180 => new lang_string('numdays', '', 180),
|
||||
150 => new lang_string('numdays', '', 150),
|
||||
120 => new lang_string('numdays', '', 120),
|
||||
90 => new lang_string('numdays', '', 90),
|
||||
60 => new lang_string('numdays', '', 60),
|
||||
30 => new lang_string('numdays', '', 30),
|
||||
5 => new lang_string('numdays', '', 5));
|
||||
$temp->add(new admin_setting_configcheckbox('calendar_customexport', new lang_string('configcalendarcustomexport', 'admin'), new lang_string('helpcalendarcustomexport','admin'), 1));
|
||||
$temp->add(new admin_setting_configselect('calendar_exportlookahead', new lang_string('configexportlookahead','admin'), new lang_string('helpexportlookahead', 'admin'), 365, $days));
|
||||
$temp->add(new admin_setting_configselect('calendar_exportlookback', new lang_string('configexportlookback','admin'), new lang_string('helpexportlookback', 'admin'), 5, $days));
|
||||
$temp->add(new admin_setting_configtext('calendar_exportsalt', new lang_string('calendarexportsalt','admin'), new lang_string('configcalendarexportsalt', 'admin'), random_string(60)));
|
||||
$temp->add(new admin_setting_configcheckbox('calendar_showicalsource', new lang_string('configshowicalsource', 'admin'), new lang_string('helpshowicalsource','admin'), 1));
|
||||
$ADMIN->add('appearance', $temp);
|
||||
|
||||
// blog
|
||||
@@ -110,17 +96,9 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
);
|
||||
$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));
|
||||
$temp->add(new admin_setting_configcheckbox('navshowmycoursecategories', new lang_string('navshowmycoursecategories', 'admin'), new lang_string('navshowmycoursecategories_help', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('navshowallcourses', new lang_string('navshowallcourses', 'admin'), new lang_string('confignavshowallcourses', 'admin'), 0));
|
||||
$sortoptions = array(
|
||||
'sortorder' => new lang_string('sort_sortorder', 'admin'),
|
||||
'fullname' => new lang_string('sort_fullname', 'admin'),
|
||||
'shortname' => new lang_string('sort_shortname', 'admin'),
|
||||
'idnumber' => new lang_string('sort_idnumber', 'admin'),
|
||||
);
|
||||
$temp->add(new admin_setting_configselect('navsortmycoursessort', new lang_string('navsortmycoursessort', 'admin'), new lang_string('navsortmycoursessort_help', 'admin'), 'sortorder', $sortoptions));
|
||||
$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));
|
||||
@@ -200,10 +178,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
new lang_string('courselistshortnames_desc', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configtext('coursesperpage', new lang_string('coursesperpage', 'admin'), new lang_string('configcoursesperpage', 'admin'), 20, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('courseswithsummarieslimit', new lang_string('courseswithsummarieslimit', 'admin'), new lang_string('configcourseswithsummarieslimit', 'admin'), 10, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('courseoverviewfileslimit', new lang_string('courseoverviewfileslimit'),
|
||||
new lang_string('configcourseoverviewfileslimit', 'admin'), 1, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('courseoverviewfilesext', new lang_string('courseoverviewfilesext'),
|
||||
new lang_string('configcourseoverviewfilesext', 'admin'), '.jpg,.gif,.png'));
|
||||
$ADMIN->add('appearance', $temp);
|
||||
|
||||
$temp = new admin_settingpage('ajax', new lang_string('ajaxuse'));
|
||||
|
||||
@@ -1,84 +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/>.
|
||||
|
||||
/**
|
||||
* This file defines settingpages and externalpages under the "badges" section
|
||||
*
|
||||
* @package core
|
||||
* @subpackage badges
|
||||
* @copyright 2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @author Yuliya Bozhko <yuliya.bozhko@totaralms.com>
|
||||
*/
|
||||
|
||||
global $SITE;
|
||||
|
||||
if (!empty($CFG->enablebadges) && ($hassiteconfig || has_any_capability(array(
|
||||
'moodle/badges:viewawarded',
|
||||
'moodle/badges:createbadge',
|
||||
'moodle/badges:manageglobalsettings',
|
||||
'moodle/badges:awardbadge',
|
||||
'moodle/badges:configuremessages',
|
||||
'moodle/badges:configuredetails',
|
||||
'moodle/badges:deletebadge'), $systemcontext))) {
|
||||
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
|
||||
$globalsettings = new admin_settingpage('badgesettings', new lang_string('badgesettings', 'badges'),
|
||||
array('moodle/badges:manageglobalsettings'));
|
||||
|
||||
$globalsettings->add(new admin_setting_configtext('badges_defaultissuername',
|
||||
new lang_string('defaultissuername', 'badges'),
|
||||
new lang_string('defaultissuername_desc', 'badges'),
|
||||
$SITE->fullname ? $SITE->fullname : $SITE->shortname, PARAM_TEXT));
|
||||
|
||||
$globalsettings->add(new admin_setting_configtext('badges_defaultissuercontact',
|
||||
new lang_string('defaultissuercontact', 'badges'),
|
||||
new lang_string('defaultissuercontact_desc', 'badges'),
|
||||
get_config('moodle','supportemail'), PARAM_EMAIL));
|
||||
|
||||
$globalsettings->add(new admin_setting_configtext('badges_badgesalt',
|
||||
new lang_string('badgesalt', 'badges'),
|
||||
new lang_string('badgesalt_desc', 'badges'),
|
||||
'badges' . $SITE->timecreated, PARAM_ALPHANUM));
|
||||
|
||||
$globalsettings->add(new admin_setting_configcheckbox('badges_allowexternalbackpack',
|
||||
new lang_string('allowexternalbackpack', 'badges'),
|
||||
new lang_string('allowexternalbackpack_desc', 'badges'), 1));
|
||||
|
||||
$globalsettings->add(new admin_setting_configcheckbox('badges_allowcoursebadges',
|
||||
new lang_string('allowcoursebadges', 'badges'),
|
||||
new lang_string('allowcoursebadges_desc', 'badges'), 1));
|
||||
|
||||
$ADMIN->add('badges', $globalsettings);
|
||||
|
||||
$ADMIN->add('badges',
|
||||
new admin_externalpage('managebadges',
|
||||
new lang_string('managebadges', 'badges'),
|
||||
new moodle_url($CFG->wwwroot . '/badges/index.php', array('type' => BADGE_TYPE_SITE)),
|
||||
array('moodle/badges:viewawarded')
|
||||
)
|
||||
);
|
||||
|
||||
$ADMIN->add('badges',
|
||||
new admin_externalpage('newbadge',
|
||||
new lang_string('newbadge', 'badges'),
|
||||
new moodle_url($CFG->wwwroot . '/badges/newbadge.php', array('type' => BADGE_TYPE_SITE)),
|
||||
array('moodle/badges:createbadge')
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -8,7 +8,7 @@ if ($hassiteconfig
|
||||
or has_capability('moodle/course:create', $systemcontext)
|
||||
or has_capability('moodle/site:approvecourse', $systemcontext)) { // speedup for non-admins, add all caps used on this page
|
||||
|
||||
$ADMIN->add('courses', new admin_externalpage('coursemgmt', new lang_string('coursemgmt', 'admin'), $CFG->wwwroot . '/course/manage.php',
|
||||
$ADMIN->add('courses', new admin_externalpage('coursemgmt', new lang_string('coursemgmt', 'admin'), $CFG->wwwroot . '/course/index.php?categoryedit=on',
|
||||
array('moodle/category:manage', 'moodle/course:create')));
|
||||
|
||||
/// Course Default Settings Page
|
||||
@@ -80,6 +80,7 @@ if ($hassiteconfig
|
||||
$temp->add(new admin_setting_configselect('moodlecourse/enablecompletion', new lang_string('completion','completion'), '',
|
||||
0, array(0 => new lang_string('completiondisabled','completion'), 1 => new lang_string('completionenabled','completion'))));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('moodlecourse/completionstartonenrol', new lang_string('completionstartonenrol','completion'), new lang_string('completionstartonenrolhelp', 'completion'), 0));
|
||||
$ADMIN->add('courses', $temp);
|
||||
|
||||
/// "courserequests" settingpage
|
||||
@@ -134,11 +135,6 @@ if ($hassiteconfig
|
||||
$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)));
|
||||
$ADMIN->add('backups', $temp);
|
||||
|
||||
// Create a page for general import configuration and defaults.
|
||||
$temp = new admin_settingpage('importgeneralsettings', new lang_string('importgeneralsettings', 'backup'), 'moodle/backup:backupcourse');
|
||||
$temp->add(new admin_setting_configtext('backup/import_general_maxresults', new lang_string('importgeneralmaxresults', 'backup'), new lang_string('importgeneralmaxresults_desc', 'backup'), 10));
|
||||
$ADMIN->add('backups', $temp);
|
||||
|
||||
// Create a page for automated backups configuration and defaults.
|
||||
$temp = new admin_settingpage('automated', new lang_string('automatedsetup','backup'), 'moodle/backup:backupcourse');
|
||||
|
||||
|
||||
+16
-58
@@ -196,9 +196,9 @@ if ($hassiteconfig) {
|
||||
50, PARAM_INT, 3));
|
||||
|
||||
$ADMIN->add('portfoliosettings', $temp);
|
||||
$ADMIN->add('portfoliosettings', new admin_externalpage('portfolionew', new lang_string('addnewportfolio', 'portfolio'), $url, 'moodle/site:config', true));
|
||||
$ADMIN->add('portfoliosettings', new admin_externalpage('portfoliodelete', new lang_string('deleteportfolio', 'portfolio'), $url, 'moodle/site:config', true));
|
||||
$ADMIN->add('portfoliosettings', new admin_externalpage('portfoliocontroller', new lang_string('manageportfolios', 'portfolio'), $url, 'moodle/site:config', true));
|
||||
$ADMIN->add('portfoliosettings', new admin_externalpage('portfolionew', new lang_string('addnewportfolio', 'portfolio'), $url, 'moodle/site:config', true), '', $url);
|
||||
$ADMIN->add('portfoliosettings', new admin_externalpage('portfoliodelete', new lang_string('deleteportfolio', 'portfolio'), $url, 'moodle/site:config', true), '', $url);
|
||||
$ADMIN->add('portfoliosettings', new admin_externalpage('portfoliocontroller', new lang_string('manageportfolios', 'portfolio'), $url, 'moodle/site:config', true), '', $url);
|
||||
|
||||
foreach (portfolio_instances(false, false) as $portfolio) {
|
||||
require_once($CFG->dirroot . '/portfolio/' . $portfolio->get('plugin') . '/lib.php');
|
||||
@@ -210,7 +210,9 @@ if ($hassiteconfig) {
|
||||
$portfolio->get('name'),
|
||||
$url . '?action=edit&pf=' . $portfolio->get('id'),
|
||||
'moodle/site:config'
|
||||
)
|
||||
),
|
||||
$portfolio->get('name'),
|
||||
$url . '?action=edit&pf=' . $portfolio->get('id')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -232,15 +234,20 @@ if ($hassiteconfig) {
|
||||
$temp->add(new admin_setting_configcheckbox('legacyfilesinnewcourses', new lang_string('legacyfilesinnewcourses', 'admin'), new lang_string('legacyfilesinnewcourses_help', 'admin'), 0));
|
||||
$ADMIN->add('repositorysettings', $temp);
|
||||
$ADMIN->add('repositorysettings', new admin_externalpage('repositorynew',
|
||||
new lang_string('addplugin', 'repository'), $url, 'moodle/site:config', true));
|
||||
new lang_string('addplugin', 'repository'), $url, 'moodle/site:config', true),
|
||||
'', $url);
|
||||
$ADMIN->add('repositorysettings', new admin_externalpage('repositorydelete',
|
||||
new lang_string('deleterepository', 'repository'), $url, 'moodle/site:config', true));
|
||||
new lang_string('deleterepository', 'repository'), $url, 'moodle/site:config', true),
|
||||
'', $url);
|
||||
$ADMIN->add('repositorysettings', new admin_externalpage('repositorycontroller',
|
||||
new lang_string('manage', 'repository'), $url, 'moodle/site:config', true));
|
||||
new lang_string('manage', 'repository'), $url, 'moodle/site:config', true),
|
||||
'', $url);
|
||||
$ADMIN->add('repositorysettings', new admin_externalpage('repositoryinstancenew',
|
||||
new lang_string('createrepository', 'repository'), $url, 'moodle/site:config', true));
|
||||
new lang_string('createrepository', 'repository'), $url, 'moodle/site:config', true),
|
||||
'', $url);
|
||||
$ADMIN->add('repositorysettings', new admin_externalpage('repositoryinstanceedit',
|
||||
new lang_string('editrepositoryinstance', 'repository'), $url, 'moodle/site:config', true));
|
||||
new lang_string('editrepositoryinstance', 'repository'), $url, 'moodle/site:config', true),
|
||||
'', $url);
|
||||
foreach ($allplugins['repository'] as $repositorytype) {
|
||||
$repositorytype->load_settings($ADMIN, 'repositorysettings', $hassiteconfig);
|
||||
}
|
||||
@@ -309,7 +316,6 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext))
|
||||
require_once("$CFG->libdir/pluginlib.php");
|
||||
$allplugins = plugin_manager::instance()->get_plugins();
|
||||
}
|
||||
|
||||
// Question behaviour settings.
|
||||
$ADMIN->add('modules', new admin_category('qbehavioursettings', new lang_string('questionbehaviours', 'admin')));
|
||||
$ADMIN->add('qbehavioursettings', new admin_page_manageqbehaviours());
|
||||
@@ -317,54 +323,6 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext))
|
||||
// Question type settings.
|
||||
$ADMIN->add('modules', new admin_category('qtypesettings', new lang_string('questiontypes', 'admin')));
|
||||
$ADMIN->add('qtypesettings', new admin_page_manageqtypes());
|
||||
|
||||
// Question preview defaults.
|
||||
$settings = new admin_settingpage('qdefaultsetting',
|
||||
get_string('questionpreviewdefaults', 'question'),
|
||||
'moodle/question:config');
|
||||
$ADMIN->add('qtypesettings', $settings);
|
||||
|
||||
$settings->add(new admin_setting_heading('qdefaultsetting_preview_options',
|
||||
'', get_string('questionpreviewdefaults_desc', 'question')));
|
||||
|
||||
// These keys are question_display_options::HIDDEN and VISIBLE.
|
||||
$hiddenofvisible = array(
|
||||
0 => get_string('notshown', 'question'),
|
||||
1 => get_string('shown', 'question'),
|
||||
);
|
||||
|
||||
$settings->add(new admin_setting_question_behaviour('question_preview/behaviour',
|
||||
get_string('howquestionsbehave', 'question'), '',
|
||||
'deferredfeedback'));
|
||||
|
||||
$settings->add(new admin_setting_configselect('question_preview/correctness',
|
||||
get_string('whethercorrect', 'question'), '', 1, $hiddenofvisible));
|
||||
|
||||
// These keys are question_display_options::HIDDEN, MARK_ONLY and MARK_AND_MAX.
|
||||
$marksoptions = array(
|
||||
0 => get_string('notshown', 'question'),
|
||||
1 => get_string('showmaxmarkonly', 'question'),
|
||||
2 => get_string('showmarkandmax', 'question'),
|
||||
);
|
||||
$settings->add(new admin_setting_configselect('question_preview/marks',
|
||||
get_string('marks', 'question'), '', 1, $marksoptions));
|
||||
|
||||
$settings->add(new admin_setting_configselect('question_preview/markdp',
|
||||
get_string('decimalplacesingrades', 'question'), '', 2, array(0, 1, 2, 3, 4, 5, 6, 7)));
|
||||
|
||||
$settings->add(new admin_setting_configselect('question_preview/feedback',
|
||||
get_string('specificfeedback', 'question'), '', 1, $hiddenofvisible));
|
||||
|
||||
$settings->add(new admin_setting_configselect('question_preview/generalfeedback',
|
||||
get_string('generalfeedback', 'question'), '', 1, $hiddenofvisible));
|
||||
|
||||
$settings->add(new admin_setting_configselect('question_preview/rightanswer',
|
||||
get_string('rightanswer', 'question'), '', 1, $hiddenofvisible));
|
||||
|
||||
$settings->add(new admin_setting_configselect('question_preview/history',
|
||||
get_string('responsehistory', 'question'), '', 0, $hiddenofvisible));
|
||||
|
||||
// Settings for particular question types.
|
||||
foreach ($allplugins['qtype'] as $qtype) {
|
||||
$qtype->load_settings($ADMIN, 'qtypesettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
@@ -59,11 +59,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$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);
|
||||
$temp->add(new admin_setting_configselect('lockoutthreshold', new lang_string('lockoutthreshold', 'admin'), new lang_string('lockoutthreshold_desc', 'admin'), 0, $options));
|
||||
$temp->add(new admin_setting_configduration('lockoutwindow', new lang_string('lockoutwindow', 'admin'), new lang_string('lockoutwindow_desc', 'admin'), 60*30));
|
||||
$temp->add(new admin_setting_configduration('lockoutduration', new lang_string('lockoutduration', 'admin'), new lang_string('lockoutduration_desc', 'admin'), 60*30));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('passwordpolicy', new lang_string('passwordpolicy', 'admin'), new lang_string('configpasswordpolicy', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configtext('minpasswordlength', new lang_string('minpasswordlength', 'admin'), new lang_string('configminpasswordlength', 'admin'), 8, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('minpassworddigits', new lang_string('minpassworddigits', 'admin'), new lang_string('configminpassworddigits', 'admin'), 1, PARAM_INT));
|
||||
|
||||
@@ -7,7 +7,9 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
|
||||
// "systempaths" settingpage
|
||||
$temp = new admin_settingpage('systempaths', new lang_string('systempaths','admin'));
|
||||
|
||||
$temp->add(new admin_setting_configselect('gdversion', new lang_string('gdversion','admin'), new lang_string('configgdversion', 'admin'), check_gd_version(), array('0' => new lang_string('gdnot'),
|
||||
'1' => new lang_string('gd1'),
|
||||
'2' => new lang_string('gd2'))));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'), new lang_string('configpathtodu', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'), new lang_string('edhelpaspellpath'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'), new lang_string('pathtodot_help', 'admin'), ''));
|
||||
|
||||
@@ -41,6 +41,4 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$checkbox->set_affects_modinfo(true);
|
||||
|
||||
$optionalsubsystems->add(new admin_setting_configcheckbox('enableplagiarism', new lang_string('enableplagiarism','plagiarism'), new lang_string('configenableplagiarism','plagiarism'), 0));
|
||||
|
||||
$optionalsubsystems->add(new admin_setting_configcheckbox('enablebadges', new lang_string('enablebadges', 'badges'), new lang_string('configenablebadges', 'badges'), 1));
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('root', new admin_category('users', new lang_string('users','admin')));
|
||||
$ADMIN->add('root', new admin_category('courses', new lang_string('courses','admin')));
|
||||
$ADMIN->add('root', new admin_category('grades', new lang_string('grades')));
|
||||
$ADMIN->add('root', new admin_category('badges', new lang_string('badges'), (isset($CFG->enablebadges) && $CFG->enablebadges == 0)));
|
||||
$ADMIN->add('root', new admin_category('location', new lang_string('location','admin')));
|
||||
$ADMIN->add('root', new admin_category('language', new lang_string('language')));
|
||||
$ADMIN->add('root', new admin_category('modules', new lang_string('plugins', 'admin')));
|
||||
|
||||
@@ -150,7 +150,6 @@ if ($hassiteconfig
|
||||
'department' => new lang_string('department'),
|
||||
'institution' => new lang_string('institution'),
|
||||
)));
|
||||
$temp->add(new admin_setting_configtext('maxusersperpage', new lang_string('maxusersperpage','admin'), new lang_string('configmaxusersperpage','admin'), 100, PARAM_INT));
|
||||
$temp->add(new admin_setting_configcheckbox('enablegravatar', new lang_string('enablegravatar', 'admin'), new lang_string('enablegravatar_help', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configtext('gravatardefaulturl', new lang_string('gravatardefaulturl', 'admin'), new lang_string('gravatardefaulturl_help', 'admin'), 'mm'));
|
||||
}
|
||||
|
||||
@@ -1,97 +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/>.
|
||||
|
||||
/**
|
||||
* Steps definitions related with administration.
|
||||
*
|
||||
* @package core
|
||||
* @category test
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
|
||||
|
||||
require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
|
||||
require_once(__DIR__ . '/../../../lib/behat/behat_field_manager.php');
|
||||
|
||||
use Behat\Gherkin\Node\TableNode as TableNode,
|
||||
Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
|
||||
|
||||
/**
|
||||
* Site administration level steps definitions.
|
||||
*
|
||||
* @package core
|
||||
* @category test
|
||||
* @copyright 2013 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_admin extends behat_base {
|
||||
|
||||
/**
|
||||
* Sets the specified site settings. A table with | Setting label | value | is expected.
|
||||
*
|
||||
* @Given /^I set the following administration settings values:$/
|
||||
* @param TableNode $table
|
||||
*/
|
||||
public function i_set_the_following_administration_settings_values(TableNode $table) {
|
||||
|
||||
if (!$data = $table->getRowsHash()) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($data as $label => $value) {
|
||||
|
||||
// We expect admin block to be visible, otherwise go to homepage.
|
||||
if (!$this->getSession()->getPage()->find('css', '.block_settings')) {
|
||||
$this->getSession()->visit($this->locate_path('/'));
|
||||
$this->getSession()->wait(self::TIMEOUT, '(document.readyState === "complete")');
|
||||
}
|
||||
|
||||
// Search by label.
|
||||
$searchbox = $this->find_field('Search in settings');
|
||||
$searchbox->setValue($label);
|
||||
$submitsearch = $this->find('css', 'form.adminsearchform input[type=submit]');
|
||||
$submitsearch->press();
|
||||
|
||||
$this->getSession()->wait(self::TIMEOUT, '(document.readyState === "complete")');
|
||||
|
||||
// Admin settings does not use the same DOM structure than other moodle forms
|
||||
// but we also need to use lib/behat/form_field/* to deal with the different moodle form elements.
|
||||
$exception = new ElementNotFoundException($this->getSession(), '"' . $label . '" administration setting ');
|
||||
$fieldxpath = "//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]
|
||||
[@id=//label[contains(normalize-space(string(.)), '" . $label . "')]/@for]";
|
||||
$fieldnode = $this->find('xpath', $fieldxpath, $exception);
|
||||
$formfieldtypenode = $this->find('xpath', $fieldxpath . "/ancestor::div[@class='form-setting']
|
||||
/child::div[contains(concat(' ', @class, ' '), ' form-')]/child::*/parent::div");
|
||||
|
||||
// Getting the class which contains the field type.
|
||||
$classes = explode(' ', $formfieldtypenode->getAttribute('class'));
|
||||
foreach ($classes as $class) {
|
||||
if (substr($class, 0, 5) == 'form-') {
|
||||
$type = substr($class, 5);
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiating the appropiate field type.
|
||||
$field = behat_field_manager::get_field_instance($type, $fieldnode, $this->getSession());
|
||||
$field->set_value($value);
|
||||
|
||||
$this->find_button('Save changes')->press();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
@admin
|
||||
Feature: Display extended course names
|
||||
In order to display more info about the courses
|
||||
As a moodle admin
|
||||
I need to display courses short names along with courses full names
|
||||
|
||||
Background:
|
||||
Given the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Course fullname | C_shortname | 0 |
|
||||
And I log in as "admin"
|
||||
|
||||
Scenario: Courses list without extended course names (default value)
|
||||
Then I should see "Course fullname"
|
||||
And I should not see "C_shortname Course fullname"
|
||||
|
||||
Scenario: Courses list with extended course names
|
||||
Given I click on "Courses" "link" in the "//div[@id='settingsnav']//descendant::li[contains(concat(' ', @class, ' '), ' type_setting ')][not(contains(., 'Site administration'))][contains(., 'Appearance')]" "xpath_element"
|
||||
And I check "Display extended course names"
|
||||
When I press "Save changes"
|
||||
And I am on homepage
|
||||
Then I should see "C_shortname Course fullname"
|
||||
@@ -1,46 +0,0 @@
|
||||
@admin @_only_local
|
||||
Feature: Upload users
|
||||
In order to add users to the system
|
||||
As a moodle admin
|
||||
I need to upload files containing the users data
|
||||
|
||||
@javascript
|
||||
Scenario: Upload users enrolling them on courses and groups
|
||||
Given the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Maths | math102 | 0 |
|
||||
And the following "groups" exists:
|
||||
| name | course | idnumber |
|
||||
| Section 1 | math102 | S1 |
|
||||
| Section 3 | math102 | S3 |
|
||||
And I log in as "admin"
|
||||
And I expand "Front page settings" node
|
||||
And I expand "Site administration" node
|
||||
And I expand "Users" node
|
||||
And I expand "Accounts" node
|
||||
And I follow "Upload users"
|
||||
When I upload "lib/tests/fixtures/upload_users.csv" file to "File" filepicker
|
||||
And I press "Upload users"
|
||||
Then I should see "Upload users preview"
|
||||
And I should see "Tom"
|
||||
And I should see "Jones"
|
||||
And I should see "verysecret"
|
||||
And I should see "jonest@someplace.edu"
|
||||
And I should see "Reznor"
|
||||
And I should see "course1"
|
||||
And I should see "math102"
|
||||
And I should see "group1"
|
||||
And I should see "Section 1"
|
||||
And I press "Upload users"
|
||||
And I press "Continue"
|
||||
And I follow "Browse list of users"
|
||||
And I should see "Tom Jones"
|
||||
And I should see "Trent Reznor"
|
||||
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"
|
||||
And I select "Section 1 (1)" from "groups"
|
||||
And I wait "4" seconds
|
||||
And the "members" select box should contain "Tom Jones"
|
||||
@@ -32,7 +32,7 @@ require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/upgradable
|
||||
|
||||
require_sesskey();
|
||||
|
||||
// This calls require_login and checks moodle/site:config.
|
||||
// admin_externalpage_setup calls require_login and checks moodle/site:config
|
||||
admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('batchupgrade'));
|
||||
|
||||
$PAGE->set_pagelayout('maintenance');
|
||||
@@ -46,8 +46,7 @@ if (!$confirm) {
|
||||
die();
|
||||
}
|
||||
raise_memory_limit(MEMORY_EXTRA);
|
||||
// Release session.
|
||||
session_get_instance()->write_close();
|
||||
session_get_instance()->write_close(); // release session
|
||||
|
||||
echo $renderer->header();
|
||||
echo $renderer->heading(get_string('batchupgrade', 'tool_assignmentupgrade'));
|
||||
@@ -63,8 +62,7 @@ $total = count($assignmentids);
|
||||
foreach ($assignmentids as $assignmentid) {
|
||||
list($summary, $success, $log) = tool_assignmentupgrade_upgrade_assignment($assignmentid);
|
||||
$current += 1;
|
||||
$params = array('current'=>$current, 'total'=>$total);
|
||||
echo $renderer->heading(get_string('upgradeprogress', 'tool_assignmentupgrade', $params), 3);
|
||||
echo $renderer->heading(get_string('upgradeprogress', 'tool_assignmentupgrade', array('current'=>$current, 'total'=>$total)), 3);
|
||||
echo $renderer->convert_assignment_result($summary, $success, $log);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ require_once(dirname(__FILE__) . '/../../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/locallib.php');
|
||||
|
||||
// This calls require_login and checks moodle/site:config.
|
||||
// admin_externalpage_setup calls require_login and checks moodle/site:config
|
||||
admin_externalpage_setup('assignmentupgrade');
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_assignmentupgrade');
|
||||
|
||||
@@ -29,7 +29,7 @@ require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/upgradable
|
||||
require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/upgradableassignmentsbatchform.php');
|
||||
require_once($CFG->dirroot . '/'.$CFG->admin.'/tool/assignmentupgrade/paginationform.php');
|
||||
|
||||
// This calls require_login and checks moodle/site:config.
|
||||
// admin_externalpage_setup calls require_login and checks moodle/site:config
|
||||
admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('listnotupgraded'));
|
||||
$PAGE->navbar->add(get_string('listnotupgraded', 'tool_assignmentupgrade'));
|
||||
|
||||
@@ -57,3 +57,4 @@ if ($data && $data->selectedassignments != '' || $data && isset($data->upgradeal
|
||||
echo $renderer->assignment_list_page($assignments, $batchform, $paginationform);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -51,24 +51,17 @@ class tool_assignmentupgrade_batchoperationconfirm implements renderable {
|
||||
* Constructor for this class
|
||||
* @param stdClass $data - The data from the previous batch form
|
||||
*/
|
||||
public function __construct($data) {
|
||||
function __construct($data) {
|
||||
if (isset($data->upgradeselected)) {
|
||||
$this->continuemessage = get_string('upgradeselectedcount',
|
||||
'tool_assignmentupgrade',
|
||||
count(explode(',', $data->selectedassignments)));
|
||||
$urlparams = array('upgradeselected'=>'1',
|
||||
'confirm'=>'1',
|
||||
'sesskey'=>sesskey(),
|
||||
'selected'=>$data->selectedassignments);
|
||||
$this->continueurl = new moodle_url('/admin/tool/assignmentupgrade/batchupgrade.php', $urlparams);
|
||||
$this->continuemessage = get_string('upgradeselectedcount', 'tool_assignmentupgrade', count(explode(',', $data->selectedassignments)));
|
||||
$this->continueurl = new moodle_url('/admin/tool/assignmentupgrade/batchupgrade.php', array('upgradeselected'=>'1', 'confirm'=>'1', 'sesskey'=>sesskey(), 'selected'=>$data->selectedassignments));
|
||||
} else if (isset($data->upgradeall)) {
|
||||
if (!tool_assignmentupgrade_any_upgradable_assignments()) {
|
||||
$this->continuemessage = get_string('noassignmentstoupgrade', 'tool_assignmentupgrade');
|
||||
$this->continueurl = '';
|
||||
} else {
|
||||
$this->continuemessage = get_string('upgradeallconfirm', 'tool_assignmentupgrade');
|
||||
$urlparams = array('upgradeall'=>'1', 'confirm'=>'1', 'sesskey'=>sesskey());
|
||||
$this->continueurl = new moodle_url('/admin/tool/assignmentupgrade/batchupgrade.php', $urlparams);
|
||||
$this->continueurl = new moodle_url('/admin/tool/assignmentupgrade/batchupgrade.php', array('upgradeall'=>'1', 'confirm'=>'1', 'sesskey'=>sesskey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,8 +86,7 @@ class tool_assignmentupgrade_action {
|
||||
/**
|
||||
* Constructor to set the fields.
|
||||
*
|
||||
* In order to create a new tool_assignmentupgrade_action instance you must use
|
||||
* the tool_assignmentupgrade_action::make
|
||||
* In order to create a new tool_assignmentupgrade_action instance you must use the tool_assignmentupgrade_action::make
|
||||
* method.
|
||||
*
|
||||
* @param string $name the name of this action.
|
||||
@@ -128,13 +120,8 @@ class tool_assignmentupgrade_action {
|
||||
function tool_assignmentupgrade_any_upgradable_assignments() {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot . '/mod/assign/locallib.php');
|
||||
// First find all the unique assignment types.
|
||||
$types = $DB->get_records_sql('SELECT plugin AS assignmenttype,
|
||||
value AS version
|
||||
FROM {config_plugins}
|
||||
WHERE
|
||||
name = ? AND
|
||||
plugin LIKE ?', array('version', 'assignment_%'));
|
||||
// first find all the unique assignment types
|
||||
$types = $DB->get_records_sql('SELECT plugin AS assignmenttype, value AS version FROM {config_plugins} WHERE name = ? AND plugin LIKE ?', array('version', 'assignment_%'));
|
||||
|
||||
$upgradabletypes = array();
|
||||
|
||||
@@ -146,7 +133,7 @@ function tool_assignmentupgrade_any_upgradable_assignments() {
|
||||
}
|
||||
list($sql, $params) = $DB->get_in_or_equal($upgradabletypes);
|
||||
|
||||
$count = $DB->count_records_sql('SELECT COUNT(id) FROM {assignment} WHERE assignmenttype ' . $sql, $params);
|
||||
$count = $DB->count_records_sql('SELECT COUNT(id) from {assignment} where assignmenttype ' . $sql, $params);
|
||||
|
||||
return $count > 0;
|
||||
}
|
||||
@@ -158,14 +145,8 @@ function tool_assignmentupgrade_any_upgradable_assignments() {
|
||||
function tool_assignmentupgrade_load_all_upgradable_assignmentids() {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot . '/mod/assign/locallib.php');
|
||||
// First find all the unique assignment types.
|
||||
$types = $DB->get_records_sql('SELECT
|
||||
plugin AS assignmenttype,
|
||||
value AS version
|
||||
FROM {config_plugins}
|
||||
WHERE
|
||||
name = ? AND
|
||||
plugin LIKE ?', array('version', 'assignment_%'));
|
||||
// first find all the unique assignment types
|
||||
$types = $DB->get_records_sql('SELECT plugin AS assignmenttype, value AS version FROM {config_plugins} WHERE name = ? AND plugin LIKE ?', array('version', 'assignment_%'));
|
||||
|
||||
$upgradabletypes = array();
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
M.tool_assignmentupgrade = {
|
||||
init_upgrade_table: function(Y) {
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
require_once($CFG->libdir.'/formslib.php');
|
||||
|
||||
/** Include formslib.php */
|
||||
require_once ($CFG->libdir.'/formslib.php');
|
||||
|
||||
/**
|
||||
* Assignment upgrade table display options
|
||||
@@ -37,20 +39,20 @@ class tool_assignmentupgrade_pagination_form extends moodleform {
|
||||
/**
|
||||
* Define this form - called from the parent constructor
|
||||
*/
|
||||
public function definition() {
|
||||
function definition() {
|
||||
$mform = $this->_form;
|
||||
$instance = $this->_customdata;
|
||||
|
||||
$mform->addElement('header', 'general', get_string('assignmentsperpage', 'tool_assignmentupgrade'));
|
||||
// Visible elements.
|
||||
// visible elements
|
||||
$options = array(10=>'10', 20=>'20', 50=>'50', 100=>'100');
|
||||
$mform->addElement('select', 'perpage', get_string('assignmentsperpage', 'assign'), $options);
|
||||
|
||||
// Hidden params.
|
||||
// hidden params
|
||||
$mform->addElement('hidden', 'action', 'saveoptions');
|
||||
$mform->setType('action', PARAM_ALPHA);
|
||||
|
||||
// Buttons.
|
||||
// buttons
|
||||
$this->add_action_buttons(false, get_string('updatetable', 'tool_assignmentupgrade'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,9 +100,7 @@ class tool_assignmentupgrade_renderer extends plugin_renderer_base {
|
||||
$output = '';
|
||||
|
||||
if ($confirm->continueurl) {
|
||||
$output .= $this->output->confirm($confirm->continuemessage,
|
||||
$confirm->continueurl,
|
||||
tool_assignmentupgrade_url('listnotupgraded'));
|
||||
$output .= $this->output->confirm($confirm->continuemessage, $confirm->continueurl, tool_assignmentupgrade_url('listnotupgraded'));
|
||||
} else {
|
||||
$output .= $this->output->box($confirm->continuemessage);
|
||||
$output .= $this->output->continue_button(tool_assignmentupgrade_url('listnotupgraded'));
|
||||
@@ -117,9 +115,7 @@ class tool_assignmentupgrade_renderer extends plugin_renderer_base {
|
||||
* @param tool_assignmentupgrade_pagination_form $paginationform Form which contains the preferences for paginating the table
|
||||
* @return string html to output.
|
||||
*/
|
||||
public function assignment_list_page(tool_assignmentupgrade_assignments_table $assignments,
|
||||
tool_assignmentupgrade_batchoperations_form $batchform,
|
||||
tool_assignmentupgrade_pagination_form $paginationform) {
|
||||
public function assignment_list_page(tool_assignmentupgrade_assignments_table $assignments, tool_assignmentupgrade_batchoperations_form $batchform, tool_assignmentupgrade_pagination_form $paginationform) {
|
||||
$output = '';
|
||||
$output .= $this->header();
|
||||
$this->page->requires->js_init_call('M.tool_assignmentupgrade.init_upgrade_table', array());
|
||||
@@ -165,8 +161,7 @@ class tool_assignmentupgrade_renderer extends plugin_renderer_base {
|
||||
$output .= $this->container(get_string('conversionfailed', 'tool_assignmentupgrade', $log));
|
||||
} else {
|
||||
$output .= $this->container(get_string('upgradeassignmentsuccess', 'tool_assignmentupgrade'));
|
||||
$url = new moodle_url('/course/view.php', array('id'=>$assignmentsummary->courseid));
|
||||
$output .= $this->container(html_writer::link($url, get_string('viewcourse', 'tool_assignmentupgrade')));
|
||||
$output .= $this->container(html_writer::link(new moodle_url('/course/view.php', array('id'=>$assignmentsummary->courseid)) ,get_string('viewcourse', 'tool_assignmentupgrade')));
|
||||
}
|
||||
$output .= $this->container_end();
|
||||
|
||||
|
||||
@@ -24,9 +24,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
if ($hassiteconfig) {
|
||||
// Needs this condition or there is error on login page.
|
||||
if ($hassiteconfig) { // needs this condition or there is error on login page
|
||||
$ADMIN->add('root', new admin_externalpage('assignmentupgrade',
|
||||
get_string('pluginname', 'tool_assignmentupgrade'),
|
||||
new moodle_url('/admin/tool/assignmentupgrade/index.php')));
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,12 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
require_once($CFG->libdir.'/formslib.php');
|
||||
|
||||
/** Include formslib.php */
|
||||
require_once ($CFG->libdir.'/formslib.php');
|
||||
|
||||
/**
|
||||
* Assignment upgrade batch operations form.
|
||||
* Assignment upgrade batch operations form
|
||||
*
|
||||
* @package tool_assignmentupgrade
|
||||
* @copyright 2012 NetSpot {@link http://www.netspot.com.au}
|
||||
@@ -35,14 +37,14 @@ require_once($CFG->libdir.'/formslib.php');
|
||||
*/
|
||||
class tool_assignmentupgrade_batchoperations_form extends moodleform {
|
||||
/**
|
||||
* Define this form - is called from parent constructor.
|
||||
* Define this form - is called from parent constructor
|
||||
*/
|
||||
public function definition() {
|
||||
function definition() {
|
||||
$mform = $this->_form;
|
||||
$instance = $this->_customdata;
|
||||
|
||||
$mform->addElement('header', 'general', get_string('batchoperations', 'tool_assignmentupgrade'));
|
||||
// Visible elements.
|
||||
// visible elements
|
||||
$mform->addElement('hidden', 'selectedassignments', '', array('class'=>'selectedassignments'));
|
||||
|
||||
$mform->addElement('submit', 'upgradeselected', get_string('upgradeselected', 'tool_assignmentupgrade'));
|
||||
|
||||
@@ -36,7 +36,6 @@ require_once($CFG->dirroot.'/mod/assign/locallib.php');
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_assignmentupgrade_assignments_table extends table_sql implements renderable {
|
||||
|
||||
/** @var int $perpage */
|
||||
private $perpage = 10;
|
||||
/** @var int $rownum (global index of current row in table) */
|
||||
@@ -47,13 +46,12 @@ class tool_assignmentupgrade_assignments_table extends table_sql implements rend
|
||||
public $anyupgradableassignments = false;
|
||||
|
||||
/**
|
||||
* This table loads a list of the old assignment instances and tests them to see
|
||||
* if they can be upgraded
|
||||
* This table loads a list of the old assignment instances and tests them to see if they can be upgraded
|
||||
*
|
||||
* @param int $perpage How many per page
|
||||
* @param int $rowoffset The starting row for pagination
|
||||
*/
|
||||
public function __construct($perpage, $rowoffset=0) {
|
||||
function __construct($perpage, $rowoffset=0) {
|
||||
global $PAGE;
|
||||
parent::__construct('tool_assignmentupgrade_assignments');
|
||||
$this->perpage = $perpage;
|
||||
@@ -63,17 +61,12 @@ class tool_assignmentupgrade_assignments_table extends table_sql implements rend
|
||||
|
||||
$this->anyupgradableassignments = tool_assignmentupgrade_any_upgradable_assignments();
|
||||
|
||||
// Do some business - then set the sql.
|
||||
// do some business - then set the sql
|
||||
if ($rowoffset) {
|
||||
$this->rownum = $rowoffset - 1;
|
||||
}
|
||||
|
||||
$fields = 'a.id as id,
|
||||
a.name as name,
|
||||
a.assignmenttype as type,
|
||||
c.shortname as courseshortname,
|
||||
c.id as courseid,
|
||||
COUNT(s.id) as submissioncount';
|
||||
$fields = 'a.id as id, a.name as name, a.assignmenttype as type, c.shortname as courseshortname, c.id as courseid, COUNT(s.id) as submissioncount';
|
||||
$from = '{assignment} a JOIN {course} c ON a.course = c.id ' .
|
||||
' LEFT JOIN {assignment_submissions} s ON a.id = s.assignment';
|
||||
|
||||
@@ -87,10 +80,7 @@ class tool_assignmentupgrade_assignments_table extends table_sql implements rend
|
||||
$headers = array();
|
||||
|
||||
$columns[] = 'select';
|
||||
$headers[] = get_string('select', 'tool_assignmentupgrade') .
|
||||
'<div class="selectall">' .
|
||||
'<input type="checkbox" name="selectall" title="' . get_string('selectall') . '"/>' .
|
||||
'</div>';
|
||||
$headers[] = get_string('select', 'tool_assignmentupgrade') . '<div class="selectall"><input type="checkbox" name="selectall" title="' . get_string('selectall') . '"/></div>';
|
||||
$columns[] = 'upgradable';
|
||||
$headers[] = get_string('upgradable', 'tool_assignmentupgrade');
|
||||
$columns[] = 'id';
|
||||
@@ -104,7 +94,7 @@ class tool_assignmentupgrade_assignments_table extends table_sql implements rend
|
||||
$columns[] = 'submissioncount';
|
||||
$headers[] = get_string('submissions', 'tool_assignmentupgrade');
|
||||
|
||||
// Set the columns.
|
||||
// set the columns
|
||||
$this->define_columns($columns);
|
||||
$this->define_headers($headers);
|
||||
$this->no_sorting('upgradable');
|
||||
@@ -116,7 +106,7 @@ class tool_assignmentupgrade_assignments_table extends table_sql implements rend
|
||||
*
|
||||
* @return int The number of rows per page
|
||||
*/
|
||||
public function get_rows_per_page() {
|
||||
function get_rows_per_page() {
|
||||
return $this->perpage;
|
||||
}
|
||||
|
||||
@@ -126,9 +116,9 @@ class tool_assignmentupgrade_assignments_table extends table_sql implements rend
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_name(stdClass $row) {
|
||||
$url = new moodle_url('/mod/assignment/view.php', array('a' => $row->id));
|
||||
return html_writer::link($url, $row->name);
|
||||
function col_name(stdClass $row) {
|
||||
return html_writer::link(new moodle_url('/mod/assignment/view.php',
|
||||
array('a' => $row->id)), $row->name);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,11 +128,10 @@ class tool_assignmentupgrade_assignments_table extends table_sql implements rend
|
||||
* @param stdClass $row (contains cached result from previous upgradable check)
|
||||
* @return string
|
||||
*/
|
||||
public function col_upgradable(stdClass $row) {
|
||||
function col_upgradable(stdClass $row) {
|
||||
if ($row->upgradable) {
|
||||
$urlparams = array('id' => $row->id, 'sesskey' => sesskey());
|
||||
$url = new moodle_url('/admin/tool/assignmentupgrade/upgradesingleconfirm.php', $urlparams);
|
||||
return html_writer::link($url, get_string('supported', 'tool_assignmentupgrade'));
|
||||
return html_writer::link(new moodle_url('/admin/tool/assignmentupgrade/upgradesingleconfirm.php',
|
||||
array('id' => $row->id, 'sesskey' => sesskey())), get_string('supported', 'tool_assignmentupgrade'));
|
||||
} else {
|
||||
return get_string('notsupported', 'tool_assignmentupgrade');
|
||||
}
|
||||
@@ -154,7 +143,7 @@ class tool_assignmentupgrade_assignments_table extends table_sql implements rend
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_select(stdClass $row) {
|
||||
function col_select(stdClass $row) {
|
||||
global $CFG;
|
||||
$version = get_config('assignment_' . $row->type, 'version');
|
||||
require_once($CFG->dirroot . '/mod/assign/locallib.php');
|
||||
|
||||
@@ -30,11 +30,8 @@ require_sesskey();
|
||||
|
||||
$assignmentid = required_param('id', PARAM_INT);
|
||||
|
||||
// This calls require_login and checks moodle/site:config.
|
||||
admin_externalpage_setup('assignmentupgrade',
|
||||
'',
|
||||
array(),
|
||||
tool_assignmentupgrade_url('upgradesingle', array('id' => $assignmentid)));
|
||||
// admin_externalpage_setup calls require_login and checks moodle/site:config
|
||||
admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('upgradesingle', array('id' => $assignmentid)));
|
||||
|
||||
$PAGE->navbar->add(get_string('upgradesingle', 'tool_assignmentupgrade'));
|
||||
$renderer = $PAGE->get_renderer('tool_assignmentupgrade');
|
||||
|
||||
@@ -30,11 +30,8 @@ require_sesskey();
|
||||
|
||||
$assignmentid = required_param('id', PARAM_INT);
|
||||
|
||||
// This calls require_login and checks moodle/site:config.
|
||||
admin_externalpage_setup('assignmentupgrade',
|
||||
'',
|
||||
array(),
|
||||
tool_assignmentupgrade_url('upgradesingle', array('id' => $assignmentid)));
|
||||
// admin_externalpage_setup calls require_login and checks moodle/site:config
|
||||
admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('upgradesingle', array('id' => $assignmentid)));
|
||||
|
||||
$PAGE->navbar->add(get_string('upgradesingle', 'tool_assignmentupgrade'));
|
||||
$renderer = $PAGE->get_renderer('tool_assignmentupgrade');
|
||||
|
||||
@@ -1,98 +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 script to set up all the behat test environment.
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2013 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!
|
||||
}
|
||||
|
||||
// Is not really necessary but adding it as is a CLI_SCRIPT.
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
// Basic functions.
|
||||
require_once(__DIR__ . '/../../../../lib/clilib.php');
|
||||
require_once(__DIR__ . '/../../../../lib/behat/lib.php');
|
||||
|
||||
// Changing the cwd to admin/tool/behat/cli.
|
||||
chdir(__DIR__);
|
||||
$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) {
|
||||
// Behat and dependencies are installed and we need to install the test site.
|
||||
passthru("php util.php --install", $code);
|
||||
if ($code != 0) {
|
||||
exit($code);
|
||||
}
|
||||
|
||||
} else if ($code == BEHAT_EXITCODE_REINSTALL) {
|
||||
// Test site data is outdated.
|
||||
passthru("php util.php --drop", $code);
|
||||
if ($code != 0) {
|
||||
exit($code);
|
||||
}
|
||||
|
||||
passthru("php util.php --install", $code);
|
||||
if ($code != 0) {
|
||||
exit($code);
|
||||
}
|
||||
|
||||
} else if ($code == BEHAT_EXITCODE_COMPOSER) {
|
||||
// Missing Behat dependencies.
|
||||
|
||||
// Changing to moodle dirroot to run composer related commands at project level.
|
||||
chdir(__DIR__ . '/../../../..');
|
||||
if (!file_exists(__DIR__ . '/../../../../composer.phar')) {
|
||||
passthru("curl http://getcomposer.org/installer | php", $code);
|
||||
if ($code != 0) {
|
||||
exit($code);
|
||||
}
|
||||
}
|
||||
|
||||
passthru("php composer.phar update --dev", $code);
|
||||
if ($code != 0) {
|
||||
exit($code);
|
||||
}
|
||||
|
||||
// Returning to admin/tool/behat/cli.
|
||||
chdir(__DIR__);
|
||||
passthru("php util.php --install", $code);
|
||||
if ($code != 0) {
|
||||
exit($code);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Generic error, we just output it.
|
||||
echo implode("\n", $output)."\n";
|
||||
exit($code);
|
||||
}
|
||||
|
||||
// Enable editing mode according to config.php vars.
|
||||
passthru("php util.php --enable", $code);
|
||||
if ($code != 0) {
|
||||
exit($code);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
@@ -1,193 +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,
|
||||
'drop' => false,
|
||||
'enable' => false,
|
||||
'disable' => false,
|
||||
'diag' => false
|
||||
),
|
||||
array(
|
||||
'h' => 'help'
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Checking util.php CLI script usage.
|
||||
$help = "
|
||||
Behat utilities to manage the test environment
|
||||
|
||||
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
|
||||
|
||||
-h, --help Print out this help
|
||||
|
||||
Example from Moodle root directory:
|
||||
\$ php admin/tool/behat/cli/util.php --enable
|
||||
|
||||
More info in http://docs.moodle.org/dev/Acceptance_testing#Running_tests
|
||||
";
|
||||
|
||||
if (!empty($options['help'])) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
// Checking $CFG->behat_* vars and values.
|
||||
define('BEHAT_UTIL', true);
|
||||
define('CLI_SCRIPT', true);
|
||||
define('ABORT_AFTER_CONFIG', true);
|
||||
define('NO_OUTPUT_BUFFERING', true);
|
||||
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('log_errors', '1');
|
||||
|
||||
// Getting $CFG data.
|
||||
require_once(__DIR__ . '/../../../../config.php');
|
||||
|
||||
// CFG->behat_prefix must be set and with value different than CFG->prefix and phpunit_prefix.
|
||||
if (empty($CFG->behat_prefix) ||
|
||||
($CFG->behat_prefix == $CFG->prefix) ||
|
||||
(!empty($CFG->phpunit_prefix) && $CFG->behat_prefix == $CFG->phpunit_prefix)) {
|
||||
behat_error(BEHAT_EXITCODE_CONFIG,
|
||||
'Define $CFG->behat_prefix in config.php with a value different than $CFG->prefix and $CFG->phpunit_prefix');
|
||||
}
|
||||
|
||||
// CFG->behat_dataroot must be set and with value different than CFG->dataroot and phpunit_dataroot.
|
||||
if (empty($CFG->behat_dataroot) ||
|
||||
($CFG->behat_dataroot == $CFG->dataroot) ||
|
||||
(!empty($CFG->phpunit_dataroot) && $CFG->behat_dataroot == $CFG->phpunit_dataroot)) {
|
||||
behat_error(BEHAT_EXITCODE_CONFIG,
|
||||
'Define $CFG->behat_dataroot in config.php with a value different than $CFG->dataroot and $CFG->phpunit_dataroot');
|
||||
}
|
||||
|
||||
// Create behat_dataroot if it doesn't exists.
|
||||
if (!file_exists($CFG->behat_dataroot)) {
|
||||
if (!mkdir($CFG->behat_dataroot, $CFG->directorypermissions)) {
|
||||
behat_error(BEHAT_EXITCODE_PERMISSIONS, '$CFG->behat_dataroot directory can not be created');
|
||||
}
|
||||
}
|
||||
if (!is_dir($CFG->behat_dataroot) || !is_writable($CFG->behat_dataroot)) {
|
||||
behat_error(BEHAT_EXITCODE_PERMISSIONS, '$CFG->behat_dataroot directory has no permissions or is not a directory');
|
||||
}
|
||||
|
||||
// Check that the directory does not contains other things.
|
||||
if (!file_exists("$CFG->behat_dataroot/behattestdir.txt")) {
|
||||
if ($dh = opendir($CFG->behat_dataroot)) {
|
||||
while (($file = readdir($dh)) !== false) {
|
||||
if ($file === 'behat' or $file === '.' or $file === '..' or $file === '.DS_Store') {
|
||||
continue;
|
||||
}
|
||||
behat_error(BEHAT_EXITCODE_CONFIG, '$CFG->behat_dataroot directory is not empty, ensure this is the directory where you want to install behat test dataroot');
|
||||
}
|
||||
closedir($dh);
|
||||
unset($dh);
|
||||
unset($file);
|
||||
}
|
||||
|
||||
// Now we create dataroot directory structure for behat tests.
|
||||
testing_initdataroot($CFG->behat_dataroot, 'behat');
|
||||
}
|
||||
|
||||
// Overrides vars with behat-test ones.
|
||||
$vars = array('wwwroot', 'prefix', 'dataroot');
|
||||
foreach ($vars as $var) {
|
||||
$CFG->{$var} = $CFG->{'behat_' . $var};
|
||||
}
|
||||
|
||||
$CFG->noemailever = true;
|
||||
$CFG->passwordsaltmain = 'moodle';
|
||||
|
||||
// Unset cache and temp directories to reset them again with the new $CFG->dataroot.
|
||||
unset($CFG->cachedir);
|
||||
unset($CFG->tempdir);
|
||||
|
||||
// Continues setup.
|
||||
define('ABORT_AFTER_CONFIG_CANCEL', true);
|
||||
require("$CFG->dirroot/lib/setup.php");
|
||||
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/upgradelib.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
require_once($CFG->libdir.'/pluginlib.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));
|
||||
}
|
||||
|
||||
// Behat utilities.
|
||||
require_once($CFG->libdir . '/behat/classes/util.php');
|
||||
require_once($CFG->libdir . '/behat/classes/behat_command.php');
|
||||
|
||||
// Run command (only one per time).
|
||||
if ($options['install']) {
|
||||
behat_util::install_site();
|
||||
mtrace("Acceptance tests site installed");
|
||||
} else if ($options['drop']) {
|
||||
// Ensure no tests are running.
|
||||
test_lock::acquire('behat');
|
||||
behat_util::drop_site();
|
||||
mtrace("Acceptance tests site dropped");
|
||||
} else if ($options['enable']) {
|
||||
behat_util::start_test_mode();
|
||||
$runtestscommand = behat_command::get_behat_command() . ' --config '
|
||||
. $CFG->behat_dataroot . DIRECTORY_SEPARATOR . 'behat' . DIRECTORY_SEPARATOR . 'behat.yml';
|
||||
mtrace("Acceptance tests environment enabled, to run the tests use:\n " . $runtestscommand);
|
||||
} else if ($options['disable']) {
|
||||
behat_util::stop_test_mode();
|
||||
mtrace("Acceptance tests environment disabled");
|
||||
} else if ($options['diag']) {
|
||||
$code = behat_util::get_behat_status();
|
||||
exit($code);
|
||||
} else {
|
||||
echo $help;
|
||||
}
|
||||
|
||||
exit(0);
|
||||
@@ -1,55 +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/>.
|
||||
|
||||
/**
|
||||
* Web interface to list and filter steps
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/behat/locallib.php');
|
||||
require_once($CFG->libdir . '/behat/classes/behat_config_manager.php');
|
||||
|
||||
$filter = optional_param('filter', '', PARAM_ALPHANUMEXT);
|
||||
$type = optional_param('type', false, PARAM_ALPHAEXT);
|
||||
$component = optional_param('component', '', PARAM_ALPHAEXT);
|
||||
|
||||
admin_externalpage_setup('toolbehat');
|
||||
|
||||
// Getting available steps definitions from behat.
|
||||
$steps = tool_behat::stepsdefinitions($type, $component, $filter);
|
||||
|
||||
// Form.
|
||||
$componentswithsteps = array('' => get_string('allavailablesteps', 'tool_behat'));
|
||||
|
||||
// Complete the components list with the moodle steps definitions.
|
||||
$components = behat_config_manager::get_components_steps_definitions();
|
||||
if ($components) {
|
||||
foreach ($components as $component => $filepath) {
|
||||
// TODO Use a class static attribute instead of the class name.
|
||||
$componentswithsteps[$component] = 'Moodle ' . substr($component, 6);
|
||||
}
|
||||
}
|
||||
$form = new steps_definitions_form(null, array('components' => $componentswithsteps));
|
||||
|
||||
// Output contents.
|
||||
$renderer = $PAGE->get_renderer('tool_behat');
|
||||
echo $renderer->render_stepsdefinitions($steps, $form);
|
||||
|
||||
@@ -1,44 +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 tool_behat
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['allavailablesteps'] = 'All the available steps definitions';
|
||||
$string['giveninfo'] = 'Given. Processes to set up the environment';
|
||||
$string['installinfo'] = 'Read {$a} for installation and tests execution info';
|
||||
$string['moreinfoin'] = 'More info in {$a}';
|
||||
$string['newstepsinfo'] = 'Read {$a} for info about how to add new steps definitions';
|
||||
$string['newtestsinfo'] = 'Read {$a} for info about how to write new tests';
|
||||
$string['nostepsdefinitions'] = 'There aren\'t steps definitions matching this filters';
|
||||
$string['pluginname'] = 'Acceptance testing';
|
||||
$string['runclitool'] = 'To list the steps definitions you need to run the Behat CLI tool to create the $CFG->behat_dataroot directory. Go to your moodle dirroot and run "{$a}"';
|
||||
$string['stepsdefinitionscomponent'] = 'Area';
|
||||
$string['stepsdefinitionscontains'] = 'Contains';
|
||||
$string['stepsdefinitionsfilters'] = 'Steps definitions';
|
||||
$string['stepsdefinitionstype'] = 'Type';
|
||||
$string['theninfo'] = 'Then. Checkings to ensure the outcomes are the expected ones';
|
||||
$string['viewsteps'] = 'Filter';
|
||||
$string['wheninfo'] = 'When. Actions that provokes an event';
|
||||
$string['wrongbehatsetup'] = 'Something is wrong with behat setup, ensure:<ul>
|
||||
<li>You ran "curl http://getcomposer.org/installer | php"</li>
|
||||
<li>You ran "php composer.phar install --dev"</li>
|
||||
<li>vendor/bin/behat file has execution permissions</li></ul>';
|
||||
@@ -1,76 +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/>.
|
||||
|
||||
/**
|
||||
* Behat commands
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/behat/classes/behat_command.php');
|
||||
require_once($CFG->libdir . '/behat/classes/behat_config_manager.php');
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/behat/steps_definitions_form.php');
|
||||
|
||||
/**
|
||||
* Behat commands manager
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_behat {
|
||||
|
||||
/**
|
||||
* Lists the available steps definitions
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $component
|
||||
* @param string $filter
|
||||
* @return array System steps or empty array if case there are no steps
|
||||
*/
|
||||
public static function stepsdefinitions($type, $component, $filter) {
|
||||
|
||||
// We don't require the test environment to be enabled to list the steps definitions
|
||||
// so test writers can more easily set up the environment.
|
||||
behat_command::behat_setup_problem();
|
||||
|
||||
// The loaded steps depends on the component specified.
|
||||
behat_config_manager::update_config_file($component, false);
|
||||
|
||||
// The Moodle\BehatExtension\HelpPrinter\MoodleDefinitionsPrinter will parse this search format.
|
||||
if ($type) {
|
||||
$filter .= '&&' . $type;
|
||||
}
|
||||
|
||||
if ($filter) {
|
||||
$filteroption = ' -d "' . $filter . '"';
|
||||
} else {
|
||||
$filteroption = ' -di';
|
||||
}
|
||||
|
||||
// Get steps definitions from Behat.
|
||||
$options = ' --config="'.behat_config_manager::get_steps_list_config_filepath(). '" '.$filteroption;
|
||||
list($steps, $code) = behat_command::run($options);
|
||||
|
||||
return $steps;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,116 +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/>.
|
||||
|
||||
/**
|
||||
* Behat tool renderer
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/behat/classes/behat_command.php');
|
||||
|
||||
/**
|
||||
* Renderer for behat tool web features
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_behat_renderer extends plugin_renderer_base {
|
||||
|
||||
/**
|
||||
* Renders the list of available steps according to the submitted filters.
|
||||
*
|
||||
* @param mixed $stepsdefinitions Available steps array.
|
||||
* @param moodleform $form
|
||||
* @return string HTML code
|
||||
*/
|
||||
public function render_stepsdefinitions($stepsdefinitions, $form) {
|
||||
|
||||
$title = get_string('pluginname', 'tool_behat');
|
||||
|
||||
// Header.
|
||||
$html = $this->output->header();
|
||||
$html .= $this->output->heading($title);
|
||||
|
||||
// Info.
|
||||
$installurl = behat_command::DOCS_URL . '#Installation';
|
||||
$installlink = html_writer::tag('a', $installurl, array('href' => $installurl, 'target' => '_blank'));
|
||||
$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'));
|
||||
$infos = array(
|
||||
get_string('installinfo', 'tool_behat', $installlink),
|
||||
get_string('newtestsinfo', 'tool_behat', $writetestslink),
|
||||
get_string('newstepsinfo', 'tool_behat', $writestepslink)
|
||||
);
|
||||
|
||||
// List of steps
|
||||
$html .= $this->output->box_start();
|
||||
$html .= html_writer::tag('h1', 'Info');
|
||||
$html .= html_writer::empty_tag('div');
|
||||
$html .= html_writer::empty_tag('ul');
|
||||
$html .= html_writer::empty_tag('li');
|
||||
$html .= implode(html_writer::end_tag('li') . html_writer::empty_tag('li'), $infos);
|
||||
$html .= html_writer::end_tag('li');
|
||||
$html .= html_writer::end_tag('ul');
|
||||
$html .= html_writer::end_tag('div');
|
||||
$html .= $this->output->box_end();
|
||||
|
||||
// Form.
|
||||
ob_start();
|
||||
$form->display();
|
||||
$html .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
if (empty($stepsdefinitions)) {
|
||||
$stepsdefinitions = get_string('nostepsdefinitions', 'tool_behat');
|
||||
} else {
|
||||
|
||||
$stepsdefinitions = implode('', $stepsdefinitions);
|
||||
|
||||
// Replace text selector type arguments with a user-friendly select.
|
||||
$stepsdefinitions = preg_replace_callback('/(TEXT_SELECTOR\d?_STRING)/',
|
||||
function ($matches) {
|
||||
return html_writer::select(behat_command::$allowedtextselectors, uniqid());
|
||||
},
|
||||
$stepsdefinitions
|
||||
);
|
||||
|
||||
// Replace selector type arguments with a user-friendly select.
|
||||
$stepsdefinitions = preg_replace_callback('/(SELECTOR\d?_STRING)/',
|
||||
function ($matches) {
|
||||
return html_writer::select(behat_command::$allowedselectors, uniqid());
|
||||
},
|
||||
$stepsdefinitions
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// Steps definitions.
|
||||
$html .= html_writer::tag('div', $stepsdefinitions, array('class' => 'steps-definitions'));
|
||||
|
||||
$html .= $this->output->footer();
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Adds behat tests link in admin tree
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
if ($hassiteconfig) {
|
||||
$url = $CFG->wwwroot . '/' . $CFG->admin . '/tool/behat/index.php';
|
||||
$ADMIN->add('development', new admin_externalpage('toolbehat', get_string('pluginname', 'tool_behat'), $url));
|
||||
}
|
||||
@@ -1,67 +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/>.
|
||||
|
||||
/**
|
||||
* Steps definitions form
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir.'/formslib.php');
|
||||
|
||||
/**
|
||||
* Form to display the available steps definitions
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class steps_definitions_form extends moodleform {
|
||||
|
||||
/**
|
||||
* Form definition
|
||||
* @return void
|
||||
*/
|
||||
public function definition() {
|
||||
|
||||
$mform = $this->_form;
|
||||
|
||||
$mform->addElement('header', 'filters', get_string('stepsdefinitionsfilters', 'tool_behat'));
|
||||
|
||||
$types = array(
|
||||
'' => get_string('allavailablesteps', 'tool_behat'),
|
||||
'given' => get_string('giveninfo', 'tool_behat'),
|
||||
'when' => get_string('wheninfo', 'tool_behat'),
|
||||
'then' => get_string('theninfo', 'tool_behat')
|
||||
);
|
||||
$mform->addElement('select', 'type', get_string('stepsdefinitionstype', 'tool_behat'), $types);
|
||||
|
||||
$mform->addElement(
|
||||
'select',
|
||||
'component',
|
||||
get_string('stepsdefinitionscomponent', 'tool_behat'),
|
||||
$this->_customdata['components']
|
||||
);
|
||||
|
||||
$mform->addElement('text', 'filter', get_string('stepsdefinitionscontains', 'tool_behat'));
|
||||
|
||||
$mform->addElement('submit', 'submit', get_string('viewsteps', 'tool_behat'));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
.steps-definitions{border-style:solid;border-width:1px;border-color:#BBB;padding:5px;margin:auto;width:50%;}
|
||||
.steps-definitions .step{margin: 10px 0px 10px 0px;}
|
||||
.steps-definitions .stepdescription{color:#bf8c12;}
|
||||
.steps-definitions .steptype{color:#1467a6;margin-right: 5px;}
|
||||
.steps-definitions .stepregex{color:#060;}
|
||||
@@ -1,49 +0,0 @@
|
||||
@tool_behat
|
||||
Feature: Page contents assertions
|
||||
In order to write good tests
|
||||
As a tests writer
|
||||
I need to check the page contents
|
||||
|
||||
@javascript
|
||||
Scenario: Basic contents assertions
|
||||
Given I log in as "admin"
|
||||
And I am on homepage
|
||||
And I expand "Users" node
|
||||
And I follow "Groups"
|
||||
And I press "Create group"
|
||||
And I fill the moodle form with:
|
||||
| Group name | I'm the name |
|
||||
| Group description | I'm the description |
|
||||
And I press "Save changes"
|
||||
When I follow "Overview"
|
||||
And I wait until the page is ready
|
||||
And I wait "2" seconds
|
||||
And I hover ".region-content .generaltable td span" "css_element"
|
||||
Then I should see "I'm the description"
|
||||
And I should see "Filter groups by"
|
||||
And I should not see "Filter groupssss by"
|
||||
And I should see "Group members" in the ".region-content table th.c1" "css_element"
|
||||
And I should not see "Group membersssss" in the ".region-content table th.c1" "css_element"
|
||||
And I follow "Groups"
|
||||
And the "#groupeditform #showcreateorphangroupform" "css_element" should be enabled
|
||||
And the "#groupeditform #showeditgroupsettingsform" "css_element" should be disabled
|
||||
|
||||
@javascript
|
||||
Scenario: Locators inside specific DOM nodes using CSS selectors
|
||||
Given the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And I log in as "admin"
|
||||
And I follow "Course 1"
|
||||
When I click on "Move this to the dock" "button" in the ".block_settings" "css_element"
|
||||
Then I should not see "Question bank"
|
||||
And I click on "//div[@id='dock']/descendant::*[contains(., 'Administration')]/h2" "xpath_element"
|
||||
|
||||
@javascript
|
||||
Scenario: Locators inside specific DOM nodes using XPath
|
||||
Given the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And I log in as "admin"
|
||||
When I click on "Move this to the dock" "button" in the "//*[contains(concat(' ', normalize-space(@class), ' '), ' block_settings ')]" "xpath_element"
|
||||
Then I should not see "Turn editing on"
|
||||
@@ -1,109 +0,0 @@
|
||||
@tool_behat
|
||||
Feature: Set up contextual data for tests
|
||||
In order to write tests quickly
|
||||
As a moodle developer
|
||||
I need to fill the database with fixtures
|
||||
|
||||
Scenario: Add a bunch of users
|
||||
Given the following "users" exists:
|
||||
| username | password | firstname | lastname |
|
||||
| testuser | testuser | | |
|
||||
| testuser2 | testuser2 | TestFirstname | TestLastname |
|
||||
And I log in as "testuser"
|
||||
And I log out
|
||||
When I log in as "testuser2"
|
||||
Then I should see "TestFirstname"
|
||||
|
||||
@javascript
|
||||
Scenario: Add a bunch of courses and categories
|
||||
Given the following "categories" exists:
|
||||
| name | category | idnumber |
|
||||
| Cat 1 | 0 | CAT1 |
|
||||
| Cat 2 | CAT1 | CAT2 |
|
||||
| Cat 3 | CAT1 | CAT3 |
|
||||
And the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | COURSE1 | CAT3 |
|
||||
| Course 2 | COURSE2 | CAT3 |
|
||||
| Course 3 | COURSE3 | 0 |
|
||||
When I log in as "admin"
|
||||
Then I should see "Course 1"
|
||||
And I should see "Course 2"
|
||||
And I should see "Course 3"
|
||||
|
||||
@javascript
|
||||
Scenario: Add a bunch of groups and groupings
|
||||
Given the following "courses" exists:
|
||||
| fullname | shortname |
|
||||
| Course 1 | C1 |
|
||||
And the following "groups" exists:
|
||||
| name | course | idnumber |
|
||||
| Group 1 | C1 | G1 |
|
||||
| Group 2 | C1 | G2 |
|
||||
And the following "groupings" exists:
|
||||
| name | course | idnumber |
|
||||
| Grouping 1 | C1 | GG1 |
|
||||
| Grouping 2 | C1 | GG2 |
|
||||
When I log in as "admin"
|
||||
And I follow "Course 1"
|
||||
And I expand "Users" node
|
||||
And I follow "Groups"
|
||||
Then I should see "Group 1"
|
||||
And I should see "Group 2"
|
||||
And I follow "Groupings"
|
||||
And I should see "Grouping 1"
|
||||
And I should see "Grouping 2"
|
||||
|
||||
Scenario: Add course enrolments
|
||||
Given the following "users" exists:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
And the following "courses" exists:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
And the following "course enrolments" exists:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
When I log in as "student1"
|
||||
And I follow "Course 1"
|
||||
Then I should see "Topic 1"
|
||||
|
||||
@javascript
|
||||
Scenario: Add relations between users and groups
|
||||
Given the following "users" exists:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| student2 | Student | 2 | student2@asd.com |
|
||||
And the following "courses" exists:
|
||||
| fullname | shortname |
|
||||
| Course 1 | C1 |
|
||||
And the following "groups" exists:
|
||||
| name | course | idnumber |
|
||||
| Group 1 | C1 | G1 |
|
||||
| Group 2 | C1 | G2 |
|
||||
And the following "groupings" exists:
|
||||
| name | course | idnumber |
|
||||
| Grouping 1 | C1 | GG1 |
|
||||
And the following "course enrolments" exists:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
And the following "group members" exists:
|
||||
| user | group |
|
||||
| student1 | G1 |
|
||||
| student2 | G2 |
|
||||
And the following "grouping groups" exists:
|
||||
| grouping | group |
|
||||
| GG1 | G1 |
|
||||
When I log in as "admin"
|
||||
And I follow "Course 1"
|
||||
And I expand "Users" node
|
||||
And I follow "Groups"
|
||||
Then the "groups" select box should contain "Group 1 (1)"
|
||||
And the "groups" select box should contain "Group 2 (1)"
|
||||
And I select "Group 1 (1)" from "groups"
|
||||
And I wait "5" seconds
|
||||
And the "members" select box should contain "Student 1"
|
||||
And I select "Group 2 (1)" from "groups"
|
||||
And I wait "5" seconds
|
||||
And the "members" select box should contain "Student 2"
|
||||
@@ -1,65 +0,0 @@
|
||||
@tool_behat
|
||||
Feature: Edit capabilities
|
||||
In order to extend and restrict moodle features
|
||||
As an admin or teacher
|
||||
I need to allow/deny the existing capabilities at different levels
|
||||
|
||||
Background:
|
||||
Given the following "users" exists:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
And the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "course enrolments" exists:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@javascript
|
||||
Scenario: Default system capabilities modification
|
||||
Given I log in as "admin"
|
||||
And I set the following system permissions of "Teacher" role:
|
||||
| capability | permission |
|
||||
| block/mnet_hosts:myaddinstance | Allow |
|
||||
| moodle/community:add | Inherit |
|
||||
| moodle/grade:managesharedforms | Prevent |
|
||||
| moodle/course:request | Prohibit |
|
||||
When I follow "Edit Teacher role"
|
||||
Then the "block/mnet_hosts:myaddinstance" field should match "1" value
|
||||
And the "moodle/community:add" field should match "0" value
|
||||
And the "moodle/grade:managesharedforms" field should match "-1" value
|
||||
And the "moodle/course:request" field should match "-1000" value
|
||||
|
||||
@javascript
|
||||
Scenario: Course capabilities overrides
|
||||
Given I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I expand "Users" node
|
||||
And I follow "Permissions"
|
||||
And I override the system permissions of "Student" role with:
|
||||
| mod/forum:deleteanypost | Prohibit |
|
||||
| mod/forum:editanypost | Prevent |
|
||||
| mod/forum:addquestion | Allow |
|
||||
When I select "Student (3)" from "Advanced role override"
|
||||
Then the "mod/forum:deleteanypost" field should match "-1000" value
|
||||
And the "mod/forum:editanypost" field should match "-1" value
|
||||
And the "mod/forum:addquestion" field should match "1" value
|
||||
|
||||
@javascript
|
||||
Scenario: Module capabilities overrides
|
||||
Given I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
And I add a "Forum" to section "1" and I fill the form with:
|
||||
| Forum name | I'm the name |
|
||||
| Description | I'm the introduction |
|
||||
And I follow "I'm the name"
|
||||
And I follow "Permissions"
|
||||
And I override the system permissions of "Student" role with:
|
||||
| mod/forum:deleteanypost | Prohibit |
|
||||
| mod/forum:editanypost | Prevent |
|
||||
| mod/forum:addquestion | Allow |
|
||||
When I select "Student (3)" from "Advanced role override"
|
||||
Then the "mod/forum:deleteanypost" field should match "-1000" value
|
||||
And the "mod/forum:editanypost" field should match "-1" value
|
||||
And the "mod/forum:addquestion" field should match "1" value
|
||||
@@ -1,31 +0,0 @@
|
||||
@tool_behat
|
||||
Feature: List the system steps definitions
|
||||
In order to create new tests
|
||||
As a tests writer
|
||||
I need to list and filter the system steps definitions
|
||||
|
||||
Background:
|
||||
Given I am on homepage
|
||||
And I log in as "admin"
|
||||
And I expand "Site administration" node
|
||||
And I expand "Development" node
|
||||
And I follow "Acceptance testing"
|
||||
|
||||
@javascript
|
||||
Scenario: Accessing the list
|
||||
Then I should see "Steps definitions"
|
||||
And I should not see "There aren't steps definitions matching this filter"
|
||||
|
||||
@javascript
|
||||
Scenario: Filtering by type
|
||||
Given I select "Then. Checkings to ensure the outcomes are the expected ones" from "Type"
|
||||
When I press "Filter"
|
||||
Then I should see "Checks, that page contains specified text."
|
||||
And I should not see "Opens Moodle homepage."
|
||||
|
||||
@javascript
|
||||
Scenario: Filtering by keyword
|
||||
Given I fill in "Contains" with "homepage"
|
||||
When I press "Filter"
|
||||
Then I should see "Opens Moodle homepage."
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
@tool_behat @core_form
|
||||
Feature: Forms manipulation
|
||||
In order to interact with Moodle
|
||||
As a user
|
||||
I need to set forms values
|
||||
|
||||
@javascript
|
||||
Scenario: Basic forms manipulation
|
||||
Given I log in as "admin"
|
||||
And I follow "Admin User"
|
||||
And I follow "Edit profile"
|
||||
When I fill in "First name" with "Field value"
|
||||
And I select "Use standard web forms" from "When editing text"
|
||||
And I check "Unmask"
|
||||
Then the "First name" field should match "Field value" value
|
||||
And the "When editing text" select box should contain "Use standard web forms"
|
||||
And the "Unmask" checkbox should be checked
|
||||
And I uncheck "Unmask"
|
||||
And the "Unmask" checkbox should not be checked
|
||||
And I press "Update profile"
|
||||
|
||||
@javascript
|
||||
Scenario: Expand all fieldsets and advanced elements
|
||||
Given the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And I log in as "admin"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
And I add a "forum" to section "1"
|
||||
When I expand all fieldsets
|
||||
Then I should see "Display word count"
|
||||
And I should see "Group mode"
|
||||
And I should see "Grouping"
|
||||
And I should not see "Show more..."
|
||||
And I should see "Show less..."
|
||||
@@ -1,60 +0,0 @@
|
||||
@tool_behat
|
||||
Feature: Transform steps arguments
|
||||
In order to write tests with complex nasty arguments
|
||||
As a tests writer
|
||||
I need to apply some transformations to the steps arguments
|
||||
|
||||
Background:
|
||||
Given I am on homepage
|
||||
And the following "courses" exists:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And I log in as "admin"
|
||||
And I follow "Admin User"
|
||||
And I follow "Edit profile"
|
||||
|
||||
Scenario: Use nasty strings on steps arguments
|
||||
When I fill in "Surname" with "$NASTYSTRING1"
|
||||
And I fill in "Description" with "$NASTYSTRING2"
|
||||
And I fill in "City/town" with "$NASTYSTRING3"
|
||||
And I press "Update profile"
|
||||
And I follow "Edit profile"
|
||||
Then I should not see "NASTYSTRING"
|
||||
And the "Surname" field should match "$NASTYSTRING1" value
|
||||
And the "City/town" field should match "$NASTYSTRING3" value
|
||||
|
||||
Scenario: Use nasty strings on table nodes
|
||||
When I fill the moodle form with:
|
||||
| Surname | $NASTYSTRING1 |
|
||||
| Description | $NASTYSTRING2 |
|
||||
| City/town | $NASTYSTRING3 |
|
||||
And I press "Update profile"
|
||||
And I follow "Edit profile"
|
||||
Then I should not see "NASTYSTRING"
|
||||
And the "Surname" field should match "$NASTYSTRING1" value
|
||||
And the "City/town" field should match "$NASTYSTRING3" value
|
||||
|
||||
Scenario: Use double quotes
|
||||
When I fill the moodle form with:
|
||||
| First name | va"lue1 |
|
||||
| Description | va\"lue2 |
|
||||
And I fill in "City/town" with "va\"lue3"
|
||||
And I press "Update profile"
|
||||
And I follow "Edit profile"
|
||||
Then I should not see "NASTYSTRING"
|
||||
And the "First name" field should match "va\"lue1" value
|
||||
And the "Description" field should match "va\\"lue2" value
|
||||
And the "City/town" field should match "va\"lue3" value
|
||||
|
||||
@javascript
|
||||
Scenario: Nasty strings with other contents
|
||||
When I fill in "First name" with "My Firstname $NASTYSTRING1"
|
||||
And I fill the moodle form with:
|
||||
| Surname | My Surname $NASTYSTRING2 |
|
||||
And I press "Update profile"
|
||||
And I follow "Edit profile"
|
||||
Then I should not see "NASTYSTRING"
|
||||
And I should see "My Firstname"
|
||||
And I should see "My Surname"
|
||||
And the "First name" field should match "My Firstname $NASTYSTRING1" value
|
||||
And the "Surname" field should match "My Surname $NASTYSTRING2" value
|
||||
@@ -1,9 +0,0 @@
|
||||
@tool_behat
|
||||
Feature: Set up the testing environment
|
||||
In order to execute automated acceptance tests
|
||||
As a moodle developer
|
||||
I need to use the test environment instead of the regular environment
|
||||
|
||||
Scenario: Accessing the site
|
||||
When I am on homepage
|
||||
Then I should see "Acceptance test site"
|
||||
@@ -1,189 +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 admin/tool/behat.
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @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/behat/locallib.php');
|
||||
require_once($CFG->libdir . '/behat/classes/util.php');
|
||||
require_once($CFG->libdir . '/behat/classes/behat_config_manager.php');
|
||||
|
||||
/**
|
||||
* Allows access to internal methods without exposing them.
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class testable_behat_config_manager extends behat_config_manager {
|
||||
|
||||
/**
|
||||
* Allow access to protected method
|
||||
* @see parent::merge_config()
|
||||
* @param mixed $config
|
||||
* @param mixed $localconfig
|
||||
* @return mixed
|
||||
*/
|
||||
public static function merge_config($config, $localconfig) {
|
||||
return parent::merge_config($config, $localconfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow access to protected method
|
||||
* @see parent::get_config_file_contents()
|
||||
* @param array $features
|
||||
* @param array $stepsdefinitions
|
||||
* @return string
|
||||
*/
|
||||
public static function get_config_file_contents($features, $stepsdefinitions) {
|
||||
return parent::get_config_file_contents($features, $stepsdefinitions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tool behat tests.
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_behat_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* behat_config_manager tests.
|
||||
*/
|
||||
public function test_merge_configs() {
|
||||
|
||||
// Simple default config.
|
||||
$array1 = array(
|
||||
'the' => 'same',
|
||||
'simple' => 'value',
|
||||
'array' => array(
|
||||
'one' => 'arrayvalue1',
|
||||
'two' => 'arrayvalue2'
|
||||
)
|
||||
);
|
||||
|
||||
// Simple override.
|
||||
$array2 = array(
|
||||
'simple' => 'OVERRIDDEN1',
|
||||
'array' => array(
|
||||
'one' => 'OVERRIDDEN2'
|
||||
),
|
||||
'newprofile' => array(
|
||||
'anotherlevel' => array(
|
||||
'andanotherone' => array(
|
||||
'list1',
|
||||
'list2'
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$array = testable_behat_config_manager::merge_config($array1, $array2);
|
||||
|
||||
// Overriddes are applied.
|
||||
$this->assertEquals('OVERRIDDEN1', $array['simple']);
|
||||
$this->assertEquals('OVERRIDDEN2', $array['array']['one']);
|
||||
|
||||
// Other values are respected.
|
||||
$this->assertNotEmpty($array['array']['two']);
|
||||
|
||||
// Completely new nodes are added.
|
||||
$this->assertNotEmpty($array['newprofile']);
|
||||
$this->assertNotEmpty($array['newprofile']['anotherlevel']['andanotherone']);
|
||||
$this->assertEquals('list1', $array['newprofile']['anotherlevel']['andanotherone'][0]);
|
||||
$this->assertEquals('list2', $array['newprofile']['anotherlevel']['andanotherone'][1]);
|
||||
|
||||
// Complex override changing vectors to scalars and scalars to vectors.
|
||||
$array2 = array(
|
||||
'simple' => array(
|
||||
'simple' => 'should',
|
||||
'be' => 'overridden',
|
||||
'by' => 'this-array'
|
||||
),
|
||||
'array' => 'one'
|
||||
);
|
||||
|
||||
$array = testable_behat_config_manager::merge_config($array1, $array2);
|
||||
|
||||
// Overrides applied.
|
||||
$this->assertNotEmpty($array['simple']);
|
||||
$this->assertNotEmpty($array['array']);
|
||||
$this->assertTrue(is_array($array['simple']));
|
||||
$this->assertFalse(is_array($array['array']));
|
||||
|
||||
// Other values are maintained.
|
||||
$this->assertEquals('same', $array['the']);
|
||||
}
|
||||
|
||||
/**
|
||||
* behat_config_manager tests.
|
||||
*/
|
||||
public function test_config_file_contents() {
|
||||
global $CFG;
|
||||
|
||||
// Skip tests if behat is not installed.
|
||||
$vendorpath = $CFG->dirroot . '/vendor';
|
||||
if (!file_exists($vendorpath . '/autoload.php') || !is_dir($vendorpath . '/behat')) {
|
||||
$this->markTestSkipped('Behat not installed.');
|
||||
}
|
||||
|
||||
// To avoid user value at config.php level.
|
||||
unset($CFG->behat_config);
|
||||
|
||||
// List.
|
||||
$features = array(
|
||||
'feature1',
|
||||
'feature2',
|
||||
'feature3'
|
||||
);
|
||||
|
||||
// Associative array.
|
||||
$stepsdefinitions = array(
|
||||
'micarro' => '/me/lo/robaron',
|
||||
'anoche' => '/cuando/yo/dormia'
|
||||
);
|
||||
|
||||
$contents = testable_behat_config_manager::get_config_file_contents($features, $stepsdefinitions);
|
||||
|
||||
// YAML decides when is is necessary to wrap strings between single quotes, so not controlled
|
||||
// values like paths should not be asserted including the key name as they would depend on the
|
||||
// directories values.
|
||||
$this->assertContains($CFG->dirroot . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'behat' . DIRECTORY_SEPARATOR . 'features', $contents);
|
||||
|
||||
// Not quoted strings.
|
||||
$this->assertContains('micarro: /me/lo/robaron', $contents);
|
||||
$this->assertContains('class: behat_init_context', $contents);
|
||||
|
||||
// YAML uses single quotes to wrap URL strings.
|
||||
$this->assertContains("base_url: '" . $CFG->behat_wwwroot . "'", $contents);
|
||||
|
||||
// Lists.
|
||||
$this->assertContains('- feature1', $contents);
|
||||
$this->assertContains('- feature3', $contents);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* tool_behat version info
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2012 David Monllaó
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2012120700;
|
||||
$plugin->requires = 2012120300; // Requires Moodle 2.5.
|
||||
$plugin->component = 'tool_behat';
|
||||
@@ -4,33 +4,33 @@
|
||||
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
<TABLES>
|
||||
<TABLE NAME="tool_customlang" COMMENT="Contains the working checkout of all strings and their customization">
|
||||
<TABLE NAME="tool_customlang" COMMENT="Contains the working checkout of all strings and their customization" NEXT="tool_customlang_components">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="lang" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false" COMMENT="The code of the language this string belongs to. Like en, cs or es"/>
|
||||
<FIELD NAME="componentid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The id of the component"/>
|
||||
<FIELD NAME="stringid" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The identifier of the string"/>
|
||||
<FIELD NAME="original" TYPE="text" LENGTH="big" NOTNULL="true" SEQUENCE="false" COMMENT="English original of the string"/>
|
||||
<FIELD NAME="master" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="Master translation of the string as is distributed in the official lang pack, null if not translated"/>
|
||||
<FIELD NAME="local" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="Local customization of the string, null if not customized"/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The timestamp of when the original or master was recently modified"/>
|
||||
<FIELD NAME="timecustomized" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="The timestamp of when the value of the local translation was recently modified, null if not customized yet"/>
|
||||
<FIELD NAME="outdated" TYPE="int" LENGTH="3" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Either the English original or the master translation changed and the customization may be outdated"/>
|
||||
<FIELD NAME="modified" TYPE="int" LENGTH="3" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Has the string been modified via the translator?"/>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="lang"/>
|
||||
<FIELD NAME="lang" TYPE="char" LENGTH="20" NOTNULL="true" SEQUENCE="false" COMMENT="The code of the language this string belongs to. Like en, cs or es" PREVIOUS="id" NEXT="componentid"/>
|
||||
<FIELD NAME="componentid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The id of the component" PREVIOUS="lang" NEXT="stringid"/>
|
||||
<FIELD NAME="stringid" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The identifier of the string" PREVIOUS="componentid" NEXT="original"/>
|
||||
<FIELD NAME="original" TYPE="text" LENGTH="big" NOTNULL="true" SEQUENCE="false" COMMENT="English original of the string" PREVIOUS="stringid" NEXT="master"/>
|
||||
<FIELD NAME="master" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="Master translation of the string as is distributed in the official lang pack, null if not translated" PREVIOUS="original" NEXT="local"/>
|
||||
<FIELD NAME="local" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" COMMENT="Local customization of the string, null if not customized" PREVIOUS="master" NEXT="timemodified"/>
|
||||
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The timestamp of when the original or master was recently modified" PREVIOUS="local" NEXT="timecustomized"/>
|
||||
<FIELD NAME="timecustomized" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="The timestamp of when the value of the local translation was recently modified, null if not customized yet" PREVIOUS="timemodified" NEXT="outdated"/>
|
||||
<FIELD NAME="outdated" TYPE="int" LENGTH="3" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Either the English original or the master translation changed and the customization may be outdated" PREVIOUS="timecustomized" NEXT="modified"/>
|
||||
<FIELD NAME="modified" TYPE="int" LENGTH="3" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Has the string been modified via the translator?" PREVIOUS="outdated"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="fk_component" TYPE="foreign" FIELDS="componentid" REFTABLE="tool_customlang_components" REFFIELDS="id"/>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="fk_component"/>
|
||||
<KEY NAME="fk_component" TYPE="foreign" FIELDS="componentid" REFTABLE="tool_customlang_components" REFFIELDS="id" PREVIOUS="primary"/>
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="uq_lang_component_string" UNIQUE="true" FIELDS="lang, componentid, stringid" COMMENT="For a given language and component, string identifiers must be unique"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
<TABLE NAME="tool_customlang_components" COMMENT="Contains the list of all installed plugins that provide their own language pack">
|
||||
<TABLE NAME="tool_customlang_components" COMMENT="Contains the list of all installed plugins that provide their own language pack" PREVIOUS="tool_customlang">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The normalized name of the plugin"/>
|
||||
<FIELD NAME="version" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="The checked out version of the plugin, null if the version is unknown"/>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="name"/>
|
||||
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The normalized name of the plugin" PREVIOUS="id" NEXT="version"/>
|
||||
<FIELD NAME="version" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="The checked out version of the plugin, null if the version is unknown" PREVIOUS="name"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
|
||||
@@ -60,8 +60,8 @@ class tool_customlang_filter_form extends moodleform {
|
||||
|
||||
// Modified only
|
||||
$mform->addElement('advcheckbox', 'modified', get_string('filtermodified', 'tool_customlang'));
|
||||
$mform->setType('modified', PARAM_BOOL);
|
||||
$mform->setDefault('modified', 0);
|
||||
$mform->setType('filtermodified', PARAM_BOOL);
|
||||
$mform->setDefault('filtermodified', 0);
|
||||
|
||||
// Substring
|
||||
$mform->addElement('text', 'substring', get_string('filtersubstring', 'tool_customlang'));
|
||||
|
||||
@@ -1,574 +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/>.
|
||||
|
||||
/**
|
||||
* Provides tool_installaddon_installer related classes
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @subpackage classes
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Implements main plugin features.
|
||||
*
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_installaddon_installer {
|
||||
|
||||
/** @var tool_installaddon_installfromzip */
|
||||
protected $installfromzipform = null;
|
||||
|
||||
/**
|
||||
* Factory method returning an instance of this class.
|
||||
*
|
||||
* @return tool_installaddon_installer
|
||||
*/
|
||||
public static function instance() {
|
||||
return new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL to the main page of this admin tool
|
||||
*
|
||||
* @param array optional parameters
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function index_url(array $params = null) {
|
||||
return new moodle_url('/admin/tool/installaddon/index.php', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns URL to the repository that addons can be searched in and installed from
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_addons_repository_url() {
|
||||
global $CFG;
|
||||
|
||||
if (!empty($CFG->config_php_settings['alternativeaddonsrepositoryurl'])) {
|
||||
$url = $CFG->config_php_settings['alternativeaddonsrepositoryurl'];
|
||||
} else {
|
||||
$url = 'https://moodle.org/plugins/get.php';
|
||||
}
|
||||
|
||||
if (!$this->should_send_site_info()) {
|
||||
return new moodle_url($url);
|
||||
}
|
||||
|
||||
// Append the basic information about our site.
|
||||
$site = array(
|
||||
'fullname' => $this->get_site_fullname(),
|
||||
'url' => $this->get_site_url(),
|
||||
'majorversion' => $this->get_site_major_version(),
|
||||
);
|
||||
|
||||
$site = $this->encode_site_information($site);
|
||||
|
||||
return new moodle_url($url, array('site' => $site));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return tool_installaddon_installfromzip
|
||||
*/
|
||||
public function get_installfromzip_form() {
|
||||
global $CFG;
|
||||
require_once(dirname(__FILE__).'/installfromzip_form.php');
|
||||
|
||||
if (!is_null($this->installfromzipform)) {
|
||||
return $this->installfromzipform;
|
||||
}
|
||||
|
||||
$action = $this->index_url();
|
||||
$customdata = array('installer' => $this);
|
||||
|
||||
$this->installfromzipform = new tool_installaddon_installfromzip($action, $customdata);
|
||||
|
||||
return $this->installfromzipform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the ZIP file from the {@link tool_installaddon_installfromzip} form
|
||||
*
|
||||
* The file is saved into the given temporary location for inspection and eventual
|
||||
* deployment. The form is expected to be submitted and validated.
|
||||
*
|
||||
* @param tool_installaddon_installfromzip $form
|
||||
* @param string $targetdir full path to the directory where the ZIP should be stored to
|
||||
* @return string filename of the saved file relative to the given target
|
||||
*/
|
||||
public function save_installfromzip_file(tool_installaddon_installfromzip $form, $targetdir) {
|
||||
|
||||
$filename = clean_param($form->get_new_filename('zipfile'), PARAM_FILE);
|
||||
$form->save_file('zipfile', $targetdir.'/'.$filename);
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the saved file previously saved by {self::save_installfromzip_file()}
|
||||
*
|
||||
* The list of files found in the ZIP is returned via $zipcontentfiles parameter
|
||||
* by reference. The format of that list is array of (string)filerelpath => (bool|string)
|
||||
* where the array value is either true or a string describing the problematic file.
|
||||
*
|
||||
* @see zip_packer::extract_to_pathname()
|
||||
* @param string $zipfilepath full path to the saved ZIP file
|
||||
* @param string $targetdir full path to the directory to extract the ZIP file to
|
||||
* @param string $rootdir explicitly rename the root directory of the ZIP into this non-empty value
|
||||
* @param array list of extracted files as returned by {@link zip_packer::extract_to_pathname()}
|
||||
*/
|
||||
public function extract_installfromzip_file($zipfilepath, $targetdir, $rootdir = '') {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
|
||||
$fp = get_file_packer('application/zip');
|
||||
$files = $fp->extract_to_pathname($zipfilepath, $targetdir);
|
||||
|
||||
if ($files) {
|
||||
if (!empty($rootdir)) {
|
||||
$files = $this->rename_extracted_rootdir($targetdir, $rootdir, $files);
|
||||
}
|
||||
return $files;
|
||||
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised list of available plugin types
|
||||
*
|
||||
* @return array (string)plugintype => (string)plugin name
|
||||
*/
|
||||
public function get_plugin_types_menu() {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir.'/pluginlib.php');
|
||||
|
||||
$pluginman = plugin_manager::instance();
|
||||
|
||||
$menu = array('' => get_string('choosedots'));
|
||||
foreach (array_keys($pluginman->get_plugin_types()) as $plugintype) {
|
||||
$menu[$plugintype] = $pluginman->plugintype_name($plugintype).' ('.$plugintype.')';
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path of the root of the given plugin type
|
||||
*
|
||||
* Null is returned if the plugin type is not known. False is returned if the plugin type
|
||||
* root is expected but not found. Otherwise, string is returned.
|
||||
*
|
||||
* @param string $plugintype
|
||||
* @return string|bool|null
|
||||
*/
|
||||
public function get_plugintype_root($plugintype) {
|
||||
|
||||
$plugintypepath = null;
|
||||
foreach (get_plugin_types() as $type => $fullpath) {
|
||||
if ($type === $plugintype) {
|
||||
$plugintypepath = $fullpath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_null($plugintypepath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!is_dir($plugintypepath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $plugintypepath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it possible to create a new plugin directory for the given plugin type?
|
||||
*
|
||||
* @throws coding_exception for invalid plugin types or non-existing plugin type locations
|
||||
* @param string $plugintype
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_plugintype_writable($plugintype) {
|
||||
|
||||
$plugintypepath = $this->get_plugintype_root($plugintype);
|
||||
|
||||
if (is_null($plugintypepath)) {
|
||||
throw new coding_exception('Unknown plugin type!');
|
||||
}
|
||||
|
||||
if ($plugintypepath === false) {
|
||||
throw new coding_exception('Plugin type location does not exist!');
|
||||
}
|
||||
|
||||
return is_writable($plugintypepath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method to handle the remote request to install an add-on
|
||||
*
|
||||
* This is used as a callback when the admin picks a plugin version in the
|
||||
* Moodle Plugins directory and is redirected back to their site to install
|
||||
* it.
|
||||
*
|
||||
* This hook is called early from admin/tool/installaddon/index.php page so that
|
||||
* it has opportunity to take over the UI.
|
||||
*
|
||||
* @param tool_installaddon_renderer $output
|
||||
* @param string|null $request
|
||||
* @param bool $confirmed
|
||||
*/
|
||||
public function handle_remote_request(tool_installaddon_renderer $output, $request, $confirmed = false) {
|
||||
global $CFG;
|
||||
require_once(dirname(__FILE__).'/pluginfo_client.php');
|
||||
|
||||
if (is_null($request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $this->decode_remote_request($request);
|
||||
|
||||
if ($data === false) {
|
||||
echo $output->remote_request_invalid_page($this->index_url());
|
||||
exit();
|
||||
}
|
||||
|
||||
list($plugintype, $pluginname) = normalize_component($data->component);
|
||||
|
||||
$plugintypepath = $this->get_plugintype_root($plugintype);
|
||||
|
||||
if (file_exists($plugintypepath.'/'.$pluginname)) {
|
||||
echo $output->remote_request_alreadyinstalled_page($data, $this->index_url());
|
||||
exit();
|
||||
}
|
||||
|
||||
if (!$this->is_plugintype_writable($plugintype)) {
|
||||
$continueurl = $this->index_url(array('installaddonrequest' => $request));
|
||||
echo $output->remote_request_permcheck_page($data, $plugintypepath, $continueurl, $this->index_url());
|
||||
exit();
|
||||
}
|
||||
|
||||
$continueurl = $this->index_url(array(
|
||||
'installaddonrequest' => $request,
|
||||
'confirm' => 1,
|
||||
'sesskey' => sesskey()));
|
||||
|
||||
if (!$confirmed) {
|
||||
echo $output->remote_request_confirm_page($data, $continueurl, $this->index_url());
|
||||
exit();
|
||||
}
|
||||
|
||||
// The admin has confirmed their intention to install the add-on.
|
||||
require_sesskey();
|
||||
|
||||
// Fetch the plugin info. The essential information is the URL to download the ZIP
|
||||
// and the MD5 hash of the ZIP, obtained via HTTPS.
|
||||
$client = tool_installaddon_pluginfo_client::instance();
|
||||
|
||||
try {
|
||||
$pluginfo = $client->get_pluginfo($data->component, $data->version);
|
||||
|
||||
} catch (tool_installaddon_pluginfo_exception $e) {
|
||||
if (debugging()) {
|
||||
throw $e;
|
||||
} else {
|
||||
echo $output->remote_request_pluginfo_exception($data, $e, $this->index_url());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the ZIP with the plugin version
|
||||
$jobid = md5(rand().uniqid('', true));
|
||||
$sourcedir = make_temp_directory('tool_installaddon/'.$jobid.'/source');
|
||||
$zipfilename = 'downloaded.zip';
|
||||
|
||||
try {
|
||||
$this->download_file($pluginfo->downloadurl, $sourcedir.'/'.$zipfilename);
|
||||
|
||||
} catch (tool_installaddon_installer_exception $e) {
|
||||
if (debugging()) {
|
||||
throw $e;
|
||||
} else {
|
||||
echo $output->installer_exception($e, $this->index_url());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
// Check the MD5 checksum
|
||||
$md5expected = $pluginfo->downloadmd5;
|
||||
$md5actual = md5_file($sourcedir.'/'.$zipfilename);
|
||||
if ($md5expected !== $md5actual) {
|
||||
$e = new tool_installaddon_installer_exception('err_zip_md5', array('expected' => $md5expected, 'actual' => $md5actual));
|
||||
if (debugging()) {
|
||||
throw $e;
|
||||
} else {
|
||||
echo $output->installer_exception($e, $this->index_url());
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect to the validation page.
|
||||
$nexturl = new moodle_url('/admin/tool/installaddon/validate.php', array(
|
||||
'sesskey' => sesskey(),
|
||||
'jobid' => $jobid,
|
||||
'zip' => $zipfilename,
|
||||
'type' => $plugintype));
|
||||
redirect($nexturl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the given file into the given destination.
|
||||
*
|
||||
* This is basically a simplified version of {@link download_file_content()} from
|
||||
* Moodle itself, tuned for fetching files from moodle.org servers. Same code is used
|
||||
* in mdeploy.php for fetching available updates.
|
||||
*
|
||||
* @param string $source file url starting with http(s)://
|
||||
* @param string $target store the downloaded content to this file (full path)
|
||||
* @throws tool_installaddon_installer_exception
|
||||
*/
|
||||
public function download_file($source, $target) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
|
||||
$targetfile = fopen($target, 'w');
|
||||
|
||||
if (!$targetfile) {
|
||||
throw new tool_installaddon_installer_exception('err_download_write_file', $target);
|
||||
}
|
||||
|
||||
$options = array(
|
||||
'file' => $targetfile,
|
||||
'timeout' => 300,
|
||||
'followlocation' => true,
|
||||
'maxredirs' => 3,
|
||||
'ssl_verifypeer' => true,
|
||||
'ssl_verifyhost' => 2,
|
||||
);
|
||||
|
||||
$cacertfile = $CFG->dataroot.'/moodleorgca.crt';
|
||||
if (is_readable($cacertfile)) {
|
||||
// Do not use CA certs provided by the operating system. Instead,
|
||||
// use this CA cert to verify the ZIP provider.
|
||||
$options['cainfo'] = $cacertfile;
|
||||
}
|
||||
|
||||
$curl = new curl(array('proxy' => true));
|
||||
|
||||
$result = $curl->download_one($source, null, $options);
|
||||
|
||||
$curlinfo = $curl->get_info();
|
||||
|
||||
fclose($targetfile);
|
||||
|
||||
if ($result !== true) {
|
||||
throw new tool_installaddon_installer_exception('err_curl_exec', array(
|
||||
'url' => $source, 'errorno' => $curl->get_errno(), 'error' => $result));
|
||||
|
||||
} else if (empty($curlinfo['http_code']) or $curlinfo['http_code'] != 200) {
|
||||
throw new tool_installaddon_installer_exception('err_curl_http_code', array(
|
||||
'url' => $source, 'http_code' => $curlinfo['http_code']));
|
||||
|
||||
} else if (isset($curlinfo['ssl_verify_result']) and $curlinfo['ssl_verify_result'] != 0) {
|
||||
throw new tool_installaddon_installer_exception('err_curl_ssl_verify', array(
|
||||
'url' => $source, 'ssl_verify_result' => $curlinfo['ssl_verify_result']));
|
||||
}
|
||||
}
|
||||
|
||||
//// End of external API ///////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @see self::instance()
|
||||
*/
|
||||
protected function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string this site full name
|
||||
*/
|
||||
protected function get_site_fullname() {
|
||||
global $SITE;
|
||||
|
||||
return strip_tags($SITE->fullname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string this site URL
|
||||
*/
|
||||
protected function get_site_url() {
|
||||
global $CFG;
|
||||
|
||||
return $CFG->wwwroot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string major version like 2.5, 2.6 etc.
|
||||
*/
|
||||
protected function get_site_major_version() {
|
||||
return moodle_major_version();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the given array in a way that can be safely appended as HTTP GET param
|
||||
*
|
||||
* Be ware! The recipient may rely on the exact way how the site information is encoded.
|
||||
* Do not change anything here unless you know what you are doing and understand all
|
||||
* consequences! (Don't you love warnings like that, too? :-p)
|
||||
*
|
||||
* @param array $info
|
||||
* @return string
|
||||
*/
|
||||
protected function encode_site_information(array $info) {
|
||||
return base64_encode(json_encode($info));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide if the encoded site information should be sent to the add-ons repository site
|
||||
*
|
||||
* For now, we just return true. In the future, we may want to implement some
|
||||
* privacy aware logic (based on site/user preferences for example).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function should_send_site_info() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames the root directory of the extracted ZIP package.
|
||||
*
|
||||
* This method does not validate the presence of the single root directory
|
||||
* (the validator does it later). It just searches for the first directory
|
||||
* under the given location and renames it.
|
||||
*
|
||||
* The method will not rename the root if the requested location already
|
||||
* exists.
|
||||
*
|
||||
* @param string $dirname the location of the extracted ZIP package
|
||||
* @param string $rootdir the requested name of the root directory
|
||||
* @param array $files list of extracted files
|
||||
* @return array eventually amended list of extracted files
|
||||
*/
|
||||
protected function rename_extracted_rootdir($dirname, $rootdir, array $files) {
|
||||
|
||||
if (!is_dir($dirname)) {
|
||||
debugging('Unable to rename rootdir of non-existing content', DEBUG_DEVELOPER);
|
||||
return $files;
|
||||
}
|
||||
|
||||
if (file_exists($dirname.'/'.$rootdir)) {
|
||||
debugging('Unable to rename rootdir to already existing folder', DEBUG_DEVELOPER);
|
||||
return $files;
|
||||
}
|
||||
|
||||
$found = null; // The name of the first subdirectory under the $dirname.
|
||||
foreach (scandir($dirname) as $item) {
|
||||
if (substr($item, 0, 1) === '.') {
|
||||
continue;
|
||||
}
|
||||
if (is_dir($dirname.'/'.$item)) {
|
||||
$found = $item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_null($found)) {
|
||||
if (rename($dirname.'/'.$found, $dirname.'/'.$rootdir)) {
|
||||
$newfiles = array();
|
||||
foreach ($files as $filepath => $status) {
|
||||
$newpath = preg_replace('~^'.preg_quote($found.'/').'~', preg_quote($rootdir.'/'), $filepath);
|
||||
$newfiles[$newpath] = $status;
|
||||
}
|
||||
return $newfiles;
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the request from the Moodle Plugins directory
|
||||
*
|
||||
* @param string $request submitted via 'installaddonrequest' HTTP parameter
|
||||
* @return stdClass|bool false on error, object otherwise
|
||||
*/
|
||||
protected function decode_remote_request($request) {
|
||||
|
||||
$data = base64_decode($request, true);
|
||||
|
||||
if ($data === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = json_decode($data);
|
||||
|
||||
if (is_null($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($data->name) or !isset($data->component) or !isset($data->version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data->name = s(strip_tags($data->name));
|
||||
|
||||
if ($data->component !== clean_param($data->component, PARAM_COMPONENT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
list($plugintype, $pluginname) = normalize_component($data->component);
|
||||
|
||||
if ($plugintype === 'core') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($data->component !== $plugintype.'_'.$pluginname) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Keep this regex in sync with the one used by the download.moodle.org/api/x.y/pluginfo.php
|
||||
if (!preg_match('/^[0-9]+$/', $data->version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* General exception thrown by {@link tool_installaddon_installer} class
|
||||
*
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_installaddon_installer_exception extends moodle_exception {
|
||||
|
||||
/**
|
||||
* @param string $errorcode exception description identifier
|
||||
* @param mixed $debuginfo debugging data to display
|
||||
*/
|
||||
public function __construct($errorcode, $a=null, $debuginfo=null) {
|
||||
parent::__construct($errorcode, 'tool_installaddon', '', $a, print_r($debuginfo, true));
|
||||
}
|
||||
}
|
||||
@@ -1,95 +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/>.
|
||||
|
||||
/**
|
||||
* @package tool_installaddon
|
||||
* @subpackage classes
|
||||
* @category form
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir.'/formslib.php');
|
||||
|
||||
/**
|
||||
* Defines a simple form for uploading the add-on ZIP package
|
||||
*
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_installaddon_installfromzip extends moodleform {
|
||||
|
||||
/**
|
||||
* Defines the form elements
|
||||
*/
|
||||
public function definition() {
|
||||
|
||||
$mform = $this->_form;
|
||||
$installer = $this->_customdata['installer'];
|
||||
|
||||
$mform->addElement('header', 'general', get_string('installfromzip', 'tool_installaddon'));
|
||||
$mform->addHelpButton('general', 'installfromzip', 'tool_installaddon');
|
||||
|
||||
$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->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->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'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the form fields
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $files
|
||||
* @return array (string)field name => (string)validation error text
|
||||
*/
|
||||
public function validation($data, $files) {
|
||||
|
||||
$installer = $this->_customdata['installer'];
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,216 +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/>.
|
||||
|
||||
/**
|
||||
* Provides tool_installaddon_pluginfo_client and related classes
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @subpackage classes
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Implements a client for https://download.moodle.org/api/x.y/pluginfo.php service
|
||||
*
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_installaddon_pluginfo_client {
|
||||
|
||||
/**
|
||||
* Factory method returning an instance of this class.
|
||||
*
|
||||
* @return tool_installaddon_pluginfo_client
|
||||
*/
|
||||
public static function instance() {
|
||||
return new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the information about the plugin
|
||||
*
|
||||
* @throws tool_installaddon_pluginfo_exception
|
||||
* @param string $component
|
||||
* @param string $version
|
||||
* @return stdClass the pluginfo structure
|
||||
*/
|
||||
public function get_pluginfo($component, $version) {
|
||||
|
||||
$response = $this->call_service($component, $version);
|
||||
$response = $this->decode_response($response);
|
||||
$this->validate_response($response);
|
||||
|
||||
return $response->pluginfo;
|
||||
}
|
||||
|
||||
// End of external API /////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @see self::instance()
|
||||
*/
|
||||
protected function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the pluginfo.php service and returns the raw response
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $version
|
||||
* @return string
|
||||
*/
|
||||
protected function call_service($component, $version) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
|
||||
$curl = new curl(array('proxy' => true));
|
||||
|
||||
$response = $curl->get(
|
||||
$this->service_request_url(),
|
||||
$this->service_request_params($component, $version),
|
||||
$this->service_request_options());
|
||||
|
||||
$curlerrno = $curl->get_errno();
|
||||
$curlinfo = $curl->get_info();
|
||||
|
||||
if (!empty($curlerrno)) {
|
||||
throw new tool_installaddon_pluginfo_exception('err_curl_exec', array(
|
||||
'url' => $curlinfo['url'], 'errno' => $curlerrno, 'error' => $curl->error));
|
||||
|
||||
} else if ($curlinfo['http_code'] != 200) {
|
||||
throw new tool_installaddon_pluginfo_exception('err_curl_http_code', array(
|
||||
'url' => $curlinfo['url'], 'http_code' => $curlinfo['http_code']));
|
||||
|
||||
} else if (isset($curlinfo['ssl_verify_result']) and $curlinfo['ssl_verify_result'] != 0) {
|
||||
throw new tool_installaddon_pluginfo_exception('err_curl_ssl_verify', array(
|
||||
'url' => $curlinfo['url'], 'ssl_verify_result' => $curlinfo['ssl_verify_result']));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return URL to the pluginfo.php service
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
protected function service_request_url() {
|
||||
global $CFG;
|
||||
|
||||
if (!empty($CFG->config_php_settings['alternativepluginfoserviceurl'])) {
|
||||
$url = $CFG->config_php_settings['alternativepluginfoserviceurl'];
|
||||
} else {
|
||||
$url = 'https://download.moodle.org/api/1.2/pluginfo.php';
|
||||
}
|
||||
|
||||
return new moodle_url($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of pluginfo service parameters
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $version
|
||||
* @return array
|
||||
*/
|
||||
protected function service_request_params($component, $version) {
|
||||
|
||||
$params = array();
|
||||
$params['format'] = 'json';
|
||||
$params['plugin'] = $component.'@'.$version;
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return cURL options for the service request
|
||||
*
|
||||
* @return array of (string)param => (string)value
|
||||
*/
|
||||
protected function service_request_options() {
|
||||
global $CFG;
|
||||
|
||||
$options = array(
|
||||
'CURLOPT_SSL_VERIFYHOST' => 2, // this is the default in {@link curl} class but just in case
|
||||
'CURLOPT_SSL_VERIFYPEER' => true,
|
||||
);
|
||||
|
||||
$cacertfile = $CFG->dataroot.'/moodleorgca.crt';
|
||||
if (is_readable($cacertfile)) {
|
||||
// Do not use CA certs provided by the operating system. Instead,
|
||||
// use this CA cert to verify the updates provider.
|
||||
$options['CURLOPT_CAINFO'] = $cacertfile;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the raw service response
|
||||
*
|
||||
* @param string $raw
|
||||
* @return stdClass
|
||||
*/
|
||||
protected function decode_response($raw) {
|
||||
return json_decode($raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate decoded service response
|
||||
*
|
||||
* @param stdClass $response
|
||||
*/
|
||||
protected function validate_response($response) {
|
||||
|
||||
if (empty($response)) {
|
||||
throw new tool_installaddon_pluginfo_exception('err_response_empty');
|
||||
}
|
||||
|
||||
if (empty($response->status) or $response->status !== 'OK') {
|
||||
throw new tool_installaddon_pluginfo_exception('err_response_status', $response->status);
|
||||
}
|
||||
|
||||
if (empty($response->apiver) or $response->apiver !== '1.2') {
|
||||
throw new tool_installaddon_pluginfo_exception('err_response_api_version', $response->apiver);
|
||||
}
|
||||
|
||||
if (empty($response->pluginfo->component) or empty($response->pluginfo->downloadurl)
|
||||
or empty($response->pluginfo->downloadmd5)) {
|
||||
throw new tool_installaddon_pluginfo_exception('err_response_pluginfo');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* General exception thrown by {@link tool_installaddon_pluginfo_client} class
|
||||
*
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_installaddon_pluginfo_exception extends moodle_exception {
|
||||
|
||||
/**
|
||||
* @param string $errorcode exception description identifier
|
||||
* @param mixed $debuginfo debugging data to display
|
||||
*/
|
||||
public function __construct($errorcode, $a=null, $debuginfo=null) {
|
||||
parent::__construct($errorcode, 'tool_installaddon', '', $a, print_r($debuginfo, true));
|
||||
}
|
||||
}
|
||||
@@ -1,575 +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/>.
|
||||
|
||||
/**
|
||||
* Provides validation class to check the plugin ZIP contents
|
||||
*
|
||||
* Uses fragments of the local_plugins_archive_validator class copyrighted by
|
||||
* Marina Glancy that is part of the local_plugins plugin.
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @subpackage classes
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
if (!defined('T_ML_COMMENT')) {
|
||||
define('T_ML_COMMENT', T_COMMENT);
|
||||
} else {
|
||||
define('T_DOC_COMMENT', T_ML_COMMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the contents of extracted plugin ZIP file
|
||||
*
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_installaddon_validator {
|
||||
|
||||
/** Critical error message level, causes the validation fail. */
|
||||
const ERROR = 'error';
|
||||
|
||||
/** Warning message level, validation does not fail but the admin should be always informed. */
|
||||
const WARNING = 'warning';
|
||||
|
||||
/** Information message level that the admin should be aware of. */
|
||||
const INFO = 'info';
|
||||
|
||||
/** Debugging message level, should be displayed in debugging mode only. */
|
||||
const DEBUG = 'debug';
|
||||
|
||||
/** @var string full path to the extracted ZIP contents */
|
||||
protected $extractdir = null;
|
||||
|
||||
/** @var array as returned by {@link zip_packer::extract_to_pathname()} */
|
||||
protected $extractfiles = null;
|
||||
|
||||
/** @var bool overall result of validation */
|
||||
protected $result = null;
|
||||
|
||||
/** @var string the name of the plugin root directory */
|
||||
protected $rootdir = null;
|
||||
|
||||
/** @var array explicit list of expected/required characteristics of the ZIP */
|
||||
protected $assertions = null;
|
||||
|
||||
/** @var array of validation log messages */
|
||||
protected $messages = array();
|
||||
|
||||
/** @var array|null array of relevant data obtained from version.php */
|
||||
protected $versionphp = null;
|
||||
|
||||
/** @var string|null the name of found English language file without the .php extension */
|
||||
protected $langfilename = null;
|
||||
|
||||
/** @var moodle_url|null URL to continue with the installation of validated add-on */
|
||||
protected $continueurl = null;
|
||||
|
||||
/**
|
||||
* Factory method returning instance of the validator
|
||||
*
|
||||
* @param string $zipcontentpath full path to the extracted ZIP contents
|
||||
* @param array $zipcontentfiles (string)filerelpath => (bool|string)true or error
|
||||
* @return tool_installaddon_validator
|
||||
*/
|
||||
public static function instance($zipcontentpath, array $zipcontentfiles) {
|
||||
return new static($zipcontentpath, $zipcontentfiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expected plugin type, fail the validation otherwise
|
||||
*
|
||||
* @param string $required plugin type
|
||||
*/
|
||||
public function assert_plugin_type($required) {
|
||||
$this->assertions['plugintype'] = $required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expectation that the plugin can be installed into the given Moodle version
|
||||
*
|
||||
* @param string $required Moodle version we are about to install to
|
||||
*/
|
||||
public function assert_moodle_version($required) {
|
||||
$this->assertions['moodleversion'] = $required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the validation process against all explicit and implicit requirements
|
||||
*
|
||||
* Returns true if the validation passes (all explicit and implicit requirements
|
||||
* pass) and the plugin can be installed. Returns false if the validation fails
|
||||
* (some explicit or implicit requirement fails) and the plugin must not be
|
||||
* installed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function execute() {
|
||||
|
||||
$this->result = (
|
||||
$this->validate_files_layout()
|
||||
and $this->validate_version_php()
|
||||
and $this->validate_language_pack()
|
||||
and $this->validate_target_location()
|
||||
);
|
||||
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns overall result of the validation.
|
||||
*
|
||||
* Null is returned if the validation has not been executed yet. Otherwise
|
||||
* this method returns true (the installation can continue) or false (it is not
|
||||
* safe to continue with the installation).
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function get_result() {
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of validation log messages
|
||||
*
|
||||
* Each validation message is a plain object with properties level, msgcode
|
||||
* and addinfo.
|
||||
*
|
||||
* @return array of (int)index => (stdClass) validation message
|
||||
*/
|
||||
public function get_messages() {
|
||||
return $this->messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the information provided by the the plugin's version.php
|
||||
*
|
||||
* If version.php was not found in the plugin (which is tolerated for
|
||||
* themes only at the moment), null is returned. Otherwise the array
|
||||
* is returned. It may be empty if no information was parsed (which
|
||||
* should not happen).
|
||||
*
|
||||
* @return null|array
|
||||
*/
|
||||
public function get_versionphp_info() {
|
||||
return $this->versionphp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the English language file without the .php extension
|
||||
*
|
||||
* This can be used as a suggestion for fixing the plugin root directory in the
|
||||
* ZIP file during the upload. If no file was found, or multiple PHP files are
|
||||
* located in lang/en/ folder, then null is returned.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function get_language_file_name() {
|
||||
return $this->langfilename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rootdir of the extracted package (after eventual renaming)
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_rootdir() {
|
||||
return $this->rootdir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URL to continue to after successful validation
|
||||
*
|
||||
* @param moodle_url $url
|
||||
*/
|
||||
public function set_continue_url(moodle_url $url) {
|
||||
$this->continueurl = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL to continue to after successful validation
|
||||
*
|
||||
* Null is returned if the URL has not been explicitly set by the caller.
|
||||
*
|
||||
* @return moodle_url|null
|
||||
*/
|
||||
public function get_continue_url() {
|
||||
return $this->continueurl;
|
||||
}
|
||||
|
||||
// End of external API /////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @param string $zipcontentpath full path to the extracted ZIP contents
|
||||
* @param array $zipcontentfiles (string)filerelpath => (bool|string)true or error
|
||||
*/
|
||||
protected function __construct($zipcontentpath, array $zipcontentfiles) {
|
||||
$this->extractdir = $zipcontentpath;
|
||||
$this->extractfiles = $zipcontentfiles;
|
||||
}
|
||||
|
||||
// Validation methods //////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @return bool false if files in the ZIP do not have required layout
|
||||
*/
|
||||
protected function validate_files_layout() {
|
||||
|
||||
if (!is_array($this->extractfiles) or count($this->extractfiles) < 4) {
|
||||
// We need the English language pack with the name of the plugin at least
|
||||
$this->add_message(self::ERROR, 'filesnumber');
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($this->extractfiles as $filerelname => $filestatus) {
|
||||
if ($filestatus !== true) {
|
||||
$this->add_message(self::ERROR, 'filestatus', array('file' => $filerelname, 'status' => $filestatus));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_keys($this->extractfiles) as $filerelname) {
|
||||
if (!file_exists($this->extractdir.'/'.$filerelname)) {
|
||||
$this->add_message(self::ERROR, 'filenotexists', array('file' => $filerelname));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_keys($this->extractfiles) as $filerelname) {
|
||||
$matches = array();
|
||||
if (!preg_match("#^([^/]+)/#", $filerelname, $matches) or (!is_null($this->rootdir) and $this->rootdir !== $matches[1])) {
|
||||
$this->add_message(self::ERROR, 'onedir');
|
||||
return false;
|
||||
}
|
||||
$this->rootdir = $matches[1];
|
||||
}
|
||||
|
||||
if ($this->rootdir !== clean_param($this->rootdir, PARAM_PLUGIN)) {
|
||||
$this->add_message(self::ERROR, 'rootdirinvalid', $this->rootdir);
|
||||
return false;
|
||||
} else {
|
||||
$this->add_message(self::INFO, 'rootdir', $this->rootdir);
|
||||
}
|
||||
|
||||
return is_dir($this->extractdir.'/'.$this->rootdir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool false if the version.php file does not declare required information
|
||||
*/
|
||||
protected function validate_version_php() {
|
||||
|
||||
if (!isset($this->assertions['plugintype'])) {
|
||||
throw new coding_exception('Required plugin type must be set before calling this');
|
||||
}
|
||||
|
||||
if (!isset($this->assertions['moodleversion'])) {
|
||||
throw new coding_exception('Required Moodle version must be set before calling this');
|
||||
}
|
||||
|
||||
$fullpath = $this->extractdir.'/'.$this->rootdir.'/version.php';
|
||||
|
||||
if (!file_exists($fullpath)) {
|
||||
// This is tolerated for themes only.
|
||||
if ($this->assertions['plugintype'] === 'theme') {
|
||||
$this->add_message(self::DEBUG, 'missingversionphp');
|
||||
return true;
|
||||
} else {
|
||||
$this->add_message(self::ERROR, 'missingversionphp');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->versionphp = array();
|
||||
$info = $this->parse_version_php($fullpath);
|
||||
|
||||
if ($this->assertions['plugintype'] === 'mod') {
|
||||
$type = 'module';
|
||||
} else {
|
||||
$type = 'plugin';
|
||||
}
|
||||
|
||||
if (!isset($info[$type.'->version'])) {
|
||||
if ($type === 'module' and isset($info['plugin->version'])) {
|
||||
// Expect the activity module using $plugin in version.php instead of $module.
|
||||
$type = 'plugin';
|
||||
$this->versionphp['version'] = $info[$type.'->version'];
|
||||
$this->add_message(self::INFO, 'pluginversion', $this->versionphp['version']);
|
||||
} else {
|
||||
$this->add_message(self::ERROR, 'missingversion');
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$this->versionphp['version'] = $info[$type.'->version'];
|
||||
$this->add_message(self::INFO, 'pluginversion', $this->versionphp['version']);
|
||||
}
|
||||
|
||||
if (isset($info[$type.'->requires'])) {
|
||||
$this->versionphp['requires'] = $info[$type.'->requires'];
|
||||
if ($this->versionphp['requires'] > $this->assertions['moodleversion']) {
|
||||
$this->add_message(self::ERROR, 'requiresmoodle', $this->versionphp['requires']);
|
||||
return false;
|
||||
}
|
||||
$this->add_message(self::INFO, 'requiresmoodle', $this->versionphp['requires']);
|
||||
}
|
||||
|
||||
if (isset($info[$type.'->component'])) {
|
||||
$this->versionphp['component'] = $info[$type.'->component'];
|
||||
list($reqtype, $reqname) = normalize_component($this->versionphp['component']);
|
||||
if ($reqtype !== $this->assertions['plugintype']) {
|
||||
$this->add_message(self::ERROR, 'componentmismatchtype', array(
|
||||
'expected' => $this->assertions['plugintype'],
|
||||
'found' => $reqtype));
|
||||
return false;
|
||||
}
|
||||
if ($reqname !== $this->rootdir) {
|
||||
$this->add_message(self::ERROR, 'componentmismatchname', $reqname);
|
||||
return false;
|
||||
}
|
||||
$this->add_message(self::INFO, 'componentmatch', $this->versionphp['component']);
|
||||
}
|
||||
|
||||
if (isset($info[$type.'->maturity'])) {
|
||||
$this->versionphp['maturity'] = $info[$type.'->maturity'];
|
||||
if ($this->versionphp['maturity'] === 'MATURITY_STABLE') {
|
||||
$this->add_message(self::INFO, 'maturity', $this->versionphp['maturity']);
|
||||
} else {
|
||||
$this->add_message(self::WARNING, 'maturity', $this->versionphp['maturity']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($info[$type.'->release'])) {
|
||||
$this->versionphp['release'] = $info[$type.'->release'];
|
||||
$this->add_message(self::INFO, 'release', $this->versionphp['release']);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool false if the English language pack is not provided correctly
|
||||
*/
|
||||
protected function validate_language_pack() {
|
||||
|
||||
if (!isset($this->assertions['plugintype'])) {
|
||||
throw new coding_exception('Required plugin type must be set before calling this');
|
||||
}
|
||||
|
||||
if (!isset($this->extractfiles[$this->rootdir.'/lang/en/'])
|
||||
or $this->extractfiles[$this->rootdir.'/lang/en/'] !== true
|
||||
or !is_dir($this->extractdir.'/'.$this->rootdir.'/lang/en')) {
|
||||
$this->add_message(self::ERROR, 'missinglangenfolder');
|
||||
return false;
|
||||
}
|
||||
|
||||
$langfiles = array();
|
||||
foreach (array_keys($this->extractfiles) as $extractfile) {
|
||||
$matches = array();
|
||||
if (preg_match('#^'.preg_quote($this->rootdir).'/lang/en/([^/]+).php?$#i', $extractfile, $matches)) {
|
||||
$langfiles[] = $matches[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($langfiles)) {
|
||||
$this->add_message(self::ERROR, 'missinglangenfile');
|
||||
return false;
|
||||
} else if (count($langfiles) > 1) {
|
||||
$this->add_message(self::WARNING, 'multiplelangenfiles');
|
||||
} else {
|
||||
$this->langfilename = $langfiles[0];
|
||||
$this->add_message(self::DEBUG, 'foundlangfile', $this->langfilename);
|
||||
}
|
||||
|
||||
if ($this->assertions['plugintype'] === 'mod') {
|
||||
$expected = $this->rootdir.'.php';
|
||||
} else {
|
||||
$expected = $this->assertions['plugintype'].'_'.$this->rootdir.'.php';
|
||||
}
|
||||
|
||||
if (!isset($this->extractfiles[$this->rootdir.'/lang/en/'.$expected])
|
||||
or $this->extractfiles[$this->rootdir.'/lang/en/'.$expected] !== true
|
||||
or !is_file($this->extractdir.'/'.$this->rootdir.'/lang/en/'.$expected)) {
|
||||
$this->add_message(self::ERROR, 'missingexpectedlangenfile', $expected);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool false of the given add-on can't be installed into its location
|
||||
*/
|
||||
public function validate_target_location() {
|
||||
|
||||
if (!isset($this->assertions['plugintype'])) {
|
||||
throw new coding_exception('Required plugin type must be set before calling this');
|
||||
}
|
||||
|
||||
$plugintypepath = $this->get_plugintype_location($this->assertions['plugintype']);
|
||||
|
||||
if (is_null($plugintypepath)) {
|
||||
$this->add_message(self::ERROR, 'unknowntype', $this->assertions['plugintype']);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_dir($plugintypepath)) {
|
||||
throw new coding_exception('Plugin type location does not exist!');
|
||||
}
|
||||
|
||||
$target = $plugintypepath.'/'.$this->rootdir;
|
||||
|
||||
if (file_exists($target)) {
|
||||
$this->add_message(self::ERROR, 'targetexists', $target);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_writable($plugintypepath)) {
|
||||
$this->add_message(self::INFO, 'pathwritable', $plugintypepath);
|
||||
} else {
|
||||
$this->add_message(self::ERROR, 'pathwritable', $plugintypepath);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper methods //////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Get as much information from existing version.php as possible
|
||||
*
|
||||
* @param string full path to the version.php file
|
||||
* @return array of found meta-info declarations
|
||||
*/
|
||||
protected function parse_version_php($fullpath) {
|
||||
|
||||
$content = $this->get_stripped_file_contents($fullpath);
|
||||
|
||||
preg_match_all('#\$((plugin|module)\->(version|maturity|release|requires))=()(\d+(\.\d+)?);#m', $content, $matches1);
|
||||
preg_match_all('#\$((plugin|module)\->(maturity))=()(MATURITY_\w+);#m', $content, $matches2);
|
||||
preg_match_all('#\$((plugin|module)\->(release))=([\'"])(.*?)\4;#m', $content, $matches3);
|
||||
preg_match_all('#\$((plugin|module)\->(component))=([\'"])(.+?_.+?)\4;#m', $content, $matches4);
|
||||
|
||||
if (count($matches1[1]) + count($matches2[1]) + count($matches3[1]) + count($matches4[1])) {
|
||||
$info = array_combine(
|
||||
array_merge($matches1[1], $matches2[1], $matches3[1], $matches4[1]),
|
||||
array_merge($matches1[5], $matches2[5], $matches3[5], $matches4[5])
|
||||
);
|
||||
|
||||
} else {
|
||||
$info = array();
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the given message to the messages log
|
||||
*
|
||||
* @param string $level e.g. self::ERROR
|
||||
* @param string $msgcode may form a string
|
||||
* @param string|array|object $a optional additional info suitable for {@link get_string()}
|
||||
*/
|
||||
protected function add_message($level, $msgcode, $a = null) {
|
||||
$msg = (object)array(
|
||||
'level' => $level,
|
||||
'msgcode' => $msgcode,
|
||||
'addinfo' => $a,
|
||||
);
|
||||
$this->messages[] = $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bare PHP code from the given file
|
||||
*
|
||||
* Returns contents without PHP opening and closing tags, text outside php code,
|
||||
* comments and extra whitespaces.
|
||||
*
|
||||
* @param string $fullpath full path to the file
|
||||
* @return string
|
||||
*/
|
||||
protected function get_stripped_file_contents($fullpath) {
|
||||
|
||||
$source = file_get_contents($fullpath);
|
||||
$tokens = token_get_all($source);
|
||||
$output = '';
|
||||
$doprocess = false;
|
||||
foreach ($tokens as $token) {
|
||||
if (is_string($token)) {
|
||||
// Simple one character token.
|
||||
$id = -1;
|
||||
$text = $token;
|
||||
} else {
|
||||
// Token array.
|
||||
list($id, $text) = $token;
|
||||
}
|
||||
switch ($id) {
|
||||
case T_WHITESPACE:
|
||||
case T_COMMENT:
|
||||
case T_ML_COMMENT:
|
||||
case T_DOC_COMMENT:
|
||||
// Ignore whitespaces, inline comments, multiline comments and docblocks.
|
||||
break;
|
||||
case T_OPEN_TAG:
|
||||
// Start processing.
|
||||
$doprocess = true;
|
||||
break;
|
||||
case T_CLOSE_TAG:
|
||||
// Stop processing.
|
||||
$doprocess = false;
|
||||
break;
|
||||
default:
|
||||
// Anything else is within PHP tags, return it as is.
|
||||
if ($doprocess) {
|
||||
$output .= $text;
|
||||
if ($text === 'function') {
|
||||
// Explicitly keep the whitespace that would be ignored.
|
||||
$output .= ' ';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the full path to the root directory of the given plugin type
|
||||
*
|
||||
* @param string $plugintype
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_plugintype_location($plugintype) {
|
||||
|
||||
$plugintypepath = null;
|
||||
|
||||
foreach (get_plugin_types() as $type => $fullpath) {
|
||||
if ($type === $plugintype) {
|
||||
$plugintypepath = $fullpath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $plugintypepath;
|
||||
}
|
||||
}
|
||||
@@ -1,76 +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/>.
|
||||
|
||||
/**
|
||||
* Deploy the validated contents of the ZIP package to the $CFG->dirroot
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(dirname(__FILE__) . '/../../../config.php');
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
require_once(dirname(__FILE__).'/classes/installer.php');
|
||||
require_once(dirname(__FILE__).'/classes/validator.php');
|
||||
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
if (!empty($CFG->disableonclickaddoninstall)) {
|
||||
notice(get_string('featuredisabled', 'tool_installaddon'));
|
||||
}
|
||||
|
||||
require_sesskey();
|
||||
|
||||
$jobid = required_param('jobid', PARAM_ALPHANUM);
|
||||
$plugintype = required_param('type', PARAM_ALPHANUMEXT);
|
||||
$pluginname = required_param('name', PARAM_PLUGIN);
|
||||
|
||||
$zipcontentpath = $CFG->tempdir.'/tool_installaddon/'.$jobid.'/contents';
|
||||
|
||||
if (!is_dir($zipcontentpath)) {
|
||||
debugging('Invalid location of the extracted ZIP package: '.s($zipcontentpath), DEBUG_DEVELOPER);
|
||||
redirect(new moodle_url('/admin/tool/installaddon/index.php'),
|
||||
get_string('invaliddata', 'core_error'));
|
||||
}
|
||||
|
||||
if (!is_dir($zipcontentpath.'/'.$pluginname)) {
|
||||
debugging('Invalid location of the plugin root directory: '.$zipcontentpath.'/'.$pluginname, DEBUG_DEVELOPER);
|
||||
redirect(new moodle_url('/admin/tool/installaddon/index.php'),
|
||||
get_string('invaliddata', 'core_error'));
|
||||
}
|
||||
|
||||
$installer = tool_installaddon_installer::instance();
|
||||
|
||||
if (!$installer->is_plugintype_writable($plugintype)) {
|
||||
debugging('Plugin type location not writable', DEBUG_DEVELOPER);
|
||||
redirect(new moodle_url('/admin/tool/installaddon/index.php'),
|
||||
get_string('invaliddata', 'core_error'));
|
||||
}
|
||||
|
||||
$plugintypepath = $installer->get_plugintype_root($plugintype);
|
||||
|
||||
if (file_exists($plugintypepath.'/'.$pluginname)) {
|
||||
debugging('Target location already exists', DEBUG_DEVELOPER);
|
||||
redirect(new moodle_url('/admin/tool/installaddon/index.php'),
|
||||
get_string('invaliddata', 'core_error'));
|
||||
}
|
||||
|
||||
rename($zipcontentpath.'/'.$pluginname, $plugintypepath.'/'.$pluginname);
|
||||
fulldelete($CFG->tempdir.'/tool_installaddon/'.$jobid);
|
||||
redirect(new moodle_url('/admin'));
|
||||
@@ -1,67 +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/>.
|
||||
|
||||
/**
|
||||
* The main screen of the tool.
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(dirname(__FILE__) . '/../../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once(dirname(__FILE__).'/classes/installer.php');
|
||||
|
||||
admin_externalpage_setup('tool_installaddon_index');
|
||||
|
||||
if (!empty($CFG->disableonclickaddoninstall)) {
|
||||
notice(get_string('featuredisabled', 'tool_installaddon'));
|
||||
}
|
||||
|
||||
$installer = tool_installaddon_installer::instance();
|
||||
|
||||
$output = $PAGE->get_renderer('tool_installaddon');
|
||||
$output->set_installer_instance($installer);
|
||||
|
||||
// Handle the eventual request for installing from remote repository.
|
||||
$remoterequest = optional_param('installaddonrequest', null, PARAM_RAW);
|
||||
$confirmed = optional_param('confirm', false, PARAM_BOOL);
|
||||
$installer->handle_remote_request($output, $remoterequest, $confirmed);
|
||||
|
||||
$form = $installer->get_installfromzip_form();
|
||||
|
||||
if ($form->is_cancelled()) {
|
||||
redirect($PAGE->url);
|
||||
|
||||
} else if ($data = $form->get_data()) {
|
||||
// Save the ZIP file into a temporary location.
|
||||
$jobid = md5(rand().uniqid('', true));
|
||||
$sourcedir = make_temp_directory('tool_installaddon/'.$jobid.'/source');
|
||||
$zipfilename = $installer->save_installfromzip_file($form, $sourcedir);
|
||||
// Redirect to the validation page.
|
||||
$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.
|
||||
echo $output->index_page();
|
||||
@@ -1,102 +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 the tool_installaddon component.
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @category string
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
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 add-ons. I accept and understand that add-ons (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'] = 'Add-on installer is disabled at this site.';
|
||||
$string['installaddon'] = 'Install add-on!';
|
||||
$string['installaddons'] = 'Install add-ons';
|
||||
$string['installexception'] = 'Oops... An error occured while trying to install the add-on. Turn debugging mode on to see more details about the error.';
|
||||
$string['installfromrepo'] = 'Install add-ons from Moodle plugins directory';
|
||||
$string['installfromrepo_help'] = 'You will be redirected to the Moodle plugins directory to search for and install an add-on. Note that your site fullname, URL and major version will be sent as well, to make the installation process easier for you.';
|
||||
$string['installfromzip'] = 'Install add-on from the ZIP file';
|
||||
$string['installfromzip_help'] = 'Alternatively to installing add-ons directly from the Moodle plugins directory, you can install add-ons from manually uploaded ZIP packages. Such ZIP packages are expected to have same structure as the ones available in the Moodle plugins directory.';
|
||||
$string['installfromzipfile'] = 'ZIP package';
|
||||
$string['installfromzipfile_help'] = 'The plugin ZIP package must contain just one directory with the name of the plugin. The ZIP will be extracted into the appropriate location for the given plugin type. Packages downloaded from the Moodle plugins directory have this format.';
|
||||
$string['installfromziprootdir'] = 'Rename the root directory';
|
||||
$string['installfromziprootdir_help'] = 'Some ZIP packages, such as those generated by Github, may contain incorrect name of the root directory. You can rename the root directory of the extracted package to the correct value defined in this field.';
|
||||
$string['installfromzipsubmit'] = 'Install add-on from the ZIP file';
|
||||
$string['installfromziptype'] = 'Plugin type';
|
||||
$string['installfromziptype_help'] = 'Choose the correct type of plugin you are about to install. The installation procedure may fail badly when incorrect plugin type is provided.';
|
||||
$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> not writable';
|
||||
$string['permcheckresultyes'] = 'Plugin type location <em>{$a->path}</em> is writable';
|
||||
$string['pluginname'] = 'Add-on installer';
|
||||
$string['remoterequestalreadyinstalled'] = 'There is a request to install add-on {$a->name} ({$a->component}) version {$a->version} from the Moodle plugins directory to this site. This plugin is <strong>already installed</strong> at this site.';
|
||||
$string['remoterequestconfirm'] = 'There is a request to install add-on <strong>{$a->name}</strong> ({$a->component}) version {$a->version} from the Moodle plugins directory to this site. If you continue, the add-on ZIP package will be downloaded for validation. Nothing will be installed yet.';
|
||||
$string['remoterequestinvalid'] = 'There is a request to install add-on from the Moodle plugins directory to this site. Unfortunately, the request is not valid. The add-on cannot be installed.';
|
||||
$string['remoterequestpermcheck'] = 'There is a request to install add-on {$a->name} ({$a->component}) version {$a->version} from the Moodle plugins directory to this site. The plugin type location <strong>{$a->typepath}</strong> is <strong>not writable</strong> though. You need to give the write access for the web server user to the plugin type location now. Once the write access is granted, press the continue button to repeat the check.';
|
||||
$string['remoterequestpluginfoexception'] = 'Oops... An error occured while trying to obtain information about the add-on {$a->name} ({$a->component}) version {$a->version}. The add-on cannot be installed. Turn debugging mode on to see more details about the error.';
|
||||
$string['validation'] = 'Add-on package validation';
|
||||
$string['validationmsg_componentmatch'] = 'Full component name';
|
||||
$string['validationmsg_componentmismatchname'] = 'Add-on name mismatch';
|
||||
$string['validationmsg_componentmismatchname_help'] = 'Some ZIP packages, such as those generated by Github, may contain incorrect name of the root directory. You have to fix the name of the root directory to match the declared add-on name.';
|
||||
$string['validationmsg_componentmismatchname_info'] = 'The add-on declares its name is \'{$a}\' but that does not match the name of the root directory.';
|
||||
$string['validationmsg_componentmismatchtype'] = 'Add-on type mismatch';
|
||||
$string['validationmsg_componentmismatchtype_info'] = 'You have selected the type \'{$a->expected}\' but the add-on 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';
|
||||
$string['validationmsg_filestatus_info'] = 'Attempting to extract file {$a->file} resulted in error \'{$a->status}\'.';
|
||||
$string['validationmsg_maturity'] = 'Declared maturity level';
|
||||
$string['validationmsg_maturity_help'] = 'The add-on can declare its maturity level. If the maintainer considers the add-on stable, the declared maturity level will read MATURITY_STABLE. All other maturity levels (such as alpha or beta) should be considered unstable and a warning is raised.';
|
||||
$string['validationmsg_missingexpectedlangenfile'] = 'English language file name mismatch';
|
||||
$string['validationmsg_missingexpectedlangenfile_info'] = 'The given add-on type would need to provide the English language file {$a}.';
|
||||
$string['validationmsg_missinglangenfile'] = 'No English language file found';
|
||||
$string['validationmsg_missinglangenfolder'] = 'Missing English language folder';
|
||||
$string['validationmsg_missingversion'] = 'Add-on does not declare its version';
|
||||
$string['validationmsg_missingversionphp'] = 'File version.php not found';
|
||||
$string['validationmsg_multiplelangenfiles'] = 'Multiple English language files found';
|
||||
$string['validationmsg_onedir'] = 'Invalid structure of the ZIP package.';
|
||||
$string['validationmsg_onedir_help'] = 'The ZIP package must contain just one root directory that holds the add-on code. The name of that root directory must match the name of the plugin.';
|
||||
$string['validationmsg_pathwritable'] = 'Write access check';
|
||||
$string['validationmsg_pluginversion'] = 'Add-on version';
|
||||
$string['validationmsg_release'] = 'Add-on release';
|
||||
$string['validationmsg_requiresmoodle'] = 'Required Moodle version';
|
||||
$string['validationmsg_rootdir'] = 'Name of the add-on to be installed';
|
||||
$string['validationmsg_rootdir_help'] = 'The name of the root directory in the ZIP package forms the name of the add-on to be installed. If the name is not correct, you may wish to rename the root directory in the ZIP prior to installing the add-on.';
|
||||
$string['validationmsg_rootdirinvalid'] = 'Invalid name of the add-on';
|
||||
$string['validationmsg_rootdirinvalid_help'] = 'The name of the root directory in the ZIP package violates formal syntax requirements. Some ZIP packages, such as those generated by Github, may contain incorrect name of the root directory. You have to fix the name of the root directory to match the add-on name.';
|
||||
$string['validationmsg_targetexists'] = 'Target location already exists';
|
||||
$string['validationmsg_targetexists_help'] = 'The directory that the add-on is to be installed to, must not exist yet.';
|
||||
$string['validationmsg_unknowntype'] = 'Unknown plugin type';
|
||||
$string['validationmsglevel_debug'] = 'Debug';
|
||||
$string['validationmsglevel_error'] = 'Error';
|
||||
$string['validationmsglevel_info'] = 'OK';
|
||||
$string['validationmsglevel_warning'] = 'Warning';
|
||||
$string['validationresult0'] = 'Validation failed!';
|
||||
$string['validationresult0_help'] = 'Some serious problem was detected. It is not safe to install the add-on. See the validation log messages for more details.';
|
||||
$string['validationresult1'] = 'Validation passed!';
|
||||
$string['validationresult1_help'] = 'No serious problems were detected. You can continue with the add-on installation. See the validation log messages for more details and eventual warnings.';
|
||||
$string['validationresult1_help'] = 'The add-on package has been validated and no serious problems were detected.';
|
||||
$string['validationresultinfo'] = 'Info';
|
||||
$string['validationresultmsg'] = 'Message';
|
||||
$string['validationresultstatus'] = 'Status';
|
||||
@@ -1,74 +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/>.
|
||||
|
||||
/**
|
||||
* Checks the write permission for the given plugin type
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @subpackage ajax
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('AJAX_SCRIPT', true);
|
||||
|
||||
require(dirname(__FILE__) . '/../../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once(dirname(__FILE__).'/classes/installer.php');
|
||||
|
||||
require_login();
|
||||
|
||||
if (!has_capability('moodle/site:config', context_system::instance())) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die();
|
||||
}
|
||||
|
||||
if (!empty($CFG->disableonclickaddoninstall)) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die();
|
||||
}
|
||||
|
||||
if (!confirm_sesskey()) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die();
|
||||
}
|
||||
|
||||
$plugintype = optional_param('plugintype', null, PARAM_ALPHANUMEXT);
|
||||
if (is_null($plugintype)) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
die();
|
||||
}
|
||||
|
||||
$installer = tool_installaddon_installer::instance();
|
||||
|
||||
$plugintypepath = $installer->get_plugintype_root($plugintype);
|
||||
|
||||
if (empty($plugintypepath)) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
die();
|
||||
}
|
||||
|
||||
$response = array('path' => $plugintypepath);
|
||||
|
||||
if ($installer->is_plugintype_writable($plugintype)) {
|
||||
$response['writable'] = 1;
|
||||
} else {
|
||||
$response['writable'] = 0;
|
||||
}
|
||||
|
||||
header('Content-Type: application/json; charset: utf-8');
|
||||
echo json_encode($response);
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 266 B |
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]>
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
||||
x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" style="overflow:visible;enable-background:new 0 0 16 16;"
|
||||
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
|
||||
<defs>
|
||||
</defs>
|
||||
<path style="fill:#999999;" d="M16,9v6c0,0.5-0.5,1-1,1h-1H2H1c-0.5,0-1-0.5-1-1V9c0-0.5,0.5-1,1-1h1c0.5,0,1,0.5,1,1v4h10V9
|
||||
c0-0.5,0.5-1,1-1h1C15.5,8,16,8.5,16,9z M12.4,5.1l-0.7-0.7c-0.4-0.4-1-0.4-1.4,0L9.5,5.2V1c0-0.5-0.4-1-1-1h-1c-0.5,0-1,0.5-1,1
|
||||
v4.2L5.7,4.4C5.3,4,4.7,4,4.3,4.4L3.6,5.1c-0.4,0.4-0.4,1,0,1.4l3.7,3.7c0.2,0.2,0.5,0.3,0.7,0.3c0.3,0,0.5-0.1,0.7-0.3l3.7-3.7
|
||||
C12.8,6.2,12.8,5.5,12.4,5.1z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Output rendering for the plugin.
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @category output
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Implements the plugin renderer
|
||||
*
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_installaddon_renderer extends plugin_renderer_base {
|
||||
|
||||
/** @var tool_installaddon_installer */
|
||||
protected $installer = null;
|
||||
|
||||
/** @var tool_installaddon_validator */
|
||||
protected $validator = null;
|
||||
|
||||
/**
|
||||
* Sets the tool_installaddon_installer instance being used.
|
||||
*
|
||||
* @throws coding_exception if the installer has been already set
|
||||
* @param tool_installaddon_installer $installer
|
||||
*/
|
||||
public function set_installer_instance(tool_installaddon_installer $installer) {
|
||||
if (is_null($this->installer)) {
|
||||
$this->installer = $installer;
|
||||
} else {
|
||||
throw new coding_exception('Attempting to reset the installer instance.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tool_installaddon_validator instance being used.
|
||||
*
|
||||
* @throws coding_exception if the validator has been already set
|
||||
* @param tool_installaddon_validator $validator
|
||||
*/
|
||||
public function set_validator_instance(tool_installaddon_validator $validator) {
|
||||
if (is_null($this->validator)) {
|
||||
$this->validator = $validator;
|
||||
} else {
|
||||
throw new coding_exception('Attempting to reset the validator instance.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the index page layout
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function index_page() {
|
||||
|
||||
if (is_null($this->installer)) {
|
||||
throw new coding_exception('Installer instance has not been set.');
|
||||
}
|
||||
|
||||
$permcheckurl = new moodle_url('/admin/tool/installaddon/permcheck.php');
|
||||
$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'), 'tool_installaddon');
|
||||
|
||||
$out = $this->output->header();
|
||||
$out .= $this->index_page_heading();
|
||||
$out .= $this->index_page_repository();
|
||||
$out .= $this->index_page_upload();
|
||||
$out .= $this->output->footer();
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the validation results page layout
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function validation_page() {
|
||||
|
||||
if (is_null($this->installer)) {
|
||||
throw new coding_exception('Installer instance has not been set.');
|
||||
}
|
||||
|
||||
if (is_null($this->validator)) {
|
||||
throw new coding_exception('Validator instance has not been set.');
|
||||
}
|
||||
|
||||
$out = $this->output->header();
|
||||
$out .= $this->validation_page_heading();
|
||||
$out .= $this->validation_page_messages();
|
||||
$out .= $this->validation_page_continue();
|
||||
$out .= $this->output->footer();
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the user about invalid remote installation request.
|
||||
*
|
||||
* @param moodle_url $continueurl
|
||||
* @return string
|
||||
*/
|
||||
public function remote_request_invalid_page(moodle_url $continueurl) {
|
||||
|
||||
$out = $this->output->header();
|
||||
$out .= $this->output->heading(get_string('installfromrepo', 'tool_installaddon'));
|
||||
$out .= $this->output->box(get_string('remoterequestinvalid', 'tool_installaddon'), 'generalbox', 'notice');
|
||||
$out .= $this->output->continue_button($continueurl, 'get');
|
||||
$out .= $this->output->footer();
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the user that such plugin is already installed
|
||||
*
|
||||
* @param stdClass $data decoded request data
|
||||
* @param moodle_url $continueurl
|
||||
* @return string
|
||||
*/
|
||||
public function remote_request_alreadyinstalled_page(stdClass $data, moodle_url $continueurl) {
|
||||
|
||||
$out = $this->output->header();
|
||||
$out .= $this->output->heading(get_string('installfromrepo', 'tool_installaddon'));
|
||||
$out .= $this->output->box(get_string('remoterequestalreadyinstalled', 'tool_installaddon', $data), 'generalbox', 'notice');
|
||||
$out .= $this->output->continue_button($continueurl, 'get');
|
||||
$out .= $this->output->footer();
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Let the user confirm the remote installation request.
|
||||
*
|
||||
* @param stdClass $data decoded request data
|
||||
* @param moodle_url $continueurl
|
||||
* @param moodle_url $cancelurl
|
||||
* @return string
|
||||
*/
|
||||
public function remote_request_confirm_page(stdClass $data, moodle_url $continueurl, moodle_url $cancelurl) {
|
||||
|
||||
$out = $this->output->header();
|
||||
$out .= $this->output->heading(get_string('installfromrepo', 'tool_installaddon'));
|
||||
$out .= $this->output->confirm(get_string('remoterequestconfirm', 'tool_installaddon', $data), $continueurl, $cancelurl);
|
||||
$out .= $this->output->footer();
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the user that the target plugin type location is not writable.
|
||||
*
|
||||
* @param stdClass $data decoded request data
|
||||
* @param string $plugintypepath full path to the plugin type location
|
||||
* @param moodle_url $continueurl to repeat the write permission check
|
||||
* @param moodle_url $cancelurl to cancel the installation
|
||||
* @return string
|
||||
*/
|
||||
public function remote_request_permcheck_page(stdClass $data, $plugintypepath, moodle_url $continueurl, moodle_url $cancelurl) {
|
||||
|
||||
$data->typepath = $plugintypepath;
|
||||
|
||||
$out = $this->output->header();
|
||||
$out .= $this->output->heading(get_string('installfromrepo', 'tool_installaddon'));
|
||||
$out .= $this->output->confirm(get_string('remoterequestpermcheck', 'tool_installaddon', $data), $continueurl, $cancelurl);
|
||||
$out .= $this->output->footer();
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the user about pluginfo service call exception
|
||||
*
|
||||
* This implementation does not actually use the passed exception. Custom renderers might want to
|
||||
* display additional data obtained via {@link get_exception_info()}. Also note, this method is called
|
||||
* in non-debugging mode only. If debugging is allowed at the site, default exception handler is triggered.
|
||||
*
|
||||
* @param stdClass $data decoded request data
|
||||
* @param tool_installaddon_pluginfo_exception $e thrown exception
|
||||
* @param moodle_url $continueurl
|
||||
* @return string
|
||||
*/
|
||||
public function remote_request_pluginfo_exception(stdClass $data, tool_installaddon_pluginfo_exception $e, moodle_url $continueurl) {
|
||||
|
||||
$out = $this->output->header();
|
||||
$out .= $this->output->heading(get_string('installfromrepo', 'tool_installaddon'));
|
||||
$out .= $this->output->box(get_string('remoterequestpluginfoexception', 'tool_installaddon', $data), 'generalbox', 'notice');
|
||||
$out .= $this->output->continue_button($continueurl, 'get');
|
||||
$out .= $this->output->footer();
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the user about the installer exception
|
||||
*
|
||||
* This implementation does not actually use the passed exception. Custom renderers might want to
|
||||
* display additional data obtained via {@link get_exception_info()}. Also note, this method is called
|
||||
* in non-debugging mode only. If debugging is allowed at the site, default exception handler is triggered.
|
||||
*
|
||||
* @param tool_installaddon_installer_exception $e thrown exception
|
||||
* @param moodle_url $continueurl
|
||||
* @return string
|
||||
*/
|
||||
public function installer_exception(tool_installaddon_installer_exception $e, moodle_url $continueurl) {
|
||||
|
||||
$out = $this->output->header();
|
||||
$out .= $this->output->heading(get_string('installfromrepo', 'tool_installaddon'));
|
||||
$out .= $this->output->box(get_string('installexception', 'tool_installaddon'), 'generalbox', 'notice');
|
||||
$out .= $this->output->continue_button($continueurl, 'get');
|
||||
$out .= $this->output->footer();
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
// End of the external API /////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Renders the index page heading
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function index_page_heading() {
|
||||
return $this->output->heading(get_string('pluginname', 'tool_installaddon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the widget for browsing the add-on repository
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function index_page_repository() {
|
||||
|
||||
$url = $this->installer->get_addons_repository_url();
|
||||
|
||||
$out = $this->box(
|
||||
$this->output->single_button($url, get_string('installfromrepo', 'tool_installaddon'), 'get').
|
||||
$this->output->help_icon('installfromrepo', 'tool_installaddon'),
|
||||
'generalbox', 'installfromrepobox'
|
||||
);
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the widget for uploading the add-on ZIP package
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function index_page_upload() {
|
||||
|
||||
$form = $this->installer->get_installfromzip_form();
|
||||
|
||||
ob_start();
|
||||
$form->display();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$out = $this->box($out, 'generalbox', 'installfromzipbox');
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the page title and the overall validation verdict
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function validation_page_heading() {
|
||||
|
||||
$heading = $this->output->heading(get_string('validation', 'tool_installaddon'));
|
||||
|
||||
if ($this->validator->get_result()) {
|
||||
$status = $this->output->container(
|
||||
html_writer::span(get_string('validationresult1', 'tool_installaddon'), 'verdict').
|
||||
$this->output->help_icon('validationresult1', 'tool_installaddon'),
|
||||
array('validationresult', 'success')
|
||||
);
|
||||
} else {
|
||||
$status = $this->output->container(
|
||||
html_writer::span(get_string('validationresult0', 'tool_installaddon'), 'verdict').
|
||||
$this->output->help_icon('validationresult0', 'tool_installaddon'),
|
||||
array('validationresult', 'failure')
|
||||
);
|
||||
}
|
||||
|
||||
return $heading . $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders validation log messages.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function validation_page_messages() {
|
||||
|
||||
$validator = $this->validator; // We need this to be able to use their constants.
|
||||
$messages = $validator->get_messages();
|
||||
|
||||
if (empty($messages)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$table = new html_table();
|
||||
$table->attributes['class'] = 'validationmessages generaltable';
|
||||
$table->head = array(
|
||||
get_string('validationresultstatus', 'tool_installaddon'),
|
||||
get_string('validationresultmsg', 'tool_installaddon'),
|
||||
get_string('validationresultinfo', 'tool_installaddon')
|
||||
);
|
||||
$table->colclasses = array('msgstatus', 'msgtext', 'msginfo');
|
||||
|
||||
$stringman = get_string_manager();
|
||||
|
||||
foreach ($messages as $message) {
|
||||
|
||||
if ($message->level === $validator::DEBUG and !debugging()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$msgstatus = get_string('validationmsglevel_'.$message->level, 'tool_installaddon');
|
||||
$msgtext = $msgtext = s($message->msgcode);
|
||||
if (is_null($message->addinfo)) {
|
||||
$msginfo = '';
|
||||
} else {
|
||||
$msginfo = html_writer::tag('pre', s(print_r($message->addinfo, true)));
|
||||
}
|
||||
$msghelp = '';
|
||||
|
||||
// Replace the message code with the string if it is defined.
|
||||
if ($stringman->string_exists('validationmsg_'.$message->msgcode, 'tool_installaddon')) {
|
||||
$msgtext = get_string('validationmsg_'.$message->msgcode, 'tool_installaddon');
|
||||
// And check for the eventual help, too.
|
||||
if ($stringman->string_exists('validationmsg_'.$message->msgcode.'_help', 'tool_installaddon')) {
|
||||
$msghelp = $this->output->help_icon('validationmsg_'.$message->msgcode, 'tool_installaddon');
|
||||
}
|
||||
}
|
||||
|
||||
// Re-format the message info using a string if it is define.
|
||||
if (!is_null($message->addinfo) and $stringman->string_exists('validationmsg_'.$message->msgcode.'_info', 'tool_installaddon')) {
|
||||
$msginfo = get_string('validationmsg_'.$message->msgcode.'_info', 'tool_installaddon', $message->addinfo);
|
||||
}
|
||||
|
||||
$row = new html_table_row(array($msgstatus, $msgtext.$msghelp, $msginfo));
|
||||
$row->attributes['class'] = 'level-'.$message->level.' '.$message->msgcode;
|
||||
|
||||
$table->data[] = $row;
|
||||
}
|
||||
|
||||
return html_writer::table($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders widgets to continue from the validation results page
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function validation_page_continue() {
|
||||
|
||||
$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'));
|
||||
}
|
||||
|
||||
$cancelbutton = $this->output->single_button(
|
||||
new moodle_url('/admin/tool/installaddon/index.php'), get_string('cancel', 'core'), 'get',
|
||||
array('class' => 'singlebutton cancelbutton'));
|
||||
|
||||
return $this->output->container($cancelbutton.$contbutton, 'postvalidationbuttons');
|
||||
}
|
||||
}
|
||||
@@ -1,39 +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/>.
|
||||
|
||||
/**
|
||||
* Puts the plugin actions into the admin settings tree.
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
if ($hassiteconfig and empty($CFG->disableonclickaddoninstall)) {
|
||||
|
||||
$ADMIN->add('modules', new admin_externalpage('tool_installaddon_index',
|
||||
get_string('installaddons', 'tool_installaddon'),
|
||||
"$CFG->wwwroot/$CFG->admin/tool/installaddon/index.php"), 'modsettings');
|
||||
|
||||
$ADMIN->add('modules', new admin_externalpage('tool_installaddon_validate',
|
||||
get_string('validation', 'tool_installaddon'),
|
||||
"$CFG->wwwroot/$CFG->admin/tool/installaddon/validate.php",
|
||||
'moodle/site:config',
|
||||
true), 'modsettings');
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
#page-admin-tool-installaddon-index #installfromrepobox {
|
||||
text-align: center;
|
||||
padding-top: 2em;
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-index #installfromrepobox .singlebutton {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-index #installfromrepobox .singlebutton input[type=submit] {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .validationresult {
|
||||
margin: 2em auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .validationresult .verdict {
|
||||
margin: 0em 0.5em;
|
||||
padding: 0.5em;
|
||||
border: 2px solid;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .validationresult.success .verdict {
|
||||
background-color: #e7f1c3;
|
||||
border-color: #aaeeaa;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .validationresult.failure .verdict {
|
||||
background-color: #ffd3d9;
|
||||
border-color: #eeaaaa;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .validationmessages {
|
||||
margin: 0px auto;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .validationmessages .level-error .msgstatus {
|
||||
background-color: #ffd3d9;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .validationmessages .level-warning .msgstatus {
|
||||
background-color: #f3f2aa;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .validationmessages .level-info .msgstatus {
|
||||
background-color: #e7f1c3;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .validationmessages .level-debug .msgstatus {
|
||||
background-color: #d2ebff;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .postvalidationbuttons {
|
||||
text-align: center;
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
#page-admin-tool-installaddon-validate .postvalidationbuttons .singlebutton {
|
||||
display: inline-block;
|
||||
margin: 1em 1em;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Plugin must have more than one file.
|
||||
-1
@@ -1 +0,0 @@
|
||||
<?php
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$plugin->component = 'repository_mahara';
|
||||
$plugin->version = 2014010100;
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
echo 'One, my little hobbit, never installs malicisous add-ons';
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
$string['pluginname'] = 'Foo bar!';
|
||||
@@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$plugin->version = 2013031900;
|
||||
$plugin->component = 'local_greenbar';
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
$plugin->component = 'local_one';
|
||||
@@ -1 +0,0 @@
|
||||
Only one dir is allowed
|
||||
@@ -1 +0,0 @@
|
||||
<?php
|
||||
@@ -1 +0,0 @@
|
||||
<?php
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
$string['pluginnname'] = 'Root directory mismatch';
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<?php
|
||||
|
||||
$module->version = 2014122455;
|
||||
$plugin->version = 2014122455;
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
echo 'Do not use hardcoded strings, provide the language pack';
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
$string['pluginversion'] = 'Activity module with no version.php';
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
$string['pluginversion'] = 'A theme with no version.php';
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
// index.php
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
$string['pluginname'] = 'Foo!';
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php // $Id$
|
||||
|
||||
// I don't miss CVS, do you?
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
echo 'One, my little hobbit, never installs malicisous add-ons';
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user