Compare commits
289 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b198428e41 | |||
| a5f09bca98 | |||
| 22124a36ca | |||
| 50794f5278 | |||
| e1cad3f07b | |||
| 2e4856a81f | |||
| 211f6809b9 | |||
| ad75599c7b | |||
| ca908dd42c | |||
| 76129617e5 | |||
| 56f92fa069 | |||
| d7815b0a79 | |||
| 376a2f64f2 | |||
| 634da01c65 | |||
| 8b0bb2389c | |||
| 83b311dcb3 | |||
| 299cdee4bf | |||
| 34b451dac4 | |||
| e2ac9903d9 | |||
| ee22b6faba | |||
| a6c6690e79 | |||
| acb0617d1b | |||
| 370c8c4a06 | |||
| 4782bf39af | |||
| 39f9832ce5 | |||
| ef0d79745f | |||
| e1b1217749 | |||
| 57886390a6 | |||
| 2a6ee587d3 | |||
| 43ab5e777d | |||
| 3f96ad977e | |||
| de068eb91a | |||
| e6539e7139 | |||
| 9a6c86b23f | |||
| ec2f7c0fe9 | |||
| 2077354356 | |||
| a3bce19260 | |||
| 08943d8121 | |||
| b053efae5d | |||
| b3bd9df0fd | |||
| 1d5341843f | |||
| 5da74261d3 | |||
| ee3b7666f2 | |||
| 9c96a6fcf7 | |||
| 6ab4eaf7f2 | |||
| 46c4afbeaf | |||
| e0e75192e8 | |||
| c0078c08df | |||
| e2c4f9d374 | |||
| 1b26a3db64 | |||
| fa5aa45de4 | |||
| 9c9ac43919 | |||
| b214024bda | |||
| cd59d03500 | |||
| 0db181f9a9 | |||
| 868c037261 | |||
| a1714472d3 | |||
| 7883551c72 | |||
| bc11df440e | |||
| 4efaec0a53 | |||
| 0ded67ffd7 | |||
| 61923d3bdd | |||
| 035d608c59 | |||
| d49a5c7826 | |||
| 7305ed72ec | |||
| 7ab8ebf5b1 | |||
| c4b9758766 | |||
| 679d2d1129 | |||
| 4faf9ff6c6 | |||
| 0a77242e3c | |||
| 1453ce1208 | |||
| 798dc31ada | |||
| 4a2a533fe1 | |||
| 61373c843d | |||
| 2937760c27 | |||
| 03989cb776 | |||
| a4f78b52f6 | |||
| ecc1bd1c73 | |||
| 694f33c2f6 | |||
| d93cdd955b | |||
| d80d0b4142 | |||
| b73ab4bf04 | |||
| a398df5381 | |||
| b0ff1a1600 | |||
| 98070f7020 | |||
| 40271e858d | |||
| f839aff2b5 | |||
| 0096c60d46 | |||
| 65424cea97 | |||
| 863b9081f5 | |||
| 44c178ec4f | |||
| 0703eeca7c | |||
| 866f014372 | |||
| 22ad84cb00 | |||
| d56311006a | |||
| 30d4327769 | |||
| d987202dff | |||
| 25d288d297 | |||
| aa6b0c6d03 | |||
| 6f3819a805 | |||
| 2641b5e31e | |||
| 35db491a6d | |||
| 27deb31ded | |||
| 511e5c933a | |||
| 5574d3431b | |||
| ee8c5098c9 | |||
| 480396103b | |||
| 4e5ebf89ba | |||
| 015607040a | |||
| c58a1e9067 | |||
| eecc04f29c | |||
| f237e35755 | |||
| bee606d3b1 | |||
| 38b5816722 | |||
| 6e5e4cc208 | |||
| 4af9077f26 | |||
| 0b2c17a183 | |||
| 2a55bff8f6 | |||
| e235ef7bd9 | |||
| 47dd7dd840 | |||
| 70c75a7a47 | |||
| a7367b6cf3 | |||
| ae8dfad361 | |||
| a0bdd53e21 | |||
| c615b3e96b | |||
| e3475fd088 | |||
| e934a351e9 | |||
| 564753102d | |||
| 91916adde5 | |||
| 7af3ae4834 | |||
| fdfd266454 | |||
| f3e11eef99 | |||
| 94c5e0ade7 | |||
| 55929d8a49 | |||
| d0b1204d8e | |||
| 81a3d127b1 | |||
| 4f7eaa8b46 | |||
| 54c6679153 | |||
| 089fbd15cc | |||
| 7132749e18 | |||
| 9ca2c8dc52 | |||
| f55a4c094e | |||
| 3a3a212405 | |||
| 0998cf8010 | |||
| 3766be85b2 | |||
| 83273d25b9 | |||
| b798b05411 | |||
| 7eb50a3753 | |||
| 4a4b4e28a4 | |||
| 42c31d53c8 | |||
| ea770fe8c8 | |||
| 434a580558 | |||
| 9a7a447722 | |||
| 1bf28ecb43 | |||
| 9c99a5da5c | |||
| 95008df6d9 | |||
| f499fa90f1 | |||
| 015b617739 | |||
| 423c1d6c50 | |||
| c4bee8e510 | |||
| 023ea98fc1 | |||
| f1e0128a43 | |||
| 167b85e60c | |||
| 4b6e850e68 | |||
| e48dd422f9 | |||
| dc8b92e0b2 | |||
| 840d6ba543 | |||
| 078699a1a5 | |||
| c0266bdaf6 | |||
| 46f7f67db1 | |||
| e8b50bbe34 | |||
| 33113481b5 | |||
| 8f11f7741a | |||
| b31ec4dfbf | |||
| 2b63da7763 | |||
| 24bc58278f | |||
| b59f56c259 | |||
| 29e40f3c13 | |||
| d2707c2d28 | |||
| 898befb275 | |||
| 938267b43a | |||
| f9f5f5ddc8 | |||
| ca66ad24c8 | |||
| e1f4756dfb | |||
| 12e04336a0 | |||
| 266aa66267 | |||
| af098adec2 | |||
| 202cfa2987 | |||
| bafa907941 | |||
| f5131809c8 | |||
| 37c30f2249 | |||
| 110a3639c3 | |||
| 7631b43d33 | |||
| a51f9bd003 | |||
| e998b14686 | |||
| 5ed8d694ee | |||
| f0782cc57b | |||
| 33b74df149 | |||
| 24e0b238d3 | |||
| dfddaa8ab6 | |||
| 57b83a4f41 | |||
| c9be953f05 | |||
| 794391b978 | |||
| a7df733250 | |||
| 15d5c9a276 | |||
| ec60f63f59 | |||
| a024a024e8 | |||
| 09304bcbff | |||
| 53ef327e54 | |||
| 685a71917b | |||
| 04288af505 | |||
| 4ac6149680 | |||
| 308046f1bc | |||
| d6c2bf620c | |||
| 8869cf8cd9 | |||
| b32974f12a | |||
| 48b3e4e9b2 | |||
| 4996f75a3b | |||
| bf2cecc440 | |||
| ec920f7901 | |||
| 1131af4409 | |||
| 46d8ffcefa | |||
| e2ea9b4c09 | |||
| 523efc4cd0 | |||
| 3f853115e9 | |||
| 8a8a02c903 | |||
| 946533c623 | |||
| 1f686d7fdf | |||
| 4e9e994da4 | |||
| 3ce4575dc0 | |||
| 88dfc54de9 | |||
| d855dcd29e | |||
| 5d4bf77a16 | |||
| fc00a6641c | |||
| cee73270c7 | |||
| 245de290f7 | |||
| 1a6160df3c | |||
| 2a3df3d55c | |||
| c227fc61f1 | |||
| 38a9ba9bcd | |||
| a4e309709d | |||
| e39f3b7db2 | |||
| 2a64720ac8 | |||
| cf0307a529 | |||
| c4758ab813 | |||
| d2c91281db | |||
| 9a88b8ec35 | |||
| 7a2beab44e | |||
| a586240cc0 | |||
| d2680dbb27 | |||
| c5b884bd51 | |||
| 5d5313537b | |||
| 5e6bc1b0f3 | |||
| 65d4f096db | |||
| cb69e26b15 | |||
| f25a7d2ac7 | |||
| de760475cf | |||
| a3824e559b | |||
| 67b64f85e9 | |||
| ac11f60853 | |||
| 09558248e8 | |||
| d186ba2f81 | |||
| 7ee550a943 | |||
| e260354fc9 | |||
| cd9c54c93c | |||
| 2cd4e5f8dc | |||
| 8978731b82 | |||
| 5c06a1935b | |||
| c04e89b086 | |||
| 4909257b07 | |||
| 695675483f | |||
| c3217a6b0d | |||
| 21527bf096 | |||
| 8178cf1bb9 | |||
| bc4f56abc3 | |||
| 0864ebc14c | |||
| 31354cc381 | |||
| 422a34a6f5 | |||
| d16540aa88 | |||
| d3a76147e0 | |||
| c48f2c90cc | |||
| 1f2cde345a | |||
| 171a83f79b | |||
| a137762fec | |||
| b52ceb2972 | |||
| 400239c7c5 | |||
| 159f904af5 | |||
| a01edef5be | |||
| cfa7d2653c |
+6
-8
@@ -4,6 +4,7 @@
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
auth/cas/CAS/
|
||||
cache/stores/mongodb/MongoDB/
|
||||
enrol/lti/ims-blti/
|
||||
@@ -19,12 +20,15 @@ lib/mlbackend/php/phpml/
|
||||
lib/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
lib/phpspreadsheet/
|
||||
lib/lessphp/
|
||||
lib/phpexcel/
|
||||
lib/google/
|
||||
lib/htmlpurifier/
|
||||
lib/jabber/
|
||||
lib/minify/matthiasmullie-minify/
|
||||
lib/minify/matthiasmullie-pathconverter/
|
||||
lib/pear/Auth/RADIUS.php
|
||||
lib/pear/Crypt/CHAP.php
|
||||
lib/pear/HTML/Common.php
|
||||
lib/pear/HTML/QuickForm.php
|
||||
lib/pear/HTML/QuickForm/
|
||||
@@ -38,6 +42,7 @@ lib/yuilib/gallery/
|
||||
lib/jquery/
|
||||
lib/html2text/
|
||||
lib/markdown/
|
||||
lib/recaptchalib.php
|
||||
lib/xhprof/
|
||||
lib/horde/
|
||||
lib/requirejs/
|
||||
@@ -60,10 +65,6 @@ lib/validateurlsyntax.php
|
||||
lib/amd/src/popper.js
|
||||
lib/geopattern-php/
|
||||
lib/php-jwt/
|
||||
lib/babel-polyfill/
|
||||
lib/mdn-polyfills/
|
||||
lib/emoji-data/
|
||||
lib/h5p/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
@@ -77,13 +78,10 @@ theme/boost/amd/src/button.js
|
||||
theme/boost/amd/src/carousel.js
|
||||
theme/boost/amd/src/collapse.js
|
||||
theme/boost/amd/src/dropdown.js
|
||||
theme/boost/amd/src/index.js
|
||||
theme/boost/amd/src/modal.js
|
||||
theme/boost/amd/src/popover.js
|
||||
theme/boost/amd/src/sanitizer.js
|
||||
theme/boost/amd/src/scrollspy.js
|
||||
theme/boost/amd/src/tab.js
|
||||
theme/boost/amd/src/toast.js
|
||||
theme/boost/amd/src/tooltip.js
|
||||
theme/boost/amd/src/util.js
|
||||
theme/boost/amd/src/tether.js
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
'plugins': [
|
||||
'babel',
|
||||
'promise',
|
||||
],
|
||||
'env': {
|
||||
@@ -204,45 +203,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile*.js", "babel-plugin-add-module-to-define.js"],
|
||||
// We support es6 now. Woot!
|
||||
env: {
|
||||
es6: true
|
||||
},
|
||||
// We're using babel transpiling so use their parser
|
||||
// for linting.
|
||||
parser: 'babel-eslint',
|
||||
files: ["**/amd/src/*.js"],
|
||||
// Check AMD with some slightly stricter rules.
|
||||
rules: {
|
||||
'no-unused-vars': 'error',
|
||||
'no-implicit-globals': 'error',
|
||||
// Disable all of the rules that have babel versions.
|
||||
'new-cap': 'off',
|
||||
// Not using this rule for the time being because it isn't
|
||||
// compatible with jQuery and ES6.
|
||||
'no-invalid-this': 'off',
|
||||
'object-curly-spacing': 'off',
|
||||
'quotes': 'off',
|
||||
'semi': 'off',
|
||||
'no-unused-expressions': 'off',
|
||||
// Enable all of the babel version of these rules.
|
||||
'babel/new-cap': ['warn', { 'properties': false }],
|
||||
// Not using this rule for the time being because it isn't
|
||||
// compatible with jQuery and ES6.
|
||||
'babel/no-invalid-this': 'off',
|
||||
'babel/object-curly-spacing': 'warn',
|
||||
// This is off in the original style int.
|
||||
'babel/quotes': 'off',
|
||||
'babel/semi': 'error',
|
||||
'babel/no-unused-expressions': 'error',
|
||||
// === Promises ===
|
||||
// We have Promise now that we're using ES6.
|
||||
'promise/no-native': 'off',
|
||||
'promise/avoid-new': 'off'
|
||||
},
|
||||
parserOptions: {
|
||||
'ecmaVersion': 9,
|
||||
'sourceType': 'module'
|
||||
'no-implicit-globals': 'error'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
**/amd/**
|
||||
/*.js
|
||||
+6
-8
@@ -5,6 +5,7 @@ theme/classic/style/moodle.css
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
auth/cas/CAS/
|
||||
cache/stores/mongodb/MongoDB/
|
||||
enrol/lti/ims-blti/
|
||||
@@ -20,12 +21,15 @@ lib/mlbackend/php/phpml/
|
||||
lib/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
lib/phpspreadsheet/
|
||||
lib/lessphp/
|
||||
lib/phpexcel/
|
||||
lib/google/
|
||||
lib/htmlpurifier/
|
||||
lib/jabber/
|
||||
lib/minify/matthiasmullie-minify/
|
||||
lib/minify/matthiasmullie-pathconverter/
|
||||
lib/pear/Auth/RADIUS.php
|
||||
lib/pear/Crypt/CHAP.php
|
||||
lib/pear/HTML/Common.php
|
||||
lib/pear/HTML/QuickForm.php
|
||||
lib/pear/HTML/QuickForm/
|
||||
@@ -39,6 +43,7 @@ lib/yuilib/gallery/
|
||||
lib/jquery/
|
||||
lib/html2text/
|
||||
lib/markdown/
|
||||
lib/recaptchalib.php
|
||||
lib/xhprof/
|
||||
lib/horde/
|
||||
lib/requirejs/
|
||||
@@ -61,10 +66,6 @@ lib/validateurlsyntax.php
|
||||
lib/amd/src/popper.js
|
||||
lib/geopattern-php/
|
||||
lib/php-jwt/
|
||||
lib/babel-polyfill/
|
||||
lib/mdn-polyfills/
|
||||
lib/emoji-data/
|
||||
lib/h5p/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
@@ -78,13 +79,10 @@ theme/boost/amd/src/button.js
|
||||
theme/boost/amd/src/carousel.js
|
||||
theme/boost/amd/src/collapse.js
|
||||
theme/boost/amd/src/dropdown.js
|
||||
theme/boost/amd/src/index.js
|
||||
theme/boost/amd/src/modal.js
|
||||
theme/boost/amd/src/popover.js
|
||||
theme/boost/amd/src/sanitizer.js
|
||||
theme/boost/amd/src/scrollspy.js
|
||||
theme/boost/amd/src/tab.js
|
||||
theme/boost/amd/src/toast.js
|
||||
theme/boost/amd/src/tooltip.js
|
||||
theme/boost/amd/src/util.js
|
||||
theme/boost/amd/src/tether.js
|
||||
|
||||
+17
-32
@@ -2,6 +2,8 @@
|
||||
# process (which uses our internal CI system) this file is here for the benefit
|
||||
# of community developers git clones - see MDL-51458.
|
||||
|
||||
sudo: required
|
||||
|
||||
# We currently disable Travis notifications entirely until https://github.com/travis-ci/travis-ci/issues/4976
|
||||
# is fixed.
|
||||
notifications:
|
||||
@@ -9,21 +11,19 @@ notifications:
|
||||
|
||||
language: php
|
||||
|
||||
os: linux
|
||||
|
||||
dist: xenial
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- docker
|
||||
dist: trusty
|
||||
|
||||
php:
|
||||
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
|
||||
- 7.4
|
||||
- 7.3
|
||||
- 7.1.30 # Make this sticky because current default version (7.1.11) has a bug with redis-extension output (MDL-66062)
|
||||
|
||||
addons:
|
||||
postgresql: "9.6"
|
||||
packages:
|
||||
- mysql-server-5.6
|
||||
- mysql-client-core-5.6
|
||||
- mysql-client-5.6
|
||||
|
||||
env:
|
||||
# Although we want to run these jobs and see failures as quickly as possible, we also want to get the slowest job to
|
||||
@@ -42,18 +42,18 @@ env:
|
||||
# Perform an upgrade test too.
|
||||
- DB=pgsql TASK=UPGRADE
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
# Enable fast finish.
|
||||
# This will fail the build if a single job fails (except those in allow_failures).
|
||||
# It will not stop the jobs from running.
|
||||
fast_finish: true
|
||||
|
||||
include:
|
||||
# Run mysql only on highest - it's just too slow
|
||||
- php: 7.4
|
||||
# Run mysql only on 7.3 - it's just too slow
|
||||
- php: 7.3
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
# Run grunt/npm install on highest version too ('node' is an alias for the latest node.js version.)
|
||||
- php: 7.4
|
||||
# Run grunt/npm install on highest version ('node' is an alias for the latest node.js version.)
|
||||
- php: 7.2
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
|
||||
|
||||
cache:
|
||||
@@ -62,9 +62,8 @@ cache:
|
||||
- $HOME/.npm
|
||||
|
||||
before_install:
|
||||
- docker run -d -p 127.0.0.1:8080:80 --name exttests moodlehq/moodle-exttests
|
||||
# Avoid IPv6 default binding as service (causes redis not to start).
|
||||
- sudo service redis-server start --bind 127.0.0.1
|
||||
sudo service redis-server start --bind 127.0.0.1
|
||||
|
||||
install:
|
||||
- >
|
||||
@@ -72,10 +71,10 @@ install:
|
||||
then
|
||||
sudo mkdir /mnt/ramdisk
|
||||
sudo mount -t tmpfs -o size=1024m tmpfs /mnt/ramdisk
|
||||
sudo service mysql stop
|
||||
sudo stop mysql
|
||||
sudo mv /var/lib/mysql /mnt/ramdisk
|
||||
sudo ln -s /mnt/ramdisk/mysql /var/lib/mysql
|
||||
sudo service mysql restart
|
||||
sudo start mysql
|
||||
fi
|
||||
- >
|
||||
if [ "$DB" = 'pgsql' ];
|
||||
@@ -171,12 +170,6 @@ before_script:
|
||||
-e "/require_once/i \\\$CFG->phpunit_dataroot = '\/home\/travis\/roots\/phpunit';" \
|
||||
-e "/require_once/i \\\$CFG->phpunit_prefix = 'p_';" \
|
||||
config.php ;
|
||||
# Enable test external resources
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://127.0.0.1:8080');" \
|
||||
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://127.0.0.1:8080');" \
|
||||
config.php ;
|
||||
|
||||
# Redis cache store tests
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
|
||||
@@ -214,7 +207,7 @@ before_script:
|
||||
# We need the official upstream for comparison
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
git fetch upstream MOODLE_38_STABLE;
|
||||
git fetch upstream MOODLE_37_STABLE;
|
||||
export GIT_PREVIOUS_COMMIT="`git merge-base FETCH_HEAD $TRAVIS_COMMIT`";
|
||||
export GIT_COMMIT="$TRAVIS_COMMIT";
|
||||
export UPSTREAM_FETCH_HEAD=`git rev-parse FETCH_HEAD`
|
||||
@@ -292,11 +285,3 @@ script:
|
||||
exit 1 ;
|
||||
fi
|
||||
fi
|
||||
|
||||
after_script:
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
EXTTESTS_HITS=$(docker logs exttests 2>&1 | grep -Fv -e 'AH00558' -e '[pid 1]' | wc -l)
|
||||
echo -e "\nTest local resources number of hits: ${EXTTESTS_HITS}.\n"
|
||||
fi
|
||||
|
||||
+39
-333
@@ -24,7 +24,6 @@
|
||||
* Grunt configuration
|
||||
*/
|
||||
|
||||
/* eslint-env node */
|
||||
module.exports = function(grunt) {
|
||||
var path = require('path'),
|
||||
tasks = {},
|
||||
@@ -32,10 +31,7 @@ module.exports = function(grunt) {
|
||||
async = require('async'),
|
||||
DOMParser = require('xmldom').DOMParser,
|
||||
xpath = require('xpath'),
|
||||
semver = require('semver'),
|
||||
watchman = require('fb-watchman'),
|
||||
watchmanClient = new watchman.Client(),
|
||||
gruntFilePath = process.cwd();
|
||||
semver = require('semver');
|
||||
|
||||
// Verify the node version is new enough.
|
||||
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
|
||||
@@ -56,23 +52,10 @@ module.exports = function(grunt) {
|
||||
}
|
||||
}
|
||||
|
||||
var files = null;
|
||||
if (grunt.option('files')) {
|
||||
// Accept a comma separated list of files to process.
|
||||
files = grunt.option('files').split(',');
|
||||
}
|
||||
|
||||
var inAMD = path.basename(cwd) == 'amd';
|
||||
|
||||
// Globbing pattern for matching all AMD JS source files.
|
||||
var amdSrc = [];
|
||||
if (inAMD) {
|
||||
amdSrc.push(cwd + "/src/*.js");
|
||||
amdSrc.push(cwd + "/src/**/*.js");
|
||||
} else {
|
||||
amdSrc.push("**/amd/src/*.js");
|
||||
amdSrc.push("**/amd/src/**/*.js");
|
||||
}
|
||||
var amdSrc = [inAMD ? cwd + '/src/*.js' : '**/amd/src/*.js'];
|
||||
|
||||
/**
|
||||
* Function to generate the destination for the uglify task
|
||||
@@ -84,9 +67,10 @@ module.exports = function(grunt) {
|
||||
* @param {String} srcPath the matched src path
|
||||
* @return {String} The rewritten destination path.
|
||||
*/
|
||||
var babelRename = function(destPath, srcPath) {
|
||||
var uglifyRename = function(destPath, srcPath) {
|
||||
destPath = srcPath.replace('src', 'build');
|
||||
destPath = destPath.replace('.js', '.min.js');
|
||||
destPath = path.resolve(cwd, destPath);
|
||||
return destPath;
|
||||
};
|
||||
|
||||
@@ -127,65 +111,19 @@ module.exports = function(grunt) {
|
||||
eslint: {
|
||||
// Even though warnings dont stop the build we don't display warnings by default because
|
||||
// at this moment we've got too many core warnings.
|
||||
// To display warnings call: grunt eslint --show-lint-warnings
|
||||
// To fail on warnings call: grunt eslint --max-lint-warnings=0
|
||||
// Also --max-lint-warnings=-1 can be used to display warnings but not fail.
|
||||
options: {
|
||||
quiet: (!grunt.option('show-lint-warnings')) && (typeof grunt.option('max-lint-warnings') === 'undefined'),
|
||||
maxWarnings: ((typeof grunt.option('max-lint-warnings') !== 'undefined') ? grunt.option('max-lint-warnings') : -1)
|
||||
},
|
||||
amd: {src: files ? files : amdSrc},
|
||||
options: {quiet: !grunt.option('show-lint-warnings')},
|
||||
amd: {src: amdSrc},
|
||||
// Check YUI module source files.
|
||||
yui: {src: files ? files : ['**/yui/src/**/*.js', '!*/**/yui/src/*/meta/*.js']}
|
||||
yui: {src: ['**/yui/src/**/*.js', '!*/**/yui/src/*/meta/*.js']}
|
||||
},
|
||||
babel: {
|
||||
options: {
|
||||
sourceMaps: true,
|
||||
comments: false,
|
||||
plugins: [
|
||||
'transform-es2015-modules-amd-lazy',
|
||||
'system-import-transformer',
|
||||
// This plugin modifies the Babel transpiling for "export default"
|
||||
// so that if it's used then only the exported value is returned
|
||||
// by the generated AMD module.
|
||||
//
|
||||
// It also adds the Moodle plugin name to the AMD module definition
|
||||
// so that it can be imported as expected in other modules.
|
||||
path.resolve('babel-plugin-add-module-to-define.js'),
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-syntax-import-meta',
|
||||
['@babel/plugin-proposal-class-properties', {'loose': false}],
|
||||
'@babel/plugin-proposal-json-strings'
|
||||
],
|
||||
presets: [
|
||||
['minify', {
|
||||
// This minification plugin needs to be disabled because it breaks the
|
||||
// source map generation and causes invalid source maps to be output.
|
||||
simplify: false,
|
||||
builtIns: false
|
||||
}],
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: [
|
||||
">0.25%",
|
||||
"last 2 versions",
|
||||
"not ie <= 10",
|
||||
"not op_mini all",
|
||||
"not Opera > 0",
|
||||
"not dead"
|
||||
]
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: false
|
||||
}]
|
||||
]
|
||||
},
|
||||
dist: {
|
||||
uglify: {
|
||||
amd: {
|
||||
files: [{
|
||||
expand: true,
|
||||
src: files ? files : amdSrc,
|
||||
rename: babelRename
|
||||
}]
|
||||
src: amdSrc,
|
||||
rename: uglifyRename
|
||||
}],
|
||||
options: {report: 'none'}
|
||||
}
|
||||
},
|
||||
sass: {
|
||||
@@ -207,14 +145,6 @@ module.exports = function(grunt) {
|
||||
files: ['**/amd/src/**/*.js'],
|
||||
tasks: ['amd']
|
||||
},
|
||||
boost: {
|
||||
files: ['**/theme/boost/scss/**/*.scss'],
|
||||
tasks: ['scss']
|
||||
},
|
||||
rawcss: {
|
||||
files: ['**/*.css', '**/theme/**/!(moodle.css|editor.css)'],
|
||||
tasks: ['rawcss']
|
||||
},
|
||||
yui: {
|
||||
files: ['**/yui/src/**/*.js'],
|
||||
tasks: ['yui']
|
||||
@@ -227,21 +157,21 @@ module.exports = function(grunt) {
|
||||
shifter: {
|
||||
options: {
|
||||
recursive: true,
|
||||
paths: files ? files : [cwd]
|
||||
paths: [cwd]
|
||||
}
|
||||
},
|
||||
gherkinlint: {
|
||||
options: {
|
||||
files: files ? files : ['**/tests/behat/*.feature'],
|
||||
files: ['**/tests/behat/*.feature'],
|
||||
}
|
||||
},
|
||||
stylelint: {
|
||||
scss: {
|
||||
options: {syntax: 'scss'},
|
||||
src: files ? files : ['*/**/*.scss']
|
||||
src: ['*/**/*.scss']
|
||||
},
|
||||
css: {
|
||||
src: files ? files : ['*/**/*.css'],
|
||||
src: ['*/**/*.css'],
|
||||
options: {
|
||||
configOverrides: {
|
||||
rules: {
|
||||
@@ -362,27 +292,19 @@ module.exports = function(grunt) {
|
||||
};
|
||||
|
||||
tasks.gherkinlint = function() {
|
||||
const done = this.async();
|
||||
const options = grunt.config('gherkinlint.options');
|
||||
var done = this.async(),
|
||||
options = grunt.config('gherkinlint.options');
|
||||
|
||||
// Grab the gherkin-lint linter and required scaffolding.
|
||||
const linter = require('gherkin-lint/src/linter.js');
|
||||
const featureFinder = require('gherkin-lint/src/feature-finder.js');
|
||||
const configParser = require('gherkin-lint/src/config-parser.js');
|
||||
const formatter = require('gherkin-lint/src/formatters/stylish.js');
|
||||
|
||||
// Run the linter.
|
||||
const results = linter.lint(
|
||||
featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
|
||||
configParser.getConfiguration(configParser.defaultConfigFileName)
|
||||
);
|
||||
|
||||
// Print the results out uncondtionally.
|
||||
formatter.printResults(results);
|
||||
|
||||
// Report on the results.
|
||||
// The done function takes a bool whereby a falsey statement causes the task to fail.
|
||||
done(results.every(result => result.errors.length === 0));
|
||||
var args = grunt.file.expand(options.files);
|
||||
args.unshift(path.normalize(__dirname + '/node_modules/.bin/gherkin-lint'));
|
||||
grunt.util.spawn({
|
||||
cmd: 'node',
|
||||
args: args,
|
||||
opts: {stdio: 'inherit', env: process.env}
|
||||
}, function(error, result, code) {
|
||||
// Propagate the exit code.
|
||||
done(code === 0);
|
||||
});
|
||||
};
|
||||
|
||||
tasks.startup = function() {
|
||||
@@ -400,232 +322,23 @@ module.exports = function(grunt) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a wrapper task to handle the grunt watch command. It attempts to use
|
||||
* Watchman to monitor for file changes, if it's installed, because it's much faster.
|
||||
*
|
||||
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
|
||||
* watcher for backwards compatibility.
|
||||
*/
|
||||
tasks.watch = function() {
|
||||
var watchTaskDone = this.async();
|
||||
var watchInitialised = false;
|
||||
var watchTaskQueue = {};
|
||||
var processingQueue = false;
|
||||
|
||||
// Grab the tasks and files that have been queued up and execute them.
|
||||
var processWatchTaskQueue = function() {
|
||||
if (!Object.keys(watchTaskQueue).length || processingQueue) {
|
||||
// If there is nothing in the queue or we're already processing then wait.
|
||||
return;
|
||||
}
|
||||
|
||||
processingQueue = true;
|
||||
|
||||
// Grab all tasks currently in the queue.
|
||||
var queueToProcess = watchTaskQueue;
|
||||
// Reset the queue.
|
||||
watchTaskQueue = {};
|
||||
|
||||
async.forEachSeries(
|
||||
Object.keys(queueToProcess),
|
||||
function(task, next) {
|
||||
var files = queueToProcess[task];
|
||||
var filesOption = '--files=' + files.join(',');
|
||||
grunt.log.ok('Running task ' + task + ' for files ' + filesOption);
|
||||
|
||||
// Spawn the task in a child process so that it doesn't kill this one
|
||||
// if it failed.
|
||||
grunt.util.spawn(
|
||||
{
|
||||
// Spawn with the grunt bin.
|
||||
grunt: true,
|
||||
// Run from current working dir and inherit stdio from process.
|
||||
opts: {
|
||||
cwd: cwd,
|
||||
stdio: 'inherit'
|
||||
},
|
||||
args: [task, filesOption]
|
||||
},
|
||||
function(err, res, code) {
|
||||
if (code !== 0) {
|
||||
// The grunt task failed.
|
||||
grunt.log.error(err);
|
||||
}
|
||||
|
||||
// Move on to the next task.
|
||||
next();
|
||||
}
|
||||
);
|
||||
},
|
||||
function() {
|
||||
// No longer processing.
|
||||
processingQueue = false;
|
||||
// Once all of the tasks are done then recurse just in case more tasks
|
||||
// were queued while we were processing.
|
||||
processWatchTaskQueue();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var watchConfig = grunt.config.get(['watch']);
|
||||
watchConfig = Object.keys(watchConfig).reduce(function(carry, key) {
|
||||
if (key == 'options') {
|
||||
return carry;
|
||||
}
|
||||
|
||||
var value = watchConfig[key];
|
||||
var fileGlobs = value.files;
|
||||
var taskNames = value.tasks;
|
||||
|
||||
taskNames.forEach(function(taskName) {
|
||||
carry[taskName] = fileGlobs;
|
||||
});
|
||||
|
||||
return carry;
|
||||
}, {});
|
||||
|
||||
watchmanClient.on('error', function(error) {
|
||||
// We have to add an error handler here and parse the error string because the
|
||||
// example way from the docs to check if Watchman is installed doesn't actually work!!
|
||||
// See: https://github.com/facebook/watchman/issues/509
|
||||
if (error.message.match('Watchman was not found')) {
|
||||
// If watchman isn't installed then we should fallback to the other watch task.
|
||||
grunt.log.ok('It is recommended that you install Watchman for better performance using the "watch" command.');
|
||||
|
||||
// Fallback to the old grunt-contrib-watch task.
|
||||
grunt.renameTask('watch-grunt', 'watch');
|
||||
grunt.task.run(['watch']);
|
||||
// This task is finished.
|
||||
watchTaskDone(0);
|
||||
} else {
|
||||
grunt.log.error(error);
|
||||
// Fatal error.
|
||||
watchTaskDone(1);
|
||||
}
|
||||
});
|
||||
|
||||
watchmanClient.on('subscription', function(resp) {
|
||||
if (resp.subscription !== 'grunt-watch') {
|
||||
return;
|
||||
}
|
||||
|
||||
resp.files.forEach(function(file) {
|
||||
grunt.log.ok('File changed: ' + file.name);
|
||||
|
||||
var fullPath = cwd + '/' + file.name;
|
||||
Object.keys(watchConfig).forEach(function(task) {
|
||||
var fileGlobs = watchConfig[task];
|
||||
var match = fileGlobs.every(function(fileGlob) {
|
||||
return grunt.file.isMatch(fileGlob, fullPath);
|
||||
});
|
||||
if (match) {
|
||||
// If we are watching a subdirectory then the file.name will be relative
|
||||
// to that directory. However the grunt tasks expect the file paths to be
|
||||
// relative to the Gruntfile.js location so let's normalise them before
|
||||
// adding them to the queue.
|
||||
var relativePath = fullPath.replace(gruntFilePath + '/', '');
|
||||
if (task in watchTaskQueue) {
|
||||
if (!watchTaskQueue[task].includes(relativePath)) {
|
||||
watchTaskQueue[task] = watchTaskQueue[task].concat(relativePath);
|
||||
}
|
||||
} else {
|
||||
watchTaskQueue[task] = [relativePath];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
processWatchTaskQueue();
|
||||
});
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
// Let the user know that they may need to manually stop the Watchman daemon if they
|
||||
// no longer want it running.
|
||||
if (watchInitialised) {
|
||||
grunt.log.ok('The Watchman daemon may still be running and may need to be stopped manually.');
|
||||
}
|
||||
|
||||
process.exit();
|
||||
});
|
||||
|
||||
// Initiate the watch on the current directory.
|
||||
watchmanClient.command(['watch-project', cwd], function(watchError, watchResponse) {
|
||||
if (watchError) {
|
||||
grunt.log.error('Error initiating watch:', watchError);
|
||||
watchTaskDone(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if ('warning' in watchResponse) {
|
||||
grunt.log.error('warning: ', watchResponse.warning);
|
||||
}
|
||||
|
||||
var watch = watchResponse.watch;
|
||||
var relativePath = watchResponse.relative_path;
|
||||
watchInitialised = true;
|
||||
|
||||
watchmanClient.command(['clock', watch], function(clockError, clockResponse) {
|
||||
if (clockError) {
|
||||
grunt.log.error('Failed to query clock:', clockError);
|
||||
watchTaskDone(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the matching patterns specified in the watch config.
|
||||
var matches = Object.keys(watchConfig).map(function(task) {
|
||||
var fileGlobs = watchConfig[task];
|
||||
var fileGlobMatches = fileGlobs.map(function(fileGlob) {
|
||||
return ['match', fileGlob, 'wholename'];
|
||||
});
|
||||
|
||||
return ['allof'].concat(fileGlobMatches);
|
||||
});
|
||||
|
||||
var sub = {
|
||||
expression: ["anyof"].concat(matches),
|
||||
// Which fields we're interested in.
|
||||
fields: ["name", "size", "type"],
|
||||
// Add our time constraint.
|
||||
since: clockResponse.clock
|
||||
};
|
||||
|
||||
if (relativePath) {
|
||||
/* eslint-disable camelcase */
|
||||
sub.relative_root = relativePath;
|
||||
}
|
||||
|
||||
watchmanClient.command(['subscribe', watch, 'grunt-watch', sub], function(subscribeError) {
|
||||
if (subscribeError) {
|
||||
// Probably an error in the subscription criteria.
|
||||
grunt.log.error('failed to subscribe: ', subscribeError);
|
||||
watchTaskDone(1);
|
||||
return;
|
||||
}
|
||||
|
||||
grunt.log.ok('Listening for changes to files in ' + cwd);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// On watch, we dynamically modify config to build only affected files. This
|
||||
// method is slightly complicated to deal with multiple changed files at once (copied
|
||||
// from the grunt-contrib-watch readme).
|
||||
var changedFiles = Object.create(null);
|
||||
var onChange = grunt.util._.debounce(function() {
|
||||
var files = Object.keys(changedFiles);
|
||||
grunt.config('eslint.amd.src', files);
|
||||
grunt.config('eslint.yui.src', files);
|
||||
grunt.config('shifter.options.paths', files);
|
||||
grunt.config('gherkinlint.options.files', files);
|
||||
grunt.config('babel.dist.files', [{expand: true, src: files, rename: babelRename}]);
|
||||
changedFiles = Object.create(null);
|
||||
var files = Object.keys(changedFiles);
|
||||
grunt.config('eslint.amd.src', files);
|
||||
grunt.config('eslint.yui.src', files);
|
||||
grunt.config('uglify.amd.files', [{expand: true, src: files, rename: uglifyRename}]);
|
||||
grunt.config('shifter.options.paths', files);
|
||||
grunt.config('gherkinlint.options.files', files);
|
||||
changedFiles = Object.create(null);
|
||||
}, 200);
|
||||
|
||||
grunt.event.on('watch', function(action, filepath) {
|
||||
changedFiles[filepath] = action;
|
||||
onChange();
|
||||
changedFiles[filepath] = action;
|
||||
onChange();
|
||||
});
|
||||
|
||||
// Register NPM tasks.
|
||||
@@ -634,24 +347,17 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-sass');
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
grunt.loadNpmTasks('grunt-stylelint');
|
||||
grunt.loadNpmTasks('grunt-babel');
|
||||
|
||||
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
|
||||
grunt.renameTask('watch', 'watch-grunt');
|
||||
|
||||
// Register JS tasks.
|
||||
grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter);
|
||||
grunt.registerTask('gherkinlint', 'Run gherkinlint against the current directory', tasks.gherkinlint);
|
||||
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles);
|
||||
grunt.registerTask('watch', 'Run tasks on file changes', tasks.watch);
|
||||
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
|
||||
grunt.registerTask('amd', ['eslint:amd', 'babel']);
|
||||
grunt.registerTask('amd', ['eslint:amd', 'uglify']);
|
||||
grunt.registerTask('js', ['amd', 'yui']);
|
||||
|
||||
// Register CSS taks.
|
||||
grunt.registerTask('css', ['stylelint:scss', 'sass', 'stylelint:css']);
|
||||
grunt.registerTask('scss', ['stylelint:scss', 'sass']);
|
||||
grunt.registerTask('rawcss', ['stylelint:css']);
|
||||
|
||||
// Register the startup task.
|
||||
grunt.registerTask('startup', 'Run the correct tasks for the current directory', tasks.startup);
|
||||
|
||||
@@ -33,7 +33,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$PAGE->set_url('/admin/antiviruses.php', array('action' => $action, 'antivirus' => $antivirus));
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageantiviruses";
|
||||
|
||||
|
||||
+2
-1
@@ -11,7 +11,8 @@ require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$returnurl = new moodle_url('/admin/settings.php', array('section'=>'manageauths'));
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ $category = required_param('category', PARAM_SAFEDIR);
|
||||
$return = optional_param('return','', PARAM_ALPHA);
|
||||
$adminediting = optional_param('adminedit', -1, PARAM_BOOL);
|
||||
|
||||
/// no guest autologin
|
||||
require_login(0, false);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_url('/admin/category.php', array('category' => $category));
|
||||
|
||||
@@ -50,7 +50,6 @@ class purge_caches extends \moodleform {
|
||||
$mform->createElement('advcheckbox', 'theme', '', get_string('purgethemecache', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'lang', '', get_string('purgelangcache', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'js', '', get_string('purgejscache', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'template', '', get_string('purgetemplates', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'filter', '', get_string('purgefiltercache', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'muc', '', get_string('purgemuc', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'other', '', get_string('purgeothercaches', 'admin'))
|
||||
|
||||
@@ -1,194 +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/>.
|
||||
|
||||
/**
|
||||
* File size admin setting.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2019 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
/**
|
||||
* An admin setting to support entering and displaying of file sizes in Bytes, KB, MB or GB.
|
||||
*
|
||||
* @copyright 2019 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class filesize extends \admin_setting {
|
||||
|
||||
/** @var int The byte unit. Number of bytes in a byte */
|
||||
const UNIT_B = 1;
|
||||
|
||||
/** @var int The kilobyte unit (number of bytes in a kilobyte) */
|
||||
const UNIT_KB = 1024;
|
||||
|
||||
/** @var int The megabyte unit (number of bytes in a megabyte) */
|
||||
const UNIT_MB = 1048576;
|
||||
|
||||
/** @var int The gigabyte unit (number of bytes in a gigabyte) */
|
||||
const UNIT_GB = 1073741824;
|
||||
|
||||
/** @var int default size unit */
|
||||
protected $defaultunit;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $name unique ascii name, either 'mysetting' for settings that in config,
|
||||
* or 'myplugin/mysetting' for ones in config_plugins.
|
||||
* @param string $visiblename localised name
|
||||
* @param string $description localised long description
|
||||
* @param int|null $defaultvalue Value of the settings in bytes
|
||||
* @param int|null $defaultunit GB, MB, etc. (in bytes)
|
||||
*/
|
||||
public function __construct(string $name, string $visiblename, string $description,
|
||||
int $defaultvalue = null, int $defaultunit = null) {
|
||||
|
||||
$defaultsetting = self::parse_bytes($defaultvalue);
|
||||
|
||||
if ($defaultunit && array_key_exists($defaultunit, self::get_units())) {
|
||||
$this->defaultunit = $defaultunit;
|
||||
} else {
|
||||
$this->defaultunit = self::UNIT_MB;
|
||||
}
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns selectable units.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function get_units(): array {
|
||||
return [
|
||||
self::UNIT_GB => get_string('sizegb'),
|
||||
self::UNIT_MB => get_string('sizemb'),
|
||||
self::UNIT_KB => get_string('sizekb'),
|
||||
self::UNIT_B => get_string('sizeb'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts bytes to some more user friendly string.
|
||||
*
|
||||
* @param int $bytes The number of bytes we want to convert from
|
||||
* @return string
|
||||
*/
|
||||
protected static function get_size_text(int $bytes): string {
|
||||
if (empty($bytes)) {
|
||||
return get_string('none');
|
||||
}
|
||||
return display_size($bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds suitable units for given file size.
|
||||
*
|
||||
* @param int $bytes The number of bytes
|
||||
* @return array Parsed file size in the format of ['v' => value, 'u' => unit]
|
||||
*/
|
||||
protected static function parse_bytes(int $bytes): array {
|
||||
foreach (self::get_units() as $unit => $unused) {
|
||||
if ($bytes % $unit === 0) {
|
||||
return ['v' => (int)($bytes / $unit), 'u' => $unit];
|
||||
}
|
||||
}
|
||||
return ['v' => (int)$bytes, 'u' => self::UNIT_B];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected file size as array.
|
||||
*
|
||||
* @return array|null An array containing 'v' => xx, 'u' => xx, or null if not set
|
||||
*/
|
||||
public function get_setting(): ?array {
|
||||
$bytes = $this->config_read($this->name);
|
||||
if (is_null($bytes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::parse_bytes($bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the file size as bytes.
|
||||
*
|
||||
* @param array $data Must be form 'h' => xx, 'm' => xx
|
||||
* @return string The error string if any
|
||||
*/
|
||||
public function write_setting($data): string {
|
||||
if (!is_array($data)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!is_numeric($data['v']) || $data['v'] < 0) {
|
||||
return get_string('errorsetting', 'admin');
|
||||
}
|
||||
|
||||
$bytes = $data['v'] * $data['u'];
|
||||
|
||||
$result = $this->config_write($this->name, $bytes);
|
||||
return ($result ? '' : get_string('errorsetting', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns file size text+select fields.
|
||||
*
|
||||
* @param array $data The current setting value. Must be form 'v' => xx, 'u' => xx.
|
||||
* @param string $query Admin search query to be highlighted.
|
||||
* @return string File size text+select fields and wrapping div(s).
|
||||
*/
|
||||
public function output_html($data, $query = ''): string {
|
||||
global $OUTPUT;
|
||||
|
||||
$default = $this->get_defaultsetting();
|
||||
if (is_number($default)) {
|
||||
$defaultinfo = self::get_size_text($default);
|
||||
} else if (is_array($default)) {
|
||||
$defaultinfo = self::get_size_text($default['v'] * $default['u']);
|
||||
} else {
|
||||
$defaultinfo = null;
|
||||
}
|
||||
|
||||
$inputid = $this->get_id() . 'v';
|
||||
$units = self::get_units();
|
||||
$defaultunit = $this->defaultunit;
|
||||
|
||||
$context = (object) [
|
||||
'id' => $this->get_id(),
|
||||
'name' => $this->get_full_name(),
|
||||
'value' => $data['v'],
|
||||
'options' => array_map(function($unit, $title) use ($data, $defaultunit) {
|
||||
return [
|
||||
'value' => $unit,
|
||||
'name' => $title,
|
||||
'selected' => ($data['v'] == 0 && $unit == $defaultunit) || $unit == $data['u']
|
||||
];
|
||||
}, array_keys($units), $units)
|
||||
];
|
||||
|
||||
$element = $OUTPUT->render_from_template('core_admin/setting_configfilesize', $context);
|
||||
|
||||
return format_admin_setting($this, $this->visiblename, $element, $this->description, $inputid, '', $defaultinfo, $query);
|
||||
}
|
||||
}
|
||||
@@ -131,8 +131,7 @@ class task_log_table extends \table_sql {
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
tl.id, tl.type, tl.component, tl.classname, tl.userid, tl.timestart, tl.timeend,
|
||||
tl.dbreads, tl.dbwrites, tl.result,
|
||||
tl.*,
|
||||
tl.dbreads + tl.dbwrites AS db,
|
||||
tl.timeend - tl.timestart AS duration,
|
||||
{$userfields}
|
||||
|
||||
+186
-203
@@ -266,7 +266,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
);
|
||||
|
||||
$interactive = empty($options['non-interactive']);
|
||||
$skipdatabase = $options['skip-database'];
|
||||
|
||||
// set up language
|
||||
$lang = clean_param($options['lang'], PARAM_SAFEDIR);
|
||||
@@ -392,6 +391,7 @@ if ($interactive) {
|
||||
$CFG->wwwroot = $wwwroot;
|
||||
$CFG->httpswwwroot = $CFG->wwwroot;
|
||||
|
||||
|
||||
//We need dataroot before lang download
|
||||
$CFG->dataroot = $options['dataroot'];
|
||||
if ($interactive) {
|
||||
@@ -514,105 +514,100 @@ if ($interactive) {
|
||||
$database = $databases[$CFG->dbtype];
|
||||
|
||||
|
||||
// We cannot do any validation until all DB connection data is provided.
|
||||
$hintdatabase = '';
|
||||
do {
|
||||
echo $hintdatabase;
|
||||
|
||||
// Ask for db host.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasehost', 'install'));
|
||||
if ($options['dbhost'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbhost = cli_input($prompt, $options['dbhost']);
|
||||
|
||||
// ask for db host
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasehost', 'install'));
|
||||
if ($options['dbhost'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
|
||||
} else {
|
||||
$CFG->dbhost = $options['dbhost'];
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbhost = cli_input($prompt, $options['dbhost']);
|
||||
|
||||
// Ask for db name.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasename', 'install'));
|
||||
if ($options['dbname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbname = cli_input($prompt, $options['dbname']);
|
||||
} else {
|
||||
$CFG->dbhost = $options['dbhost'];
|
||||
}
|
||||
|
||||
// ask for db name
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasename', 'install'));
|
||||
if ($options['dbname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
|
||||
} else {
|
||||
$CFG->dbname = $options['dbname'];
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbname = cli_input($prompt, $options['dbname']);
|
||||
|
||||
// Ask for db prefix.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('dbprefix', 'install'));
|
||||
//TODO: solve somehow the prefix trouble for oci.
|
||||
if ($options['prefix'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->prefix = cli_input($prompt, $options['prefix']);
|
||||
} else {
|
||||
$CFG->dbname = $options['dbname'];
|
||||
}
|
||||
|
||||
// ask for db prefix
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('dbprefix', 'install'));
|
||||
//TODO: solve somehow the prefix trouble for oci
|
||||
if ($options['prefix'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
|
||||
} else {
|
||||
$CFG->prefix = $options['prefix'];
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->prefix = cli_input($prompt, $options['prefix']);
|
||||
|
||||
// Ask for db port.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databaseport', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
|
||||
$CFG->dboptions['dbport'] = (int) cli_input($prompt, $options['dbport']);
|
||||
} else {
|
||||
$CFG->prefix = $options['prefix'];
|
||||
}
|
||||
|
||||
// ask for db port
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databaseport', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
|
||||
$CFG->dboptions['dbport'] = (int)cli_input($prompt, $options['dbport']);
|
||||
|
||||
} else {
|
||||
$CFG->dboptions['dbport'] = (int)$options['dbport'];
|
||||
}
|
||||
if ($CFG->dboptions['dbport'] <= 0) {
|
||||
$CFG->dboptions['dbport'] = '';
|
||||
}
|
||||
|
||||
// ask for db socket
|
||||
if ($CFG->ostype === 'WINDOWS') {
|
||||
$CFG->dboptions['dbsocket'] = '';
|
||||
|
||||
} else if ($interactive and empty($CFG->dboptions['dbport'])) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasesocket', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
|
||||
$CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
|
||||
|
||||
} else {
|
||||
$CFG->dboptions['dbsocket'] = $options['dbsocket'];
|
||||
}
|
||||
|
||||
// ask for db user
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databaseuser', 'install'));
|
||||
if ($options['dbuser'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
|
||||
} else {
|
||||
$CFG->dboptions['dbport'] = (int) $options['dbport'];
|
||||
}
|
||||
if ($CFG->dboptions['dbport'] <= 0) {
|
||||
$CFG->dboptions['dbport'] = '';
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbuser = cli_input($prompt, $options['dbuser']);
|
||||
|
||||
// Ask for db socket.
|
||||
if ($CFG->ostype === 'WINDOWS') {
|
||||
$CFG->dboptions['dbsocket'] = '';
|
||||
|
||||
} else if ($interactive and empty($CFG->dboptions['dbport'])) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasesocket', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
|
||||
$CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
|
||||
|
||||
} else {
|
||||
$CFG->dboptions['dbsocket'] = $options['dbsocket'];
|
||||
}
|
||||
|
||||
// Ask for db user.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databaseuser', 'install'));
|
||||
if ($options['dbuser'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbuser = cli_input($prompt, $options['dbuser']);
|
||||
|
||||
} else {
|
||||
$CFG->dbuser = $options['dbuser'];
|
||||
}
|
||||
|
||||
// Ask for db password.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasepass', 'install'));
|
||||
} else {
|
||||
$CFG->dbuser = $options['dbuser'];
|
||||
}
|
||||
|
||||
// ask for db password
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasepass', 'install'));
|
||||
do {
|
||||
if ($options['dbpass'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbpass']);
|
||||
} else {
|
||||
@@ -620,118 +615,110 @@ do {
|
||||
}
|
||||
|
||||
$CFG->dbpass = cli_input($prompt, $options['dbpass']);
|
||||
if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation.
|
||||
$distro = distro_pre_create_db($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
|
||||
array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']),
|
||||
$distro);
|
||||
if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation
|
||||
$distro = distro_pre_create_db($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersist'=>0, 'dbport'=>$CFG->dboptions['dbport'], 'dbsocket'=>$CFG->dboptions['dbsocket']), $distro);
|
||||
}
|
||||
$hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
|
||||
array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
|
||||
$hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersist'=>0, 'dbport'=>$CFG->dboptions['dbport'], 'dbsocket'=>$CFG->dboptions['dbsocket']));
|
||||
} while ($hint_database !== '');
|
||||
|
||||
} else {
|
||||
$CFG->dbpass = $options['dbpass'];
|
||||
$hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
|
||||
array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
|
||||
if ($hintdatabase !== '') {
|
||||
cli_error(get_string('dbconnectionerror', 'install'));
|
||||
}
|
||||
} else {
|
||||
$CFG->dbpass = $options['dbpass'];
|
||||
$hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersist'=>0, 'dbport'=>$CFG->dboptions['dbport'], 'dbsocket'=>$CFG->dboptions['dbsocket']));
|
||||
if ($hint_database !== '') {
|
||||
cli_error(get_string('dbconnectionerror', 'install'));
|
||||
}
|
||||
} while ($hintdatabase !== '');
|
||||
}
|
||||
|
||||
// If --skip-database option is provided, we do not need to ask for site fullname, shortname, adminuser, adminpass, adminemail.
|
||||
// These fields will be requested during the database install part.
|
||||
if (!$skipdatabase) {
|
||||
// Ask for fullname.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('fullsitename', 'moodle'));
|
||||
// ask for fullname
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('fullsitename', 'moodle'));
|
||||
|
||||
if ($options['fullname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
|
||||
do {
|
||||
$options['fullname'] = cli_input($prompt, $options['fullname']);
|
||||
} while (empty($options['fullname']));
|
||||
if ($options['fullname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
|
||||
} else {
|
||||
if (empty($options['fullname'])) {
|
||||
$a = (object)['option' => 'fullname', 'value' => $options['fullname']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for shortname.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('shortsitename', 'moodle'));
|
||||
|
||||
if ($options['shortname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
|
||||
do {
|
||||
$options['shortname'] = cli_input($prompt, $options['shortname']);
|
||||
} while (empty($options['shortname']));
|
||||
} else {
|
||||
if (empty($options['shortname'])) {
|
||||
$a = (object)['option' => 'shortname', 'value' => $options['shortname']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for admin user name.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminusername', 'install'));
|
||||
if (!empty($options['adminuser'])) {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
do {
|
||||
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
|
||||
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
|
||||
} else {
|
||||
if ((empty($options['adminuser']) || $options['adminuser'] === 'guest')) {
|
||||
$a = (object)['option' => 'adminuser', 'value' => $options['adminuser']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for admin user password.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminpassword', 'install'));
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
do {
|
||||
$options['adminpass'] = cli_input($prompt);
|
||||
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
|
||||
} else {
|
||||
if ((empty($options['adminpass']) or $options['adminpass'] === 'admin')) {
|
||||
$a = (object)['option' => 'adminpass', 'value' => $options['adminpass']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for the admin email address.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminemail', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
|
||||
$options['adminemail'] = cli_input($prompt, $options['adminemail']);
|
||||
}
|
||||
|
||||
// Validate that the address provided was an e-mail address.
|
||||
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
|
||||
$a = (object)['option' => 'adminemail', 'value' => $options['adminemail']];
|
||||
do {
|
||||
$options['fullname'] = cli_input($prompt, $options['fullname']);
|
||||
} while (empty($options['fullname']));
|
||||
} else {
|
||||
if (empty($options['fullname'])) {
|
||||
$a = (object)array('option'=>'fullname', 'value'=>$options['fullname']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// ask for shortname
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('shortsitename', 'moodle'));
|
||||
|
||||
if ($options['shortname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
|
||||
do {
|
||||
$options['shortname'] = cli_input($prompt, $options['shortname']);
|
||||
} while (empty($options['shortname']));
|
||||
} else {
|
||||
if (empty($options['shortname'])) {
|
||||
$a = (object)array('option'=>'shortname', 'value'=>$options['shortname']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// ask for admin user name
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminusername', 'install'));
|
||||
if (!empty($options['adminuser'])) {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
do {
|
||||
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
|
||||
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
|
||||
} else {
|
||||
if (empty($options['adminuser']) or $options['adminuser'] === 'guest') {
|
||||
$a = (object)array('option'=>'adminuser', 'value'=>$options['adminuser']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// ask for admin user password
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminpassword', 'install'));
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
do {
|
||||
$options['adminpass'] = cli_input($prompt);
|
||||
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
|
||||
} else {
|
||||
if (empty($options['adminpass']) or $options['adminpass'] === 'admin') {
|
||||
$a = (object)array('option'=>'adminpass', 'value'=>$options['adminpass']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for the admin email address.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminemail', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
|
||||
$options['adminemail'] = cli_input($prompt, $options['adminemail']);
|
||||
}
|
||||
|
||||
// Validate that the address provided was an e-mail address.
|
||||
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
|
||||
$a = (object) array('option' => 'adminemail', 'value' => $options['adminemail']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
|
||||
// Ask for the upgrade key.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
@@ -750,27 +737,23 @@ if ($options['upgradekey'] !== '') {
|
||||
$CFG->upgradekey = $options['upgradekey'];
|
||||
}
|
||||
|
||||
// The user does not also need to pass agree-license when --skip-database is provided as the user will need to accept
|
||||
// the license again in the database install part.
|
||||
if (!$skipdatabase) {
|
||||
if ($interactive) {
|
||||
if (!$options['agree-license']) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('copyrightnotice'));
|
||||
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
|
||||
echo get_string('gpl3')."\n\n";
|
||||
echo get_string('doyouagree')."\n";
|
||||
$prompt = get_string('cliyesnoprompt', 'admin');
|
||||
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
|
||||
if ($input == get_string('clianswerno', 'admin')) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$options['agree-license'] && !$skipdatabase) {
|
||||
cli_error(get_string('climustagreelicense', 'install'));
|
||||
if ($interactive) {
|
||||
if (!$options['agree-license']) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('copyrightnotice'));
|
||||
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
|
||||
echo get_string('gpl3')."\n\n";
|
||||
echo get_string('doyouagree')."\n";
|
||||
$prompt = get_string('cliyesnoprompt', 'admin');
|
||||
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
|
||||
if ($input == get_string('clianswerno', 'admin')) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$options['agree-license']) {
|
||||
cli_error(get_string('climustagreelicense', 'install'));
|
||||
}
|
||||
}
|
||||
|
||||
// Finally we have all info needed for config.php
|
||||
@@ -818,7 +801,7 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
cli_error(get_string('pluginschecktodo', 'admin'));
|
||||
}
|
||||
|
||||
if (!$skipdatabase) {
|
||||
if (!$options['skip-database']) {
|
||||
install_cli_database($options, $interactive);
|
||||
// This needs to happen at the end to ensure it occurs after all caches
|
||||
// have been purged for the last time.
|
||||
|
||||
@@ -94,7 +94,7 @@ if ($options['password'] == '' ) {
|
||||
|
||||
$errmsg = '';//prevent eclipse warning
|
||||
if (!$options['ignore-password-policy'] ) {
|
||||
if (!check_password_policy($password, $errmsg, $user)) {
|
||||
if (!check_password_policy($password, $errmsg)) {
|
||||
cli_error(html_to_text($errmsg, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,8 +52,7 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'allow-unstable' => false,
|
||||
'help' => false,
|
||||
'lang' => $lang,
|
||||
'verbose-settings' => false,
|
||||
'is-pending' => false,
|
||||
'verbose-settings' => false
|
||||
),
|
||||
array(
|
||||
'h' => 'help'
|
||||
@@ -89,8 +88,6 @@ Options:
|
||||
--verbose-settings Show new settings values. By default only the name of
|
||||
new core or plugin settings are displayed. This option
|
||||
outputs the new values as well as the setting name.
|
||||
--is-pending If an upgrade is needed it exits with an error code of
|
||||
2 so it distinct from other types of errors.
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
@@ -119,10 +116,6 @@ if (!moodle_needs_upgrading()) {
|
||||
cli_error(get_string('cliupgradenoneed', 'core_admin', $newversion), 0);
|
||||
}
|
||||
|
||||
if ($options['is-pending']) {
|
||||
cli_error(get_string('cliupgradepending', 'core_admin'), 2);
|
||||
}
|
||||
|
||||
// Test environment first.
|
||||
list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
|
||||
if (!$envstatus) {
|
||||
|
||||
@@ -32,7 +32,8 @@ $syscontext = context_system::instance();
|
||||
$PAGE->set_url('/admin/courseformats.php');
|
||||
$PAGE->set_context($syscontext);
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', $syscontext);
|
||||
require_sesskey();
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section' => 'manageformats'));
|
||||
|
||||
@@ -32,7 +32,8 @@ $syscontext = context_system::instance();
|
||||
$PAGE->set_url('/admin/customfields.php');
|
||||
$PAGE->set_context($syscontext);
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', $syscontext);
|
||||
require_sesskey();
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section' => 'managecustomfields'));
|
||||
|
||||
@@ -33,7 +33,8 @@ $syscontext = context_system::instance();
|
||||
$PAGE->set_url('/admin/dataformats.php');
|
||||
$PAGE->set_context($syscontext);
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', $syscontext);
|
||||
require_sesskey();
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section' => 'managedataformats'));
|
||||
|
||||
+2
-1
@@ -15,7 +15,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$PAGE->set_url('/admin/editors.php', array('action'=>$action, 'editor'=>$editor));
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageeditors";
|
||||
|
||||
|
||||
+2
-1
@@ -35,7 +35,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$PAGE->set_url('/admin/enrol.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
require_sesskey();
|
||||
|
||||
$enabled = enrol_get_plugins(true);
|
||||
|
||||
@@ -2451,7 +2451,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.0.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_74" message="unsupportedphpversion74" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -2633,7 +2632,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.1.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_74" message="unsupportedphpversion74" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -2982,366 +2980,4 @@
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.9" requires="3.5">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.2.29" />
|
||||
<VENDOR name="mysql" version="5.6" />
|
||||
<VENDOR name="postgres" version="9.5" />
|
||||
<VENDOR name="mssql" version="11.0" />
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.2.0" 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="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlrpc" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="xmlrpcrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.10" requires="3.5">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.2.29" />
|
||||
<VENDOR name="mysql" version="5.7" />
|
||||
<VENDOR name="postgres" version="9.6" />
|
||||
<VENDOR name="mssql" version="11.0" />
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.2.0" 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="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlrpc" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="xmlrpcrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
+10
-29
@@ -226,7 +226,7 @@ if (!core_tables_exist()) {
|
||||
}
|
||||
if (empty($confirmrelease)) {
|
||||
require_once($CFG->libdir.'/environmentlib.php');
|
||||
list($envstatus, $environmentresults) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
|
||||
list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
|
||||
$strcurrentrelease = get_string('currentrelease');
|
||||
|
||||
$PAGE->navbar->add($strcurrentrelease);
|
||||
@@ -235,7 +235,7 @@ if (!core_tables_exist()) {
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
echo $output->install_environment_page($maturity, $envstatus, $environmentresults, $release);
|
||||
echo $output->install_environment_page($maturity, $envstatus, $environment_results, $release);
|
||||
die();
|
||||
}
|
||||
|
||||
@@ -358,9 +358,9 @@ if (!$cache and $version > $CFG->version) { // upgrade
|
||||
echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite);
|
||||
die();
|
||||
|
||||
} else if (empty($confirmrelease)) {
|
||||
} else if (empty($confirmrelease)){
|
||||
require_once($CFG->libdir.'/environmentlib.php');
|
||||
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
|
||||
list($envstatus, $environment_results) = check_moodle_environment($release, ENV_SELECT_RELEASE);
|
||||
$strcurrentrelease = get_string('currentrelease');
|
||||
|
||||
$PAGE->navbar->add($strcurrentrelease);
|
||||
@@ -368,7 +368,7 @@ if (!$cache and $version > $CFG->version) { // upgrade
|
||||
$PAGE->set_heading($strcurrentrelease);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
|
||||
echo $output->upgrade_environment_page($release, $envstatus, $environment_results);
|
||||
die();
|
||||
|
||||
} else if (empty($confirmplugins)) {
|
||||
@@ -509,8 +509,7 @@ if (!$cache and $version > $CFG->version) { // upgrade
|
||||
// Always verify plugin dependencies!
|
||||
$failed = array();
|
||||
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
|
||||
array('confirmplugincheck' => 0)));
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
|
||||
die();
|
||||
}
|
||||
unset($failed);
|
||||
@@ -534,10 +533,7 @@ if (!$cache and $branch <> $CFG->branch) { // Update the branch
|
||||
|
||||
if (!$cache and moodle_needs_upgrading()) {
|
||||
|
||||
$PAGE->set_url(new moodle_url($PAGE->url, array(
|
||||
'confirmrelease' => $confirmrelease,
|
||||
'confirmplugincheck' => $confirmplugins,
|
||||
)));
|
||||
$PAGE->set_url(new moodle_url($PAGE->url, array('confirmplugincheck' => $confirmplugins)));
|
||||
|
||||
check_upgrade_key($upgradekeyhash);
|
||||
|
||||
@@ -547,21 +543,7 @@ if (!$cache and moodle_needs_upgrading()) {
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
|
||||
if (empty($confirmrelease)) {
|
||||
require_once($CFG->libdir . '/environmentlib.php');
|
||||
|
||||
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
|
||||
$strcurrentrelease = get_string('currentrelease');
|
||||
|
||||
$PAGE->navbar->add($strcurrentrelease);
|
||||
$PAGE->set_title($strcurrentrelease);
|
||||
$PAGE->set_heading($strcurrentrelease);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
|
||||
die();
|
||||
|
||||
} else if (!$confirmplugins) {
|
||||
if (!$confirmplugins) {
|
||||
$strplugincheck = get_string('plugincheck');
|
||||
|
||||
$PAGE->navbar->add($strplugincheck);
|
||||
@@ -702,8 +684,7 @@ if (!$cache and moodle_needs_upgrading()) {
|
||||
$failed = array();
|
||||
if (!$pluginman->all_plugins_ok($version, $failed)) {
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
|
||||
array('confirmplugincheck' => 0)));
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
|
||||
die();
|
||||
}
|
||||
unset($failed);
|
||||
@@ -821,7 +802,7 @@ $SESSION->admin_critical_warning = ($insecuredataroot==INSECURE_DATAROOT_ERROR);
|
||||
$adminroot = admin_get_root();
|
||||
|
||||
// Check if there are any new admin settings which have still yet to be set
|
||||
if (any_new_admin_settings($adminroot)) {
|
||||
if (any_new_admin_settings($adminroot)){
|
||||
redirect('upgradesettings.php');
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -23,7 +23,8 @@ require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/licenselib.php');
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=managelicenses";
|
||||
|
||||
|
||||
+2
-1
@@ -35,7 +35,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$PAGE->set_url('/admin/media.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
require_sesskey();
|
||||
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('media');
|
||||
|
||||
+11
-31
@@ -33,17 +33,13 @@ $allprocessors = get_message_processors();
|
||||
$processors = array_filter($allprocessors, function($processor) {
|
||||
return $processor->enabled;
|
||||
});
|
||||
$disabledprocessors = array_filter($allprocessors, function($processor) {
|
||||
return !$processor->enabled;
|
||||
});
|
||||
|
||||
// Fetch message providers.
|
||||
$providers = get_message_providers();
|
||||
// Fetch the manage message outputs interface.
|
||||
$preferences = get_message_output_default_preferences();
|
||||
|
||||
if (($form = data_submitted()) && confirm_sesskey()) {
|
||||
$newpreferences = array();
|
||||
$preferences = array();
|
||||
// Prepare default message outputs settings.
|
||||
foreach ($providers as $provider) {
|
||||
$componentproviderbase = $provider->component.'_'.$provider->name;
|
||||
@@ -51,9 +47,9 @@ if (($form = data_submitted()) && confirm_sesskey()) {
|
||||
$providerdisabled = false;
|
||||
if (!isset($form->$disableprovidersetting)) {
|
||||
$providerdisabled = true;
|
||||
$newpreferences[$disableprovidersetting] = 1;
|
||||
$preferences[$disableprovidersetting] = 1;
|
||||
} else {
|
||||
$newpreferences[$disableprovidersetting] = 0;
|
||||
$preferences[$disableprovidersetting] = 0;
|
||||
}
|
||||
|
||||
foreach (array('permitted', 'loggedin', 'loggedoff') as $setting) {
|
||||
@@ -79,36 +75,20 @@ if (($form = data_submitted()) && confirm_sesskey()) {
|
||||
$form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 1;
|
||||
}
|
||||
// Record the site preference.
|
||||
$newpreferences[$processor->name.'_provider_'.$componentprovidersetting] = $value;
|
||||
$preferences[$processor->name.'_provider_'.$componentprovidersetting] = $value;
|
||||
}
|
||||
} else {
|
||||
$newsettings = array();
|
||||
if (property_exists($form, $componentprovidersetting)) {
|
||||
// We must be processing loggedin or loggedoff checkboxes.
|
||||
// Store defained comma-separated processors as setting value.
|
||||
// Using array_filter eliminates elements set to 0 above.
|
||||
$newsettings = array_keys(array_filter($form->{$componentprovidersetting}));
|
||||
}
|
||||
|
||||
// Let's join existing setting values for disabled processors.
|
||||
$property = 'message_provider_'.$componentprovidersetting;
|
||||
if (property_exists($preferences, $property)) {
|
||||
$existingsetting = $preferences->$property;
|
||||
foreach ($disabledprocessors as $disable) {
|
||||
if (strpos($existingsetting, $disable->name) > -1) {
|
||||
$newsettings[] = $disable->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$value = join(',', $newsettings);
|
||||
} else if (array_key_exists($componentprovidersetting, $form)) {
|
||||
// We must be processing loggedin or loggedoff checkboxes. Store
|
||||
// defained comma-separated processors as setting value.
|
||||
// Using array_filter eliminates elements set to 0 above.
|
||||
$value = join(',', array_keys(array_filter($form->{$componentprovidersetting})));
|
||||
if (empty($value)) {
|
||||
$value = null;
|
||||
}
|
||||
}
|
||||
if ($setting != 'permitted') {
|
||||
// We have already recoded site preferences for 'permitted' type.
|
||||
$newpreferences['message_provider_'.$componentprovidersetting] = $value;
|
||||
$preferences['message_provider_'.$componentprovidersetting] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +102,7 @@ if (($form = data_submitted()) && confirm_sesskey()) {
|
||||
\core_message\api::update_processor_status($processor, $enabled);
|
||||
}
|
||||
|
||||
foreach ($newpreferences as $name => $value) {
|
||||
foreach ($preferences as $name => $value) {
|
||||
set_config($name, $value, 'message');
|
||||
}
|
||||
$transaction->allow_commit();
|
||||
|
||||
@@ -34,6 +34,9 @@ $step = optional_param('step', 'verify', PARAM_ALPHA);
|
||||
$hostid = required_param('hostid', PARAM_INT);
|
||||
|
||||
|
||||
|
||||
$context = context_system::instance();
|
||||
|
||||
$mnet = get_mnet_environment();
|
||||
|
||||
$PAGE->set_url('/admin/mnet/delete.php');
|
||||
|
||||
+2
-1
@@ -43,8 +43,9 @@ $confirminstallupdate = optional_param('confirminstallupdate', false, PARAM_BOOL
|
||||
// NOTE: do not use admin_externalpage_setup() here because it loads
|
||||
// full admin tree which is not possible during uninstallation.
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
$syscontext = context_system::instance();
|
||||
require_capability('moodle/site:config', $syscontext);
|
||||
|
||||
// URL params we want to maintain on redirects.
|
||||
$pageparams = array('updatesonly' => $updatesonly, 'contribonly' => $contribonly);
|
||||
|
||||
@@ -31,7 +31,7 @@ require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/tablelib.php');
|
||||
|
||||
// Check permissions.
|
||||
require_login(null, false);
|
||||
require_login();
|
||||
$systemcontext = context_system::instance();
|
||||
require_capability('moodle/question:config', $systemcontext);
|
||||
|
||||
|
||||
+2
-2
@@ -30,12 +30,12 @@ require_once($CFG->libdir . '/questionlib.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/tablelib.php');
|
||||
|
||||
admin_externalpage_setup('manageqtypes');
|
||||
|
||||
// Check permissions.
|
||||
$systemcontext = context_system::instance();
|
||||
require_capability('moodle/question:config', $systemcontext);
|
||||
$canviewreports = has_capability('report/questioninstances:view', $systemcontext);
|
||||
|
||||
admin_externalpage_setup('manageqtypes');
|
||||
$thispageurl = new moodle_url('/admin/qtypes.php');
|
||||
|
||||
$qtypes = question_bank::get_all_qtypes();
|
||||
|
||||
@@ -45,8 +45,8 @@ $error = optional_param('error', '', PARAM_ALPHANUM);
|
||||
|
||||
admin_externalpage_setup('registrationmoodleorg');
|
||||
|
||||
if (parse_url($url, PHP_URL_HOST) !== parse_url(HUB_MOODLEORGHUBURL, PHP_URL_HOST)) {
|
||||
// Allow other plugins to confirm registration on custom hubs. Plugins implementing this
|
||||
if ($url !== HUB_MOODLEORGHUBURL) {
|
||||
// Allow other plugins to confirm registration on hubs other than moodle.net . Plugins implementing this
|
||||
// callback need to redirect or exit. See https://docs.moodle.org/en/Hub_registration .
|
||||
$callbacks = get_plugins_with_function('hub_registration');
|
||||
foreach ($callbacks as $plugintype => $plugins) {
|
||||
|
||||
@@ -32,4 +32,5 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
debugging('Support for alternative hubs has been removed from Moodle in 3.4.', DEBUG_DEVELOPER);
|
||||
debugging('Support for alternative hubs has been removed from Moodle in 3.4. For communication with moodle.net ' .
|
||||
'see lib/classes/hub/ .', DEBUG_DEVELOPER);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
|
||||
* @copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com
|
||||
*
|
||||
* This page displays the site registration form.
|
||||
* This page displays the site registration form for Moodle.net.
|
||||
* It handles redirection to the hub to continue the registration workflow process.
|
||||
* It also handles update operation by web service.
|
||||
*/
|
||||
@@ -32,25 +32,24 @@ require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
admin_externalpage_setup('registrationmoodleorg');
|
||||
|
||||
$unregistration = optional_param('unregistration', false, PARAM_BOOL);
|
||||
$confirm = optional_param('confirm', false, PARAM_BOOL);
|
||||
$unregistration = optional_param('unregistration', 0, PARAM_INT);
|
||||
|
||||
if ($unregistration && \core\hub\registration::is_registered()) {
|
||||
if ($confirm) {
|
||||
require_sesskey();
|
||||
\core\hub\registration::unregister(false, false);
|
||||
$siteunregistrationform = new \core\hub\site_unregistration_form();
|
||||
|
||||
if ($siteunregistrationform->is_cancelled()) {
|
||||
redirect(new moodle_url('/admin/registration/index.php'));
|
||||
} else if ($data = $siteunregistrationform->get_data()) {
|
||||
\core\hub\registration::unregister($data->unpublishalladvertisedcourses,
|
||||
$data->unpublishalluploadedcourses);
|
||||
if (!\core\hub\registration::is_registered()) {
|
||||
redirect(new moodle_url('/admin/registration/index.php'));
|
||||
}
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->confirm(
|
||||
get_string('registerwithmoodleorgremove', 'core_hub'),
|
||||
new moodle_url(new moodle_url('/admin/registration/index.php', ['unregistration' => 1, 'confirm' => 1])),
|
||||
new moodle_url(new moodle_url('/admin/registration/index.php'))
|
||||
);
|
||||
echo $OUTPUT->heading(get_string('unregisterfrom', 'hub', 'Moodle.net'), 3, 'main');
|
||||
$siteunregistrationform->display();
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
}
|
||||
@@ -83,7 +82,7 @@ if ($fromform = $siteregistrationform->get_data()) {
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
// Current status of registration.
|
||||
// Current status of registration on Moodle.net.
|
||||
|
||||
$notificationtype = \core\output\notification::NOTIFY_ERROR;
|
||||
if (\core\hub\registration::is_registered()) {
|
||||
@@ -105,11 +104,11 @@ if (\core\hub\registration::is_registered()) {
|
||||
|
||||
// Heading.
|
||||
if (\core\hub\registration::is_registered()) {
|
||||
echo $OUTPUT->heading(get_string('registerwithmoodleorgupdate', 'core_hub'));
|
||||
echo $OUTPUT->heading(get_string('updatesite', 'hub', 'Moodle.net'));
|
||||
} else if ($isinitialregistration) {
|
||||
echo $OUTPUT->heading(get_string('registerwithmoodleorgcomplete', 'core_hub'));
|
||||
echo $OUTPUT->heading(get_string('completeregistration', 'hub'));
|
||||
} else {
|
||||
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'core_hub'));
|
||||
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
|
||||
}
|
||||
|
||||
$renderer = $PAGE->get_renderer('core', 'admin');
|
||||
@@ -120,9 +119,8 @@ $siteregistrationform->display();
|
||||
if (\core\hub\registration::is_registered()) {
|
||||
// Unregister link.
|
||||
$unregisterhuburl = new moodle_url("/admin/registration/index.php", ['unregistration' => 1]);
|
||||
echo html_writer::div(html_writer::link($unregisterhuburl, get_string('unregister', 'hub')), 'unregister mt-2');
|
||||
echo html_writer::div(html_writer::link($unregisterhuburl, get_string('unregister', 'hub')), 'unregister');
|
||||
} else if ($isinitialregistration) {
|
||||
echo html_writer::div(html_writer::link(new moodle_url($returnurl), get_string('skipregistration', 'hub')),
|
||||
'skipregistration mt-2');
|
||||
echo html_writer::div(html_writer::link(new moodle_url($returnurl), get_string('skipregistration', 'hub')), 'skipregistration');
|
||||
}
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -39,8 +39,8 @@ $token = optional_param('token', '', PARAM_TEXT);
|
||||
|
||||
admin_externalpage_setup('registrationmoodleorg');
|
||||
|
||||
if (parse_url($url, PHP_URL_HOST) !== parse_url(HUB_MOODLEORGHUBURL, PHP_URL_HOST)) {
|
||||
// Allow other plugins to renew registration on custom hubs. Plugins implementing this
|
||||
if ($url !== HUB_MOODLEORGHUBURL) {
|
||||
// Allow other plugins to renew registration on hubs other than moodle.net . Plugins implementing this
|
||||
// callback need to redirect or exit. See https://docs.moodle.org/en/Hub_registration .
|
||||
$callbacks = get_plugins_with_function('hub_registration');
|
||||
foreach ($callbacks as $plugintype => $plugins) {
|
||||
@@ -56,7 +56,7 @@ if (parse_url($url, PHP_URL_HOST) !== parse_url(HUB_MOODLEORGHUBURL, PHP_URL_HOS
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('renewregistration', 'hub'), 3, 'main');
|
||||
$hublink = html_writer::tag('a', HUB_MOODLEORGHUBURL, array('href' => HUB_MOODLEORGHUBURL));
|
||||
$hublink = html_writer::tag('a', 'Moodle.net', array('href' => HUB_MOODLEORGHUBURL));
|
||||
|
||||
$deletedregmsg = get_string('previousregistrationdeleted', 'hub', $hublink);
|
||||
|
||||
|
||||
+48
-80
@@ -361,15 +361,14 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$output = '';
|
||||
|
||||
if ($checker->enabled()) {
|
||||
$output .= $this->container_start('checkforupdates mb-4');
|
||||
$output .= $this->container_start('checkforupdates');
|
||||
$output .= $this->single_button(
|
||||
new moodle_url($reloadurl, array('fetchupdates' => 1)),
|
||||
get_string('checkforupdates', 'core_plugin')
|
||||
);
|
||||
if ($timefetched = $checker->get_last_timefetched()) {
|
||||
$timefetched = userdate($timefetched, get_string('strftimedatetime', 'core_langconfig'));
|
||||
$output .= $this->container(get_string('checkforupdateslast', 'core_plugin', $timefetched),
|
||||
'lasttimefetched small text-muted mt-1');
|
||||
$output .= $this->container(get_string('checkforupdateslast', 'core_plugin', $timefetched), 'lasttimefetched');
|
||||
}
|
||||
$output .= $this->container_end();
|
||||
}
|
||||
@@ -824,7 +823,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
}
|
||||
}
|
||||
|
||||
$updateinfo .= $this->container_start('checkforupdates mt-1');
|
||||
$updateinfo .= $this->container_start('checkforupdates');
|
||||
$fetchurl = new moodle_url('/admin/index.php', array('fetchupdates' => 1, 'sesskey' => sesskey(), 'cache' => 0));
|
||||
$updateinfo .= $this->single_button($fetchurl, get_string('checkforupdates', 'core_plugin'));
|
||||
if ($fetch) {
|
||||
@@ -913,7 +912,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
*/
|
||||
protected function moodle_available_update_info(\core\update\info $updateinfo) {
|
||||
|
||||
$boxclasses = 'moodleupdateinfo mb-2';
|
||||
$boxclasses = 'moodleupdateinfo';
|
||||
$info = array();
|
||||
|
||||
if (isset($updateinfo->release)) {
|
||||
@@ -933,8 +932,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
}
|
||||
|
||||
if (isset($updateinfo->download)) {
|
||||
$info[] = html_writer::link($updateinfo->download, get_string('download'),
|
||||
array('class' => 'info download btn btn-secondary'));
|
||||
$info[] = html_writer::link($updateinfo->download, get_string('download'), array('class' => 'info download'));
|
||||
}
|
||||
|
||||
if (isset($updateinfo->url)) {
|
||||
@@ -942,9 +940,9 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
array('class' => 'info more'));
|
||||
}
|
||||
|
||||
$box = $this->output->container_start($boxclasses);
|
||||
$box .= $this->output->container(implode(html_writer::tag('span', ' | ', array('class' => 'separator')), $info), '');
|
||||
$box .= $this->output->container_end();
|
||||
$box = $this->output->box_start($boxclasses);
|
||||
$box .= $this->output->box(implode(html_writer::tag('span', ' ', array('class' => 'separator')), $info), '');
|
||||
$box .= $this->output->box_end();
|
||||
|
||||
return $box;
|
||||
}
|
||||
@@ -1056,7 +1054,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$displayname = new html_table_cell(
|
||||
$icon.
|
||||
html_writer::span($plugin->displayname, 'pluginname').
|
||||
html_writer::div($plugin->get_dir(), 'plugindir text-muted small')
|
||||
html_writer::div($plugin->get_dir(), 'plugindir')
|
||||
);
|
||||
|
||||
$versiondb = new html_table_cell($plugin->versiondb);
|
||||
@@ -1091,17 +1089,17 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
break;
|
||||
case core_plugin_manager::PLUGIN_STATUS_NODB:
|
||||
case core_plugin_manager::PLUGIN_STATUS_UPTODATE:
|
||||
$statusclass .= $dependenciesok ? 'badge-light' : 'badge-warning';
|
||||
$statusclass .= $dependenciesok ? '' : 'badge-warning';
|
||||
break;
|
||||
}
|
||||
$status = html_writer::span(get_string('status_' . $statuscode, 'core_plugin'), $statusclass);
|
||||
|
||||
if (!empty($installabortable[$plugin->component])) {
|
||||
$status .= $this->output->single_button(
|
||||
new moodle_url($this->page->url, array('abortinstall' => $plugin->component, 'confirmplugincheck' => 0)),
|
||||
new moodle_url($this->page->url, array('abortinstall' => $plugin->component)),
|
||||
get_string('cancelinstallone', 'core_plugin'),
|
||||
'post',
|
||||
array('class' => 'actionbutton cancelinstallone d-block mt-1')
|
||||
array('class' => 'actionbutton cancelinstallone')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1110,7 +1108,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
new moodle_url($this->page->url, array('abortupgrade' => $plugin->component)),
|
||||
get_string('cancelupgradeone', 'core_plugin'),
|
||||
'post',
|
||||
array('class' => 'actionbutton cancelupgradeone d-block mt-1')
|
||||
array('class' => 'actionbutton cancelupgradeone')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1180,7 +1178,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
}
|
||||
}
|
||||
|
||||
$out .= $this->output->container_start('actions mb-2');
|
||||
$out .= $this->output->container_start('actions');
|
||||
|
||||
$installableupdates = $pluginman->filter_installable($pluginman->available_updates());
|
||||
if ($installableupdates) {
|
||||
@@ -1188,16 +1186,16 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
new moodle_url($this->page->url, array('installupdatex' => 1)),
|
||||
get_string('updateavailableinstallall', 'core_admin', count($installableupdates)),
|
||||
'post',
|
||||
array('class' => 'singlebutton updateavailableinstallall mr-1')
|
||||
array('class' => 'singlebutton updateavailableinstallall')
|
||||
);
|
||||
}
|
||||
|
||||
if ($installabortable) {
|
||||
$out .= $this->output->single_button(
|
||||
new moodle_url($this->page->url, array('abortinstallx' => 1, 'confirmplugincheck' => 0)),
|
||||
new moodle_url($this->page->url, array('abortinstallx' => 1)),
|
||||
get_string('cancelinstallall', 'core_plugin', count($installabortable)),
|
||||
'post',
|
||||
array('class' => 'singlebutton cancelinstallall mr-1')
|
||||
array('class' => 'singlebutton cancelinstallall')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1206,17 +1204,15 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
new moodle_url($this->page->url, array('abortupgradex' => 1)),
|
||||
get_string('cancelupgradeall', 'core_plugin', count($upgradeabortable)),
|
||||
'post',
|
||||
array('class' => 'singlebutton cancelupgradeall mr-1')
|
||||
array('class' => 'singlebutton cancelupgradeall')
|
||||
);
|
||||
}
|
||||
|
||||
$out .= html_writer::div(html_writer::link(new moodle_url($this->page->url, array('showallplugins' => 0)),
|
||||
get_string('plugincheckattention', 'core_plugin')).' '.html_writer::span($sumattention, 'badge badge-light'),
|
||||
'btn btn-link mr-1');
|
||||
get_string('plugincheckattention', 'core_plugin')).' '.html_writer::span($sumattention, 'badge'));
|
||||
|
||||
$out .= html_writer::div(html_writer::link(new moodle_url($this->page->url, array('showallplugins' => 1)),
|
||||
get_string('plugincheckall', 'core_plugin')).' '.html_writer::span($sumtotal, 'badge badge-light'),
|
||||
'btn btn-link mr-1');
|
||||
get_string('plugincheckall', 'core_plugin')).' '.html_writer::span($sumtotal, 'badge'));
|
||||
|
||||
$out .= $this->output->container_end(); // End of .actions container.
|
||||
$out .= $this->output->container_end(); // End of #plugins-check-info container.
|
||||
@@ -1284,13 +1280,12 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
}
|
||||
}
|
||||
|
||||
$out = $this->output->container_start('plugins-check-dependencies mb-4');
|
||||
$out = $this->output->container_start('plugins-check-dependencies');
|
||||
|
||||
if ($unavailable or $unknown) {
|
||||
$out .= $this->output->heading(get_string('misdepsunavail', 'core_plugin'));
|
||||
if ($unknown) {
|
||||
$out .= $this->output->render((new \core\output\notification(get_string('misdepsunknownlist', 'core_plugin',
|
||||
implode(', ', $unknown))))->set_show_closebutton(false));
|
||||
$out .= $this->output->notification(get_string('misdepsunknownlist', 'core_plugin', implode($unknown, ', ')));
|
||||
}
|
||||
if ($unavailable) {
|
||||
$unavailablelist = array();
|
||||
@@ -1304,18 +1299,18 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
}
|
||||
$unavailablelist[] = $unavailablelistitem;
|
||||
}
|
||||
$out .= $this->output->render((new \core\output\notification(get_string('misdepsunavaillist', 'core_plugin',
|
||||
implode(', ', $unavailablelist))))->set_show_closebutton(false));
|
||||
$out .= $this->output->notification(get_string('misdepsunavaillist', 'core_plugin',
|
||||
implode($unavailablelist, ', ')));
|
||||
}
|
||||
$out .= $this->output->container_start('plugins-check-dependencies-actions mb-4');
|
||||
$out .= $this->output->container_start('plugins-check-dependencies-actions');
|
||||
$out .= ' '.html_writer::link(new moodle_url('/admin/tool/installaddon/'),
|
||||
get_string('dependencyuploadmissing', 'core_plugin'), array('class' => 'btn btn-secondary'));
|
||||
get_string('dependencyuploadmissing', 'core_plugin'));
|
||||
$out .= $this->output->container_end(); // End of .plugins-check-dependencies-actions container.
|
||||
}
|
||||
|
||||
if ($available) {
|
||||
$out .= $this->output->heading(get_string('misdepsavail', 'core_plugin'));
|
||||
$out .= $this->output->container_start('plugins-check-dependencies-actions mb-2');
|
||||
$out .= $this->output->container_start('plugins-check-dependencies-actions');
|
||||
|
||||
$installable = $pluginman->filter_installable($available);
|
||||
if ($installable) {
|
||||
@@ -1323,13 +1318,12 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
new moodle_url($this->page->url, array('installdepx' => 1)),
|
||||
get_string('dependencyinstallmissing', 'core_plugin', count($installable)),
|
||||
'post',
|
||||
array('class' => 'singlebutton dependencyinstallmissing d-inline-block mr-1')
|
||||
array('class' => 'singlebutton dependencyinstallmissing')
|
||||
);
|
||||
}
|
||||
|
||||
$out .= html_writer::div(html_writer::link(new moodle_url('/admin/tool/installaddon/'),
|
||||
get_string('dependencyuploadmissing', 'core_plugin'), array('class' => 'btn btn-link')),
|
||||
'dependencyuploadmissing d-inline-block mr-1');
|
||||
get_string('dependencyuploadmissing', 'core_plugin')), 'dependencyuploadmissing');
|
||||
|
||||
$out .= $this->output->container_end(); // End of .plugins-check-dependencies-actions container.
|
||||
|
||||
@@ -1370,7 +1364,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
if ($CFG->branch == str_replace('.', '', $moodle->release)) {
|
||||
$supportedmoodles[] = html_writer::span($moodle->release, 'badge badge-success');
|
||||
} else {
|
||||
$supportedmoodles[] = html_writer::span($moodle->release, 'badge badge-light');
|
||||
$supportedmoodles[] = html_writer::span($moodle->release, 'label');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,7 +1378,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
}
|
||||
$info = html_writer::div(
|
||||
get_string('requiredby', 'core_plugin', implode(', ', $requriedby)),
|
||||
'requiredby mb-1'
|
||||
'requiredby'
|
||||
);
|
||||
} else {
|
||||
$info = '';
|
||||
@@ -1395,39 +1389,38 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$info .= html_writer::div(
|
||||
html_writer::link('https://moodle.org/plugins/view.php?plugin='.$plugin->component,
|
||||
get_string('misdepinfoplugin', 'core_plugin')),
|
||||
'misdepinfoplugin d-inline-block mr-3 mb-1'
|
||||
'misdepinfoplugin'
|
||||
);
|
||||
|
||||
$info .= html_writer::div(
|
||||
html_writer::link('https://moodle.org/plugins/pluginversion.php?id='.$plugin->version->id,
|
||||
get_string('misdepinfoversion', 'core_plugin')),
|
||||
'misdepinfoversion d-inline-block mr-3 mb-1'
|
||||
'misdepinfoversion'
|
||||
);
|
||||
|
||||
$info .= html_writer::div(html_writer::link($plugin->version->downloadurl, get_string('download')),
|
||||
'misdepdownload d-inline-block mr-3 mb-1');
|
||||
$info .= html_writer::div(html_writer::link($plugin->version->downloadurl, get_string('download')), 'misdepdownload');
|
||||
|
||||
if ($pluginman->is_remote_plugin_installable($plugin->component, $plugin->version->version, $reason)) {
|
||||
$info .= $this->output->single_button(
|
||||
new moodle_url($this->page->url, array('installdep' => $plugin->component)),
|
||||
get_string('dependencyinstall', 'core_plugin'),
|
||||
'post',
|
||||
array('class' => 'singlebutton dependencyinstall mr-3 mb-1')
|
||||
array('class' => 'singlebutton dependencyinstall')
|
||||
);
|
||||
} else {
|
||||
$reasonhelp = $this->info_remote_plugin_not_installable($reason);
|
||||
if ($reasonhelp) {
|
||||
$info .= html_writer::div($reasonhelp, 'reasonhelp dependencyinstall d-inline-block mr-3 mb-1');
|
||||
$info .= html_writer::div($reasonhelp, 'reasonhelp dependencyinstall');
|
||||
}
|
||||
}
|
||||
|
||||
$info .= $this->output->container_end(); // End of .actions container.
|
||||
|
||||
$table->data[] = array(
|
||||
html_writer::div($plugin->name, 'name').' '.html_writer::div($plugin->component, 'component text-muted small'),
|
||||
html_writer::div($plugin->name, 'name').' '.html_writer::div($plugin->component, 'component'),
|
||||
$plugin->version->release,
|
||||
$plugin->version->version,
|
||||
implode(' ', $supportedmoodles),
|
||||
implode($supportedmoodles, ' '),
|
||||
$info
|
||||
);
|
||||
}
|
||||
@@ -1470,24 +1463,22 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
foreach ($pluginman->resolve_requirements($plugin, $version) as $reqname => $reqinfo) {
|
||||
if ($reqname === 'core') {
|
||||
if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_OK) {
|
||||
$class = 'requires-ok text-muted';
|
||||
$class = 'requires-ok';
|
||||
$label = '';
|
||||
} else {
|
||||
$class = 'requires-failed';
|
||||
$label = html_writer::span(get_string('dependencyfails', 'core_plugin'), 'badge badge-danger');
|
||||
}
|
||||
if ($reqinfo->reqver != ANY_VERSION) {
|
||||
$requires[] = html_writer::tag('li',
|
||||
html_writer::span(get_string('moodleversion', 'core_plugin', $plugin->versionrequires), 'dep dep-core').
|
||||
' '.$label, array('class' => $class));
|
||||
}
|
||||
$requires[] = html_writer::tag('li',
|
||||
html_writer::span(get_string('moodleversion', 'core_plugin', $plugin->versionrequires), 'dep dep-core').
|
||||
' '.$label, array('class' => $class));
|
||||
|
||||
} else {
|
||||
$actions = array();
|
||||
|
||||
if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_OK) {
|
||||
$label = '';
|
||||
$class = 'requires-ok text-muted';
|
||||
$class = 'requires-ok';
|
||||
|
||||
} else if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_MISSING) {
|
||||
if ($reqinfo->availability == $pluginman::REQUIREMENT_AVAILABLE) {
|
||||
@@ -1541,14 +1532,13 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
return '';
|
||||
}
|
||||
|
||||
$out = html_writer::tag('ul', implode("\n", $requires), array('class' => 'm-0'));
|
||||
$out = html_writer::tag('ul', implode("\n", $requires));
|
||||
|
||||
if ($displayuploadlink) {
|
||||
$out .= html_writer::div(
|
||||
html_writer::link(
|
||||
new moodle_url('/admin/tool/installaddon/'),
|
||||
get_string('dependencyuploadmissing', 'core_plugin'),
|
||||
array('class' => 'btn btn-secondary btn-sm m-1')
|
||||
get_string('dependencyuploadmissing', 'core_plugin')
|
||||
),
|
||||
'dependencyuploadmissing'
|
||||
);
|
||||
@@ -1558,8 +1548,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$out .= html_writer::div(
|
||||
html_writer::link(
|
||||
new moodle_url($this->page->url, array('sesskey' => sesskey(), 'fetchupdates' => 1)),
|
||||
get_string('checkforupdates', 'core_plugin'),
|
||||
array('class' => 'btn btn-secondary btn-sm m-1')
|
||||
get_string('checkforupdates', 'core_plugin')
|
||||
),
|
||||
'checkforupdates'
|
||||
);
|
||||
@@ -2020,7 +2009,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
if (empty($CFG->docroot) or $environment_result->plugin) {
|
||||
$report = get_string($stringtouse, 'admin', $rec);
|
||||
} else {
|
||||
$report = $this->doc_link(join('/', $linkparts), get_string($stringtouse, 'admin', $rec), true);
|
||||
$report = $this->doc_link(join($linkparts, '/'), get_string($stringtouse, 'admin', $rec), true);
|
||||
}
|
||||
// Enclose report text in div so feedback text will be displayed underneath it.
|
||||
$report = html_writer::div($report);
|
||||
@@ -2121,27 +2110,6 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
* @return string
|
||||
*/
|
||||
public function moodleorg_registration_message() {
|
||||
|
||||
$out = format_text(get_string('registerwithmoodleorginfo', 'core_hub'), FORMAT_MARKDOWN);
|
||||
|
||||
$out .= html_writer::link(
|
||||
new moodle_url('/admin/settings.php', ['section' => 'moodleservices']),
|
||||
$this->output->pix_icon('i/info', '').' '.get_string('registerwithmoodleorginfoapp', 'core_hub'),
|
||||
['class' => 'btn btn-link', 'role' => 'opener', 'target' => '_href']
|
||||
);
|
||||
|
||||
$out .= html_writer::link(
|
||||
HUB_MOODLEORGHUBURL,
|
||||
$this->output->pix_icon('i/stats', '').' '.get_string('registerwithmoodleorginfostats', 'core_hub'),
|
||||
['class' => 'btn btn-link', 'role' => 'opener', 'target' => '_href']
|
||||
);
|
||||
|
||||
$out .= html_writer::link(
|
||||
HUB_MOODLEORGHUBURL.'/sites',
|
||||
$this->output->pix_icon('i/location', '').' '.get_string('registerwithmoodleorginfosites', 'core_hub'),
|
||||
['class' => 'btn btn-link', 'role' => 'opener', 'target' => '_href']
|
||||
);
|
||||
|
||||
return $this->output->box($out);
|
||||
return format_text(get_string('registermoodlenet', 'admin'), FORMAT_HTML, ['noclean' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,13 +123,13 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
}
|
||||
$instanceoptionnames = repository::static_function($repository, 'get_instance_option_names');
|
||||
if (!empty($instanceoptionnames)) {
|
||||
if (property_exists($fromform, 'enablecourseinstances')) {
|
||||
if (array_key_exists('enablecourseinstances', $fromform)) {
|
||||
$settings['enablecourseinstances'] = $fromform->enablecourseinstances;
|
||||
}
|
||||
else {
|
||||
$settings['enablecourseinstances'] = 0;
|
||||
}
|
||||
if (property_exists($fromform, 'enableuserinstances')) {
|
||||
if (array_key_exists('enableuserinstances', $fromform)) {
|
||||
$settings['enableuserinstances'] = $fromform->enableuserinstances;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -36,12 +36,15 @@ if (!is_siteadmin()) {
|
||||
}
|
||||
|
||||
$admisselector = new core_role_admins_existing_selector();
|
||||
$admisselector->set_extra_fields(array('username', 'email'));
|
||||
|
||||
$potentialadmisselector = new core_role_admins_potential_selector();
|
||||
$potentialadmisselector->set_extra_fields(array('username', 'email'));
|
||||
|
||||
if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
|
||||
if ($userstoadd = $potentialadmisselector->get_selected_users()) {
|
||||
$user = reset($userstoadd);
|
||||
$username = $potentialadmisselector->output_user($user);
|
||||
$username = fullname($user) . " ($user->username, $user->email)";
|
||||
echo $OUTPUT->header();
|
||||
$yesurl = new moodle_url('/admin/roles/admins.php', array('confirmadd'=>$user->id, 'sesskey'=>sesskey()));
|
||||
echo $OUTPUT->confirm(get_string('confirmaddadmin', 'core_role', $username), $yesurl, $PAGE->url);
|
||||
@@ -55,7 +58,7 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
|
||||
if ($USER->id == $user->id) {
|
||||
// Can not remove self.
|
||||
} else {
|
||||
$username = $admisselector->output_user($user);
|
||||
$username = fullname($user) . " ($user->username, $user->email)";
|
||||
echo $OUTPUT->header();
|
||||
$yesurl = new moodle_url('/admin/roles/admins.php', array('confirmdel'=>$user->id, 'sesskey'=>sesskey()));
|
||||
echo $OUTPUT->confirm(get_string('confirmdeladmin', 'core_role', $username), $yesurl, $PAGE->url);
|
||||
|
||||
@@ -46,6 +46,25 @@ $controller = new $classformode[$mode]();
|
||||
|
||||
if (optional_param('submit', false, PARAM_BOOL) && data_submitted() && confirm_sesskey()) {
|
||||
$controller->process_submission();
|
||||
$event = null;
|
||||
// Create event depending on mode.
|
||||
switch ($mode) {
|
||||
case 'assign':
|
||||
$event = \core\event\role_allow_assign_updated::create(array('context' => $syscontext));
|
||||
break;
|
||||
case 'override':
|
||||
$event = \core\event\role_allow_override_updated::create(array('context' => $syscontext));
|
||||
break;
|
||||
case 'switch':
|
||||
$event = \core\event\role_allow_switch_updated::create(array('context' => $syscontext));
|
||||
break;
|
||||
case 'view':
|
||||
$event = \core\event\role_allow_view_updated::create(array('context' => $syscontext));
|
||||
break;
|
||||
}
|
||||
if ($event) {
|
||||
$event->trigger();
|
||||
}
|
||||
redirect($baseurl);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,4 @@ class core_role_allow_assign_page extends core_role_allow_role_page {
|
||||
public function get_intro_text() {
|
||||
return get_string('configallowassign', 'core_admin');
|
||||
}
|
||||
|
||||
protected function get_eventclass() {
|
||||
return \core\event\role_allow_assign_updated::class;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,4 @@ class core_role_allow_override_page extends core_role_allow_role_page {
|
||||
public function get_intro_text() {
|
||||
return get_string('configallowoverride2', 'core_admin');
|
||||
}
|
||||
|
||||
protected function get_eventclass() {
|
||||
return \core\event\role_allow_override_updated::class;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,36 +59,12 @@ abstract class core_role_allow_role_page {
|
||||
*/
|
||||
public function process_submission() {
|
||||
global $DB;
|
||||
|
||||
$context = context_system::instance();
|
||||
$this->load_current_settings();
|
||||
|
||||
// Delete all records, then add back the ones that should be allowed.
|
||||
$DB->delete_records($this->tablename);
|
||||
foreach ($this->roles as $fromroleid => $notused) {
|
||||
foreach ($this->roles as $targetroleid => $alsonotused) {
|
||||
$isallowed = $this->allowed[$fromroleid][$targetroleid];
|
||||
if (optional_param('s_' . $fromroleid . '_' . $targetroleid, false, PARAM_BOOL)) {
|
||||
$this->set_allow($fromroleid, $targetroleid);
|
||||
// Only trigger events if this role allow relationship did not exist and the checkbox element
|
||||
// has been submitted.
|
||||
if (!$isallowed) {
|
||||
$eventclass = $this->get_eventclass();
|
||||
$eventclass::create([
|
||||
'context' => $context,
|
||||
'objectid' => $fromroleid,
|
||||
'other' => ['targetroleid' => $targetroleid, 'allow' => true]
|
||||
])->trigger();
|
||||
}
|
||||
} else if ($isallowed) {
|
||||
// When the user has deselect an existing role allow checkbox but it is in the list of roles
|
||||
// allowances.
|
||||
$eventclass = $this->get_eventclass();
|
||||
$eventclass::create([
|
||||
'context' => $context,
|
||||
'objectid' => $fromroleid,
|
||||
'other' => ['targetroleid' => $targetroleid, 'allow' => false]
|
||||
])->trigger();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,10 +161,4 @@ abstract class core_role_allow_role_page {
|
||||
* @return string
|
||||
*/
|
||||
public abstract function get_intro_text();
|
||||
|
||||
/**
|
||||
* Returns the allow class respective event class name.
|
||||
* @return string
|
||||
*/
|
||||
protected abstract function get_eventclass();
|
||||
}
|
||||
|
||||
@@ -58,8 +58,4 @@ class core_role_allow_switch_page extends core_role_allow_role_page {
|
||||
public function get_intro_text() {
|
||||
return get_string('configallowswitch', 'core_admin');
|
||||
}
|
||||
|
||||
protected function get_eventclass() {
|
||||
return \core\event\role_allow_switch_updated::class;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,8 +74,4 @@ class core_role_allow_view_page extends core_role_allow_role_page {
|
||||
public function get_intro_text() {
|
||||
return get_string('configallowview', 'core_admin');
|
||||
}
|
||||
|
||||
protected function get_eventclass() {
|
||||
return \core\event\role_allow_view_updated::class;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,19 +157,19 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
// Allowed roles.
|
||||
$allow = optional_param_array('allowassign', null, PARAM_INT);
|
||||
if (!is_null($allow)) {
|
||||
$this->allowassign = array_filter($allow);
|
||||
$this->allowassign = $allow;
|
||||
}
|
||||
$allow = optional_param_array('allowoverride', null, PARAM_INT);
|
||||
if (!is_null($allow)) {
|
||||
$this->allowoverride = array_filter($allow);
|
||||
$this->allowoverride = $allow;
|
||||
}
|
||||
$allow = optional_param_array('allowswitch', null, PARAM_INT);
|
||||
if (!is_null($allow)) {
|
||||
$this->allowswitch = array_filter($allow);
|
||||
$this->allowswitch = $allow;
|
||||
}
|
||||
$allow = optional_param_array('allowview', null, PARAM_INT);
|
||||
if (!is_null($allow)) {
|
||||
$this->allowview = array_filter($allow);
|
||||
$this->allowview = $allow;
|
||||
}
|
||||
|
||||
// Now read the permissions for each capability.
|
||||
@@ -434,7 +434,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
}
|
||||
|
||||
public function save_changes() {
|
||||
global $DB, $USER;
|
||||
global $DB;
|
||||
|
||||
if (!$this->roleid) {
|
||||
// Creating role.
|
||||
@@ -444,20 +444,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
// Updating role.
|
||||
$DB->update_record('role', $this->role);
|
||||
|
||||
// Trigger role updated event.
|
||||
\core\event\role_updated::create([
|
||||
'userid' => $USER->id,
|
||||
'objectid' => $this->role->id,
|
||||
'context' => $this->context,
|
||||
'other' => [
|
||||
'name' => $this->role->name,
|
||||
'shortname' => $this->role->shortname,
|
||||
'description' => $this->role->description,
|
||||
'archetype' => $this->role->archetype,
|
||||
'contextlevels' => $this->contextlevels
|
||||
]
|
||||
])->trigger();
|
||||
|
||||
// This will ensure the course contacts cache is purged so name changes get updated in
|
||||
// the UI. It would be better to do this only when we know that fields affected are
|
||||
// updated. But thats getting into the weeds of the coursecat cache and role edits
|
||||
@@ -487,17 +473,10 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
$addfunction = "core_role_set_{$type}_allowed";
|
||||
$deltable = 'role_allow_'.$type;
|
||||
$field = 'allow'.$type;
|
||||
$eventclass = "\\core\\event\\role_allow_" . $type . "_updated";
|
||||
$context = context_system::instance();
|
||||
|
||||
foreach ($current as $roleid) {
|
||||
if (!in_array($roleid, $wanted)) {
|
||||
$DB->delete_records($deltable, array('roleid'=>$this->roleid, $field=>$roleid));
|
||||
$eventclass::create([
|
||||
'context' => $context,
|
||||
'objectid' => $this->roleid,
|
||||
'other' => ['targetroleid' => $roleid, 'allow' => false]
|
||||
])->trigger();
|
||||
continue;
|
||||
}
|
||||
$key = array_search($roleid, $wanted);
|
||||
@@ -509,14 +488,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
$roleid = $this->roleid;
|
||||
}
|
||||
$addfunction($this->roleid, $roleid);
|
||||
|
||||
if (in_array($roleid, $wanted)) {
|
||||
$eventclass::create([
|
||||
'context' => $context,
|
||||
'objectid' => $this->roleid,
|
||||
'other' => ['targetroleid' => $roleid, 'allow' => true]
|
||||
])->trigger();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,9 +589,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
if ($this->roleid == 0) {
|
||||
$options[-1] = get_string('thisnewrole', 'core_role');
|
||||
}
|
||||
return
|
||||
html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'allow'.$type.'[]', 'value' => "")) .
|
||||
html_writer::select($options, 'allow'.$type.'[]', $selected, false, array('multiple' => 'multiple',
|
||||
return html_writer::select($options, 'allow'.$type.'[]', $selected, false, array('multiple' => 'multiple',
|
||||
'size' => 10, 'class' => 'form-control'));
|
||||
}
|
||||
|
||||
@@ -654,7 +623,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
echo "</label>\n";
|
||||
}
|
||||
if ($helpicon) {
|
||||
echo '<span class="float-sm-right text-nowrap">'.$helpicon.'</span>';
|
||||
echo '<span class="pull-xs-right text-nowrap">'.$helpicon.'</span>';
|
||||
}
|
||||
echo '</div>';
|
||||
if (isset($this->errors[$name])) {
|
||||
|
||||
+14
-3
@@ -52,12 +52,10 @@ if ($return === 'manage') {
|
||||
$returnurl = new moodle_url('/admin/roles/define.php', array('action'=>'view', 'roleid'=>$roleid));;
|
||||
}
|
||||
|
||||
admin_externalpage_setup('defineroles', '', array('action' => $action, 'roleid' => $roleid),
|
||||
new moodle_url('/admin/roles/define.php'));
|
||||
|
||||
// Check access permissions.
|
||||
$systemcontext = context_system::instance();
|
||||
require_capability('moodle/role:manage', $systemcontext);
|
||||
admin_externalpage_setup('defineroles', '', array('action' => $action, 'roleid' => $roleid), new moodle_url('/admin/roles/define.php'));
|
||||
|
||||
// Export role.
|
||||
if ($action === 'export') {
|
||||
@@ -200,6 +198,19 @@ if (optional_param('cancel', false, PARAM_BOOL)) {
|
||||
if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey() && $definitiontable->is_submission_valid()) {
|
||||
$definitiontable->save_changes();
|
||||
$tableroleid = $definitiontable->get_role_id();
|
||||
// Trigger event.
|
||||
$event = \core\event\role_capabilities_updated::create(
|
||||
array(
|
||||
'context' => $systemcontext,
|
||||
'objectid' => $tableroleid
|
||||
)
|
||||
);
|
||||
$event->set_legacy_logdata(array(SITEID, 'role', $action, 'admin/roles/define.php?action=view&roleid=' . $tableroleid,
|
||||
$definitiontable->get_role_name(), '', $USER->id));
|
||||
if (!empty($role)) {
|
||||
$event->add_record_snapshot('role', $role);
|
||||
}
|
||||
$event->trigger();
|
||||
|
||||
if ($action === 'add') {
|
||||
redirect(new moodle_url('/admin/roles/define.php', array('action'=>'view', 'roleid'=>$definitiontable->get_role_id())));
|
||||
|
||||
@@ -46,11 +46,10 @@ if ($action) {
|
||||
$baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/roles/manage.php';
|
||||
$defineurl = $CFG->wwwroot . '/' . $CFG->admin . '/roles/define.php';
|
||||
|
||||
admin_externalpage_setup('defineroles');
|
||||
|
||||
// Check access permissions.
|
||||
$systemcontext = context_system::instance();
|
||||
require_capability('moodle/role:manage', $systemcontext);
|
||||
admin_externalpage_setup('defineroles');
|
||||
|
||||
// Get some basic data we are going to need.
|
||||
$roles = role_fix_names(get_all_roles(), $systemcontext, ROLENAME_ORIGINAL);
|
||||
|
||||
@@ -134,6 +134,22 @@ $overridestable->read_submitted_permissions();
|
||||
if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
$overridestable->save_changes();
|
||||
$rolename = $overridableroles[$roleid];
|
||||
// Trigger event.
|
||||
$event = \core\event\role_capabilities_updated::create(
|
||||
array(
|
||||
'context' => $context,
|
||||
'objectid' => $roleid,
|
||||
)
|
||||
);
|
||||
|
||||
$event->set_legacy_logdata(
|
||||
array(
|
||||
$course->id, 'role', 'override', 'admin/roles/override.php?contextid=' . $context->id . '&roleid=' . $roleid,
|
||||
$rolename, '', $USER->id
|
||||
)
|
||||
);
|
||||
$event->add_record_snapshot('role', $role);
|
||||
$event->trigger();
|
||||
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ $PAGE->set_pagelayout('admin');
|
||||
|
||||
// Check login and permissions.
|
||||
if ($course->id == SITEID) {
|
||||
require_login(null, false);
|
||||
require_login();
|
||||
$PAGE->set_context($usercontext);
|
||||
} else {
|
||||
require_login($course);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
if ($hassiteconfig && \core_analytics\manager::is_analytics_enabled()) {
|
||||
if ($hassiteconfig) {
|
||||
|
||||
$settings = new admin_settingpage('analyticssite', new lang_string('analyticssiteinfo', 'analytics'));
|
||||
$ADMIN->add('analytics', $settings);
|
||||
|
||||
@@ -76,24 +76,6 @@ preferences,moodle|/user/preferences.php|t/preferences',
|
||||
|
||||
$ADMIN->add('appearance', $temp);
|
||||
|
||||
// Course colours section.
|
||||
$temp = new admin_settingpage('coursecolors', new lang_string('coursecolorsettings', 'admin'));
|
||||
$temp->add(new admin_setting_heading('coursecolorheading', '',
|
||||
new lang_string('coursecolorheading_desc', 'admin')));
|
||||
|
||||
$basecolors = ['#81ecec', '#74b9ff', '#a29bfe', '#dfe6e9', '#00b894',
|
||||
'#0984e3', '#b2bec3', '#fdcb6e', '#fd79a8', '#6c5ce7'];
|
||||
|
||||
foreach ($basecolors as $key => $color) {
|
||||
$number = $key + 1;
|
||||
$name = 'core_admin/coursecolor' . $number;
|
||||
$title = get_string('coursecolor', 'admin', $number);
|
||||
$setting = new admin_setting_configcolourpicker($name, $title, '', $color);
|
||||
$temp->add($setting);
|
||||
}
|
||||
|
||||
$ADMIN->add('appearance', $temp);
|
||||
|
||||
// Calendar settings.
|
||||
$temp = new admin_settingpage('calendar', new lang_string('calendarsettings','admin'));
|
||||
|
||||
@@ -197,10 +179,6 @@ preferences,moodle|/user/preferences.php|t/preferences',
|
||||
'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_configcheckbox('navsortmycourseshiddenlast',
|
||||
new lang_string('navsortmycourseshiddenlast', 'admin'),
|
||||
new lang_string('navsortmycourseshiddenlast_help', 'admin'),
|
||||
1));
|
||||
$temp->add(new admin_setting_configtext('navcourselimit', new lang_string('navcourselimit', 'admin'),
|
||||
new lang_string('confignavcourselimit', 'admin'), 10, PARAM_INT));
|
||||
$temp->add(new admin_setting_configcheckbox('usesitenameforsitepages', new lang_string('usesitenameforsitepages', 'admin'), new lang_string('configusesitenameforsitepages', 'admin'), 0));
|
||||
@@ -279,10 +257,4 @@ preferences,moodle|/user/preferences.php|t/preferences',
|
||||
$temp->add(new admin_setting_configtextarea('additionalhtmlfooter', new lang_string('additionalhtmlfooter', 'admin'), new lang_string('additionalhtmlfooter_desc', 'admin'), '', PARAM_RAW));
|
||||
$ADMIN->add('appearance', $temp);
|
||||
|
||||
$setting = new admin_setting_configcheckbox('cachetemplates', new lang_string('cachetemplates', 'admin'),
|
||||
new lang_string('cachetemplates_help', 'admin'), 1);
|
||||
$setting->set_updatedcallback('template_reset_all_caches');
|
||||
$temp = new admin_settingpage('templates', new lang_string('templates', 'admin'));
|
||||
$temp->add($setting);
|
||||
$ADMIN->add('appearance', $temp);
|
||||
} // end of speedup
|
||||
|
||||
@@ -105,6 +105,13 @@ if (($hassiteconfig || has_any_capability(array(
|
||||
new lang_string('sitebackpack_help', 'badges'),
|
||||
1, $choices));
|
||||
|
||||
$warning = badges_verify_site_backpack();
|
||||
if (!empty($warning)) {
|
||||
$backpacksettings->add(new admin_setting_description('badges_site_backpack_verify',
|
||||
new lang_string('sitebackpackverify', 'badges'),
|
||||
$warning));
|
||||
}
|
||||
|
||||
$ADMIN->add('badges', $backpacksettings);
|
||||
|
||||
$ADMIN->add('badges',
|
||||
|
||||
@@ -163,15 +163,9 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
|
||||
// "courserequests" settingpage.
|
||||
$temp = new admin_settingpage('courserequest', new lang_string('courserequest'));
|
||||
$temp->add(new admin_setting_configcheckbox('enablecourserequests',
|
||||
new lang_string('enablecourserequests', 'admin'),
|
||||
new lang_string('configenablecourserequests', 'admin'), 1));
|
||||
$temp->add(new admin_settings_coursecat_select('defaultrequestcategory',
|
||||
new lang_string('defaultrequestcategory', 'admin'),
|
||||
new lang_string('configdefaultrequestcategory', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('lockrequestcategory',
|
||||
new lang_string('lockrequestcategory', 'admin'),
|
||||
new lang_string('configlockrequestcategory', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('enablecourserequests', new lang_string('enablecourserequests', 'admin'), new lang_string('configenablecourserequests', 'admin'), 0));
|
||||
$temp->add(new admin_settings_coursecat_select('defaultrequestcategory', new lang_string('defaultrequestcategory', 'admin'), new lang_string('configdefaultrequestcategory', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('requestcategoryselection', new lang_string('requestcategoryselection', 'admin'), new lang_string('configrequestcategoryselection', 'admin'), 0));
|
||||
$temp->add(new admin_setting_users_with_capability('courserequestnotify', new lang_string('courserequestnotify', 'admin'), new lang_string('configcourserequestnotify2', 'admin'), array(), 'moodle/site:approvecourse'));
|
||||
$ADMIN->add('courses', $temp);
|
||||
|
||||
@@ -212,11 +206,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_role_assignments', new lang_string('generalroleassignments','backup'), new lang_string('configgeneralroleassignments','backup'), array('value'=>1, 'locked'=>0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_activities', new lang_string('generalactivities','backup'), new lang_string('configgeneralactivities','backup'), array('value'=>1, 'locked'=>0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_blocks', new lang_string('generalblocks','backup'), new lang_string('configgeneralblocks','backup'), array('value'=>1, 'locked'=>0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock(
|
||||
'backup/backup_general_files',
|
||||
new lang_string('generalfiles', 'backup'),
|
||||
new lang_string('configgeneralfiles', 'backup'),
|
||||
array('value' => '1', 'locked' => 0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_filters', new lang_string('generalfilters','backup'), new lang_string('configgeneralfilters','backup'), array('value'=>1, 'locked'=>0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_comments', new lang_string('generalcomments','backup'), new lang_string('configgeneralcomments','backup'), array('value'=>1, 'locked'=>0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_badges', new lang_string('generalbadges','backup'), new lang_string('configgeneralbadges','backup'), array('value'=>1,'locked'=>0)));
|
||||
@@ -352,10 +341,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_role_assignments', new lang_string('generalroleassignments','backup'), new lang_string('configgeneralroleassignments','backup'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_activities', new lang_string('generalactivities','backup'), new lang_string('configgeneralactivities','backup'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_blocks', new lang_string('generalblocks','backup'), new lang_string('configgeneralblocks','backup'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox(
|
||||
'backup/backup_auto_files',
|
||||
new lang_string('generalfiles', 'backup'),
|
||||
new lang_string('configgeneralfiles', 'backup'), '1'));
|
||||
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_filters', new lang_string('generalfilters','backup'), new lang_string('configgeneralfilters','backup'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_comments', new lang_string('generalcomments','backup'), new lang_string('configgeneralcomments','backup'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_badges', new lang_string('generalbadges','backup'), new lang_string('configgeneralbadges','backup'), 1));
|
||||
|
||||
@@ -29,17 +29,13 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$temp->add(new admin_setting_configcheckbox('forceclean', new lang_string('forceclean', 'core_admin'),
|
||||
new lang_string('forceclean_desc', 'core_admin'), 0));
|
||||
|
||||
// Relative course dates mode setting.
|
||||
$temp->add(new admin_setting_configcheckbox('enablecourserelativedates',
|
||||
new lang_string('enablecourserelativedates', 'core_admin'),
|
||||
new lang_string('enablecourserelativedates_desc', 'core_admin'), 0));
|
||||
|
||||
$ADMIN->add('experimental', $temp);
|
||||
|
||||
// "debugging" settingpage
|
||||
$temp = new admin_settingpage('debugging', new lang_string('debugging', 'admin'));
|
||||
$temp->add(new admin_setting_special_debug());
|
||||
$temp->add(new admin_setting_configcheckbox('debugdisplay', new lang_string('debugdisplay', 'admin'), new lang_string('configdebugdisplay', 'admin'), ini_get_bool('display_errors')));
|
||||
$temp->add(new admin_setting_configcheckbox('debugsmtp', new lang_string('debugsmtp', 'admin'), new lang_string('configdebugsmtp', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('perfdebug', new lang_string('perfdebug', 'admin'), new lang_string('configperfdebug', 'admin'), '7', '15', '7'));
|
||||
$temp->add(new admin_setting_configcheckbox('debugstringids', new lang_string('debugstringids', 'admin'), new lang_string('debugstringids_desc', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('debugvalidators', new lang_string('debugvalidators', 'admin'), new lang_string('configdebugvalidators', 'admin'), 0));
|
||||
|
||||
@@ -58,7 +58,7 @@ if (!during_initial_install()) { //do not use during installation
|
||||
foreach ($roles as $role) {
|
||||
if (empty($role->archetype) or $role->archetype === 'guest' or $role->archetype === 'frontpage' or $role->archetype === 'student') {
|
||||
$options[$role->id] = $role->localname;
|
||||
if ($role->archetype === 'frontpage' && !$defaultfrontpageroleid) {
|
||||
if ($role->archetype === 'frontpage') {
|
||||
$defaultfrontpageroleid = $role->id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* H5P settings link.
|
||||
*
|
||||
* @package core_h5p
|
||||
* @copyright 2019 Amaia Anabitarte <amaia@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
// Settings page.
|
||||
$ADMIN->add('h5p', new admin_externalpage('h5psettings', get_string('h5pmanage', 'core_h5p'),
|
||||
new moodle_url('/h5p/libraries.php'), ['moodle/site:config', 'moodle/h5p:updatelibraries']));
|
||||
@@ -175,13 +175,6 @@ if ($hassiteconfig) {
|
||||
$plugin->load_settings($ADMIN, 'antivirussettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
// Machine learning backend plugins.
|
||||
$ADMIN->add('modules', new admin_category('mlbackendsettings', new lang_string('mlbackendsettings', 'admin')));
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('mlbackend');
|
||||
foreach ($plugins as $plugin) {
|
||||
$plugin->load_settings($ADMIN, 'mlbackendsettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
/// License types
|
||||
$ADMIN->add('modules', new admin_category('licensesettings', new lang_string('licenses')));
|
||||
$temp = new admin_settingpage('managelicenses', new lang_string('managelicenses', 'admin'));
|
||||
|
||||
@@ -1,29 +1,4 @@
|
||||
<?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 security related settings links for security category to admin tree.
|
||||
*
|
||||
* @copyright 1999 Martin Dougiamas http://dougiamas.com
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_admin\local\settings\filesize;
|
||||
|
||||
if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
|
||||
@@ -42,7 +17,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$temp->add(new admin_setting_configcheckbox('forcelogin', new lang_string('forcelogin', 'admin'), new lang_string('configforcelogin', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('forceloginforprofiles', new lang_string('forceloginforprofiles', 'admin'), new lang_string('configforceloginforprofiles', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('forceloginforprofileimage', new lang_string('forceloginforprofileimage', 'admin'), new lang_string('forceloginforprofileimage_help', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('opentowebcrawlers', new lang_string('opentowebcrawlers', 'admin'), new lang_string('configopentowebcrawlers', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('opentogoogle', new lang_string('opentogoogle', 'admin'), new lang_string('configopentogoogle', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configselect('allowindexing', new lang_string('allowindexing', 'admin'), new lang_string('allowindexing_desc', 'admin'),
|
||||
0,
|
||||
array(0 => new lang_string('allowindexingexceptlogin', 'admin'),
|
||||
@@ -61,9 +36,12 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
// maxbytes set to 0 will allow the maximum server limit for uploads
|
||||
$temp->add(new admin_setting_configselect('maxbytes', new lang_string('maxbytes', 'admin'), new lang_string('configmaxbytes', 'admin'), 0, $max_upload_choices));
|
||||
// 100MB
|
||||
$defaultuserquota = 100 * filesize::UNIT_MB;
|
||||
$temp->add(new filesize('userquota', new lang_string('userquota', 'admin'),
|
||||
new lang_string('userquota_desc', 'admin'), $defaultuserquota));
|
||||
$defaultuserquota = 104857600;
|
||||
$params = new stdClass();
|
||||
$params->bytes = $defaultuserquota;
|
||||
$params->displaysize = display_size($defaultuserquota);
|
||||
$temp->add(new admin_setting_configtext('userquota', new lang_string('userquota', 'admin'),
|
||||
new lang_string('configuserquota', 'admin', $params), $defaultuserquota, PARAM_INT, 30));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('allowobjectembed', new lang_string('allowobjectembed', 'admin'), new lang_string('configallowobjectembed', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('enabletrusttext', new lang_string('enabletrusttext', 'admin'), new lang_string('configenabletrusttext', 'admin'), 0));
|
||||
|
||||
@@ -97,10 +97,7 @@ $options = array(
|
||||
GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR => 'HTTP_CLIENT, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR|GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'REMOTE_ADDR');
|
||||
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'),
|
||||
new lang_string('configgetremoteaddrconf', 'admin'),
|
||||
GETREMOTEADDR_SKIP_DEFAULT, $options));
|
||||
$temp->add(new admin_setting_configtext('reverseproxyignore', new lang_string('reverseproxyignore', 'admin'), new lang_string('configreverseproxyignore', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'), new lang_string('configgetremoteaddrconf', 'admin'), 0, $options));
|
||||
|
||||
$temp->add(new admin_setting_heading('webproxy', new lang_string('webproxy', 'admin'), new lang_string('webproxyinfo', 'admin')));
|
||||
$temp->add(new admin_setting_configtext('proxyhost', new lang_string('proxyhost', 'admin'), new lang_string('configproxyhost', 'admin'), '', PARAM_HOST));
|
||||
@@ -175,10 +172,7 @@ $temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_stri
|
||||
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp->add(new admin_setting_configduration('filescleanupperiod',
|
||||
new lang_string('filescleanupperiod', 'admin'),
|
||||
new lang_string('filescleanupperiod_help', 'admin'),
|
||||
86400));
|
||||
|
||||
|
||||
$ADMIN->add('server', new admin_externalpage('environment', new lang_string('environment','admin'), "$CFG->wwwroot/$CFG->admin/environment.php"));
|
||||
$ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo'), "$CFG->wwwroot/$CFG->admin/phpinfo.php"));
|
||||
@@ -274,14 +268,6 @@ $temp->add(
|
||||
]
|
||||
)
|
||||
);
|
||||
$temp->add(
|
||||
new admin_setting_configcheckbox(
|
||||
'task_logtostdout',
|
||||
new lang_string('task_logtostdout', 'admin'),
|
||||
new lang_string('task_logtostdout_desc', 'admin'),
|
||||
1
|
||||
)
|
||||
);
|
||||
|
||||
if (\core\task\logmanager::uses_standard_settings()) {
|
||||
$temp->add(
|
||||
|
||||
@@ -49,29 +49,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$optionalsubsystems->add(new admin_setting_configcheckbox('allowstealth', new lang_string('allowstealthmodules'),
|
||||
new lang_string('allowstealthmodules_help'), 0, 1, 0));
|
||||
|
||||
$optionalsubsystems->add(new admin_setting_configcheckbox('enableanalytics', new lang_string('enableanalytics', 'admin'),
|
||||
new lang_string('configenableanalytics', 'admin'), 1, 1, 0));
|
||||
|
||||
$fullunicodesupport = true;
|
||||
if ($DB->get_dbfamily() == 'mysql') {
|
||||
$collation = $DB->get_dbcollation();
|
||||
$collationinfo = explode('_', $collation);
|
||||
$charset = reset($collationinfo);
|
||||
$fullunicodesupport = $charset === 'utf8mb4';
|
||||
}
|
||||
|
||||
if ($fullunicodesupport) {
|
||||
$optionalsubsystems->add(new admin_setting_configcheckbox(
|
||||
'allowemojipicker',
|
||||
new lang_string('allowemojipicker', 'admin'),
|
||||
new lang_string('configallowemojipicker', 'admin'),
|
||||
1
|
||||
));
|
||||
} else {
|
||||
$optionalsubsystems->add(new admin_setting_description(
|
||||
'allowemojipicker',
|
||||
new lang_string('allowemojipicker', 'admin'),
|
||||
new lang_string('configallowemojipickerincompatible', 'admin')
|
||||
));
|
||||
}
|
||||
$optionalsubsystems->add(new admin_setting_configcheckbox('enablecoursepublishing',
|
||||
new lang_string('enablecoursepublishing', 'hub'), new lang_string('enablecoursepublishing_help', 'hub'), 0));
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ $ADMIN->add('root', new admin_category('grades', new lang_string('grades')));
|
||||
$ADMIN->add('root', new admin_category('analytics', new lang_string('analytics', 'analytics')));
|
||||
$ADMIN->add('root', new admin_category('competencies', new lang_string('competencies', 'core_competency')));
|
||||
$ADMIN->add('root', new admin_category('badges', new lang_string('badges'), empty($CFG->enablebadges)));
|
||||
$ADMIN->add('root', new admin_category('h5p', new lang_string('h5p', 'core_h5p')));
|
||||
$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('messaging', new lang_string('messagingcategory', 'admin')));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
// This file defines settingpages and externalpages under the "users" category.
|
||||
// This file defines settingpages and externalpages under the "users" category
|
||||
|
||||
$ADMIN->add('users', new admin_category('accounts', new lang_string('accounts', 'admin')));
|
||||
$ADMIN->add('users', new admin_category('roles', new lang_string('permissions', 'role')));
|
||||
@@ -13,47 +13,15 @@ if ($hassiteconfig
|
||||
or has_capability('moodle/role:manage', $systemcontext)
|
||||
or has_capability('moodle/role:assign', $systemcontext)
|
||||
or has_capability('moodle/cohort:manage', $systemcontext)
|
||||
or has_capability('moodle/cohort:view', $systemcontext)) { // Speedup for non-admins, add all caps used on this page.
|
||||
or has_capability('moodle/cohort:view', $systemcontext)) { // speedup for non-admins, add all caps used on this page
|
||||
|
||||
|
||||
// Stuff under the "accounts" subcategory.
|
||||
// stuff under the "accounts" subcategory
|
||||
$ADMIN->add('accounts', new admin_externalpage('editusers', new lang_string('userlist','admin'), "$CFG->wwwroot/$CFG->admin/user.php", array('moodle/user:update', 'moodle/user:delete')));
|
||||
$ADMIN->add('accounts', new admin_externalpage('userbulk', new lang_string('userbulk','admin'), "$CFG->wwwroot/$CFG->admin/user/user_bulk.php", array('moodle/user:update', 'moodle/user:delete')));
|
||||
$ADMIN->add('accounts', new admin_externalpage('addnewuser', new lang_string('addnewuser'), "$CFG->wwwroot/user/editadvanced.php?id=-1", 'moodle/user:create'));
|
||||
|
||||
// User management settingpage.
|
||||
$temp = new admin_settingpage('usermanagement', new lang_string('usermanagement', 'admin'));
|
||||
if ($ADMIN->fulltree) {
|
||||
$choices = array();
|
||||
$choices['realname'] = new lang_string('fullnameuser');
|
||||
$choices['lastname'] = new lang_string('lastname');
|
||||
$choices['firstname'] = new lang_string('firstname');
|
||||
$choices['username'] = new lang_string('username');
|
||||
$choices['email'] = new lang_string('email');
|
||||
$choices['city'] = new lang_string('city');
|
||||
$choices['country'] = new lang_string('country');
|
||||
$choices['confirmed'] = new lang_string('confirmed', 'admin');
|
||||
$choices['suspended'] = new lang_string('suspended', 'auth');
|
||||
$choices['profile'] = new lang_string('profilefields', 'admin');
|
||||
$choices['courserole'] = new lang_string('courserole', 'filters');
|
||||
$choices['anycourses'] = new lang_string('anycourses', 'filters');
|
||||
$choices['systemrole'] = new lang_string('globalrole', 'role');
|
||||
$choices['cohort'] = new lang_string('idnumber', 'core_cohort');
|
||||
$choices['firstaccess'] = new lang_string('firstaccess', 'filters');
|
||||
$choices['lastaccess'] = new lang_string('lastaccess');
|
||||
$choices['neveraccessed'] = new lang_string('neveraccessed', 'filters');
|
||||
$choices['timemodified'] = new lang_string('lastmodified');
|
||||
$choices['nevermodified'] = new lang_string('nevermodified', 'filters');
|
||||
$choices['auth'] = new lang_string('authentication');
|
||||
$choices['idnumber'] = new lang_string('idnumber');
|
||||
$choices['lastip'] = new lang_string('lastip');
|
||||
$choices['mnethostid'] = new lang_string('mnetidprovider', 'mnet');
|
||||
$temp->add(new admin_setting_configmultiselect('userfiltersdefault', new lang_string('userfiltersdefault', 'admin'),
|
||||
new lang_string('userfiltersdefault_desc', 'admin'), array('realname'), $choices));
|
||||
}
|
||||
$ADMIN->add('accounts', $temp);
|
||||
|
||||
// User default preferences settingpage.
|
||||
// "User default preferences" settingpage.
|
||||
$temp = new admin_settingpage('userdefaultpreferences', new lang_string('userdefaultpreferences', 'admin'));
|
||||
if ($ADMIN->fulltree) {
|
||||
$choices = array();
|
||||
@@ -94,9 +62,9 @@ if ($hassiteconfig
|
||||
$ADMIN->add('accounts', new admin_externalpage('cohorts', new lang_string('cohorts', 'cohort'), $CFG->wwwroot . '/cohort/index.php', array('moodle/cohort:manage', 'moodle/cohort:view')));
|
||||
|
||||
|
||||
// Stuff under the "roles" subcategory.
|
||||
// stuff under the "roles" subcategory
|
||||
|
||||
// User policies settingpage.
|
||||
// "userpolicies" settingpage
|
||||
$temp = new admin_settingpage('userpolicies', new lang_string('userpolicies', 'admin'));
|
||||
if ($ADMIN->fulltree) {
|
||||
if (!during_initial_install()) {
|
||||
@@ -170,7 +138,7 @@ if ($hassiteconfig
|
||||
$temp->add(new admin_setting_configselect('restorernewroleid', new lang_string('restorernewroleid', 'admin'),
|
||||
new lang_string('restorernewroleid_help', 'admin'), $defaultteacherid, $restorersnewrole));
|
||||
|
||||
// Release memory.
|
||||
// release memory
|
||||
unset($otherroles);
|
||||
unset($guestroles);
|
||||
unset($userroles);
|
||||
@@ -241,7 +209,7 @@ if ($hassiteconfig
|
||||
$ADMIN->add('roles', new admin_externalpage('assignroles', new lang_string('assignglobalroles', 'role'), "$CFG->wwwroot/$CFG->admin/roles/assign.php?contextid=".$systemcontext->id, 'moodle/role:assign'));
|
||||
$ADMIN->add('roles', new admin_externalpage('checkpermissions', new lang_string('checkglobalpermissions', 'role'), "$CFG->wwwroot/$CFG->admin/roles/check.php?contextid=".$systemcontext->id, array('moodle/role:assign', 'moodle/role:safeoverride', 'moodle/role:override', 'moodle/role:manage')));
|
||||
|
||||
} // End of speedup.
|
||||
} // end of speedup
|
||||
|
||||
// Privacy settings.
|
||||
if ($hassiteconfig) {
|
||||
@@ -260,28 +228,10 @@ if ($hassiteconfig) {
|
||||
$temp->add($setting);
|
||||
|
||||
// See {@link https://gdpr-info.eu/art-8-gdpr/}.
|
||||
// See {@link https://www.betterinternetforkids.eu/web/portal/practice/awareness/detail?articleId=3017751}.
|
||||
$ageofdigitalconsentmap = implode(PHP_EOL, [
|
||||
'*, 16',
|
||||
'AT, 14',
|
||||
'BE, 13',
|
||||
'BG, 14',
|
||||
'CY, 14',
|
||||
'CZ, 15',
|
||||
'DK, 13',
|
||||
'EE, 13',
|
||||
'ES, 14',
|
||||
'FI, 13',
|
||||
'FR, 15',
|
||||
'GB, 13',
|
||||
'GR, 15',
|
||||
'IT, 14',
|
||||
'LT, 14',
|
||||
'LV, 13',
|
||||
'MT, 13',
|
||||
'NO, 13',
|
||||
'PT, 13',
|
||||
'SE, 13',
|
||||
'US, 13'
|
||||
]);
|
||||
$setting = new admin_setting_agedigitalconsentmap('agedigitalconsentmap',
|
||||
|
||||
+5
-4
@@ -40,14 +40,15 @@ $strheading = get_string('tasklogs', 'tool_task');
|
||||
$PAGE->set_title($strheading);
|
||||
$PAGE->set_heading($strheading);
|
||||
|
||||
require_login();
|
||||
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
admin_externalpage_setup('tasklogs');
|
||||
|
||||
$logid = optional_param('logid', null, PARAM_INT);
|
||||
$download = optional_param('download', false, PARAM_BOOL);
|
||||
|
||||
if (null !== $logid) {
|
||||
// Raise memory limit in case the log is large.
|
||||
raise_memory_limit(MEMORY_HUGE);
|
||||
$log = $DB->get_record('task_log', ['id' => $logid], '*', MUST_EXIST);
|
||||
|
||||
if ($download) {
|
||||
@@ -55,7 +56,7 @@ if (null !== $logid) {
|
||||
header("Content-Disposition: attachment; filename=\"{$filename}\"");
|
||||
}
|
||||
|
||||
readstring_accel($log->output, 'text/plain');
|
||||
readstring_accel($log->output, 'text/plain', false);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -64,7 +65,7 @@ $renderer = $PAGE->get_renderer('tool_task');
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render_from_template('core_admin/tasklogs', (object) [
|
||||
'action' => $pageurl->out(),
|
||||
'filter' => htmlentities($filter),
|
||||
'filter' => $filter,
|
||||
'resultfilteroptions' => [
|
||||
(object) [
|
||||
'value' => -1,
|
||||
|
||||
@@ -49,28 +49,15 @@
|
||||
}}
|
||||
<div class="form-item row" id="{{id}}">
|
||||
<div class="form-label col-sm-3 text-sm-right">
|
||||
{{#customcontrol}}
|
||||
<p {{#labelfor}}id="{{labelfor}}_label"{{/labelfor}}>
|
||||
{{{title}}}
|
||||
{{#override}}
|
||||
<div class="form-overridden">{{override}}</div>
|
||||
{{/override}}
|
||||
{{#warning}}
|
||||
<div class="form-warning">{{warning}}</div>
|
||||
{{/warning}}
|
||||
</p>
|
||||
{{/customcontrol}}
|
||||
{{^customcontrol}}
|
||||
<label {{#labelfor}}for="{{labelfor}}"{{/labelfor}}>
|
||||
{{{title}}}
|
||||
{{#override}}
|
||||
<div class="form-overridden">{{override}}</div>
|
||||
{{/override}}
|
||||
{{#warning}}
|
||||
<div class="form-warning">{{warning}}</div>
|
||||
{{/warning}}
|
||||
</label>
|
||||
{{/customcontrol}}
|
||||
<label {{#labelfor}}for="{{labelfor}}"{{/labelfor}}>
|
||||
{{{title}}}
|
||||
{{#override}}
|
||||
<div class="form-overridden">{{override}}</div>
|
||||
{{/override}}
|
||||
{{#warning}}
|
||||
<div class="form-warning">{{warning}}</div>
|
||||
{{/warning}}
|
||||
</label>
|
||||
<span class="form-shortname d-block small text-muted">{{{name}}}</span>
|
||||
</div>
|
||||
<div class="form-setting col-sm-9">
|
||||
@@ -85,16 +72,3 @@
|
||||
{{#dependenton}}<div class="form-dependenton mb-4 text-muted">{{{.}}}</div>{{/dependenton}}
|
||||
</div>
|
||||
</div>
|
||||
{{#customcontrol}}
|
||||
{{#js}}
|
||||
require(['jquery'], function($) {
|
||||
$('#{{id}}_label').css('cursor', 'default');
|
||||
$('#{{id}}_label').click(function() {
|
||||
$('#{{id}}')
|
||||
.find('button, a, input:not([type="hidden"]), select, textarea, [tabindex]')
|
||||
.filter(':not([disabled]):not([tabindex="0"]):not([tabindex="-1"])')
|
||||
.first().focus();
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
{{/customcontrol}}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_admin/setting_configfilesize
|
||||
|
||||
Admin file size setting template.
|
||||
|
||||
Context variables required for this template:
|
||||
* name - form element name
|
||||
* options - list of options for units containing name, value, selected
|
||||
* value - yes
|
||||
* id - element id
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"name": "test",
|
||||
"value": "5",
|
||||
"id": "test0",
|
||||
"options": [ { "name": "KB", "value": "1024", "selected": true } ]
|
||||
}
|
||||
}}
|
||||
{{!
|
||||
Setting configfilesize.
|
||||
}}
|
||||
<div class="form-filesize defaultsnext">
|
||||
<div class="form-inline">
|
||||
<input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr">
|
||||
<label class="sr-only" for="{{id}}u">{{#str}}filesizeunits, admin{{/str}}</label>
|
||||
<select id="{{id}}u" name="{{name}}[u]" class="form-control custom-select">
|
||||
{{#options}}
|
||||
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
|
||||
{{/options}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -46,14 +46,13 @@ if ($data) {
|
||||
$emailuser->email = $data->recipient;
|
||||
$emailuser->id = -99;
|
||||
|
||||
$subject = get_string('testoutgoingmailconf_subject', 'admin',
|
||||
format_string($SITE->fullname, true, ['context' => context_system::instance()]));
|
||||
$subject = get_string('testoutgoingmailconf_subject', 'admin', $SITE->fullname);
|
||||
$messagetext = get_string('testoutgoingmailconf_message', 'admin');
|
||||
|
||||
// Manage Moodle debugging options.
|
||||
$debuglevel = $CFG->debug;
|
||||
$debugdisplay = $CFG->debugdisplay;
|
||||
$debugsmtp = $CFG->debugsmtp ?? null; // This might not be set as it's optional.
|
||||
$debugsmtp = $CFG->debugsmtp;
|
||||
$CFG->debugdisplay = true;
|
||||
$CFG->debugsmtp = true;
|
||||
$CFG->debug = 15;
|
||||
@@ -67,12 +66,7 @@ if ($data) {
|
||||
// Restore Moodle debugging options.
|
||||
$CFG->debug = $debuglevel;
|
||||
$CFG->debugdisplay = $debugdisplay;
|
||||
|
||||
// Restore the debugsmtp config, if it was set originally.
|
||||
unset($CFG->debugsmtp);
|
||||
if (!is_null($debugsmtp)) {
|
||||
$CFG->debugsmtp = $debugsmtp;
|
||||
}
|
||||
$CFG->debugsmtp = $debugsmtp;
|
||||
|
||||
if ($success) {
|
||||
$msgparams = new stdClass();
|
||||
|
||||
@@ -48,11 +48,13 @@ class behat_admin extends behat_base {
|
||||
* @param TableNode $table
|
||||
*/
|
||||
public function i_set_the_following_administration_settings_values(TableNode $table) {
|
||||
|
||||
if (!$data = $table->getRowsHash()) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($data as $label => $value) {
|
||||
|
||||
$this->execute('behat_navigation::i_select_from_flat_navigation_drawer', [get_string('administrationsite')]);
|
||||
|
||||
// Search by label.
|
||||
@@ -74,17 +76,38 @@ class behat_admin extends behat_base {
|
||||
"@id=//span[contains(normalize-space(.), $label)]/preceding-sibling::label[1]/@for]";
|
||||
$fieldnode = $this->find('xpath', $fieldxpath, $exception);
|
||||
|
||||
$formfieldtypenode = $this->find('xpath', $fieldxpath .
|
||||
"/ancestor::div[contains(concat(' ', @class, ' '), ' form-setting ')]" .
|
||||
"/child::div[contains(concat(' ', @class, ' '), ' form-')]/child::*/parent::div");
|
||||
|
||||
} catch (ElementNotFoundException $e) {
|
||||
|
||||
// Multi element settings, interacting only the first one.
|
||||
$fieldxpath = "//*[label[contains(., $label)]|span[contains(., $label)]]" .
|
||||
"/ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' form-item ')]" .
|
||||
"/descendant::div[contains(concat(' ', @class, ' '), ' form-group ')]" .
|
||||
"/descendant::*[self::input | self::textarea | self::select]" .
|
||||
"[not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]";
|
||||
$fieldnode = $this->find('xpath', $fieldxpath);
|
||||
|
||||
// It is the same one that contains the type.
|
||||
$formfieldtypenode = $fieldnode;
|
||||
}
|
||||
|
||||
$this->execute('behat_forms::i_set_the_field_with_xpath_to', [$fieldxpath, $value]);
|
||||
$this->execute("behat_general::i_click_on", [get_string('savechanges'), 'button']);
|
||||
// Getting the class which contains the field type.
|
||||
$classes = explode(' ', $formfieldtypenode->getAttribute('class'));
|
||||
$type = false;
|
||||
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(get_string('savechanges'))->press();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email | auth | confirmed | lastip |
|
||||
| user1 | User | One | one@example.com | manual | 0 | 127.0.1.1 |
|
||||
| user2 | User | Two | two@example.com | ldap | 1 | 0.0.0.0 |
|
||||
| user3 | User | Three | three@example.com | manual | 1 | 0.0.0.0 |
|
||||
| user4 | User | Four | four@example.com | ldap | 0 | 127.0.1.2 |
|
||||
| username | firstname | lastname | email | auth | confirmed |
|
||||
| user1 | User | One | one@example.com | manual | 0 |
|
||||
| user2 | User | Two | two@example.com | ldap | 1 |
|
||||
| user3 | User | Three | three@example.com | manual | 1 |
|
||||
| user4 | User | Four | four@example.com | ldap | 0 |
|
||||
And the following "cohorts" exist:
|
||||
| name | idnumber |
|
||||
| Cohort 1 | CH1 |
|
||||
@@ -82,25 +82,3 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
|
||||
And I should not see "User Two"
|
||||
And I should not see "User Three"
|
||||
And I should see "User Four"
|
||||
|
||||
Scenario: Filter user accounts by last IP address
|
||||
When I set the following fields to these values:
|
||||
| id_lastip | 127.0.1.1 |
|
||||
And I press "Add filter"
|
||||
Then I should see "User One"
|
||||
And I should not see "User Two"
|
||||
And I should not see "User Three"
|
||||
And I should not see "User Four"
|
||||
And I press "Remove all filters"
|
||||
And I set the following fields to these values:
|
||||
| id_lastip | 127.0.1.2 |
|
||||
And I press "Add filter"
|
||||
And I should not see "User One"
|
||||
And I should not see "User Two"
|
||||
And I should not see "User Three"
|
||||
And I should see "User Four"
|
||||
And I press "Remove all filters"
|
||||
And I should see "User One"
|
||||
And I should see "User Two"
|
||||
And I should see "User Three"
|
||||
And I should see "User Four"
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
@core @core_admin @javascript
|
||||
Feature: An administrator can configure the available user list filters
|
||||
In order to have all needed user filters instantly at hand
|
||||
As an admin
|
||||
I want to configure the filters which are shown as default
|
||||
|
||||
Scenario: Do not change the user filter default configuration
|
||||
When I log in as "admin"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
Then I should see "User full name"
|
||||
And I should not see "Surname" in the "New filter" "fieldset"
|
||||
And I should not see "Firstname" in the "New filter" "fieldset"
|
||||
And I should not see "Username" in the "New filter" "fieldset"
|
||||
And I should not see "Email address" in the "New filter" "fieldset"
|
||||
And I should not see "City/town" in the "New filter" "fieldset"
|
||||
And I should not see "Country" in the "New filter" "fieldset"
|
||||
And I should not see "Confirmed" in the "New filter" "fieldset"
|
||||
And I should not see "Suspended account" in the "New filter" "fieldset"
|
||||
And I should not see "User profile fields" in the "New filter" "fieldset"
|
||||
And I should not see "Course role" in the "New filter" "fieldset"
|
||||
And I should not see "Enrolled in any course" in the "New filter" "fieldset"
|
||||
And I should not see "System role" in the "New filter" "fieldset"
|
||||
And I should not see "Cohort ID" in the "New filter" "fieldset"
|
||||
And I should not see "First access" in the "New filter" "fieldset"
|
||||
And I should not see "Last access" in the "New filter" "fieldset"
|
||||
And I should not see "Last modified" in the "New filter" "fieldset"
|
||||
And I should not see "Authentication" in the "New filter" "fieldset"
|
||||
And I should not see "ID number" in the "New filter" "fieldset"
|
||||
And I should not see "Last IP address" in the "New filter" "fieldset"
|
||||
And I should not see "MNet ID provider" in the "New filter" "fieldset"
|
||||
And I navigate to "Users > Accounts > Bulk user actions" in site administration
|
||||
Then I should see "User full name"
|
||||
And I should not see "Surname" in the "New filter" "fieldset"
|
||||
And I should not see "Firstname" in the "New filter" "fieldset"
|
||||
And I should not see "Username" in the "New filter" "fieldset"
|
||||
And I should not see "Email address" in the "New filter" "fieldset"
|
||||
And I should not see "City/town" in the "New filter" "fieldset"
|
||||
And I should not see "Country" in the "New filter" "fieldset"
|
||||
And I should not see "Confirmed" in the "New filter" "fieldset"
|
||||
And I should not see "Suspended account" in the "New filter" "fieldset"
|
||||
And I should not see "User profile fields" in the "New filter" "fieldset"
|
||||
And I should not see "Course role" in the "New filter" "fieldset"
|
||||
And I should not see "Enrolled in any course" in the "New filter" "fieldset"
|
||||
And I should not see "System role" in the "New filter" "fieldset"
|
||||
And I should not see "Cohort ID" in the "New filter" "fieldset"
|
||||
And I should not see "First access" in the "New filter" "fieldset"
|
||||
And I should not see "Last access" in the "New filter" "fieldset"
|
||||
And I should not see "Last modified" in the "New filter" "fieldset"
|
||||
And I should not see "Authentication" in the "New filter" "fieldset"
|
||||
And I should not see "ID number" in the "New filter" "fieldset"
|
||||
And I should not see "Last IP address" in the "New filter" "fieldset"
|
||||
And I should not see "MNet ID provider" in the "New filter" "fieldset"
|
||||
|
||||
Scenario: Change the user filter default configuration to something else
|
||||
Given the following config values are set as admin:
|
||||
| userfiltersdefault | realname,username,email |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
Then I should see "User full name"
|
||||
And I should not see "Surname" in the "New filter" "fieldset"
|
||||
And I should not see "Firstname" in the "New filter" "fieldset"
|
||||
And I should see "Username" in the "New filter" "fieldset"
|
||||
And I should see "Email address" in the "New filter" "fieldset"
|
||||
And I should not see "City/town" in the "New filter" "fieldset"
|
||||
And I should not see "Country" in the "New filter" "fieldset"
|
||||
And I should not see "Confirmed" in the "New filter" "fieldset"
|
||||
And I should not see "Suspended account" in the "New filter" "fieldset"
|
||||
And I should not see "User profile fields" in the "New filter" "fieldset"
|
||||
And I should not see "Course role" in the "New filter" "fieldset"
|
||||
And I should not see "Enrolled in any course" in the "New filter" "fieldset"
|
||||
And I should not see "System role" in the "New filter" "fieldset"
|
||||
And I should not see "Cohort ID" in the "New filter" "fieldset"
|
||||
And I should not see "First access" in the "New filter" "fieldset"
|
||||
And I should not see "Last access" in the "New filter" "fieldset"
|
||||
And I should not see "Last modified" in the "New filter" "fieldset"
|
||||
And I should not see "Authentication" in the "New filter" "fieldset"
|
||||
And I should not see "ID number" in the "New filter" "fieldset"
|
||||
And I should not see "Last IP address" in the "New filter" "fieldset"
|
||||
And I should not see "MNet ID provider" in the "New filter" "fieldset"
|
||||
And I navigate to "Users > Accounts > Bulk user actions" in site administration
|
||||
Then I should see "User full name"
|
||||
And I should not see "Surname" in the "New filter" "fieldset"
|
||||
And I should not see "Firstname" in the "New filter" "fieldset"
|
||||
And I should see "Username" in the "New filter" "fieldset"
|
||||
And I should see "Email address" in the "New filter" "fieldset"
|
||||
And I should not see "City/town" in the "New filter" "fieldset"
|
||||
And I should not see "Country" in the "New filter" "fieldset"
|
||||
And I should not see "Confirmed" in the "New filter" "fieldset"
|
||||
And I should not see "Suspended account" in the "New filter" "fieldset"
|
||||
And I should not see "User profile fields" in the "New filter" "fieldset"
|
||||
And I should not see "Course role" in the "New filter" "fieldset"
|
||||
And I should not see "Enrolled in any course" in the "New filter" "fieldset"
|
||||
And I should not see "System role" in the "New filter" "fieldset"
|
||||
And I should not see "Cohort ID" in the "New filter" "fieldset"
|
||||
And I should not see "First access" in the "New filter" "fieldset"
|
||||
And I should not see "Last access" in the "New filter" "fieldset"
|
||||
And I should not see "Last modified" in the "New filter" "fieldset"
|
||||
And I should not see "Authentication" in the "New filter" "fieldset"
|
||||
And I should not see "ID number" in the "New filter" "fieldset"
|
||||
And I should not see "Last IP address" in the "New filter" "fieldset"
|
||||
And I should not see "MNet ID provider" in the "New filter" "fieldset"
|
||||
|
||||
Scenario: Change the user filter default configuration to no filter at all
|
||||
Given the following config values are set as admin:
|
||||
| userfiltersdefault | |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
Then I should see "User full name"
|
||||
And I should not see "Surname" in the "New filter" "fieldset"
|
||||
And I should not see "Firstname" in the "New filter" "fieldset"
|
||||
And I should not see "Username" in the "New filter" "fieldset"
|
||||
And I should not see "Email address" in the "New filter" "fieldset"
|
||||
And I should not see "City/town" in the "New filter" "fieldset"
|
||||
And I should not see "Country" in the "New filter" "fieldset"
|
||||
And I should not see "Confirmed" in the "New filter" "fieldset"
|
||||
And I should not see "Suspended account" in the "New filter" "fieldset"
|
||||
And I should not see "User profile fields" in the "New filter" "fieldset"
|
||||
And I should not see "Course role" in the "New filter" "fieldset"
|
||||
And I should not see "Enrolled in any course" in the "New filter" "fieldset"
|
||||
And I should not see "System role" in the "New filter" "fieldset"
|
||||
And I should not see "Cohort ID" in the "New filter" "fieldset"
|
||||
And I should not see "First access" in the "New filter" "fieldset"
|
||||
And I should not see "Last access" in the "New filter" "fieldset"
|
||||
And I should not see "Last modified" in the "New filter" "fieldset"
|
||||
And I should not see "Authentication" in the "New filter" "fieldset"
|
||||
And I should not see "ID number" in the "New filter" "fieldset"
|
||||
And I should not see "Last IP address" in the "New filter" "fieldset"
|
||||
And I should not see "MNet ID provider" in the "New filter" "fieldset"
|
||||
And I navigate to "Users > Accounts > Bulk user actions" in site administration
|
||||
Then I should see "User full name"
|
||||
And I should not see "Surname" in the "New filter" "fieldset"
|
||||
And I should not see "Firstname" in the "New filter" "fieldset"
|
||||
And I should not see "Username" in the "New filter" "fieldset"
|
||||
And I should not see "Email address" in the "New filter" "fieldset"
|
||||
And I should not see "City/town" in the "New filter" "fieldset"
|
||||
And I should not see "Country" in the "New filter" "fieldset"
|
||||
And I should not see "Confirmed" in the "New filter" "fieldset"
|
||||
And I should not see "Suspended account" in the "New filter" "fieldset"
|
||||
And I should not see "User profile fields" in the "New filter" "fieldset"
|
||||
And I should not see "Course role" in the "New filter" "fieldset"
|
||||
And I should not see "Enrolled in any course" in the "New filter" "fieldset"
|
||||
And I should not see "System role" in the "New filter" "fieldset"
|
||||
And I should not see "Cohort ID" in the "New filter" "fieldset"
|
||||
And I should not see "First access" in the "New filter" "fieldset"
|
||||
And I should not see "Last access" in the "New filter" "fieldset"
|
||||
And I should not see "Last modified" in the "New filter" "fieldset"
|
||||
And I should not see "Authentication" in the "New filter" "fieldset"
|
||||
And I should not see "ID number" in the "New filter" "fieldset"
|
||||
And I should not see "Last IP address" in the "New filter" "fieldset"
|
||||
And I should not see "MNet ID provider" in the "New filter" "fieldset"
|
||||
@@ -9,7 +9,6 @@ Feature: Manage tokens
|
||||
| username | password | firstname | lastname |
|
||||
| testuser | testuser | Joe | Bloggs |
|
||||
| testuser2 | testuser2 | TestFirstname | TestLastname |
|
||||
And I change window size to "small"
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
|
||||
|
||||
+3
-1
@@ -12,7 +12,9 @@
|
||||
$PAGE->set_url('/admin/timezone.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$strtimezone = get_string("timezone");
|
||||
$strsavechanges = get_string("savechanges");
|
||||
|
||||
+1
-2
@@ -1,2 +1 @@
|
||||
define ("tool_analytics/log_info",["jquery","core/str","core/modal_factory","core/notification"],function(a,b,c,d){return{loadInfo:function loadInfo(e,f){var g=a("[data-model-log-id=\""+e+"\"]");b.get_string("loginfo","tool_analytics").then(function(b){var d=a("<ul>");f.forEach(function(a){d.append("<li>"+a+"</li>")});d.append("</ul>");return c.create({title:b,body:d.html(),large:!0},g)}).catch(d.exception)}}});
|
||||
//# sourceMappingURL=log_info.min.js.map
|
||||
define(["jquery","core/str","core/modal_factory","core/notification"],function(a,b,c,d){return{loadInfo:function(e,f){var g=a('[data-model-log-id="'+e+'"]');b.get_string("loginfo","tool_analytics").then(function(b){var d=a("<ul>");return f.forEach(function(a){d.append("<li>"+a+"</li>")}),d.append("</ul>"),c.create({title:b,body:d.html(),large:!0},g)})["catch"](d.exception)}}});
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["../src/log_info.js"],"names":["define","$","str","ModalFactory","Notification","loadInfo","id","info","link","get_string","then","langString","bodyInfo","forEach","item","append","create","title","body","html","large","catch","exception"],"mappings":"AAwBAA,OAAM,2BAAC,CAAC,QAAD,CAAW,UAAX,CAAuB,oBAAvB,CAA6C,mBAA7C,CAAD,CAAoE,SAASC,CAAT,CAAYC,CAAZ,CAAiBC,CAAjB,CAA+BC,CAA/B,CAA6C,CAEnH,MAAoD,CAShDC,QAAQ,CAAE,kBAASC,CAAT,CAAaC,CAAb,CAAmB,CAEzB,GAAIC,CAAAA,CAAI,CAAGP,CAAC,CAAC,wBAAyBK,CAAzB,CAA8B,KAA/B,CAAZ,CACAJ,CAAG,CAACO,UAAJ,CAAe,SAAf,CAA0B,gBAA1B,EAA4CC,IAA5C,CAAiD,SAASC,CAAT,CAAqB,CAElE,GAAIC,CAAAA,CAAQ,CAAGX,CAAC,CAAC,MAAD,CAAhB,CACAM,CAAI,CAACM,OAAL,CAAa,SAASC,CAAT,CAAe,CACxBF,CAAQ,CAACG,MAAT,CAAgB,OAASD,CAAT,CAAgB,OAAhC,CACH,CAFD,EAGAF,CAAQ,CAACG,MAAT,CAAgB,OAAhB,EAEA,MAAOZ,CAAAA,CAAY,CAACa,MAAb,CAAoB,CACvBC,KAAK,CAAEN,CADgB,CAEvBO,IAAI,CAAEN,CAAQ,CAACO,IAAT,EAFiB,CAGvBC,KAAK,GAHkB,CAApB,CAIJZ,CAJI,CAMV,CAdD,EAcGa,KAdH,CAcSjB,CAAY,CAACkB,SAdtB,CAeH,CA3B+C,CA6BvD,CA/BK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Shows a dialogue with info about this logs.\n *\n * @module tool_analytics/log_info\n * @class log_info\n * @package tool_analytics\n * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/modal_factory', 'core/notification'], function($, str, ModalFactory, Notification) {\n\n return /** @alias module:tool_analytics/log_info */ {\n\n /**\n * Prepares a modal info for a log's results.\n *\n * @method loadInfo\n * @param {int} id\n * @param {string[]} info\n */\n loadInfo: function(id, info) {\n\n var link = $('[data-model-log-id=\"' + id + '\"]');\n str.get_string('loginfo', 'tool_analytics').then(function(langString) {\n\n var bodyInfo = $(\"<ul>\");\n info.forEach(function(item) {\n bodyInfo.append('<li>' + item + '</li>');\n });\n bodyInfo.append(\"</ul>\");\n\n return ModalFactory.create({\n title: langString,\n body: bodyInfo.html(),\n large: true,\n }, link);\n\n }).catch(Notification.exception);\n }\n };\n});\n"],"file":"log_info.min.js"}
|
||||
+1
-2
@@ -1,2 +1 @@
|
||||
define ("tool_analytics/model",["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],function(b,c,d,e,f,g,h){var i={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},delete:{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}},j=function(a){var c=b(a).closest("[data-model-name]");if(c.length){return c.attr("data-model-name")}else{d.error("Unexpected DOM error - unable to obtain the model name");return""}};return{confirmAction:function confirmAction(a,h){b("[data-action-id=\""+a+"\"]").on("click",function(k){k.preventDefault();var l=b(k.currentTarget);if("undefined"==typeof i[h]){d.error("Action \""+h+"\" is not allowed.");return}var a=[i[h].title,i[h].body];a[1].param=j(l);var m=c.get_strings(a),n=f.create({type:f.types.SAVE_CANCEL});b.when(m,n).then(function(a,b){b.setTitle(a[0]);b.setBody(a[1]);b.setSaveButtonText(a[0]);b.getRoot().on(g.save,function(){window.location.href=l.attr("href")});b.show();return b}).fail(e.exception)})},selectEvaluationOptions:function selectEvaluationOptions(a,d){b("[data-action-id=\""+a+"\"]").on("click",function(i){i.preventDefault();var j=b(i.currentTarget),a=b(this).attr("data-timesplitting-methods"),k=c.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluate",component:"tool_analytics"}]),l=f.create({type:f.types.SAVE_CANCEL}),m=h.render("tool_analytics/evaluation_options",{trainedexternally:d,timesplittingmethods:JSON.parse(a)});b.when(k,l).then(function(a,c){c.getRoot().on(g.hidden,c.destroy.bind(c));c.setTitle(a[0]);c.setSaveButtonText(a[1]);c.setBody(m);c.getRoot().on(g.save,function(){var a=b("input[name='evaluationmode']:checked").val();if("trainedmodel"==a){j.attr("href",j.attr("href")+"&mode=trainedmodel")}var c=b("#id-evaluation-timesplitting").val();j.attr("href",j.attr("href")+"×plitting="+c);window.location.href=j.attr("href")});c.show();return c}).fail(e.exception)})},selectExportOptions:function selectExportOptions(a,d){b("[data-action-id=\""+a+"\"]").on("click",function(i){i.preventDefault();var j=b(i.currentTarget);if(!d){j.attr("href",j.attr("href")+"&action=exportmodel&includeweights=0");window.location.href=j.attr("href");return}var a=c.get_strings([{key:"export",component:"tool_analytics"}]),k=f.create({type:f.types.SAVE_CANCEL}),l=h.render("tool_analytics/export_options",{});b.when(a,k).then(function(a,c){c.getRoot().on(g.hidden,c.destroy.bind(c));c.setTitle(a[0]);c.setSaveButtonText(a[0]);c.setBody(l);c.getRoot().on(g.save,function(){var a=b("input[name='exportoption']:checked").val();if("exportdata"==a){j.attr("href",j.attr("href")+"&action=exportdata")}else{j.attr("href",j.attr("href")+"&action=exportmodel");if(b("#id-includeweights").is(":checked")){j.attr("href",j.attr("href")+"&includeweights=1")}else{j.attr("href",j.attr("href")+"&includeweights=0")}}window.location.href=j.attr("href")});c.show();return c}).fail(e.exception)})}}});
|
||||
//# sourceMappingURL=model.min.js.map
|
||||
define(["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],function(a,b,c,d,e,f,g){var h={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},"delete":{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}},i=function(b){var d=a(b).closest("[data-model-name]");return d.length?d.attr("data-model-name"):(c.error("Unexpected DOM error - unable to obtain the model name"),"")};return{confirmAction:function(g,j){a('[data-action-id="'+g+'"]').on("click",function(g){g.preventDefault();var k=a(g.currentTarget);if("undefined"==typeof h[j])return void c.error('Action "'+j+'" is not allowed.');var l=[h[j].title,h[j].body];l[1].param=i(k);var m=b.get_strings(l),n=e.create({type:e.types.SAVE_CANCEL});a.when(m,n).then(function(a,b){return b.setTitle(a[0]),b.setBody(a[1]),b.setSaveButtonText(a[0]),b.getRoot().on(f.save,function(){window.location.href=k.attr("href")}),b.show(),b}).fail(d.exception)})},selectEvaluationOptions:function(c,h,i){a('[data-action-id="'+c+'"]').on("click",function(c){c.preventDefault();var j=a(c.currentTarget),k=b.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluate",component:"tool_analytics"}]),l=e.create({type:e.types.SAVE_CANCEL}),m=g.render("tool_analytics/evaluation_options",{trainedexternally:h,timesplittingmethods:i});a.when(k,l).then(function(b,c){return c.getRoot().on(f.hidden,c.destroy.bind(c)),c.setTitle(b[0]),c.setSaveButtonText(b[1]),c.setBody(m),c.getRoot().on(f.save,function(){var b=a("input[name='evaluationmode']:checked").val();"trainedmodel"==b&&j.attr("href",j.attr("href")+"&mode=trainedmodel");var c=a("#id-evaluation-timesplitting").val();j.attr("href",j.attr("href")+"×plitting="+c),window.location.href=j.attr("href")}),c.show(),c}).fail(d.exception)})},selectExportOptions:function(c,h){a('[data-action-id="'+c+'"]').on("click",function(c){c.preventDefault();var i=a(c.currentTarget);if(!h)return i.attr("href",i.attr("href")+"&action=exportmodel&includeweights=0"),void(window.location.href=i.attr("href"));var j=b.get_strings([{key:"export",component:"tool_analytics"}]),k=e.create({type:e.types.SAVE_CANCEL}),l=g.render("tool_analytics/export_options",{});a.when(j,k).then(function(b,c){return c.getRoot().on(f.hidden,c.destroy.bind(c)),c.setTitle(b[0]),c.setSaveButtonText(b[0]),c.setBody(l),c.getRoot().on(f.save,function(){var b=a("input[name='exportoption']:checked").val();"exportdata"==b?i.attr("href",i.attr("href")+"&action=exportdata"):(i.attr("href",i.attr("href")+"&action=exportmodel"),a("#id-includeweights").is(":checked")?i.attr("href",i.attr("href")+"&includeweights=1"):i.attr("href",i.attr("href")+"&includeweights=0")),window.location.href=i.attr("href")}),c.show(),c}).fail(d.exception)})}}});
|
||||
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
define ("tool_analytics/potential-contexts",["jquery","core/ajax"],function(a,b){return{processResults:function processResults(b,c){var d=[];if(a.isArray(c)){a.each(c,function(a,b){d.push({value:b.id,label:b.name})});return d}else{return c}},transport:function transport(c,d,e,f){var g,h=a(c).attr("modelid")||null;g=b.call([{methodname:"tool_analytics_potential_contexts",args:{query:d,modelid:h}}]);g[0].then(e).fail(f)}}});
|
||||
//# sourceMappingURL=potential-contexts.min.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["../src/potential-contexts.js"],"names":["define","$","Ajax","processResults","selector","results","contexts","isArray","each","index","context","push","value","id","label","name","transport","query","success","failure","promise","modelid","attr","call","methodname","args","then","fail"],"mappings":"AAyBAA,OAAM,qCAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAE9C,MAA8D,CAE1DC,cAAc,CAAE,wBAASC,CAAT,CAAmBC,CAAnB,CAA4B,CACxC,GAAIC,CAAAA,CAAQ,CAAG,EAAf,CACA,GAAIL,CAAC,CAACM,OAAF,CAAUF,CAAV,CAAJ,CAAwB,CACpBJ,CAAC,CAACO,IAAF,CAAOH,CAAP,CAAgB,SAASI,CAAT,CAAgBC,CAAhB,CAAyB,CACrCJ,CAAQ,CAACK,IAAT,CAAc,CACVC,KAAK,CAAEF,CAAO,CAACG,EADL,CAEVC,KAAK,CAAEJ,CAAO,CAACK,IAFL,CAAd,CAIH,CALD,EAMA,MAAOT,CAAAA,CAEV,CATD,IASO,CACH,MAAOD,CAAAA,CACV,CACJ,CAhByD,CAkB1DW,SAAS,CAAE,mBAASZ,CAAT,CAAmBa,CAAnB,CAA0BC,CAA1B,CAAmCC,CAAnC,CAA4C,IAC/CC,CAAAA,CAD+C,CAG/CC,CAAO,CAAGpB,CAAC,CAACG,CAAD,CAAD,CAAYkB,IAAZ,CAAiB,SAAjB,GAA+B,IAHM,CAInDF,CAAO,CAAGlB,CAAI,CAACqB,IAAL,CAAU,CAAC,CACjBC,UAAU,CAAE,mCADK,CAEjBC,IAAI,CAAE,CACFR,KAAK,CAAEA,CADL,CAEFI,OAAO,CAAEA,CAFP,CAFW,CAAD,CAAV,CAAV,CAQAD,CAAO,CAAC,CAAD,CAAP,CAAWM,IAAX,CAAgBR,CAAhB,EAAyBS,IAAzB,CAA8BR,CAA9B,CACH,CA/ByD,CAmCjE,CArCK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Potential contexts selector module.\n *\n * @module tool_analytics/potential-contexts\n * @class potential-contexts\n * @package tool_analytics\n * @copyright 2019 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n return /** @alias module:tool_analytics/potential-contexts */ {\n\n processResults: function(selector, results) {\n var contexts = [];\n if ($.isArray(results)) {\n $.each(results, function(index, context) {\n contexts.push({\n value: context.id,\n label: context.name\n });\n });\n return contexts;\n\n } else {\n return results;\n }\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n let modelid = $(selector).attr('modelid') || null;\n promise = Ajax.call([{\n methodname: 'tool_analytics_potential_contexts',\n args: {\n query: query,\n modelid: modelid\n }\n }]);\n\n promise[0].then(success).fail(failure);\n }\n\n };\n\n});\n"],"file":"potential-contexts.min.js"}
|
||||
@@ -114,14 +114,12 @@ define(['jquery', 'core/str', 'core/log', 'core/notification', 'core/modal_facto
|
||||
* @param {String} actionId
|
||||
* @param {Boolean} trainedOnlyExternally
|
||||
*/
|
||||
selectEvaluationOptions: function(actionId, trainedOnlyExternally) {
|
||||
selectEvaluationOptions: function(actionId, trainedOnlyExternally, timeSplittingMethods) {
|
||||
$('[data-action-id="' + actionId + '"]').on('click', function(ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
var a = $(ev.currentTarget);
|
||||
|
||||
var timeSplittingMethods = $(this).attr('data-timesplitting-methods');
|
||||
|
||||
var stringsPromise = Str.get_strings([
|
||||
{
|
||||
key: 'evaluatemodel',
|
||||
@@ -134,7 +132,7 @@ define(['jquery', 'core/str', 'core/log', 'core/notification', 'core/modal_facto
|
||||
var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL});
|
||||
var bodyPromise = Templates.render('tool_analytics/evaluation_options', {
|
||||
trainedexternally: trainedOnlyExternally,
|
||||
timesplittingmethods: JSON.parse(timeSplittingMethods)
|
||||
timesplittingmethods: timeSplittingMethods
|
||||
});
|
||||
|
||||
$.when(stringsPromise, modalPromise).then(function(strings, modal) {
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Potential contexts selector module.
|
||||
*
|
||||
* @module tool_analytics/potential-contexts
|
||||
* @class potential-contexts
|
||||
* @package tool_analytics
|
||||
* @copyright 2019 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define(['jquery', 'core/ajax'], function($, Ajax) {
|
||||
|
||||
return /** @alias module:tool_analytics/potential-contexts */ {
|
||||
|
||||
processResults: function(selector, results) {
|
||||
var contexts = [];
|
||||
if ($.isArray(results)) {
|
||||
$.each(results, function(index, context) {
|
||||
contexts.push({
|
||||
value: context.id,
|
||||
label: context.name
|
||||
});
|
||||
});
|
||||
return contexts;
|
||||
|
||||
} else {
|
||||
return results;
|
||||
}
|
||||
},
|
||||
|
||||
transport: function(selector, query, success, failure) {
|
||||
var promise;
|
||||
|
||||
let modelid = $(selector).attr('modelid') || null;
|
||||
promise = Ajax.call([{
|
||||
methodname: 'tool_analytics_potential_contexts',
|
||||
args: {
|
||||
query: query,
|
||||
modelid: modelid
|
||||
}
|
||||
}]);
|
||||
|
||||
promise[0].then(success).fail(failure);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
@@ -1,113 +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 is the external API for this component.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_analytics;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once("$CFG->libdir/externallib.php");
|
||||
|
||||
use external_api;
|
||||
use external_function_parameters;
|
||||
use external_value;
|
||||
use external_single_structure;
|
||||
use external_multiple_structure;
|
||||
|
||||
/**
|
||||
* This is the external API for this component.
|
||||
*
|
||||
* @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class external extends external_api {
|
||||
|
||||
const MAX_CONTEXTS_RETURNED = 100;
|
||||
|
||||
/**
|
||||
* potential_contexts parameters.
|
||||
*
|
||||
* @since Moodle 3.8
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function potential_contexts_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'query' => new external_value(PARAM_NOTAGS, 'The model id', VALUE_DEFAULT),
|
||||
'modelid' => new external_value(PARAM_INT, 'The model id', VALUE_DEFAULT)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the contexts that match the provided query.
|
||||
*
|
||||
* @since Moodle 3.8
|
||||
* @param string|null $query
|
||||
* @param int|null $modelid
|
||||
* @return array an array of contexts
|
||||
*/
|
||||
public static function potential_contexts(?string $query = null, ?int $modelid = null) {
|
||||
|
||||
$params = self::validate_parameters(self::potential_contexts_parameters(), ['modelid' => $modelid, 'query' => $query]);
|
||||
|
||||
\core_analytics\manager::check_can_manage_models();
|
||||
|
||||
if ($params['modelid']) {
|
||||
$model = new \core_analytics\model($params['modelid']);
|
||||
$contexts = ($model->get_analyser(['notimesplitting' => true]))::potential_context_restrictions($params['query']);
|
||||
} else {
|
||||
$contexts = \core_analytics\manager::get_potential_context_restrictions(null, $params['query']);
|
||||
}
|
||||
|
||||
$contextoptions = [];
|
||||
$i = 0;
|
||||
foreach ($contexts as $contextid => $contextname) {
|
||||
|
||||
if ($i === self::MAX_CONTEXTS_RETURNED) {
|
||||
// Limited to MAX_CONTEXTS_RETURNED items.
|
||||
break;
|
||||
}
|
||||
|
||||
$contextoptions[] = ['id' => $contextid, 'name' => $contextname];
|
||||
$i++;
|
||||
}
|
||||
|
||||
return $contextoptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* potential_contexts return
|
||||
*
|
||||
* @since Moodle 3.8
|
||||
* @return external_description
|
||||
*/
|
||||
public static function potential_contexts_returns() {
|
||||
return new external_multiple_structure(
|
||||
new external_single_structure([
|
||||
'id' => new external_value(PARAM_INT, 'ID of the context'),
|
||||
'name' => new external_value(PARAM_NOTAGS, 'The context name')
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -65,15 +65,6 @@ class edit_model extends \moodleform {
|
||||
$mform->addRule('target', get_string('required'), 'required', null, 'client');
|
||||
}
|
||||
|
||||
if (!empty($this->_customdata['targetname']) && !empty($this->_customdata['targetclass'])) {
|
||||
$mform->addElement('static', 'targetname', get_string('target', 'tool_analytics'), $this->_customdata['targetname']);
|
||||
$mform->addElement('hidden', 'target',
|
||||
\tool_analytics\output\helper::class_to_option($this->_customdata['targetclass']));
|
||||
// We won't update the model's target so no worries about its format (we can't use PARAM_ALPHANUMEXT
|
||||
// because of class_to_option).
|
||||
$mform->setType('target', PARAM_TEXT);
|
||||
}
|
||||
|
||||
// Indicators.
|
||||
if (!$this->_customdata['staticmodel']) {
|
||||
$indicators = array();
|
||||
@@ -90,13 +81,6 @@ class edit_model extends \moodleform {
|
||||
}
|
||||
|
||||
// Time-splitting methods.
|
||||
if (!empty($this->_customdata['invalidcurrenttimesplitting'])) {
|
||||
$mform->addElement('html', $OUTPUT->notification(
|
||||
get_string('invalidcurrenttimesplitting', 'tool_analytics'),
|
||||
\core\output\notification::NOTIFY_WARNING)
|
||||
);
|
||||
}
|
||||
|
||||
$timesplittings = array('' => '');
|
||||
foreach ($this->_customdata['timesplittings'] as $classname => $timesplitting) {
|
||||
$optionname = \tool_analytics\output\helper::class_to_option($classname);
|
||||
@@ -105,28 +89,6 @@ class edit_model extends \moodleform {
|
||||
$mform->addElement('select', 'timesplitting', get_string('timesplittingmethod', 'analytics'), $timesplittings);
|
||||
$mform->addHelpButton('timesplitting', 'timesplittingmethod', 'analytics');
|
||||
|
||||
// Contexts restriction.
|
||||
if (!empty($this->_customdata['supportscontexts'])) {
|
||||
|
||||
$options = [
|
||||
'ajax' => 'tool_analytics/potential-contexts',
|
||||
'multiple' => true,
|
||||
'noselectionstring' => get_string('all')
|
||||
];
|
||||
|
||||
if (!empty($this->_customdata['id'])) {
|
||||
$options['modelid'] = $this->_customdata['id'];
|
||||
$contexts = $this->load_current_contexts();
|
||||
} else {
|
||||
// No need to preload any selected contexts.
|
||||
$contexts = [];
|
||||
}
|
||||
|
||||
$mform->addElement('autocomplete', 'contexts', get_string('contexts', 'tool_analytics'), $contexts, $options);
|
||||
$mform->setType('contexts', PARAM_INT);
|
||||
$mform->addHelpButton('contexts', 'contexts', 'tool_analytics');
|
||||
}
|
||||
|
||||
// Predictions processor.
|
||||
if (!$this->_customdata['staticmodel']) {
|
||||
$defaultprocessor = \core_analytics\manager::get_predictions_processor_name(
|
||||
@@ -168,35 +130,11 @@ class edit_model extends \moodleform {
|
||||
public function validation($data, $files) {
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
$targetclass = \tool_analytics\output\helper::option_to_class($data['target']);
|
||||
$target = \core_analytics\manager::get_target($targetclass);
|
||||
|
||||
if (!empty($data['timesplitting'])) {
|
||||
$timesplittingclass = \tool_analytics\output\helper::option_to_class($data['timesplitting']);
|
||||
if (\core_analytics\manager::is_valid($timesplittingclass, '\core_analytics\local\time_splitting\base') === false) {
|
||||
$realtimesplitting = \tool_analytics\output\helper::option_to_class($data['timesplitting']);
|
||||
if (\core_analytics\manager::is_valid($realtimesplitting, '\core_analytics\local\time_splitting\base') === false) {
|
||||
$errors['timesplitting'] = get_string('errorinvalidtimesplitting', 'analytics');
|
||||
}
|
||||
|
||||
$timesplitting = \core_analytics\manager::get_time_splitting($timesplittingclass);
|
||||
if (!$target->can_use_timesplitting($timesplitting)) {
|
||||
$errors['timesplitting'] = get_string('invalidtimesplitting', 'tool_analytics');
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['contexts'])) {
|
||||
|
||||
$analyserclass = $target->get_analyser_class();
|
||||
if (!$potentialcontexts = $analyserclass::potential_context_restrictions()) {
|
||||
$errors['contexts'] = get_string('errornocontextrestrictions', 'analytics');
|
||||
} else {
|
||||
|
||||
// Flip the contexts array so we can just diff by key.
|
||||
$selectedcontexts = array_flip($data['contexts']);
|
||||
$invalidcontexts = array_diff_key($selectedcontexts, $potentialcontexts);
|
||||
if (!empty($invalidcontexts)) {
|
||||
$errors['contexts'] = get_string('errorinvalidcontexts', 'analytics');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->_customdata['staticmodel']) {
|
||||
@@ -218,18 +156,4 @@ class edit_model extends \moodleform {
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the currently selected context options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function load_current_contexts() {
|
||||
$contexts = [];
|
||||
foreach ($this->_customdata['contexts'] as $context) {
|
||||
$contexts[$context->id] = $context->get_context_name(true, true);
|
||||
}
|
||||
|
||||
return $contexts;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,50 +105,4 @@ class helper {
|
||||
$PAGE->reset_theme_and_output();
|
||||
$PAGE->set_context(\context_system::instance());
|
||||
}
|
||||
/**
|
||||
* Convert a list of contexts to an associative array where the value is the context name.
|
||||
*
|
||||
* @param array $contexts
|
||||
* @param \moodle_url $url
|
||||
* @param \renderer_base $output
|
||||
* @param int|null $selected
|
||||
* @param bool $includeall
|
||||
* @param bool $shortentext
|
||||
* @return \stdClass
|
||||
*/
|
||||
public static function prediction_context_selector(array $contexts, \moodle_url $url, \renderer_base $output,
|
||||
?int $selected = null, ?bool $includeall = false, ?bool $shortentext = true): \stdClass {
|
||||
|
||||
foreach ($contexts as $contextid => $unused) {
|
||||
// We prepare this to be used as single_select template options.
|
||||
$context = \context::instance_by_id($contextid);
|
||||
|
||||
// Special name for system level predictions as showing "System is not visually nice".
|
||||
if ($contextid == SYSCONTEXTID) {
|
||||
$contextname = get_string('allpredictions', 'tool_analytics');
|
||||
} else {
|
||||
if ($shortentext) {
|
||||
$contextname = shorten_text($context->get_context_name(false, true), 40);
|
||||
} else {
|
||||
$contextname = $context->get_context_name(false, true);
|
||||
}
|
||||
}
|
||||
$contexts[$contextid] = $contextname;
|
||||
}
|
||||
|
||||
if ($includeall) {
|
||||
$contexts[0] = get_string('all');
|
||||
$nothing = '';
|
||||
} else {
|
||||
$nothing = array('' => 'choosedots');
|
||||
}
|
||||
|
||||
\core_collator::asort($contexts);
|
||||
|
||||
if (!$selected) {
|
||||
$selected = '';
|
||||
}
|
||||
$singleselect = new \single_select($url, 'contextid', $contexts, $selected, $nothing);
|
||||
return $singleselect->export_for_template($output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,184 +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/>.
|
||||
|
||||
/**
|
||||
* Insights report renderable.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_analytics\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
/**
|
||||
* Insights report renderable.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class insights_report implements \renderable, \templatable {
|
||||
|
||||
/**
|
||||
* @var \core_analytics\model
|
||||
*/
|
||||
private $model = null;
|
||||
|
||||
/**
|
||||
* @var \context
|
||||
*/
|
||||
private $context = null;
|
||||
|
||||
/**
|
||||
* Inits the insights report renderable.
|
||||
*
|
||||
* @param \core_analytics\model $model
|
||||
* @param int|null $contextid
|
||||
* @return null
|
||||
*/
|
||||
public function __construct(\core_analytics\model $model, ?int $contextid = null) {
|
||||
$this->model = $model;
|
||||
if ($contextid) {
|
||||
$this->context = \context::instance_by_id($contextid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the data.
|
||||
*
|
||||
* @param \renderer_base $output
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output): \stdClass {
|
||||
|
||||
// Prepare the context object.
|
||||
$data = new \stdClass();
|
||||
$data->modelname = $this->model->get_name();
|
||||
|
||||
$data->charts = [];
|
||||
|
||||
$predictionactionrecords = $this->model->get_prediction_actions($this->context);
|
||||
|
||||
// Context selector.
|
||||
$predictioncontexts = $this->model->get_predictions_contexts(false);
|
||||
if ($predictioncontexts && count($predictioncontexts) > 1) {
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', ['id' => $this->model->get_id(),
|
||||
'action' => 'insightsreport']);
|
||||
|
||||
if ($this->context) {
|
||||
$selected = $this->context->id;
|
||||
} else {
|
||||
// This is the 'all' option.
|
||||
$selected = 0;
|
||||
}
|
||||
$data->contextselect = \tool_analytics\output\helper::prediction_context_selector($predictioncontexts,
|
||||
$url, $output, $selected, true, false);
|
||||
}
|
||||
|
||||
if ($predictionactionrecords->valid()) {
|
||||
|
||||
foreach ($predictionactionrecords as $record) {
|
||||
|
||||
// Using this unusual execution flow to init the chart data because $predictionactionrecords
|
||||
// is a \moodle_recordset.
|
||||
if (empty($actionlabels)) {
|
||||
list($actionlabels, $actionvalues, $actiontypes) = $this->init_action_labels($record);
|
||||
}
|
||||
|
||||
// One value for each action.
|
||||
$actionvalues['separated'][$record->actionname]++;
|
||||
|
||||
// Grouped value.
|
||||
$actiontype = $actiontypes[$record->actionname];
|
||||
$actionvalues['grouped'][$actiontype]++;
|
||||
}
|
||||
$predictionactionrecords->close();
|
||||
|
||||
// Actions doughtnut.
|
||||
$chart = new \core\chart_pie();
|
||||
$chart->set_doughnut(true);
|
||||
$chart->set_title(get_string('actionsexecutedbyusers', 'tool_analytics'));
|
||||
$series = new \core\chart_series(get_string('actions', 'tool_analytics'),
|
||||
array_values($actionvalues['separated']));
|
||||
$chart->add_series($series);
|
||||
$chart->set_labels(array_values($actionlabels['separated']));
|
||||
$data->separatedchart = $output->render($chart);
|
||||
|
||||
// Positive/negative/neutral bar chart.
|
||||
$chart = new \core\chart_bar();
|
||||
$chart->set_title(get_string('actionexecutedgroupedusefulness', 'tool_analytics'));
|
||||
$series = new \core\chart_series(get_string('actions', 'tool_analytics'),
|
||||
array_values($actionvalues['grouped']));
|
||||
$chart->add_series($series);
|
||||
$chart->set_labels(array_values($actionlabels['grouped']));
|
||||
$data->groupedchart = $output->render($chart);
|
||||
|
||||
} else {
|
||||
$predictionactionrecords->close();
|
||||
$data->noactions = [
|
||||
'message' => get_string('noactionsfound', 'tool_analytics'),
|
||||
'announce' => true,
|
||||
];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the action labels and values in this model.
|
||||
*
|
||||
* @param \stdClass $predictionactionrecord
|
||||
* @return array Two-dimensional array with the labels and values initialised to zero.
|
||||
*/
|
||||
private function init_action_labels(\stdClass $predictionactionrecord): array {
|
||||
|
||||
$predictioncontext = \context::instance_by_id($predictionactionrecord->contextid);
|
||||
|
||||
// Just 1 result, we just want to retrieve the prediction action names.
|
||||
list ($unused, $predictions) = $this->model->get_predictions($predictioncontext, false, 0, 1);
|
||||
|
||||
// We pass 'true' for $isinsightuser so all the prediction actions available for this target are returning.
|
||||
$predictionactions = $this->model->get_target()->prediction_actions(reset($predictions), true, true);
|
||||
|
||||
$actionlabels = [];
|
||||
$actionvalues = ['separated' => [], 'grouped' => []];
|
||||
$actiontypes = [];
|
||||
foreach ($predictionactions as $action) {
|
||||
$actionlabels['separated'][$action->get_action_name()] = $action->get_text();
|
||||
$actionvalues['separated'][$action->get_action_name()] = 0;
|
||||
$actiontypes[$action->get_action_name()] = $action->get_type();
|
||||
}
|
||||
|
||||
$bulkactions = $this->model->get_target()->bulk_actions($predictions);
|
||||
foreach ($bulkactions as $action) {
|
||||
$actionlabels['separated'][$action->get_action_name()] = $action->get_text();
|
||||
$actionvalues['separated'][$action->get_action_name()] = 0;
|
||||
$actiontypes[$action->get_action_name()] = $action->get_type();
|
||||
}
|
||||
|
||||
$actionlabels['grouped'][\core_analytics\action::TYPE_POSITIVE] = get_string('useful', 'analytics');
|
||||
$actionlabels['grouped'][\core_analytics\action::TYPE_NEUTRAL] = get_string('neutral', 'analytics');
|
||||
$actionlabels['grouped'][\core_analytics\action::TYPE_NEGATIVE] = get_string('notuseful', 'analytics');
|
||||
|
||||
$actionvalues['grouped'][\core_analytics\action::TYPE_POSITIVE] = 0;
|
||||
$actionvalues['grouped'][\core_analytics\action::TYPE_NEUTRAL] = 0;
|
||||
$actionvalues['grouped'][\core_analytics\action::TYPE_NEGATIVE] = 0;
|
||||
|
||||
return [$actionlabels, $actionvalues, $actiontypes];
|
||||
}
|
||||
}
|
||||
@@ -76,8 +76,7 @@ class invalid_analysables implements \renderable, \templatable {
|
||||
|
||||
$offset = $this->page * $this->perpage;
|
||||
|
||||
$contexts = $this->model->get_contexts();
|
||||
$analysables = $this->model->get_analyser(['notimesplitting' => true])->get_analysables_iterator(null, $contexts);
|
||||
$analysables = $this->model->get_analyser(['notimesplitting' => true])->get_analysables_iterator();
|
||||
|
||||
$skipped = 0;
|
||||
$enoughresults = false;
|
||||
|
||||
@@ -97,9 +97,16 @@ class models_list implements \renderable, \templatable {
|
||||
}
|
||||
|
||||
// Evaluation options.
|
||||
$timesplittingsforevaluation = \core_analytics\manager::get_time_splitting_methods_for_evaluation(true);
|
||||
$timesplittingmethods = [
|
||||
['id' => 'all', 'text' => get_string('alltimesplittingmethods', 'tool_analytics')],
|
||||
];
|
||||
foreach (\core_analytics\manager::get_time_splitting_methods_for_evaluation(true) as $timesplitting) {
|
||||
$timesplittingmethods[] = [
|
||||
'id' => \tool_analytics\output\helper::class_to_option($timesplitting->get_id()),
|
||||
'text' => $timesplitting->get_name()->out(),
|
||||
];
|
||||
}
|
||||
|
||||
$misconfiguredmodels = [];
|
||||
$data->models = array();
|
||||
foreach ($this->models as $model) {
|
||||
$modeldata = $model->export($output);
|
||||
@@ -116,10 +123,6 @@ class models_list implements \renderable, \templatable {
|
||||
describe its purpose.", DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
if ($model->invalid_timesplitting_selected()) {
|
||||
$misconfiguredmodels[$model->get_id()] = $model->get_name();
|
||||
}
|
||||
|
||||
// Check if there is a help icon for the indicators to show.
|
||||
if (!empty($modeldata->indicators)) {
|
||||
$indicators = array();
|
||||
@@ -153,7 +156,7 @@ class models_list implements \renderable, \templatable {
|
||||
$modeldata->timesplittinghelp = $helpicon->export_for_template($output);
|
||||
} else {
|
||||
// We really want to encourage developers to add help to their time splitting methods.
|
||||
debugging("The analysis interval '{$modeldata->timesplitting}' should include a '{$identifier}_help'
|
||||
debugging("The time splitting method '{$modeldata->timesplitting}' should include a '{$identifier}_help'
|
||||
string to describe its purpose.", DEBUG_DEVELOPER);
|
||||
}
|
||||
} else {
|
||||
@@ -163,20 +166,36 @@ class models_list implements \renderable, \templatable {
|
||||
|
||||
// Has this model generated predictions?.
|
||||
$predictioncontexts = $model->get_predictions_contexts();
|
||||
$anypredictionobtained = $model->any_prediction_obtained();
|
||||
|
||||
// Model predictions list.
|
||||
if (!$model->is_enabled()) {
|
||||
$modeldata->noinsights = get_string('disabledmodel', 'analytics');
|
||||
} else if ($model->uses_insights()) {
|
||||
if ($predictioncontexts) {
|
||||
$url = new \moodle_url('/report/insights/insights.php', array('modelid' => $model->get_id()));
|
||||
$modeldata->insights = \tool_analytics\output\helper::prediction_context_selector($predictioncontexts,
|
||||
$url, $output);
|
||||
|
||||
foreach ($predictioncontexts as $contextid => $unused) {
|
||||
// We prepare this to be used as single_select template options.
|
||||
$context = \context::instance_by_id($contextid);
|
||||
|
||||
// Special name for system level predictions as showing "System is not visually nice".
|
||||
if ($contextid == SYSCONTEXTID) {
|
||||
$contextname = get_string('allpredictions', 'tool_analytics');
|
||||
} else {
|
||||
$contextname = shorten_text($context->get_context_name(false, true), 40);
|
||||
}
|
||||
$predictioncontexts[$contextid] = $contextname;
|
||||
}
|
||||
\core_collator::asort($predictioncontexts);
|
||||
|
||||
if (!empty($predictioncontexts)) {
|
||||
$url = new \moodle_url('/report/insights/insights.php', array('modelid' => $model->get_id()));
|
||||
$singleselect = new \single_select($url, 'contextid', $predictioncontexts);
|
||||
$modeldata->insights = $singleselect->export_for_template($output);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($modeldata->insights)) {
|
||||
if ($anypredictionobtained) {
|
||||
if ($model->any_prediction_obtained()) {
|
||||
$modeldata->noinsights = get_string('noinsights', 'analytics');
|
||||
} else {
|
||||
$modeldata->noinsights = get_string('nopredictionsyet', 'analytics');
|
||||
@@ -197,11 +216,10 @@ class models_list implements \renderable, \templatable {
|
||||
|
||||
// Get predictions.
|
||||
if (!$onlycli && $modeldata->enabled && !empty($modeldata->timesplitting)) {
|
||||
$urlparams['action'] = 'scheduledanalysis';
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url,
|
||||
new \pix_icon('i/notifications', get_string('executescheduledanalysis', 'tool_analytics')),
|
||||
get_string('executescheduledanalysis', 'tool_analytics'));
|
||||
$urlparams['action'] = 'getpredictions';
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon('i/notifications',
|
||||
get_string('getpredictions', 'tool_analytics')), get_string('getpredictions', 'tool_analytics'));
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
|
||||
@@ -213,29 +231,26 @@ class models_list implements \renderable, \templatable {
|
||||
|
||||
$actionid = 'evaluate-' . $model->get_id();
|
||||
|
||||
// Evaluation options.
|
||||
$modeltimesplittingmethods = $this->timesplittings_options_for_evaluation($model, $timesplittingsforevaluation);
|
||||
|
||||
$modeltimesplittingmethods = $timesplittingmethods;
|
||||
// Include the current time-splitting method as the default selection method the model already have one.
|
||||
if ($model->get_model_obj()->timesplitting) {
|
||||
$currenttimesplitting = ['id' => 'current', 'text' => get_string('currenttimesplitting', 'tool_analytics')];
|
||||
array_unshift($modeltimesplittingmethods, $currenttimesplitting);
|
||||
}
|
||||
|
||||
$evaluateparams = [$actionid, $trainedonlyexternally];
|
||||
$evaluateparams = [$actionid, $trainedonlyexternally, $modeltimesplittingmethods];
|
||||
$PAGE->requires->js_call_amd('tool_analytics/model', 'selectEvaluationOptions', $evaluateparams);
|
||||
$urlparams['action'] = 'evaluate';
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon('i/calc', get_string('evaluate', 'tool_analytics')),
|
||||
get_string('evaluate', 'tool_analytics'), ['data-action-id' => $actionid,
|
||||
'data-timesplitting-methods' => json_encode($modeltimesplittingmethods)]);
|
||||
get_string('evaluate', 'tool_analytics'), ['data-action-id' => $actionid]);
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
|
||||
// Machine-learning-based models evaluation log.
|
||||
if (!$model->is_static() && $model->get_logs()) {
|
||||
$urlparams['action'] = 'log';
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon('i/report', get_string('viewlog', 'tool_analytics')),
|
||||
get_string('viewlog', 'tool_analytics'));
|
||||
$actionsmenu->add($icon);
|
||||
@@ -243,7 +258,7 @@ class models_list implements \renderable, \templatable {
|
||||
|
||||
// Edit model.
|
||||
$urlparams['action'] = 'edit';
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon('t/edit', get_string('edit')), get_string('edit'));
|
||||
$actionsmenu->add($icon);
|
||||
|
||||
@@ -260,7 +275,7 @@ class models_list implements \renderable, \templatable {
|
||||
$icontype = 'i/checked';
|
||||
}
|
||||
$urlparams['action'] = $action;
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon($icontype, $text), $text);
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
@@ -273,7 +288,7 @@ class models_list implements \renderable, \templatable {
|
||||
|
||||
if ($fullysetup || $istrained) {
|
||||
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
// Clear the previous action param from the URL, we will set it in JS.
|
||||
$url->remove_params('action');
|
||||
|
||||
@@ -288,31 +303,22 @@ class models_list implements \renderable, \templatable {
|
||||
}
|
||||
}
|
||||
|
||||
// Insights report.
|
||||
if (!empty($anypredictionobtained) && $model->uses_insights()) {
|
||||
$urlparams['action'] = 'insightsreport';
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$pix = new \pix_icon('i/report', get_string('insightsreport', 'tool_analytics'));
|
||||
$icon = new \action_menu_link_secondary($url, $pix, get_string('insightsreport', 'tool_analytics'));
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
|
||||
// Invalid analysables.
|
||||
$analyser = $model->get_analyser(['notimesplitting' => true]);
|
||||
if (!$analyser instanceof \core_analytics\local\analyser\sitewide) {
|
||||
$urlparams['action'] = 'invalidanalysables';
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$pix = new \pix_icon('i/report', get_string('invalidanalysables', 'tool_analytics'));
|
||||
$icon = new \action_menu_link_secondary($url, $pix, get_string('invalidanalysables', 'tool_analytics'));
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
|
||||
// Clear model.
|
||||
if (!empty($anypredictionobtained) || $model->is_trained()) {
|
||||
if (!empty($predictioncontexts) || $model->is_trained()) {
|
||||
$actionid = 'clear-' . $model->get_id();
|
||||
$PAGE->requires->js_call_amd('tool_analytics/model', 'confirmAction', [$actionid, 'clear']);
|
||||
$urlparams['action'] = 'clear';
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon('e/cleanup_messy_code',
|
||||
get_string('clearpredictions', 'tool_analytics')), get_string('clearpredictions', 'tool_analytics'),
|
||||
['data-action-id' => $actionid]);
|
||||
@@ -323,7 +329,7 @@ class models_list implements \renderable, \templatable {
|
||||
$actionid = 'delete-' . $model->get_id();
|
||||
$PAGE->requires->js_call_amd('tool_analytics/model', 'confirmAction', [$actionid, 'delete']);
|
||||
$urlparams['action'] = 'delete';
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $urlparams);
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon('t/delete',
|
||||
get_string('delete', 'tool_analytics')), get_string('delete', 'tool_analytics'),
|
||||
['data-action-id' => $actionid]);
|
||||
@@ -334,10 +340,10 @@ class models_list implements \renderable, \templatable {
|
||||
$data->models[] = $modeldata;
|
||||
}
|
||||
|
||||
$data->warnings = [];
|
||||
$data->infos = [];
|
||||
if (!$onlycli) {
|
||||
$data->warnings[] = (object)array('message' => get_string('bettercli', 'tool_analytics'), 'closebutton' => true);
|
||||
$data->warnings = array(
|
||||
(object)array('message' => get_string('bettercli', 'tool_analytics'), 'closebutton' => true)
|
||||
);
|
||||
} else {
|
||||
$url = new \moodle_url('/admin/settings.php', array('section' => 'analyticssettings'),
|
||||
'id_s_analytics_onlycli');
|
||||
@@ -346,43 +352,12 @@ class models_list implements \renderable, \templatable {
|
||||
if (is_siteadmin()) {
|
||||
$langstrid = 'clievaluationandpredictions';
|
||||
}
|
||||
$data->infos[] = (object)array('message' => get_string($langstrid, 'tool_analytics', $url->out()),
|
||||
'closebutton' => true);
|
||||
}
|
||||
|
||||
if ($misconfiguredmodels) {
|
||||
$warningstr = get_string('invalidtimesplittinginmodels', 'tool_analytics', implode(', ', $misconfiguredmodels));
|
||||
$data->warnings[] = (object)array('message' => $warningstr, 'closebutton' => true);
|
||||
$data->infos = array(
|
||||
(object)array('message' => get_string($langstrid, 'tool_analytics', $url->out()),
|
||||
'closebutton' => true)
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of time splitting methods that are available for evaluation.
|
||||
*
|
||||
* @param \core_analytics\model $model
|
||||
* @param array $timesplittingsforevaluation
|
||||
* @return array
|
||||
*/
|
||||
private function timesplittings_options_for_evaluation(\core_analytics\model $model,
|
||||
array $timesplittingsforevaluation): array {
|
||||
|
||||
$modeltimesplittingmethods = [
|
||||
['id' => 'all', 'text' => get_string('alltimesplittingmethods', 'tool_analytics')],
|
||||
];
|
||||
$potentialtimesplittingmethods = $model->get_potential_timesplittings();
|
||||
foreach ($timesplittingsforevaluation as $timesplitting) {
|
||||
if (empty($potentialtimesplittingmethods[$timesplitting->get_id()])) {
|
||||
// This time-splitting method can not be used for this model.
|
||||
continue;
|
||||
}
|
||||
$modeltimesplittingmethods[] = [
|
||||
'id' => \tool_analytics\output\helper::class_to_option($timesplitting->get_id()),
|
||||
'text' => $timesplitting->get_name()->out(),
|
||||
];
|
||||
}
|
||||
|
||||
return $modeltimesplittingmethods;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,9 +90,9 @@ class renderer extends plugin_renderer_base {
|
||||
$langstrdata = (object)array('name' => $timesplitting->get_name(), 'id' => $timesplittingid);
|
||||
|
||||
if (CLI_SCRIPT) {
|
||||
$output .= $OUTPUT->heading(get_string('scheduledanalysisresultscli', 'tool_analytics', $langstrdata), 3);
|
||||
$output .= $OUTPUT->heading(get_string('getpredictionsresultscli', 'tool_analytics', $langstrdata), 3);
|
||||
} else {
|
||||
$output .= $OUTPUT->heading(get_string('scheduledanalysisresults', 'tool_analytics', $langstrdata), 3);
|
||||
$output .= $OUTPUT->heading(get_string('getpredictionsresults', 'tool_analytics', $langstrdata), 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,17 +208,6 @@ class renderer extends plugin_renderer_base {
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer to template.
|
||||
*
|
||||
* @param \tool_analytics\output\insights_report $insightsreport
|
||||
* @return string HTML
|
||||
*/
|
||||
protected function render_insights_report(\tool_analytics\output\insights_report $insightsreport): string {
|
||||
$data = $insightsreport->export_for_template($this);
|
||||
return parent::render_from_template('tool_analytics/insights_report', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer to template.
|
||||
*
|
||||
@@ -229,26 +218,4 @@ class renderer extends plugin_renderer_base {
|
||||
$data = $invalidanalysables->export_for_template($this);
|
||||
return parent::render_from_template('tool_analytics/invalid_analysables', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an analytics disabled notification.
|
||||
*
|
||||
* @return string HTML
|
||||
*/
|
||||
public function render_analytics_disabled() {
|
||||
global $OUTPUT, $PAGE, $FULLME;
|
||||
|
||||
$PAGE->set_url($FULLME);
|
||||
$PAGE->set_title(get_string('pluginname', 'tool_analytics'));
|
||||
$PAGE->set_heading(get_string('pluginname', 'tool_analytics'));
|
||||
|
||||
$output = $OUTPUT->header();
|
||||
$output .= $OUTPUT->notification(get_string('analyticsdisabled', 'analytics'), \core\output\notification::NOTIFY_INFO);
|
||||
$output .= \html_writer::tag('a', get_string('continue'), ['class' => 'btn btn-primary',
|
||||
'href' => (new \moodle_url('/'))->out()]);
|
||||
$output .= $OUTPUT->footer();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,11 +52,6 @@ class predict_models extends \core\task\scheduled_task {
|
||||
public function execute() {
|
||||
global $OUTPUT, $PAGE;
|
||||
|
||||
if (!\core_analytics\manager::is_analytics_enabled()) {
|
||||
mtrace(get_string('analyticsdisabled', 'analytics'));
|
||||
return;
|
||||
}
|
||||
|
||||
$models = \core_analytics\manager::get_all_models(true, true);
|
||||
if (!$models) {
|
||||
mtrace(get_string('errornoenabledandtrainedmodels', 'tool_analytics'));
|
||||
@@ -64,9 +59,6 @@ class predict_models extends \core\task\scheduled_task {
|
||||
}
|
||||
|
||||
foreach ($models as $model) {
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
|
||||
$result = $model->predict();
|
||||
|
||||
// Reset the page as some indicators may call external functions that overwrite the page context.
|
||||
@@ -74,6 +66,7 @@ class predict_models extends \core\task\scheduled_task {
|
||||
|
||||
if ($result) {
|
||||
echo $OUTPUT->heading(get_string('modelresults', 'tool_analytics', $model->get_name()));
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_get_predictions_results(false, array(), $result, $model->get_analyser()->get_logs());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,11 +52,6 @@ class train_models extends \core\task\scheduled_task {
|
||||
public function execute() {
|
||||
global $OUTPUT, $PAGE;
|
||||
|
||||
if (!\core_analytics\manager::is_analytics_enabled()) {
|
||||
mtrace(get_string('analyticsdisabled', 'analytics'));
|
||||
return;
|
||||
}
|
||||
|
||||
$models = \core_analytics\manager::get_all_models(true);
|
||||
if (!$models) {
|
||||
mtrace(get_string('errornoenabledmodels', 'tool_analytics'));
|
||||
@@ -75,8 +70,6 @@ class train_models extends \core\task\scheduled_task {
|
||||
continue;
|
||||
}
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
|
||||
$result = $model->train();
|
||||
|
||||
// Reset the page as some indicators may call external functions that overwrite the page context.
|
||||
@@ -84,6 +77,8 @@ class train_models extends \core\task\scheduled_task {
|
||||
|
||||
if ($result) {
|
||||
echo $OUTPUT->heading(get_string('modelresults', 'tool_analytics', $model->get_name()));
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_get_predictions_results($result, $model->get_analyser()->get_logs());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,20 +32,20 @@ $help = "Enables the provided model.
|
||||
Options:
|
||||
--modelid Model id
|
||||
--list List models
|
||||
--analysisinterval Time splitting method full class name
|
||||
--timesplitting Time splitting method full class name
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$ php admin/tool/analytics/cli/enable_model.php --modelid=1 --analysisinterval=\"\\core\\analytics\\time_splitting\\quarters\"
|
||||
\$ php admin/tool/analytics/cli/enable_model.php --modelid=1 --timesplitting=\"\\core\\analytics\\time_splitting\\quarters\"
|
||||
";
|
||||
|
||||
// Now get cli options.
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
array(
|
||||
'help' => false,
|
||||
'list' => false,
|
||||
'modelid' => false,
|
||||
'analysisinterval' => false
|
||||
'help' => false,
|
||||
'list' => false,
|
||||
'modelid' => false,
|
||||
'timesplitting' => false
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
@@ -57,17 +57,12 @@ if ($options['help']) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!\core_analytics\manager::is_analytics_enabled()) {
|
||||
echo get_string('analyticsdisabled', 'analytics') . PHP_EOL;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['list'] || $options['modelid'] === false) {
|
||||
\tool_analytics\clihelper::list_models();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['analysisinterval'] === false) {
|
||||
if ($options['timesplitting'] === false) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
@@ -78,7 +73,7 @@ if ($options['analysisinterval'] === false) {
|
||||
$model = new \core_analytics\model($options['modelid']);
|
||||
|
||||
// Evaluate its suitability to predict accurately.
|
||||
$model->enable($options['analysisinterval']);
|
||||
$model->enable($options['timesplitting']);
|
||||
|
||||
cli_heading(get_string('success'));
|
||||
exit(0);
|
||||
|
||||
@@ -33,7 +33,8 @@ Options:
|
||||
--modelid Model id
|
||||
--list List models
|
||||
--non-interactive Not interactive questions
|
||||
--analysisinterval Restrict the evaluation to 1 single analysis interval (Optional)
|
||||
--timesplitting Restrict the evaluation to 1 single time splitting method (Optional)
|
||||
--filter Analyser dependant. e.g. A courseid would evaluate the model using a single course (Optional)
|
||||
--mode 'configuration' or 'trainedmodel'. You can only use mode=trainedmodel when the trained" .
|
||||
" model was imported" . "
|
||||
--reuse-prev-analysed Reuse recently analysed courses instead of analysing the whole site. Set it to false while" .
|
||||
@@ -41,7 +42,7 @@ Options:
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$ php admin/tool/analytics/cli/evaluate_model.php --modelid=1 --analysisinterval='\\core\\analytics\\time_splitting\\quarters'
|
||||
\$ php admin/tool/analytics/cli/evaluate_model.php --modelid=1 --timesplitting='\\core\\analytics\\time_splitting\\quarters' --filter=123,321
|
||||
";
|
||||
|
||||
// Now get cli options.
|
||||
@@ -50,10 +51,11 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'help' => false,
|
||||
'modelid' => false,
|
||||
'list' => false,
|
||||
'analysisinterval' => false,
|
||||
'timesplitting' => false,
|
||||
'mode' => 'configuration',
|
||||
'reuse-prev-analysed' => true,
|
||||
'non-interactive' => false,
|
||||
'filter' => false
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
@@ -65,11 +67,6 @@ if ($options['help']) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!\core_analytics\manager::is_analytics_enabled()) {
|
||||
echo get_string('analyticsdisabled', 'analytics') . PHP_EOL;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['list']) {
|
||||
\tool_analytics\clihelper::list_models();
|
||||
exit(0);
|
||||
@@ -81,12 +78,17 @@ if ($options['modelid'] === false) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Reformat them as an array.
|
||||
if ($options['filter'] !== false) {
|
||||
$options['filter'] = explode(',', $options['filter']);
|
||||
}
|
||||
|
||||
if ($options['mode'] !== 'configuration' && $options['mode'] !== 'trainedmodel') {
|
||||
cli_error('Error: The provided mode is not supported');
|
||||
}
|
||||
|
||||
if ($options['mode'] == 'trainedmodel' && $options['analysisinterval']) {
|
||||
cli_error('Sorry, no analysis interval can be specified when using \'trainedmodel\' mode.');
|
||||
if ($options['mode'] == 'trainedmodel' && $options['timesplitting']) {
|
||||
cli_error('Sorry, no time splitting method can be specified when using \'trainedmodel\' mode.');
|
||||
}
|
||||
|
||||
// We need admin permissions.
|
||||
@@ -100,10 +102,9 @@ if ($options['reuse-prev-analysed']) {
|
||||
mtrace(get_string('evaluationinbatches', 'tool_analytics'));
|
||||
}
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
|
||||
$analyseroptions = array(
|
||||
'timesplitting' => $options['analysisinterval'],
|
||||
'filter' => $options['filter'],
|
||||
'timesplitting' => $options['timesplitting'],
|
||||
'reuseprevanalysed' => $options['reuse-prev-analysed'],
|
||||
'mode' => $options['mode'],
|
||||
);
|
||||
@@ -113,6 +114,7 @@ $results = $model->evaluate($analyseroptions);
|
||||
// Reset the page as some indicators may call external functions that overwrite the page context.
|
||||
\tool_analytics\output\helper::reset_page();
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_evaluate_results($results, $model->get_analyser()->get_logs());
|
||||
|
||||
// Check that we have, at leasa,t 1 valid dataset (not necessarily good) to use.
|
||||
|
||||
@@ -27,13 +27,6 @@ require_once(__DIR__ . '/../../../config.php');
|
||||
require_login();
|
||||
\core_analytics\manager::check_can_manage_models();
|
||||
|
||||
if (!\core_analytics\manager::is_analytics_enabled()) {
|
||||
$PAGE->set_context(\context_system::instance());
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_analytics_disabled();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$returnurl = new \moodle_url('/admin/tool/analytics/index.php');
|
||||
$url = new \moodle_url('/admin/tool/analytics/createmodel.php');
|
||||
$title = get_string('createmodel', 'tool_analytics');
|
||||
@@ -45,8 +38,6 @@ $targets = array_filter(\core_analytics\manager::get_all_targets(), function($ta
|
||||
return (!$target->based_on_assumptions());
|
||||
});
|
||||
|
||||
// Set 'supportscontexts' to true as at this stage we don't know if the contexts are supported by
|
||||
// the selected target.
|
||||
$customdata = array(
|
||||
'trainedmodel' => false,
|
||||
'staticmodel' => false,
|
||||
@@ -54,7 +45,6 @@ $customdata = array(
|
||||
'indicators' => \core_analytics\manager::get_all_indicators(),
|
||||
'timesplittings' => \core_analytics\manager::get_all_time_splittings(),
|
||||
'predictionprocessors' => \core_analytics\manager::get_all_prediction_processors(),
|
||||
'supportscontexts' => true,
|
||||
);
|
||||
$mform = new \tool_analytics\output\form\edit_model(null, $customdata);
|
||||
|
||||
@@ -89,8 +79,8 @@ if ($mform->is_cancelled()) {
|
||||
$indicators = array_diff_key($indicators, $invalidindicators);
|
||||
}
|
||||
|
||||
// Update the model with the rest of the data provided in the form.
|
||||
$model->update($data->enabled, $indicators, $timesplitting, $predictionsprocessor, $data->contexts);
|
||||
// Update the model with the valid list of indicators.
|
||||
$model->update($data->enabled, $indicators, $timesplitting, $predictionsprocessor);
|
||||
|
||||
$message = '';
|
||||
$messagetype = \core\output\notification::NOTIFY_SUCCESS;
|
||||
|
||||
@@ -1,37 +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 analytics webservice definitions.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$functions = array(
|
||||
|
||||
'tool_analytics_potential_contexts' => array(
|
||||
'classname' => 'tool_analytics\external',
|
||||
'methodname' => 'potential_contexts',
|
||||
'description' => 'Retrieve the list of potential contexts for a model.',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
|
||||
),
|
||||
);
|
||||
@@ -27,13 +27,6 @@ require_once(__DIR__ . '/../../../config.php');
|
||||
require_login();
|
||||
\core_analytics\manager::check_can_manage_models();
|
||||
|
||||
if (!\core_analytics\manager::is_analytics_enabled()) {
|
||||
$PAGE->set_context(\context_system::instance());
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_analytics_disabled();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$returnurl = new \moodle_url('/admin/tool/analytics/index.php');
|
||||
$url = new \moodle_url('/admin/tool/analytics/importmodel.php');
|
||||
$title = get_string('importmodel', 'tool_analytics');
|
||||
@@ -63,4 +56,4 @@ if ($form->is_cancelled()) {
|
||||
|
||||
echo $OUTPUT->header();
|
||||
$form->display();
|
||||
echo $OUTPUT->footer();
|
||||
echo $OUTPUT->footer();
|
||||
@@ -1 +0,0 @@
|
||||
getpredictions,tool_analytics
|
||||
@@ -23,14 +23,9 @@
|
||||
*/
|
||||
|
||||
$string['accuracy'] = 'Accuracy';
|
||||
$string['actions'] = 'Actions';
|
||||
$string['actionsexecutedbyusers'] = 'Actions executed by users';
|
||||
$string['actionsexecutedbyusersfor'] = 'Actions executed by users for "{$a}" model';
|
||||
$string['actionexecutedgroupedusefulness'] = 'Grouped actions';
|
||||
$string['allpredictions'] = 'All predictions';
|
||||
$string['alltimesplittingmethods'] = 'All analysis intervals';
|
||||
$string['alltimesplittingmethods'] = 'All time-splitting methods';
|
||||
$string['analysingsitedata'] = 'Analysing the site';
|
||||
$string['analysis'] = 'Analysis';
|
||||
$string['analyticmodels'] = 'Analytics models';
|
||||
$string['bettercli'] = 'Evaluating models and generating predictions may involve heavy processing. It is recommended to run these actions from the command line.';
|
||||
$string['cantguessstartdate'] = 'Can\'t guess the start date';
|
||||
@@ -38,24 +33,22 @@ $string['cantguessenddate'] = 'Can\'t guess the end date';
|
||||
$string['classdoesnotexist'] = 'Class {$a} does not exist';
|
||||
$string['clearpredictions'] = 'Clear predictions';
|
||||
$string['clearmodelpredictions'] = 'Are you sure you want to clear all "{$a}" predictions?';
|
||||
$string['clienablemodel'] = 'You can enable the model by selecting an analysis interval by its ID. Note that you can also enable it later using the web interface (\'none\' to exit).';
|
||||
$string['clienablemodel'] = 'You can enable the model by selecting a time-splitting method by its ID. Note that you can also enable it later using the web interface (\'none\' to exit).';
|
||||
$string['clievaluationandpredictions'] = 'A scheduled task iterates through enabled models and gets predictions. Models evaluation via the web interface is disabled. You can allow these processes to be executed manually via the web interface by disabling the <a href="{$a}">\'onlycli\'</a> analytics setting.';
|
||||
$string['clievaluationandpredictionsnoadmin'] = 'A scheduled task iterates through enabled models and gets predictions. Models evaluation via the web interface is disabled. It may be enabled by a site administrator.';
|
||||
$string['component'] = 'Component';
|
||||
$string['componentcore'] = 'Core';
|
||||
$string['componentselect'] = 'Select all models provided by the component \'{$a}\'';
|
||||
$string['componentselectnone'] = 'Unselect all';
|
||||
$string['contexts'] = 'Contexts';
|
||||
$string['contexts_help'] = 'The model will be limited to this set of contexts. No context restrictions will be applied if no contexts are selected.';
|
||||
$string['createmodel'] = 'Create model';
|
||||
$string['currenttimesplitting'] = 'Current analysis interval';
|
||||
$string['currenttimesplitting'] = 'Current time-splitting method';
|
||||
$string['delete'] = 'Delete';
|
||||
$string['deletemodelconfirmation'] = 'Are you sure you want to delete "{$a}"? These changes cannot be reverted.';
|
||||
$string['disabled'] = 'Disabled';
|
||||
$string['editmodel'] = 'Edit "{$a}" model';
|
||||
$string['edittrainedwarning'] = 'This model has already been trained. Note that changing its indicators or its analysis interval will delete its previous predictions and start generating new predictions.';
|
||||
$string['edittrainedwarning'] = 'This model has already been trained. Note that changing its indicators or its time-splitting method will delete its previous predictions and start generating new predictions.';
|
||||
$string['enabled'] = 'Enabled';
|
||||
$string['errorcantenablenotimesplitting'] = 'You need to select an analysis interval before enabling the model';
|
||||
$string['errorcantenablenotimesplitting'] = 'You need to select a time-splitting method before enabling the model';
|
||||
$string['errornoenabledandtrainedmodels'] = 'There are no enabled and trained models to predict.';
|
||||
$string['errornoenabledmodels'] = 'There are no enabled models to train.';
|
||||
$string['errornoexport'] = 'Only trained models can be exported';
|
||||
@@ -78,13 +71,15 @@ $string['evaluationmodecoltrainedmodel'] = 'Trained model';
|
||||
$string['evaluationmodecolconfiguration'] = 'Configuration';
|
||||
$string['evaluationmodeconfiguration'] = 'Evaluate the model configuration';
|
||||
$string['evaluationinbatches'] = 'The site contents are calculated and stored in batches. The evaluation process may be stopped at any time. The next time it is run, it will continue from the point when it was stopped.';
|
||||
$string['executescheduledanalysis'] = 'Execute scheduled analysis';
|
||||
$string['export'] = 'Export';
|
||||
$string['exportincludeweights'] = 'Include the weights of the trained model';
|
||||
$string['exportmodel'] = 'Export configuration';
|
||||
$string['exporttrainingdata'] = 'Export training data';
|
||||
$string['getpredictionsresultscli'] = 'Results using {$a->name} (id: {$a->id}) time-splitting method';
|
||||
$string['getpredictionsresults'] = 'Results using {$a->name} time-splitting method';
|
||||
$string['extrainfo'] = 'Info';
|
||||
$string['generalerror'] = 'Evaluation error. Status code {$a}';
|
||||
$string['getpredictions'] = 'Get predictions';
|
||||
$string['goodmodel'] = 'This is a good model for using to obtain predictions. Enable it to start obtaining predictions.';
|
||||
$string['importmodel'] = 'Import model';
|
||||
$string['indicators'] = 'Indicators';
|
||||
@@ -92,7 +87,6 @@ $string['indicators_help'] = 'The indicators are what you think will lead to an
|
||||
$string['indicators_link'] = 'Indicators';
|
||||
$string['indicatorsnum'] = 'Number of indicators: {$a}';
|
||||
$string['info'] = 'Info';
|
||||
$string['insightsreport'] = 'Insights report';
|
||||
$string['ignoreversionmismatches'] = 'Ignore version mismatches';
|
||||
$string['ignoreversionmismatchescheckbox'] = 'Ignore the differences between this site version and the original site version.';
|
||||
$string['importedsuccessfully'] = 'The model has been successfully imported.';
|
||||
@@ -100,10 +94,7 @@ $string['insights'] = 'Insights';
|
||||
$string['invalidanalysables'] = 'Invalid site elements';
|
||||
$string['invalidanalysablesinfo'] = 'This page lists analysable elements that can\'t be used by this prediction model. The listed elements can\'t be used either to train the prediction model nor can the prediction model obtain predictions for them.';
|
||||
$string['invalidanalysablestable'] = 'Invalid site analysable elements table';
|
||||
$string['invalidcurrenttimesplitting'] = 'The current analysis interval is invalid for the target of this model. Please select a different interval.';
|
||||
$string['invalidindicatorsremoved'] = 'A new model has been added. Indicators that don\'t work with the selected target have been automatically removed.';
|
||||
$string['invalidtimesplitting'] = 'The selected analysis interval is invalid for the selected target.';
|
||||
$string['invalidtimesplittinginmodels'] = 'The analysis interval used by some of the models is invalid. Please select a different interval for the following models: {$a}';
|
||||
$string['invalidindicatorsremoved'] = 'A new model has been added. Indicators that do not work with the selected target have been automatically removed.';
|
||||
$string['invalidprediction'] = 'Invalid to get predictions';
|
||||
$string['invalidtraining'] = 'Invalid to train the model';
|
||||
$string['loginfo'] = 'Log extra info';
|
||||
@@ -112,13 +103,12 @@ $string['modelid'] = 'Model ID';
|
||||
$string['modelinvalidanalysables'] = 'Invalid analysable elements for "{$a}" model';
|
||||
$string['modelname'] = 'Model name';
|
||||
$string['modelresults'] = '{$a} results';
|
||||
$string['modeltimesplitting'] = 'Analysis interval';
|
||||
$string['modeltimesplitting'] = 'Time splitting';
|
||||
$string['newmodel'] = 'New model';
|
||||
$string['nextpage'] = 'Next page';
|
||||
$string['noactionsfound'] = 'Users have not executed any actions on the generated insights.';
|
||||
$string['nodatatoevaluate'] = 'There is no data to evaluate the model';
|
||||
$string['nodatatopredict'] = 'No new elements to get predictions for.';
|
||||
$string['nodatatotrain'] = 'There is no new data that can be used for training.';
|
||||
$string['nodatatopredict'] = 'No new elements to get predictions for';
|
||||
$string['nodatatotrain'] = 'There is no new data that can be used for training';
|
||||
$string['noinvalidanalysables'] = 'This site does not contain any invalid analysable element.';
|
||||
$string['notdefined'] = 'Not yet defined';
|
||||
$string['pluginname'] = 'Analytic models';
|
||||
@@ -135,14 +125,12 @@ $string['restoredefaultsome'] = 'Succesfully re-created {$a->count} new model(s)
|
||||
$string['restoredefaultsubmit'] = 'Restore selected';
|
||||
$string['samestartdate'] = 'Current start date is good';
|
||||
$string['sameenddate'] = 'Current end date is good';
|
||||
$string['scheduledanalysisresults'] = 'Results using {$a->name} analysis interval';
|
||||
$string['scheduledanalysisresultscli'] = 'Results using {$a->name} (id: {$a->id}) analysis interval';
|
||||
$string['selecttimesplittingforevaluation'] = 'Select the analysis interval you want to use to evaluate the model configuration.';
|
||||
$string['selecttimesplittingforevaluation'] = 'Select the time-splitting method you want to use to evaluate the model configuration.';
|
||||
$string['target'] = 'Target';
|
||||
$string['target_help'] = 'The target is what the model will predict.';
|
||||
$string['target_link'] = 'Targets';
|
||||
$string['timesplittingnotdefined'] = 'No analysis interval is defined.';
|
||||
$string['timesplittingnotdefined_help'] = 'You need to select an analysis interval before enabling the model.';
|
||||
$string['timesplittingnotdefined'] = 'Time splitting is not defined.';
|
||||
$string['timesplittingnotdefined_help'] = 'You need to select a time-splitting method before enabling the model.';
|
||||
$string['trainandpredictmodel'] = 'Training model and calculating predictions';
|
||||
$string['trainingprocessfinished'] = 'Training process finished';
|
||||
$string['trainingresults'] = 'Training results';
|
||||
@@ -152,6 +140,3 @@ $string['viewlog'] = 'Evaluation log';
|
||||
$string['weeksenddateautomaticallyset'] = 'End date automatically set based on start date and the number of sections';
|
||||
$string['weeksenddatedefault'] = 'End date automatically calculated from the course start date.';
|
||||
$string['privacy:metadata'] = 'The Analytic models plugin does not store any personal data.';
|
||||
|
||||
// Deprecated since Moodle 3.8.
|
||||
$string['getpredictions'] = 'Get predictions';
|
||||
|
||||
@@ -33,13 +33,6 @@ require_login();
|
||||
$model = new \core_analytics\model($id);
|
||||
\core_analytics\manager::check_can_manage_models();
|
||||
|
||||
if (!\core_analytics\manager::is_analytics_enabled()) {
|
||||
$PAGE->set_context(\context_system::instance());
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_analytics_disabled();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$returnurl = new \moodle_url('/admin/tool/analytics/index.php');
|
||||
$params = array('id' => $id, 'action' => $action);
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $params);
|
||||
@@ -52,8 +45,8 @@ switch ($action) {
|
||||
case 'evaluate':
|
||||
$title = get_string('evaluatemodel', 'tool_analytics');
|
||||
break;
|
||||
case 'scheduledanalysis':
|
||||
$title = get_string('analysis', 'tool_analytics');
|
||||
case 'getpredictions':
|
||||
$title = get_string('getpredictions', 'tool_analytics');
|
||||
break;
|
||||
case 'log':
|
||||
$title = get_string('viewlog', 'tool_analytics');
|
||||
@@ -76,9 +69,6 @@ switch ($action) {
|
||||
case 'clear':
|
||||
$title = get_string('clearpredictions', 'tool_analytics');
|
||||
break;
|
||||
case 'insightsreport':
|
||||
$title = get_string('insightsreport', 'tool_analytics');
|
||||
break;
|
||||
case 'invalidanalysables':
|
||||
$title = get_string('invalidanalysables', 'tool_analytics');
|
||||
break;
|
||||
@@ -120,21 +110,13 @@ switch ($action) {
|
||||
case 'edit':
|
||||
confirm_sesskey();
|
||||
|
||||
$invalidcurrenttimesplitting = $model->invalid_timesplitting_selected();
|
||||
$potentialtimesplittings = $model->get_potential_timesplittings();
|
||||
|
||||
$customdata = array(
|
||||
'id' => $model->get_id(),
|
||||
'trainedmodel' => $model->is_trained(),
|
||||
'staticmodel' => $model->is_static(),
|
||||
'invalidcurrenttimesplitting' => (!empty($invalidcurrenttimesplitting)),
|
||||
'targetclass' => $model->get_target()->get_id(),
|
||||
'targetname' => $model->get_target()->get_name(),
|
||||
'indicators' => $model->get_potential_indicators(),
|
||||
'timesplittings' => $potentialtimesplittings,
|
||||
'predictionprocessors' => \core_analytics\manager::get_all_prediction_processors(),
|
||||
'supportscontexts' => ($model->get_analyser(['notimesplitting' => true]))::context_restriction_support(),
|
||||
'contexts' => $model->get_contexts(),
|
||||
'timesplittings' => \core_analytics\manager::get_all_time_splittings(),
|
||||
'predictionprocessors' => \core_analytics\manager::get_all_prediction_processors()
|
||||
);
|
||||
$mform = new \tool_analytics\output\form\edit_model(null, $customdata);
|
||||
|
||||
@@ -159,11 +141,7 @@ switch ($action) {
|
||||
$predictionsprocessor = false;
|
||||
}
|
||||
|
||||
if (!isset($data->contexts)) {
|
||||
$data->contexts = null;
|
||||
}
|
||||
|
||||
$model->update($data->enabled, $indicators, $timesplitting, $predictionsprocessor, $data->contexts);
|
||||
$model->update($data->enabled, $indicators, $timesplitting, $predictionsprocessor);
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
@@ -174,9 +152,6 @@ switch ($action) {
|
||||
$callable = array('\tool_analytics\output\helper', 'class_to_option');
|
||||
$modelobj->indicators = array_map($callable, json_decode($modelobj->indicators));
|
||||
$modelobj->timesplitting = \tool_analytics\output\helper::class_to_option($modelobj->timesplitting);
|
||||
if ($modelobj->contextids) {
|
||||
$modelobj->contexts = array_map($callable, json_decode($modelobj->contextids));
|
||||
}
|
||||
$modelobj->predictionsprocessor = \tool_analytics\output\helper::class_to_option($modelobj->predictionsprocessor);
|
||||
$mform->set_data($modelobj);
|
||||
$mform->display();
|
||||
@@ -225,7 +200,7 @@ switch ($action) {
|
||||
echo $renderer->render_evaluate_results($results, $model->get_analyser()->get_logs());
|
||||
break;
|
||||
|
||||
case 'scheduledanalysis':
|
||||
case 'getpredictions':
|
||||
confirm_sesskey();
|
||||
|
||||
if ($onlycli) {
|
||||
@@ -298,18 +273,6 @@ switch ($action) {
|
||||
redirect($returnurl);
|
||||
break;
|
||||
|
||||
case 'insightsreport':
|
||||
|
||||
$contextid = optional_param('contextid', null, PARAM_INT);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$renderable = new \tool_analytics\output\insights_report($model, $contextid);
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render($renderable);
|
||||
|
||||
break;
|
||||
|
||||
case 'invalidanalysables':
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
@@ -27,13 +27,6 @@ require_once(__DIR__ . '/../../../config.php');
|
||||
require_login();
|
||||
\core_analytics\manager::check_can_manage_models();
|
||||
|
||||
if (!\core_analytics\manager::is_analytics_enabled()) {
|
||||
$PAGE->set_context(\context_system::instance());
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_analytics_disabled();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$confirmed = optional_param('confirmed', false, PARAM_BOOL);
|
||||
$restoreids = optional_param_array('restoreid', [], PARAM_ALPHANUM);
|
||||
|
||||
|
||||
@@ -24,7 +24,5 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
if (\core_analytics\manager::is_analytics_enabled()) {
|
||||
$ADMIN->add('analytics', new admin_externalpage('analyticmodels', get_string('analyticmodels', 'tool_analytics'),
|
||||
"$CFG->wwwroot/$CFG->admin/tool/analytics/index.php", 'moodle/analytics:managemodels'));
|
||||
}
|
||||
$ADMIN->add('analytics', new admin_externalpage('analyticmodels', get_string('analyticmodels', 'tool_analytics'),
|
||||
"$CFG->wwwroot/$CFG->admin/tool/analytics/index.php", 'moodle/analytics:managemodels'));
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_analytics/insights_report
|
||||
|
||||
Template for the insights report.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"modelname": "Not engaging courses",
|
||||
"noactions": {
|
||||
"message": "Users have not executed any actions on the generated insights.",
|
||||
"announce": "true"
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
<div class="box">
|
||||
<h3>{{#str}}actionsexecutedbyusersfor, tool_analytics, {{modelname}}{{/str}}</h3>
|
||||
|
||||
{{#contextselect}}
|
||||
<div class="mt-3">
|
||||
{{> core/single_select }}
|
||||
</div>
|
||||
{{/contextselect}}
|
||||
|
||||
{{#noactions}}
|
||||
<div class="mt-3 mb-1">
|
||||
{{> core/notification_info}}
|
||||
</div>
|
||||
{{/noactions}}
|
||||
{{^noanalysables}}
|
||||
<div class="row">
|
||||
<div class="col-xl-6">
|
||||
{{{separatedchart}}}
|
||||
</div>
|
||||
<div class="col-xl-6">
|
||||
{{{groupedchart}}}
|
||||
</div>
|
||||
</div>
|
||||
{{/noanalysables}}
|
||||
</div>
|
||||
@@ -58,7 +58,7 @@
|
||||
"models": [
|
||||
{
|
||||
"defid": "id24680aceg",
|
||||
"targetname": "Courses at risk of not starting",
|
||||
"targetname": "No teaching",
|
||||
"targetclass": "\\core\\analytics\\target\\no_teaching",
|
||||
"indicatorsnum": 2,
|
||||
"indicators": [
|
||||
|
||||
@@ -15,55 +15,55 @@ Feature: Restoring default models
|
||||
Scenario: Restore a single deleted default model
|
||||
Given I log in as "manager"
|
||||
And I navigate to "Analytics > Analytics models" in site administration
|
||||
# Delete 'Courses at risk of not starting' model.
|
||||
And I click on "Delete" "link" in the "Courses at risk of not starting" "table_row"
|
||||
# Delete 'No teaching' model.
|
||||
And I click on "Delete" "link" in the "No teaching" "table_row"
|
||||
And I should see "Analytics models"
|
||||
And I should not see "Courses at risk of not starting"
|
||||
And I should not see "No teaching"
|
||||
# Delete 'Students at risk of dropping out' model.
|
||||
And I click on "Delete" "link" in the "Students at risk of dropping out" "table_row"
|
||||
And I should see "Analytics models"
|
||||
And I should not see "Students at risk of dropping out"
|
||||
# Go to the page for restoring deleted models.
|
||||
When I click on "Restore default models" "link"
|
||||
And I should see "Courses at risk of not starting"
|
||||
And I should see "No teaching"
|
||||
And I should see "Students at risk of dropping out"
|
||||
# Select and restore the 'Courses at risk of not starting' model.
|
||||
And I set the field with xpath "//tr[contains(normalize-space(.), 'Courses at risk of not starting')]//input[@type='checkbox']" to "1"
|
||||
# Select and restore the 'No teaching' model.
|
||||
And I set the field with xpath "//tr[contains(normalize-space(.), 'No teaching')]//input[@type='checkbox']" to "1"
|
||||
And I click on "Restore selected" "button"
|
||||
Then I should see "Succesfully re-created 1 new model(s)."
|
||||
And I should see "Analytics models"
|
||||
And I should see "Courses at risk of not starting"
|
||||
And I should see "No teaching"
|
||||
And I should not see "Students at risk of dropping out"
|
||||
|
||||
Scenario: Restore multiple deleted default models at once
|
||||
Given I log in as "manager"
|
||||
And I navigate to "Analytics > Analytics models" in site administration
|
||||
# Delete 'Courses at risk of not starting' model.
|
||||
And I click on "Delete" "link" in the "Courses at risk of not starting" "table_row"
|
||||
# Delete 'No teaching' model.
|
||||
And I click on "Delete" "link" in the "No teaching" "table_row"
|
||||
And I should see "Analytics models"
|
||||
And I should not see "Courses at risk of not starting"
|
||||
And I should not see "No teaching"
|
||||
# Delete 'Students at risk of dropping out' model.
|
||||
And I click on "Delete" "link" in the "Students at risk of dropping out" "table_row"
|
||||
And I should see "Analytics models"
|
||||
And I should not see "Students at risk of dropping out"
|
||||
# Go to the page for restoring deleted models.
|
||||
When I click on "Restore default models" "link"
|
||||
And I should see "Courses at risk of not starting"
|
||||
And I should see "No teaching"
|
||||
And I should see "Students at risk of dropping out"
|
||||
# Select and restore both models.
|
||||
And I set the field with xpath "//tr[contains(normalize-space(.), 'Courses at risk of not starting')]//input[@type='checkbox']" to "1"
|
||||
And I set the field with xpath "//tr[contains(normalize-space(.), 'No teaching')]//input[@type='checkbox']" to "1"
|
||||
And I set the field with xpath "//tr[contains(normalize-space(.), 'Students at risk of dropping out')]//input[@type='checkbox']" to "1"
|
||||
And I click on "Restore selected" "button"
|
||||
Then I should see "Succesfully re-created 2 new model(s)."
|
||||
And I should see "Analytics models"
|
||||
And I should see "Courses at risk of not starting"
|
||||
And I should see "No teaching"
|
||||
And I should see "Students at risk of dropping out"
|
||||
|
||||
Scenario: Going to the restore page while no models can be restored
|
||||
Given I log in as "manager"
|
||||
And I navigate to "Analytics > Analytics models" in site administration
|
||||
And I should see "Analytics models"
|
||||
And I should see "Courses at risk of not starting"
|
||||
And I should see "No teaching"
|
||||
When I click on "Restore default models" "link"
|
||||
Then I should see "All default models provided by core and installed plugins have been created. No new models were found; there is nothing to restore."
|
||||
And I click on "Back" "link"
|
||||
@@ -73,23 +73,23 @@ Feature: Restoring default models
|
||||
Scenario: User can select and restore all missing models
|
||||
Given I log in as "manager"
|
||||
And I navigate to "Analytics > Analytics models" in site administration
|
||||
# Delete 'Courses at risk of not starting' model.
|
||||
And I click on "Actions" "link" in the "Courses at risk of not starting" "table_row"
|
||||
And I click on "Delete" "link" in the "Courses at risk of not starting" "table_row"
|
||||
# Delete 'No teaching' model.
|
||||
And I click on "Actions" "link" in the "No teaching" "table_row"
|
||||
And I click on "Delete" "link" in the "No teaching" "table_row"
|
||||
And I click on "Delete" "button" in the "Delete" "dialogue"
|
||||
And I should see "Analytics models"
|
||||
And I should not see "Courses at risk of not starting"
|
||||
And I should not see "No teaching"
|
||||
# Delete 'Students at risk of dropping out' model.
|
||||
And I click on "Actions" "link" in the "Students at risk of dropping out" "table_row"
|
||||
And I click on "Delete" "link" in the "Students at risk of dropping out" "table_row"
|
||||
And I click on "Delete" "button" in the "Delete" "dialogue"
|
||||
And I should see "Analytics models"
|
||||
And I should not see "Courses at risk of not starting"
|
||||
And I should not see "No teaching"
|
||||
And I should not see "Students at risk of dropping out"
|
||||
# Go to the page for restoring deleted models.
|
||||
And I click on "New model" "link"
|
||||
And I click on "Restore default models" "link"
|
||||
And I should see "Courses at risk of not starting"
|
||||
And I should see "No teaching"
|
||||
And I should see "Students at risk of dropping out"
|
||||
# Attempt to submit the form without selecting any model.
|
||||
And I click on "Restore selected" "button"
|
||||
@@ -99,5 +99,5 @@ Feature: Restoring default models
|
||||
And I click on "Restore selected" "button"
|
||||
Then I should see "Succesfully re-created 2 new model(s)."
|
||||
And I should see "Analytics models"
|
||||
And I should see "Courses at risk of not starting"
|
||||
And I should see "No teaching"
|
||||
And I should see "Students at risk of dropping out"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user