Compare commits
285 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e4341402a | |||
| 0a5af1649f | |||
| b194f1a2e3 | |||
| 14ecaeea08 | |||
| c28de2e556 | |||
| 706571e94f | |||
| 0801d7dc95 | |||
| 77da99fe77 | |||
| c88b34c0fa | |||
| 23dbc35541 | |||
| e9609517d2 | |||
| efc9c7572b | |||
| 05263df3b0 | |||
| dc30c8fa2f | |||
| 8b3ee7d311 | |||
| 5823f7e1bd | |||
| 4dfa466691 | |||
| 226ca38be3 | |||
| 145e6deee7 | |||
| d53a5789a8 | |||
| 640534676c | |||
| 49371ca433 | |||
| 5697a42fc2 | |||
| 0ba4ffe353 | |||
| 31bae37249 | |||
| 2423a989fc | |||
| 67103939ac | |||
| 4f91eb0ba1 | |||
| 07cb3212c5 | |||
| 550e03463b | |||
| 4f2c5e18c0 | |||
| 73aad88f63 | |||
| 88d7acff69 | |||
| 59f5f4a9df | |||
| 14509286e4 | |||
| 6b661ab0a2 | |||
| 57cb067173 | |||
| 65e5e9f454 | |||
| 7984ae3581 | |||
| f786e59224 | |||
| c46c38d355 | |||
| 67c112bf9c | |||
| 61812e3dd8 | |||
| eaeed5b281 | |||
| d259cafd3c | |||
| e632f4ece5 | |||
| aff28d6243 | |||
| 653ec0d0b0 | |||
| 62a71e4a17 | |||
| 35657809ed | |||
| c61c5009a8 | |||
| fe9e229248 | |||
| db500a32a1 | |||
| 75ead1e8cf | |||
| c7c9f4a46e | |||
| 8e9c8f6583 | |||
| 037bf82652 | |||
| 5341d76031 | |||
| e71b162d09 | |||
| 58099bd24d | |||
| c7da8264d0 | |||
| ca47e80375 | |||
| 40e7ac2c70 | |||
| d7a2d1a2c8 | |||
| d971e7dffe | |||
| 56855a2842 | |||
| 7563339608 | |||
| 89d85f5a4b | |||
| 74823e4e45 | |||
| 7a0e1cd70c | |||
| 4534c7b531 | |||
| 16f2fe5514 | |||
| eee0d699c3 | |||
| 0d74c11cf7 | |||
| 6aebb4375f | |||
| 32f2e90522 | |||
| 8e62bc79c7 | |||
| c36c507277 | |||
| 813f289b60 | |||
| e318be3772 | |||
| a67ff779d5 | |||
| 222a87ae98 | |||
| 8d0dd90520 | |||
| cccb1a6d21 | |||
| 3d8a2c5cd9 | |||
| ebe0cf3ed4 | |||
| 9938165bb8 | |||
| 101271fd28 | |||
| 4ca3991e56 | |||
| f6736dedd1 | |||
| 5be425cf9e | |||
| 0f0b45fd59 | |||
| f05e2e6690 | |||
| b0b68a0bd4 | |||
| 7abe668bd6 | |||
| b31f3097c2 | |||
| 82b3050e72 | |||
| 153f74956d | |||
| 8b017ea78c | |||
| cea093be87 | |||
| 970c74b280 | |||
| 04e5ef2a3e | |||
| b2a90870ce | |||
| ae60722b14 | |||
| 26277438ed | |||
| 17eb11f801 | |||
| 3ae9ed890f | |||
| 0ff0caefc0 | |||
| a5efab81c9 | |||
| bc84e4e4ae | |||
| e70d1e66d6 | |||
| e256446c75 | |||
| e4780bf151 | |||
| 4b8d403606 | |||
| 8a32c0fdb3 | |||
| a27fa5b50e | |||
| 3cf5c5152e | |||
| c484b0574e | |||
| dec00f6a53 | |||
| d51518e24d | |||
| 94925c38d0 | |||
| 7abd8de776 | |||
| a358927e9e | |||
| 49e5b8438c | |||
| 2b026b44f7 | |||
| 63bfa5afdb | |||
| d08cd28dae | |||
| 5d7d2c0a45 | |||
| 9eb46e7d75 | |||
| 481220cb4c | |||
| d47b680074 | |||
| 76b6407cb8 | |||
| ca1e040bbf | |||
| 1312c844a1 | |||
| a21c3208ea | |||
| a1692f6362 | |||
| 9bcb6e1bec | |||
| 192a355707 | |||
| 3709386ed5 | |||
| c159483796 | |||
| 9bdff1611b | |||
| ca18b0c33d | |||
| 0fb6f059a9 | |||
| 7dc35ed9d2 | |||
| 481a5ce58b | |||
| af153671de | |||
| 48b929667e | |||
| 6dc00c8423 | |||
| 290ec233f5 | |||
| 56aa74ed3c | |||
| fe3d722d69 | |||
| 792560a608 | |||
| 7041dc6f8a | |||
| 57fb48743f | |||
| a9712dacbe | |||
| c0f4b8b3c1 | |||
| 9a9b9e53f0 | |||
| e1d15194bc | |||
| 5b2f32ca92 | |||
| a53a439c08 | |||
| 2c12e7f534 | |||
| 7255306cc8 | |||
| b545e84294 | |||
| 72ebc73897 | |||
| 856e1c24c2 | |||
| 5b1dffd5b0 | |||
| 6ebff58d8c | |||
| 54bee25c65 | |||
| 355fefbe71 | |||
| 11a24a823b | |||
| 75797500ae | |||
| e2b8d30052 | |||
| 571e862135 | |||
| 1e9ba1916b | |||
| ddd849e1d5 | |||
| 760ed1dfde | |||
| 95a6fe8b05 | |||
| 0fca28e197 | |||
| cc5235bb77 | |||
| 1099b7ce1d | |||
| dc403b8386 | |||
| 23bec87007 | |||
| 924db1a0a6 | |||
| f8326931a1 | |||
| 0a98628841 | |||
| d72a096797 | |||
| a6379acaf3 | |||
| e002d8c2db | |||
| 2b7268d645 | |||
| 6e34867b93 | |||
| 9a6e95557f | |||
| 88daff0ff3 | |||
| 3309800768 | |||
| adbba36a63 | |||
| 37ff4578be | |||
| cbc3742d71 | |||
| 56e407f8a0 | |||
| 362e7721f5 | |||
| 53fd95f715 | |||
| 078aaae0cf | |||
| 4f66cd826f | |||
| 028f587670 | |||
| 0b2e862c7a | |||
| 8db0bcc018 | |||
| bb6a2082f8 | |||
| dfac161651 | |||
| f41c1f82bc | |||
| 443f993467 | |||
| 0e72aac68a | |||
| 4cd564dd65 | |||
| c6c462903e | |||
| be4a2e7773 | |||
| 283140134b | |||
| c779c4fa0b | |||
| 4577aa88fd | |||
| 3add309d96 | |||
| 1c2a935975 | |||
| 574aa817c1 | |||
| 98a7bb9cd5 | |||
| f35ff40f4a | |||
| 2529f11ce3 | |||
| 26f4cf3ad8 | |||
| 23ec9e80b4 | |||
| 8710174991 | |||
| e399833263 | |||
| 59411b45f6 | |||
| 767622050e | |||
| 6696cff321 | |||
| f59741cc6c | |||
| 524724c642 | |||
| ca31084da2 | |||
| 52ecbf8f4c | |||
| d9c2abaa65 | |||
| 30613bca8d | |||
| cb3bad1d50 | |||
| e4eab531bf | |||
| 068d573375 | |||
| df78e4c8ab | |||
| 5fbe152a58 | |||
| 7fe005f6d1 | |||
| 2a615a6031 | |||
| cb065a2d2f | |||
| e0adce5360 | |||
| 613db5afcb | |||
| b38538fbdf | |||
| f96167c02e | |||
| c708549705 | |||
| d14281e215 | |||
| 19f6ca9457 | |||
| 7b4eb6082f | |||
| 8b8fbc6b84 | |||
| 906b385784 | |||
| e13e5a42bc | |||
| 1fcfc991b9 | |||
| a4eaa35e23 | |||
| df6749b03b | |||
| 6fc4a6c17a | |||
| f13c34e4a9 | |||
| 0899f6b9f9 | |||
| b68abdc7c2 | |||
| 7e68b9a0af | |||
| 63752139c4 | |||
| 67803cb430 | |||
| 54b24b8a24 | |||
| 3e97f327cf | |||
| e91ffe1531 | |||
| c4d5303ce0 | |||
| 0712ef7f54 | |||
| ddf6c958f8 | |||
| fbf216799c | |||
| f8b0ee68bf | |||
| 069683984a | |||
| 7a7dd2ff1f | |||
| 8a0ed98b81 | |||
| ce904a961d | |||
| 5ff898804f | |||
| 3bb50a471c | |||
| 660182a172 | |||
| e8f0664d53 | |||
| cb495b995c | |||
| c37bbda3ef | |||
| 81432e74f4 | |||
| d231bf1272 | |||
| 1aee3e9394 | |||
| 9362f598dd |
+1
-5
@@ -3,10 +3,10 @@
|
||||
*/**/build/
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
auth/fc/fcFPP.php
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
filter/tex/mimetex.*
|
||||
@@ -14,7 +14,6 @@ lib/editor/atto/yui/src/rangy/js/*.*
|
||||
lib/editor/tinymce/plugins/pdw/tinymce/
|
||||
lib/editor/tinymce/plugins/spellchecker/rpc.php
|
||||
lib/editor/tinymce/tiny_mce/
|
||||
lib/mlbackend/php/phpml/
|
||||
lib/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
@@ -59,12 +58,9 @@ lib/maxmind/MaxMind/
|
||||
lib/ltiprovider/
|
||||
lib/amd/src/truncate.js
|
||||
lib/fonts/
|
||||
lib/validateurlsyntax.php
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
media/player/videojs/amd/src/videojs-flash-lazy.js
|
||||
media/player/videojs/videojs/video-js.swf
|
||||
mod/assign/feedback/editpdf/fpdi/
|
||||
repository/s3/S3.php
|
||||
theme/boost/scss/bootstrap/
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
{
|
||||
'plugins': [
|
||||
'promise',
|
||||
],
|
||||
'env': {
|
||||
'browser': true,
|
||||
'amd': true
|
||||
@@ -16,7 +13,6 @@
|
||||
|
||||
// === Possible Errors ===
|
||||
'comma-dangle': 'off',
|
||||
'no-compare-neg-zero': 'error',
|
||||
'no-cond-assign': 'error',
|
||||
'no-console': 'error',
|
||||
'no-constant-condition': 'error',
|
||||
@@ -68,6 +64,7 @@
|
||||
'no-fallthrough': 'error',
|
||||
'no-floating-decimal': 'warn',
|
||||
'no-global-assign': 'warn',
|
||||
// Enabled by grunt for AMD modules: 'no-implicit-globals': 'error',
|
||||
'no-implied-eval': 'error',
|
||||
'no-invalid-this': 'error',
|
||||
'no-iterator': 'error',
|
||||
@@ -106,7 +103,6 @@
|
||||
'block-spacing': 'warn',
|
||||
'brace-style': ['warn', '1tbs'],
|
||||
'camelcase': 'warn',
|
||||
'capitalized-comments': ['warn', 'always', { 'ignoreConsecutiveComments': true }],
|
||||
'comma-spacing': ['warn', { 'before': false, 'after': true }],
|
||||
'comma-style': ['warn', 'last'],
|
||||
'computed-property-spacing': 'error',
|
||||
@@ -174,41 +170,11 @@
|
||||
'unicode-bom': 'error',
|
||||
'wrap-regex': 'off',
|
||||
|
||||
// === Promises ===
|
||||
'promise/always-return': 'warn',
|
||||
'promise/no-return-wrap': 'warn',
|
||||
'promise/param-names': 'warn',
|
||||
'promise/catch-or-return': ['warn', {terminationMethod: ['catch', 'fail']}],
|
||||
'promise/no-native': 'warn',
|
||||
'promise/no-promise-in-callback': 'warn',
|
||||
'promise/no-callback-in-promise': 'warn',
|
||||
'promise/avoid-new': 'warn',
|
||||
|
||||
// === Deprecations ===
|
||||
"no-restricted-properties": ['warn', {
|
||||
'object': 'M',
|
||||
'property': 'str',
|
||||
'message': 'Use AMD module "core/str" or M.util.get_string()'
|
||||
}],
|
||||
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/yui/src/**/*.js"],
|
||||
// Disable some rules which we can't safely define for YUI rollups.
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'no-unused-expressions': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["**/amd/src/*.js"],
|
||||
// Check AMD with some slightly stricter rules.
|
||||
rules: {
|
||||
'no-unused-vars': 'error',
|
||||
'no-implicit-globals': 'error'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
**/yui/build/** -diff
|
||||
**/amd/build/** -diff
|
||||
lib/dml/oci_native_moodle_package.sql text eol=lf
|
||||
theme/bootstrapbase/style/editor.css -diff
|
||||
theme/bootstrapbase/style/moodle.css -diff
|
||||
|
||||
+1
-6
@@ -2,13 +2,12 @@
|
||||
theme/bootstrapbase/style/
|
||||
theme/clean/style/custom.css
|
||||
theme/more/style/custom.css
|
||||
theme/boost/style/moodle.css
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
auth/fc/fcFPP.php
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
filter/tex/mimetex.*
|
||||
@@ -16,7 +15,6 @@ lib/editor/atto/yui/src/rangy/js/*.*
|
||||
lib/editor/tinymce/plugins/pdw/tinymce/
|
||||
lib/editor/tinymce/plugins/spellchecker/rpc.php
|
||||
lib/editor/tinymce/tiny_mce/
|
||||
lib/mlbackend/php/phpml/
|
||||
lib/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
@@ -61,12 +59,9 @@ lib/maxmind/MaxMind/
|
||||
lib/ltiprovider/
|
||||
lib/amd/src/truncate.js
|
||||
lib/fonts/
|
||||
lib/validateurlsyntax.php
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
media/player/videojs/amd/src/videojs-flash-lazy.js
|
||||
media/player/videojs/videojs/video-js.swf
|
||||
mod/assign/feedback/editpdf/fpdi/
|
||||
repository/s3/S3.php
|
||||
theme/boost/scss/bootstrap/
|
||||
|
||||
+10
-11
@@ -1,22 +1,18 @@
|
||||
{
|
||||
"plugins": [
|
||||
"stylelint-csstree-validator"
|
||||
],
|
||||
"rules": {
|
||||
"csstree/validator": true,
|
||||
"at-rule-empty-line-before": [ "always",
|
||||
{"except": [ "blockless-after-blockless"], ignore: ["after-comment", "inside-block"]}
|
||||
{"except": [ "blockless-group"], ignore: ["after-comment", "all-nested"]}
|
||||
],
|
||||
"at-rule-name-case": "lower",
|
||||
"at-rule-name-space-after": "always-single-line",
|
||||
"at-rule-no-unknown": null, # Enabled for non-scss in grunt.
|
||||
"at-rule-semicolon-newline-after": "always",
|
||||
"at-rule-semicolon-space-before": "never",
|
||||
"block-closing-brace-newline-after": "always",
|
||||
"block-closing-brace-newline-before": "always",
|
||||
"block-closing-brace-newline-before": "always-multi-line",
|
||||
"block-closing-brace-space-before": "always-single-line",
|
||||
"block-no-empty": true,
|
||||
"block-opening-brace-newline-after": "always",
|
||||
"block-no-single-line": true,
|
||||
"block-opening-brace-newline-after": "always-multi-line",
|
||||
"block-opening-brace-space-after": "always-single-line",
|
||||
"block-opening-brace-space-before": "always",
|
||||
"color-hex-case": ["lower", { "severity": "warning" }],
|
||||
@@ -25,6 +21,7 @@
|
||||
"declaration-bang-space-after": "never",
|
||||
"declaration-bang-space-before": "always",
|
||||
"declaration-block-no-duplicate-properties": true,
|
||||
"declaration-block-no-ignored-properties": true,
|
||||
"declaration-block-no-shorthand-property-overrides": true,
|
||||
"declaration-block-semicolon-newline-after": "always-multi-line",
|
||||
"declaration-block-semicolon-space-after": "always-single-line",
|
||||
@@ -35,7 +32,6 @@
|
||||
"declaration-colon-space-after": "always-single-line",
|
||||
"declaration-colon-space-before": "never",
|
||||
"declaration-no-important": true,
|
||||
"font-family-no-duplicate-names": true,
|
||||
"function-calc-no-unspaced-operator": true,
|
||||
"function-comma-newline-after": "always-multi-line",
|
||||
"function-comma-space-after": "always-single-line",
|
||||
@@ -45,7 +41,7 @@
|
||||
"function-name-case": "lower",
|
||||
"function-parentheses-newline-inside": "always-multi-line",
|
||||
"function-parentheses-space-inside": "never-single-line",
|
||||
"function-url-scheme-blacklist": ["data"],
|
||||
"function-url-data-uris": never,
|
||||
"function-whitespace-after": "always",
|
||||
"indentation": 4,
|
||||
"keyframe-declaration-no-important": true,
|
||||
@@ -54,12 +50,14 @@
|
||||
"max-line-length": [132, { "severity": "warning" }],
|
||||
"media-feature-colon-space-after": "always",
|
||||
"media-feature-colon-space-before": "never",
|
||||
"media-feature-no-missing-punctuation": true,
|
||||
"media-feature-parentheses-space-inside": "never",
|
||||
"media-feature-range-operator-space-after": "always",
|
||||
"media-feature-range-operator-space-before": "always",
|
||||
"media-query-list-comma-newline-after": "always-multi-line",
|
||||
"media-query-list-comma-space-after": "always-single-line",
|
||||
"media-query-list-comma-space-before": "never",
|
||||
"no-browser-hacks": null, # Enabled for non-scss in grunt.
|
||||
"no-empty-source": true,
|
||||
"no-eol-whitespace": true,
|
||||
"no-extra-semicolons": [true, { "severity": "warning" }],
|
||||
@@ -80,10 +78,11 @@
|
||||
"selector-pseudo-class-parentheses-space-inside": "never",
|
||||
"selector-pseudo-element-case": "lower",
|
||||
"selector-pseudo-element-no-unknown": true,
|
||||
"selector-root-no-composition": true,
|
||||
"selector-type-case": "lower",
|
||||
"selector-type-no-unknown": true,
|
||||
"string-no-newline": true,
|
||||
"time-min-milliseconds": 100,
|
||||
"time-no-imperceptible": true,
|
||||
"unit-blacklist": ["pt"],
|
||||
"unit-case": "lower",
|
||||
"unit-no-unknown": true,
|
||||
|
||||
+28
-24
@@ -13,25 +13,24 @@ language: php
|
||||
|
||||
php:
|
||||
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
|
||||
- 7.2
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 5.6
|
||||
|
||||
addons:
|
||||
postgresql: "9.6"
|
||||
postgresql: "9.3"
|
||||
packages:
|
||||
- mysql-server-5.6
|
||||
- mysql-client-core-5.6
|
||||
- mysql-client-5.6
|
||||
|
||||
# Redis tests are currently failing on php 7.2 due to https://bugs.php.net/bug.php?id=75628
|
||||
# services:
|
||||
# - redis-server
|
||||
services:
|
||||
- redis-server
|
||||
|
||||
env:
|
||||
# Although we want to run these jobs and see failures as quickly as possible, we also want to get the slowest job to
|
||||
# start first so that the total run time is not too high.
|
||||
#
|
||||
# We only run MySQL on PHP 7.2, so run that first.
|
||||
# We only run MySQL on PHP 7.1, so run that first.
|
||||
# CI Tests should be second-highest in priority as these only take <= 60 seconds to run under normal circumstances.
|
||||
# Postgres is significantly is pretty reasonable in its run-time.
|
||||
|
||||
@@ -54,16 +53,23 @@ matrix:
|
||||
fast_finish: true
|
||||
|
||||
include:
|
||||
# Run grunt/npm install on lowest supported npm version
|
||||
- php: 7.1
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='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'
|
||||
- php: 7.1
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='node'
|
||||
|
||||
exclude:
|
||||
# MySQL - it's just too slow.
|
||||
# Exclude it on all versions except for 7.2
|
||||
# Exclude it on all versions except for 7.1
|
||||
|
||||
- env: DB=mysqli TASK=PHPUNIT
|
||||
php: 7.0
|
||||
php: 5.6
|
||||
|
||||
# Moodle 2.7 is not compatible with PHP 7 for the upgrade test.
|
||||
- env: DB=pgsql TASK=UPGRADE
|
||||
php: 7.1
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@@ -71,6 +77,8 @@ cache:
|
||||
- $HOME/.npm
|
||||
|
||||
install:
|
||||
- sudo apt-get -y install haveged
|
||||
- sudo service haveged start
|
||||
- >
|
||||
if [ "$DB" = 'mysqli' ];
|
||||
then
|
||||
@@ -89,7 +97,7 @@ install:
|
||||
sudo service postgresql stop
|
||||
sudo mv /var/lib/postgresql /mnt/ramdisk
|
||||
sudo ln -s /mnt/ramdisk/postgresql /var/lib/postgresql
|
||||
sudo service postgresql start 9.6
|
||||
sudo service postgresql start 9.3
|
||||
fi
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
@@ -100,9 +108,8 @@ install:
|
||||
fi
|
||||
|
||||
# Enable Redis.
|
||||
# Redis tests are currently failing on php 7.2 due to https://bugs.php.net/bug.php?id=75628
|
||||
# echo 'extension="redis.so"' > /tmp/redis.ini
|
||||
# phpenv config-add /tmp/redis.ini
|
||||
echo 'extension="redis.so"' > /tmp/redis.ini
|
||||
phpenv config-add /tmp/redis.ini
|
||||
|
||||
# Install composer dependencies.
|
||||
# We need --no-interaction in case we hit API limits for composer. This causes it to fall back to a standard clone.
|
||||
@@ -173,11 +180,10 @@ before_script:
|
||||
mkdir -p "$HOME"/roots/phpunit
|
||||
|
||||
# The phpunit dataroot and prefix..
|
||||
# Redis tests are currently failing on php 7.2 due to https://bugs.php.net/bug.php?id=75628
|
||||
# -e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
|
||||
sed -i \
|
||||
-e "/require_once/i \\\$CFG->phpunit_dataroot = '\/home\/travis\/roots\/phpunit';" \
|
||||
-e "/require_once/i \\\$CFG->phpunit_prefix = 'p_';" \
|
||||
-e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
|
||||
config.php ;
|
||||
|
||||
# Initialise PHPUnit for Moodle.
|
||||
@@ -207,7 +213,7 @@ before_script:
|
||||
# We need the official upstream for comparison
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
git fetch upstream MOODLE_34_STABLE;
|
||||
git fetch upstream MOODLE_33_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`
|
||||
@@ -227,9 +233,9 @@ before_script:
|
||||
# We need the official upstream.
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
# Checkout 30 STABLE branch (the first version compatible with PHP 7.x)
|
||||
git fetch upstream MOODLE_30_STABLE;
|
||||
git checkout MOODLE_30_STABLE;
|
||||
# Checkout 27 STABLE branch.
|
||||
git fetch upstream MOODLE_27_STABLE;
|
||||
git checkout MOODLE_27_STABLE;
|
||||
|
||||
# Perform the upgrade
|
||||
php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
|
||||
@@ -248,7 +254,7 @@ script:
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
vendor/bin/phpunit --fail-on-risky --disallow-test-output --verbose;
|
||||
vendor/bin/phpunit;
|
||||
fi
|
||||
|
||||
- >
|
||||
@@ -263,9 +269,7 @@ script:
|
||||
grunt ;
|
||||
# Add all files to the git index and then run diff --cached to see all changes.
|
||||
# This ensures that we get the status of all files, including new files.
|
||||
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
|
||||
git add . ;
|
||||
git reset -- npm-shrinkwrap.json ;
|
||||
git diff --cached --exit-code ;
|
||||
fi
|
||||
|
||||
|
||||
+22
-4
@@ -112,9 +112,26 @@ module.exports = function(grunt) {
|
||||
// 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.
|
||||
options: {quiet: !grunt.option('show-lint-warnings')},
|
||||
amd: {src: amdSrc},
|
||||
amd: {
|
||||
src: amdSrc,
|
||||
// Check AMD with some slightly stricter rules.
|
||||
rules: {
|
||||
'no-unused-vars': 'error',
|
||||
'no-implicit-globals': 'error'
|
||||
}
|
||||
},
|
||||
// Check YUI module source files.
|
||||
yui: {src: ['**/yui/src/**/*.js', '!*/**/yui/src/*/meta/*.js']}
|
||||
yui: {
|
||||
src: ['**/yui/src/**/*.js', '!*/**/yui/src/*/meta/*.js'],
|
||||
options: {
|
||||
// Disable some rules which we can't safely define for YUI rollups.
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'no-unused-expressions': 'off'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
amd: {
|
||||
@@ -177,6 +194,7 @@ module.exports = function(grunt) {
|
||||
rules: {
|
||||
// These rules have to be disabled in .stylelintrc for scss compat.
|
||||
"at-rule-no-unknown": true,
|
||||
"no-browser-hacks": [true, {"severity": "warning"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -193,6 +211,7 @@ module.exports = function(grunt) {
|
||||
rules: {
|
||||
// These rules have to be disabled in .stylelintrc for scss compat.
|
||||
"at-rule-no-unknown": true,
|
||||
"no-browser-hacks": [true, {"severity": "warning"}]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,8 +233,7 @@ module.exports = function(grunt) {
|
||||
'# Generated by "grunt ignorefiles"',
|
||||
'theme/bootstrapbase/style/',
|
||||
'theme/clean/style/custom.css',
|
||||
'theme/more/style/custom.css',
|
||||
'theme/boost/style/moodle.css'
|
||||
'theme/more/style/custom.css'
|
||||
].concat(thirdPartyPaths);
|
||||
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
|
||||
};
|
||||
|
||||
@@ -165,12 +165,6 @@ function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts,
|
||||
// If custom field then pick name from database.
|
||||
$fieldshortname = str_replace('profile_field_', '', $fieldname);
|
||||
$fieldname = $customfieldname[$fieldshortname]->name;
|
||||
if (core_text::strlen($fieldshortname) > 67) {
|
||||
// If custom profile field name is longer than 67 characters we will not be able to store the setting
|
||||
// such as 'field_updateremote_profile_field_NOTSOSHORTSHORTNAME' in the database because the character
|
||||
// limit for the setting name is 100.
|
||||
continue;
|
||||
}
|
||||
} elseif ($fieldname == 'url') {
|
||||
$fieldname = get_string('webpage');
|
||||
} else {
|
||||
|
||||
+9
-13
@@ -54,16 +54,14 @@ $statusmsg = '';
|
||||
$errormsg = '';
|
||||
|
||||
if ($data = data_submitted() and confirm_sesskey()) {
|
||||
$count = admin_write_settings($data);
|
||||
if (admin_write_settings($data)) {
|
||||
$statusmsg = get_string('changessaved');
|
||||
}
|
||||
|
||||
if (empty($adminroot->errors)) {
|
||||
// No errors. Did we change any setting? If so, then indicate success.
|
||||
if ($count) {
|
||||
$statusmsg = get_string('changessaved');
|
||||
} else {
|
||||
switch ($return) {
|
||||
case 'site': redirect("$CFG->wwwroot/");
|
||||
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
|
||||
}
|
||||
switch ($return) {
|
||||
case 'site': redirect("$CFG->wwwroot/");
|
||||
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
|
||||
}
|
||||
} else {
|
||||
$errormsg = get_string('errorwithsettings', 'admin');
|
||||
@@ -75,7 +73,7 @@ if ($data = data_submitted() and confirm_sesskey()) {
|
||||
if ($PAGE->user_allowed_editing() && $adminediting != -1) {
|
||||
$USER->editing = $adminediting;
|
||||
}
|
||||
$buttons = null;
|
||||
|
||||
if ($PAGE->user_allowed_editing()) {
|
||||
$url = clone($PAGE->url);
|
||||
if ($PAGE->user_is_editing()) {
|
||||
@@ -129,9 +127,7 @@ if ($savebutton) {
|
||||
$visiblepathtosection = array_reverse($settingspage->visiblepath);
|
||||
$PAGE->set_title("$SITE->shortname: " . implode(": ",$visiblepathtosection));
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
if ($buttons) {
|
||||
$PAGE->set_button($buttons);
|
||||
}
|
||||
$PAGE->set_button($buttons);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
|
||||
@@ -1,41 +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/>.
|
||||
/**
|
||||
* Privacy Subsystem implementation for core_admin.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_admin\privacy;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for core_admin implementing null_provider.
|
||||
*
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -1,119 +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/>.
|
||||
|
||||
/**
|
||||
* Build and store theme CSS.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once("$CFG->libdir/clilib.php");
|
||||
require_once("$CFG->libdir/csslib.php");
|
||||
require_once("$CFG->libdir/outputlib.php");
|
||||
|
||||
$longparams = [
|
||||
'themes' => null,
|
||||
'direction' => null,
|
||||
'help' => false,
|
||||
'verbose' => false
|
||||
];
|
||||
|
||||
$shortmappings = [
|
||||
't' => 'themes',
|
||||
'd' => 'direction',
|
||||
'h' => 'help',
|
||||
'v' => 'verbose'
|
||||
];
|
||||
|
||||
// Get CLI params.
|
||||
list($options, $unrecognized) = cli_get_params($longparams, $shortmappings);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
echo
|
||||
"Compile the CSS for one or more installed themes.
|
||||
Existing CSS caches will replaced.
|
||||
By default all themes will be recompiled unless otherwise specified.
|
||||
|
||||
Options:
|
||||
-t, --themes A comma separated list of themes to be compiled
|
||||
-d, --direction Only compile a single direction (either ltr or rtl)
|
||||
-v, --verbose Print info comments to stdout
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$ sudo -u www-data /usr/bin/php admin/cli/build_theme_css.php --themes=boost --direction=ltr
|
||||
";
|
||||
|
||||
die;
|
||||
}
|
||||
|
||||
if (empty($options['verbose'])) {
|
||||
$trace = new null_progress_trace();
|
||||
} else {
|
||||
$trace = new text_progress_trace();
|
||||
}
|
||||
|
||||
cli_heading('Build theme css');
|
||||
|
||||
// Determine which themes we need to build.
|
||||
$themenames = [];
|
||||
if (is_null($options['themes'])) {
|
||||
$trace->output('No themes specified. Finding all installed themes.');
|
||||
$themenames = array_keys(core_component::get_plugin_list('theme'));
|
||||
} else {
|
||||
if (is_string($options['themes'])) {
|
||||
$themenames = explode(',', $options['themes']);
|
||||
} else {
|
||||
cli_error('--themes must be a comma separated list of theme names');
|
||||
}
|
||||
}
|
||||
|
||||
$trace->output('Checking that each theme is correctly installed...');
|
||||
$themeconfigs = [];
|
||||
foreach ($themenames as $themename) {
|
||||
if (is_null(theme_get_config_file_path($themename))) {
|
||||
cli_error("Unable to find theme config for {$themename}");
|
||||
}
|
||||
|
||||
// Load the config for the theme.
|
||||
$themeconfigs[] = theme_config::load($themename);
|
||||
}
|
||||
|
||||
$directions = ['ltr', 'rtl'];
|
||||
|
||||
if (!is_null($options['direction'])) {
|
||||
if (!in_array($options['direction'], $directions)) {
|
||||
cli_error("--direction must be either ltr or rtl");
|
||||
}
|
||||
|
||||
$directions = [$options['direction']];
|
||||
}
|
||||
|
||||
$trace->output('Building CSS for themes: ' . implode(', ', $themenames));
|
||||
theme_build_css_for_themes($themeconfigs, $directions);
|
||||
|
||||
exit(0);
|
||||
@@ -73,7 +73,6 @@ foreach ($rs as $user) {
|
||||
echo "Redeleting user $user->id: $user->username ($user->email)\n";
|
||||
delete_user($user);
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
cli_heading('Deleting all leftovers');
|
||||
|
||||
|
||||
@@ -146,9 +146,14 @@ define('PHPUNIT_TEST', false);
|
||||
|
||||
define('IGNORE_COMPONENT_CACHE', true);
|
||||
|
||||
// Check that PHP is of a sufficient version as soon as possible.
|
||||
require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
|
||||
moodle_require_minimum_php_version();
|
||||
// Check that PHP is of a sufficient version
|
||||
if (version_compare(phpversion(), "5.6.5") < 0) {
|
||||
$phpversion = phpversion();
|
||||
// do NOT localise - lang strings would not work here and we CAN NOT move it after installib
|
||||
fwrite(STDERR, "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).\n");
|
||||
fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// set up configuration
|
||||
global $CFG;
|
||||
@@ -803,12 +808,6 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
|
||||
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.
|
||||
// This will build a cached version of the current theme for the user
|
||||
// to immediately start browsing the site.
|
||||
require_once($CFG->libdir.'/upgradelib.php');
|
||||
upgrade_themes();
|
||||
} else {
|
||||
echo get_string('cliskipdatabase', 'install')."\n";
|
||||
}
|
||||
|
||||
@@ -62,9 +62,14 @@ Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/install_database.php --lang=cs --adminpass=soMePass123 --agree-license
|
||||
";
|
||||
|
||||
// Check that PHP is of a sufficient version as soon as possible.
|
||||
require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
|
||||
moodle_require_minimum_php_version();
|
||||
// Check that PHP is of a sufficient version
|
||||
if (version_compare(phpversion(), "5.6.5") < 0) {
|
||||
$phpversion = phpversion();
|
||||
// do NOT localise - lang strings would not work here and we CAN NOT move it after installib
|
||||
fwrite(STDERR, "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).\n");
|
||||
fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Nothing to do if config.php does not exist
|
||||
$configfile = __DIR__.'/../../config.php';
|
||||
@@ -178,12 +183,5 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
|
||||
install_cli_database($options, true);
|
||||
|
||||
// This needs to happen at the end to ensure it occurs after all caches
|
||||
// have been purged for the last time.
|
||||
// This will build a cached version of the current theme for the user
|
||||
// to immediately start browsing the site.
|
||||
require_once($CFG->libdir.'/upgradelib.php');
|
||||
upgrade_themes();
|
||||
|
||||
echo get_string('cliinstallfinished', 'install')."\n";
|
||||
exit(0); // 0 means success
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* CLI script to kill all user sessions without asking for confirmation.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2017 Alexander Bias <alexander.bias@uni-ulm.de>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(array('help' => false), array('h' => 'help'));
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2);
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
$help =
|
||||
"Kill all Moodle sessions
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/kill_all_sessions.php
|
||||
";
|
||||
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
\core\session\manager::kill_all_sessions();
|
||||
|
||||
exit(0);
|
||||
@@ -203,7 +203,7 @@ if (!empty($options['collation'])) {
|
||||
$DB->change_database_structure($sql);
|
||||
} else {
|
||||
echo "ERROR (unknown column type: $column->type)\n";
|
||||
$errors++;
|
||||
$error++;
|
||||
continue;
|
||||
}
|
||||
echo "CONVERTED\n";
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* CLI script to purge caches without asking for confirmation.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2011 David Mudrak <david@moodle.com>
|
||||
@@ -52,4 +50,4 @@ Example:
|
||||
|
||||
purge_all_caches();
|
||||
|
||||
exit(0);
|
||||
exit(0);
|
||||
@@ -187,11 +187,5 @@ upgrade_noncore(true);
|
||||
admin_apply_default_settings(NULL, false);
|
||||
admin_apply_default_settings(NULL, false);
|
||||
|
||||
// This needs to happen at the end to ensure it occurs after all caches
|
||||
// have been purged for the last time.
|
||||
// This will build a cached version of the current theme for the user
|
||||
// to immediately start browsing the site.
|
||||
upgrade_themes();
|
||||
|
||||
echo get_string('cliupgradefinished', 'admin')."\n";
|
||||
exit(0); // 0 means success
|
||||
|
||||
@@ -1754,7 +1754,6 @@
|
||||
<VENDOR name="oracle" version="10.2" />
|
||||
</DATABASE>
|
||||
<PHP version="5.6.5" level="required">
|
||||
<RESTRICT function="restrict_php_version_72" message="unsupportedphpversion72" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -1920,7 +1919,6 @@
|
||||
<VENDOR name="oracle" version="10.2" />
|
||||
</DATABASE>
|
||||
<PHP version="5.6.5" level="required">
|
||||
<RESTRICT function="restrict_php_version_72" message="unsupportedphpversion72" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -2083,720 +2081,4 @@
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.4" requires="3.0">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="5.5.31" />
|
||||
<VENDOR name="mysql" version="5.5.31" />
|
||||
<VENDOR name="postgres" version="9.3" />
|
||||
<VENDOR name="mssql" version="10.0" />
|
||||
<VENDOR name="oracle" version="10.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.0.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_73" message="unsupportedphpversion73" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="mbstringrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="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_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.5" requires="3.1">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="5.5.31" />
|
||||
<VENDOR name="mysql" version="5.5.31" />
|
||||
<VENDOR name="postgres" version="9.3" />
|
||||
<VENDOR name="mssql" version="10.0" />
|
||||
<VENDOR name="oracle" version="10.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.0.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_73" message="unsupportedphpversion73" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="mbstringrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="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_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.6" requires="3.1">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="5.5.31" />
|
||||
<VENDOR name="mysql" version="5.6" />
|
||||
<VENDOR name="postgres" version="9.4" />
|
||||
<VENDOR name="mssql" version="10.0" />
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.0.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="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="mbstringrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="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.7" requires="3.2">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="5.5.31" />
|
||||
<VENDOR name="mysql" version="5.6" />
|
||||
<VENDOR name="postgres" version="9.4" />
|
||||
<VENDOR name="mssql" version="10.0" />
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.1.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="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="mbstringrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="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
-21
@@ -29,9 +29,14 @@ if (!file_exists('../config.php')) {
|
||||
die();
|
||||
}
|
||||
|
||||
// Check that PHP is of a sufficient version as soon as possible.
|
||||
require_once(__DIR__.'/../lib/phpminimumversionlib.php');
|
||||
moodle_require_minimum_php_version();
|
||||
// Check that PHP is of a sufficient version as soon as possible
|
||||
if (version_compare(phpversion(), '5.6.5') < 0) {
|
||||
$phpversion = phpversion();
|
||||
// do NOT localise - lang strings would not work here and we CAN NOT move it to later place
|
||||
echo "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).<br />";
|
||||
echo "Please upgrade your server software or install older Moodle version.";
|
||||
die();
|
||||
}
|
||||
|
||||
// make sure iconv is available and actually works
|
||||
if (!function_exists('iconv')) {
|
||||
@@ -699,7 +704,6 @@ if (!$cache and moodle_needs_upgrading()) {
|
||||
if (during_initial_install()) {
|
||||
set_config('rolesactive', 1); // after this, during_initial_install will return false.
|
||||
set_config('adminsetuppending', 1);
|
||||
set_config('registrationpending', 1); // Remind to register site after all other setup is finished.
|
||||
// we need this redirect to setup proper session
|
||||
upgrade_finished("index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
}
|
||||
@@ -815,9 +819,6 @@ if (isset($SESSION->pluginuninstallreturn)) {
|
||||
}
|
||||
}
|
||||
|
||||
// If site registration needs updating, redirect.
|
||||
\core\hub\registration::registration_reminder('/admin/index.php');
|
||||
|
||||
// Everything should now be set up, and the user is an admin
|
||||
|
||||
// Print default admin page with notifications.
|
||||
@@ -861,23 +862,12 @@ if ($updateschecker->enabled()) {
|
||||
|
||||
$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
|
||||
//check if the site is registered on Moodle.org
|
||||
$registered = \core\hub\registration::is_registered();
|
||||
$registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
|
||||
// Check if there are any cache warnings.
|
||||
$cachewarnings = cache_helper::warnings();
|
||||
// Check if there are events 1 API handlers.
|
||||
$eventshandlers = $DB->get_records_sql('SELECT DISTINCT component FROM {events_handlers}');
|
||||
$themedesignermode = !empty($CFG->themedesignermode);
|
||||
$mobileconfigured = !empty($CFG->enablemobilewebservice);
|
||||
$invalidforgottenpasswordurl = !empty($CFG->forgottenpasswordurl) && empty(clean_param($CFG->forgottenpasswordurl, PARAM_URL));
|
||||
|
||||
// Check if a directory with development libraries exists.
|
||||
if (empty($CFG->disabledevlibdirscheck) && (is_dir($CFG->dirroot.'/vendor') || is_dir($CFG->dirroot.'/node_modules'))) {
|
||||
$devlibdir = true;
|
||||
} else {
|
||||
$devlibdir = false;
|
||||
}
|
||||
// Check if the site is being foced onto ssl.
|
||||
$overridetossl = !empty($CFG->overridetossl);
|
||||
|
||||
admin_externalpage_setup('adminnotifications');
|
||||
|
||||
@@ -885,5 +875,4 @@ $output = $PAGE->get_renderer('core', 'admin');
|
||||
|
||||
echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed, $cronoverdue, $dbproblems,
|
||||
$maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
|
||||
$registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir,
|
||||
$mobileconfigured, $overridetossl, $invalidforgottenpasswordurl);
|
||||
$registered, $cachewarnings, $eventshandlers, $themedesignermode);
|
||||
|
||||
@@ -29,10 +29,9 @@ require_once($CFG->libdir.'/adminlib.php');
|
||||
$confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
|
||||
|
||||
admin_externalpage_setup('purgecaches');
|
||||
|
||||
// If we have got here as a confirmed aciton, do it.
|
||||
if ($confirm && confirm_sesskey()) {
|
||||
if ($confirm && isloggedin() && confirm_sesskey()) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
// Valid request. Purge, and redirect the user back to where they came from.
|
||||
purge_all_caches();
|
||||
@@ -46,6 +45,8 @@ if ($confirm && confirm_sesskey()) {
|
||||
}
|
||||
|
||||
// Otherwise, show a button to actually purge the caches.
|
||||
admin_externalpage_setup('purgecaches');
|
||||
|
||||
$actionurl = new moodle_url('/admin/purgecaches.php', array('sesskey'=>sesskey(), 'confirm'=>1));
|
||||
if ($returnurl) {
|
||||
$actionurl->param('returnurl', $returnurl);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
/*
|
||||
* @package moodle
|
||||
* @subpackage registration
|
||||
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
require('../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
|
||||
|
||||
$newtoken = optional_param('newtoken', '', PARAM_ALPHANUM);
|
||||
$url = optional_param('url', '', PARAM_URL);
|
||||
@@ -43,19 +44,7 @@ $hubname = optional_param('hubname', '', PARAM_TEXT);
|
||||
$token = optional_param('token', '', PARAM_TEXT);
|
||||
$error = optional_param('error', '', PARAM_ALPHANUM);
|
||||
|
||||
admin_externalpage_setup('registrationmoodleorg');
|
||||
|
||||
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) {
|
||||
foreach ($plugins as $plugin => $callback) {
|
||||
$callback('confirm');
|
||||
}
|
||||
}
|
||||
throw new moodle_exception('errorotherhubsnotsupported', 'hub');
|
||||
}
|
||||
admin_externalpage_setup('registrationhubs');
|
||||
|
||||
if (!empty($error) and $error == 'urlalreadyexist') {
|
||||
throw new moodle_exception('urlalreadyregistered', 'hub',
|
||||
@@ -63,22 +52,38 @@ if (!empty($error) and $error == 'urlalreadyexist') {
|
||||
}
|
||||
|
||||
//check that we are waiting a confirmation from this hub, and check that the token is correct
|
||||
core\hub\registration::confirm_registration($token, $newtoken, $hubname);
|
||||
$registrationmanager = new registration_manager();
|
||||
$registeredhub = $registrationmanager->get_unconfirmedhub($url);
|
||||
if (!empty($registeredhub) and $registeredhub->token == $token) {
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('registrationconfirmed', 'hub'), 3, 'main');
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('registrationconfirmed', 'hub'), 3, 'main');
|
||||
|
||||
// Display notification message.
|
||||
echo $OUTPUT->notification(get_string('registrationconfirmedon', 'hub'), 'notifysuccess');
|
||||
$registeredhub->token = $newtoken;
|
||||
$registeredhub->confirmed = 1;
|
||||
$registeredhub->hubname = $hubname;
|
||||
$registrationmanager->update_registeredhub($registeredhub);
|
||||
|
||||
// Display continue button.
|
||||
$returnurl = !empty($SESSION->registrationredirect) ? clean_param($SESSION->registrationredirect, PARAM_LOCALURL) : null;
|
||||
unset($SESSION->registrationredirect);
|
||||
$continueurl = new moodle_url($returnurl ?: '/admin/registration/index.php');
|
||||
$continuebutton = $OUTPUT->render(new single_button($continueurl, get_string('continue')));
|
||||
$continuebutton = html_writer::tag('div', $continuebutton, array('class' => 'mdl-align'));
|
||||
echo $continuebutton;
|
||||
// Display notification message.
|
||||
echo $OUTPUT->notification(get_string('registrationconfirmedon', 'hub'), 'notifysuccess');
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
//display continue button
|
||||
$registrationpage = new moodle_url('/admin/registration/index.php');
|
||||
$continuebutton = $OUTPUT->render(new single_button($registrationpage, get_string('continue', 'hub')));
|
||||
$continuebutton = html_writer::tag('div', $continuebutton, array('class' => 'mdl-align'));
|
||||
echo $continuebutton;
|
||||
|
||||
if (!extension_loaded('xmlrpc')) {
|
||||
//display notice about xmlrpc
|
||||
$xmlrpcnotification = $OUTPUT->doc_link('admin/environment/php_extension/xmlrpc', '');
|
||||
$xmlrpcnotification .= get_string('xmlrpcdisabledregistration', 'hub');
|
||||
echo $OUTPUT->notification($xmlrpcnotification);
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
} else {
|
||||
throw new moodle_exception('wrongtoken', 'hub',
|
||||
$CFG->wwwroot . '/' . $CFG->admin . '/registration/index.php');
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
/*
|
||||
* @package moodle
|
||||
* @subpackage registration
|
||||
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
|
||||
@@ -30,7 +30,482 @@
|
||||
* The forms needed by registration pages.
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
debugging('Support for alternative hubs has been removed from Moodle in 3.4. For communication with moodle.net ' .
|
||||
'see lib/classes/hub/ .', DEBUG_DEVELOPER);
|
||||
require_once($CFG->libdir . '/formslib.php');
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
|
||||
|
||||
/**
|
||||
* This form display a unregistration form.
|
||||
*/
|
||||
class site_unregistration_form extends moodleform {
|
||||
|
||||
public function definition() {
|
||||
$mform = & $this->_form;
|
||||
$mform->addElement('header', 'site', get_string('unregister', 'hub'));
|
||||
|
||||
$huburl = $this->_customdata['huburl'];
|
||||
$hubname = $this->_customdata['hubname'];
|
||||
|
||||
$unregisterlabel = get_string('unregister', 'hub');
|
||||
$mform->addElement('checkbox', 'unpublishalladvertisedcourses', '',
|
||||
' ' . get_string('unpublishalladvertisedcourses', 'hub'));
|
||||
$mform->setType('unpublishalladvertisedcourses', PARAM_INT);
|
||||
$mform->addElement('checkbox', 'unpublishalluploadedcourses', '',
|
||||
' ' . get_string('unpublishalluploadedcourses', 'hub'));
|
||||
$mform->setType('unpublishalluploadedcourses', PARAM_INT);
|
||||
|
||||
$mform->addElement('hidden', 'confirm', 1);
|
||||
$mform->setType('confirm', PARAM_INT);
|
||||
$mform->addElement('hidden', 'unregistration', 1);
|
||||
$mform->setType('unregistration', PARAM_INT);
|
||||
$mform->addElement('hidden', 'huburl', $huburl);
|
||||
$mform->setType('huburl', PARAM_URL);
|
||||
$mform->addElement('hidden', 'hubname', $hubname);
|
||||
$mform->setType('hubname', PARAM_TEXT);
|
||||
|
||||
$this->add_action_buttons(true, $unregisterlabel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This form display a clean registration data form.
|
||||
*/
|
||||
class site_clean_registration_data_form extends moodleform {
|
||||
|
||||
public function definition() {
|
||||
$mform = & $this->_form;
|
||||
$mform->addElement('header', 'site', get_string('unregister', 'hub'));
|
||||
|
||||
$huburl = $this->_customdata['huburl'];
|
||||
$hubname = $this->_customdata['hubname'];
|
||||
|
||||
|
||||
$unregisterlabel = get_string('forceunregister', 'hub');
|
||||
$mform->addElement('static', '', get_string('warning', 'hub'), get_string('forceunregisterconfirmation', 'hub', $hubname));
|
||||
|
||||
$mform->addElement('hidden', 'confirm', 1);
|
||||
$mform->setType('confirm', PARAM_INT);
|
||||
$mform->addElement('hidden', 'unregistration', 1);
|
||||
$mform->setType('unregistration', PARAM_INT);
|
||||
$mform->addElement('hidden', 'cleanregdata', 1);
|
||||
$mform->setType('cleanregdata', PARAM_INT);
|
||||
$mform->addElement('hidden', 'huburl', $huburl);
|
||||
$mform->setType('huburl', PARAM_URL);
|
||||
$mform->addElement('hidden', 'hubname', $hubname);
|
||||
$mform->setType('hubname', PARAM_TEXT);
|
||||
|
||||
$this->add_action_buttons(true, $unregisterlabel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This form display a hub selector.
|
||||
* The hub list is retrieved from Moodle.org hub directory.
|
||||
* Also displayed, a text field to enter private hub url + its password
|
||||
*/
|
||||
class hub_selector_form extends moodleform {
|
||||
|
||||
public function definition() {
|
||||
global $CFG, $OUTPUT;
|
||||
$mform = & $this->_form;
|
||||
$mform->addElement('header', 'site', get_string('selecthub', 'hub'));
|
||||
|
||||
//retrieve the hub list on the hub directory by web service
|
||||
$function = 'hubdirectory_get_hubs';
|
||||
$params = array();
|
||||
$serverurl = HUB_HUBDIRECTORYURL . "/local/hubdirectory/webservice/webservices.php";
|
||||
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
|
||||
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, 'publichubdirectory');
|
||||
try {
|
||||
$hubs = $xmlrpcclient->call($function, $params);
|
||||
} catch (Exception $e) {
|
||||
$error = $OUTPUT->notification(get_string('errorhublisting', 'hub', $e->getMessage()));
|
||||
$mform->addElement('static', 'errorhub', '', $error);
|
||||
$hubs = array();
|
||||
}
|
||||
|
||||
//remove moodle.org from the hub list
|
||||
foreach ($hubs as $key => $hub) {
|
||||
if ($hub['url'] == HUB_MOODLEORGHUBURL) {
|
||||
unset($hubs[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
//Public hub list
|
||||
$options = array();
|
||||
foreach ($hubs as $hub) {
|
||||
//to not display a name longer than 100 character (too big)
|
||||
if (core_text::strlen($hub['name']) > 100) {
|
||||
$hubname = core_text::substr($hub['name'], 0, 100);
|
||||
$hubname = $hubname . "...";
|
||||
} else {
|
||||
$hubname = $hub['name'];
|
||||
}
|
||||
$options[$hub['url']] = $hubname;
|
||||
$mform->addElement('hidden', clean_param($hub['url'], PARAM_ALPHANUMEXT), $hubname);
|
||||
$mform->setType(clean_param($hub['url'], PARAM_ALPHANUMEXT), PARAM_ALPHANUMEXT);
|
||||
}
|
||||
if (!empty($hubs)) {
|
||||
$mform->addElement('select', 'publichub', get_string('publichub', 'hub'),
|
||||
$options, array("size" => 15));
|
||||
$mform->setType('publichub', PARAM_URL);
|
||||
}
|
||||
|
||||
$mform->addElement('static', 'or', '', get_string('orenterprivatehub', 'hub'));
|
||||
|
||||
//Private hub
|
||||
$mform->addElement('text', 'unlistedurl', get_string('privatehuburl', 'hub'),
|
||||
array('class' => 'registration_textfield'));
|
||||
$mform->setType('unlistedurl', PARAM_URL);
|
||||
$mform->addElement('text', 'password', get_string('password'),
|
||||
array('class' => 'registration_textfield'));
|
||||
$mform->setType('password', PARAM_RAW);
|
||||
|
||||
$this->add_action_buttons(false, get_string('selecthub', 'hub'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the unlisted URL is a URL
|
||||
*/
|
||||
function validation($data, $files) {
|
||||
global $CFG;
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
$unlistedurl = $this->_form->_submitValues['unlistedurl'];
|
||||
|
||||
if (empty($unlistedurl)) {
|
||||
$errors['unlistedurl'] = get_string('badurlformat', 'hub');
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The site registration form. Information will be sent to a given hub.
|
||||
*/
|
||||
class site_registration_form extends moodleform {
|
||||
|
||||
public function definition() {
|
||||
global $CFG, $DB;
|
||||
|
||||
$strrequired = get_string('required');
|
||||
$mform = & $this->_form;
|
||||
$huburl = $this->_customdata['huburl'];
|
||||
$hubname = $this->_customdata['hubname'];
|
||||
$password = $this->_customdata['password'];
|
||||
$admin = get_admin();
|
||||
$site = get_site();
|
||||
|
||||
//retrieve config for this hub and set default if they don't exist
|
||||
$cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
|
||||
$sitename = get_config('hub', 'site_name_' . $cleanhuburl);
|
||||
if ($sitename === false) {
|
||||
$sitename = format_string($site->fullname, true, array('context' => context_course::instance(SITEID)));
|
||||
}
|
||||
$sitedescription = get_config('hub', 'site_description_' . $cleanhuburl);
|
||||
if ($sitedescription === false) {
|
||||
$sitedescription = $site->summary;
|
||||
}
|
||||
$contactname = get_config('hub', 'site_contactname_' . $cleanhuburl);
|
||||
if ($contactname === false) {
|
||||
$contactname = fullname($admin, true);
|
||||
}
|
||||
$contactemail = get_config('hub', 'site_contactemail_' . $cleanhuburl);
|
||||
if ($contactemail === false) {
|
||||
$contactemail = $admin->email;
|
||||
}
|
||||
$contactphone = get_config('hub', 'site_contactphone_' . $cleanhuburl);
|
||||
if ($contactphone === false) {
|
||||
$contactphone = $admin->phone1;
|
||||
}
|
||||
$imageurl = get_config('hub', 'site_imageurl_' . $cleanhuburl);
|
||||
$privacy = get_config('hub', 'site_privacy_' . $cleanhuburl);
|
||||
$address = get_config('hub', 'site_address_' . $cleanhuburl);
|
||||
$region = get_config('hub', 'site_region_' . $cleanhuburl);
|
||||
$country = get_config('hub', 'site_country_' . $cleanhuburl);
|
||||
if ($country === false) {
|
||||
$country = $admin->country;
|
||||
}
|
||||
$language = get_config('hub', 'site_language_' . $cleanhuburl);
|
||||
if ($language === false) {
|
||||
$language = explode('_', current_language())[0];
|
||||
}
|
||||
$geolocation = get_config('hub', 'site_geolocation_' . $cleanhuburl);
|
||||
$contactable = get_config('hub', 'site_contactable_' . $cleanhuburl);
|
||||
$emailalert = get_config('hub', 'site_emailalert_' . $cleanhuburl);
|
||||
$emailalert = ($emailalert === 0) ? 0 : 1;
|
||||
$coursesnumber = get_config('hub', 'site_coursesnumber_' . $cleanhuburl);
|
||||
$usersnumber = get_config('hub', 'site_usersnumber_' . $cleanhuburl);
|
||||
$roleassignmentsnumber = get_config('hub', 'site_roleassignmentsnumber_' . $cleanhuburl);
|
||||
$postsnumber = get_config('hub', 'site_postsnumber_' . $cleanhuburl);
|
||||
$questionsnumber = get_config('hub', 'site_questionsnumber_' . $cleanhuburl);
|
||||
$resourcesnumber = get_config('hub', 'site_resourcesnumber_' . $cleanhuburl);
|
||||
$badgesnumber = get_config('hub', 'site_badges_' . $cleanhuburl);
|
||||
$issuedbadgesnumber = get_config('hub', 'site_issuedbadges_' . $cleanhuburl);
|
||||
$mediancoursesize = get_config('hub', 'site_mediancoursesize_' . $cleanhuburl);
|
||||
$participantnumberaveragecfg = get_config('hub', 'site_participantnumberaverage_' . $cleanhuburl);
|
||||
$modulenumberaveragecfg = get_config('hub', 'site_modulenumberaverage_' . $cleanhuburl);
|
||||
|
||||
//hidden parameters
|
||||
$mform->addElement('hidden', 'huburl', $huburl);
|
||||
$mform->setType('huburl', PARAM_URL);
|
||||
$mform->addElement('hidden', 'hubname', $hubname);
|
||||
$mform->setType('hubname', PARAM_TEXT);
|
||||
$mform->addElement('hidden', 'password', $password);
|
||||
$mform->setType('password', PARAM_RAW);
|
||||
|
||||
//the input parameters
|
||||
$mform->addElement('header', 'moodle', get_string('registrationinfo', 'hub'));
|
||||
|
||||
$mform->addElement('text', 'name', get_string('sitename', 'hub'),
|
||||
array('class' => 'registration_textfield'));
|
||||
$mform->addRule('name', $strrequired, 'required', null, 'client');
|
||||
$mform->setType('name', PARAM_TEXT);
|
||||
$mform->setDefault('name', $sitename);
|
||||
$mform->addHelpButton('name', 'sitename', 'hub');
|
||||
|
||||
$options = array();
|
||||
$registrationmanager = new registration_manager();
|
||||
$options[HUB_SITENOTPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITENOTPUBLISHED);
|
||||
$options[HUB_SITENAMEPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITENAMEPUBLISHED);
|
||||
$options[HUB_SITELINKPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITELINKPUBLISHED);
|
||||
$mform->addElement('select', 'privacy', get_string('siteprivacy', 'hub'), $options);
|
||||
$mform->setDefault('privacy', $privacy);
|
||||
$mform->setType('privacy', PARAM_ALPHA);
|
||||
$mform->addHelpButton('privacy', 'privacy', 'hub');
|
||||
unset($options);
|
||||
|
||||
$mform->addElement('textarea', 'description', get_string('sitedesc', 'hub'),
|
||||
array('rows' => 8, 'cols' => 41));
|
||||
$mform->addRule('description', $strrequired, 'required', null, 'client');
|
||||
$mform->setDefault('description', $sitedescription);
|
||||
$mform->setType('description', PARAM_TEXT);
|
||||
$mform->addHelpButton('description', 'sitedesc', 'hub');
|
||||
|
||||
$languages = get_string_manager()->get_list_of_languages();
|
||||
core_collator::asort($languages);
|
||||
$mform->addElement('select', 'language', get_string('sitelang', 'hub'),
|
||||
$languages);
|
||||
$mform->setType('language', PARAM_ALPHANUMEXT);
|
||||
$mform->addHelpButton('language', 'sitelang', 'hub');
|
||||
$mform->setDefault('language', $language);
|
||||
|
||||
$mform->addElement('textarea', 'address', get_string('postaladdress', 'hub'),
|
||||
array('rows' => 4, 'cols' => 41));
|
||||
$mform->setType('address', PARAM_TEXT);
|
||||
$mform->setDefault('address', $address);
|
||||
$mform->addHelpButton('address', 'postaladdress', 'hub');
|
||||
|
||||
//TODO: use the region array I generated
|
||||
// $mform->addElement('select', 'region', get_string('selectaregion'), array('-' => '-'));
|
||||
// $mform->setDefault('region', $region);
|
||||
$mform->addElement('hidden', 'regioncode', '-');
|
||||
$mform->setType('regioncode', PARAM_ALPHANUMEXT);
|
||||
|
||||
$countries = get_string_manager()->get_list_of_countries();
|
||||
$mform->addElement('select', 'countrycode', get_string('sitecountry', 'hub'), $countries);
|
||||
$mform->setDefault('countrycode', $country);
|
||||
$mform->setType('countrycode', PARAM_ALPHANUMEXT);
|
||||
$mform->addHelpButton('countrycode', 'sitecountry', 'hub');
|
||||
|
||||
$mform->addElement('text', 'geolocation', get_string('sitegeolocation', 'hub'),
|
||||
array('class' => 'registration_textfield'));
|
||||
$mform->setDefault('geolocation', $geolocation);
|
||||
$mform->setType('geolocation', PARAM_RAW);
|
||||
$mform->addHelpButton('geolocation', 'sitegeolocation', 'hub');
|
||||
|
||||
$mform->addElement('text', 'contactname', get_string('siteadmin', 'hub'),
|
||||
array('class' => 'registration_textfield'));
|
||||
$mform->addRule('contactname', $strrequired, 'required', null, 'client');
|
||||
$mform->setType('contactname', PARAM_TEXT);
|
||||
$mform->setDefault('contactname', $contactname);
|
||||
$mform->addHelpButton('contactname', 'siteadmin', 'hub');
|
||||
|
||||
$mform->addElement('text', 'contactphone', get_string('sitephone', 'hub'),
|
||||
array('class' => 'registration_textfield'));
|
||||
$mform->setType('contactphone', PARAM_TEXT);
|
||||
$mform->addHelpButton('contactphone', 'sitephone', 'hub');
|
||||
$mform->setForceLtr('contactphone');
|
||||
|
||||
$mform->addElement('text', 'contactemail', get_string('siteemail', 'hub'),
|
||||
array('class' => 'registration_textfield'));
|
||||
$mform->addRule('contactemail', $strrequired, 'required', null, 'client');
|
||||
$mform->setType('contactemail', PARAM_EMAIL);
|
||||
$mform->setDefault('contactemail', $contactemail);
|
||||
$mform->addHelpButton('contactemail', 'siteemail', 'hub');
|
||||
|
||||
$options = array();
|
||||
$options[0] = get_string("registrationcontactno");
|
||||
$options[1] = get_string("registrationcontactyes");
|
||||
$mform->addElement('select', 'contactable', get_string('siteregistrationcontact', 'hub'), $options);
|
||||
$mform->setDefault('contactable', $contactable);
|
||||
$mform->setType('contactable', PARAM_INT);
|
||||
$mform->addHelpButton('contactable', 'siteregistrationcontact', 'hub');
|
||||
unset($options);
|
||||
|
||||
$options = array();
|
||||
$options[0] = get_string("registrationno");
|
||||
$options[1] = get_string("registrationyes");
|
||||
$mform->addElement('select', 'emailalert', get_string('siteregistrationemail', 'hub'), $options);
|
||||
$mform->setDefault('emailalert', $emailalert);
|
||||
$mform->setType('emailalert', PARAM_INT);
|
||||
$mform->addHelpButton('emailalert', 'siteregistrationemail', 'hub');
|
||||
unset($options);
|
||||
|
||||
//TODO site logo
|
||||
$mform->addElement('hidden', 'imageurl', ''); //TODO: temporary
|
||||
$mform->setType('imageurl', PARAM_URL);
|
||||
|
||||
$mform->addElement('static', 'urlstring', get_string('siteurl', 'hub'), $CFG->wwwroot);
|
||||
$mform->addHelpButton('urlstring', 'siteurl', 'hub');
|
||||
|
||||
$mform->addElement('static', 'versionstring', get_string('siteversion', 'hub'), $CFG->version);
|
||||
$mform->addElement('hidden', 'moodleversion', $CFG->version);
|
||||
$mform->setType('moodleversion', PARAM_INT);
|
||||
$mform->addHelpButton('versionstring', 'siteversion', 'hub');
|
||||
|
||||
$mform->addElement('static', 'releasestring', get_string('siterelease', 'hub'), $CFG->release);
|
||||
$mform->addElement('hidden', 'moodlerelease', $CFG->release);
|
||||
$mform->setType('moodlerelease', PARAM_TEXT);
|
||||
$mform->addHelpButton('releasestring', 'siterelease', 'hub');
|
||||
|
||||
/// Display statistic that are going to be retrieve by the hub
|
||||
$coursecount = $DB->count_records('course') - 1;
|
||||
$usercount = $DB->count_records('user', array('deleted' => 0));
|
||||
$roleassigncount = $DB->count_records('role_assignments');
|
||||
$postcount = $DB->count_records('forum_posts');
|
||||
$questioncount = $DB->count_records('question');
|
||||
$resourcecount = $DB->count_records('resource');
|
||||
require_once($CFG->dirroot . "/course/lib.php");
|
||||
$participantnumberaverage = number_format(average_number_of_participants(), 2);
|
||||
$modulenumberaverage = number_format(average_number_of_courses_modules(), 2);
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
$badges = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
|
||||
$issuedbadges = $DB->count_records('badge_issued');
|
||||
|
||||
if (HUB_MOODLEORGHUBURL != $huburl) {
|
||||
$mform->addElement('checkbox', 'courses', get_string('sendfollowinginfo', 'hub'),
|
||||
" " . get_string('coursesnumber', 'hub', $coursecount));
|
||||
$mform->setDefault('courses', $coursesnumber != -1);
|
||||
$mform->setType('courses', PARAM_INT);
|
||||
$mform->addHelpButton('courses', 'sendfollowinginfo', 'hub');
|
||||
|
||||
$mform->addElement('checkbox', 'users', '',
|
||||
" " . get_string('usersnumber', 'hub', $usercount));
|
||||
$mform->setDefault('users', $usersnumber != -1);
|
||||
$mform->setType('users', PARAM_INT);
|
||||
|
||||
$mform->addElement('checkbox', 'roleassignments', '',
|
||||
" " . get_string('roleassignmentsnumber', 'hub', $roleassigncount));
|
||||
$mform->setDefault('roleassignments', $roleassignmentsnumber != -1);
|
||||
$mform->setType('roleassignments', PARAM_INT);
|
||||
|
||||
$mform->addElement('checkbox', 'posts', '',
|
||||
" " . get_string('postsnumber', 'hub', $postcount));
|
||||
$mform->setDefault('posts', $postsnumber != -1);
|
||||
$mform->setType('posts', PARAM_INT);
|
||||
|
||||
$mform->addElement('checkbox', 'questions', '',
|
||||
" " . get_string('questionsnumber', 'hub', $questioncount));
|
||||
$mform->setDefault('questions', $questionsnumber != -1);
|
||||
$mform->setType('questions', PARAM_INT);
|
||||
|
||||
$mform->addElement('checkbox', 'resources', '',
|
||||
" " . get_string('resourcesnumber', 'hub', $resourcecount));
|
||||
$mform->setDefault('resources', $resourcesnumber != -1);
|
||||
$mform->setType('resources', PARAM_INT);
|
||||
|
||||
$mform->addElement('checkbox', 'badges', '',
|
||||
" " . get_string('badgesnumber', 'hub', $badges));
|
||||
$mform->setDefault('badges', $badgesnumber != -1);
|
||||
$mform->setType('badges', PARAM_INT);
|
||||
|
||||
$mform->addElement('checkbox', 'issuedbadges', '',
|
||||
" " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
|
||||
$mform->setDefault('issuedbadges', $issuedbadgesnumber != -1);
|
||||
$mform->setType('issuedbadges', PARAM_INT);
|
||||
|
||||
$mform->addElement('checkbox', 'participantnumberaverage', '',
|
||||
" " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
|
||||
$mform->setDefault('participantnumberaverage', $participantnumberaveragecfg != -1);
|
||||
$mform->setType('participantnumberaverage', PARAM_FLOAT);
|
||||
|
||||
$mform->addElement('checkbox', 'modulenumberaverage', '',
|
||||
" " . get_string('modulenumberaverage', 'hub', $modulenumberaverage));
|
||||
$mform->setDefault('modulenumberaverage', $modulenumberaveragecfg != -1);
|
||||
$mform->setType('modulenumberaverage', PARAM_FLOAT);
|
||||
} else {
|
||||
$mform->addElement('static', 'courseslabel', get_string('sendfollowinginfo', 'hub'),
|
||||
" " . get_string('coursesnumber', 'hub', $coursecount));
|
||||
$mform->addElement('hidden', 'courses', 1);
|
||||
$mform->setType('courses', PARAM_INT);
|
||||
$mform->addHelpButton('courseslabel', 'sendfollowinginfo', 'hub');
|
||||
|
||||
$mform->addElement('static', 'userslabel', '',
|
||||
" " . get_string('usersnumber', 'hub', $usercount));
|
||||
$mform->addElement('hidden', 'users', 1);
|
||||
$mform->setType('users', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'roleassignmentslabel', '',
|
||||
" " . get_string('roleassignmentsnumber', 'hub', $roleassigncount));
|
||||
$mform->addElement('hidden', 'roleassignments', 1);
|
||||
$mform->setType('roleassignments', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'postslabel', '',
|
||||
" " . get_string('postsnumber', 'hub', $postcount));
|
||||
$mform->addElement('hidden', 'posts', 1);
|
||||
$mform->setType('posts', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'questionslabel', '',
|
||||
" " . get_string('questionsnumber', 'hub', $questioncount));
|
||||
$mform->addElement('hidden', 'questions', 1);
|
||||
$mform->setType('questions', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'resourceslabel', '',
|
||||
" " . get_string('resourcesnumber', 'hub', $resourcecount));
|
||||
$mform->addElement('hidden', 'resources', 1);
|
||||
$mform->setType('resources', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'badgeslabel', '',
|
||||
" " . get_string('badgesnumber', 'hub', $badges));
|
||||
$mform->addElement('hidden', 'badges', 1);
|
||||
$mform->setType('badges', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'issuedbadgeslabel', '',
|
||||
" " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
|
||||
$mform->addElement('hidden', 'issuedbadges', true);
|
||||
$mform->setType('issuedbadges', PARAM_INT);
|
||||
|
||||
$mform->addElement('static', 'participantnumberaveragelabel', '',
|
||||
" " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
|
||||
$mform->addElement('hidden', 'participantnumberaverage', 1);
|
||||
$mform->setType('participantnumberaverage', PARAM_FLOAT);
|
||||
|
||||
$mform->addElement('static', 'modulenumberaveragelabel', '',
|
||||
" " . get_string('modulenumberaverage', 'hub', $modulenumberaverage));
|
||||
$mform->addElement('hidden', 'modulenumberaverage', 1);
|
||||
$mform->setType('modulenumberaverage', PARAM_FLOAT);
|
||||
}
|
||||
|
||||
//check if it's a first registration or update
|
||||
$hubregistered = $registrationmanager->get_registeredhub($huburl);
|
||||
|
||||
if (!empty($hubregistered)) {
|
||||
$buttonlabel = get_string('updatesite', 'hub',
|
||||
!empty($hubname) ? $hubname : $huburl);
|
||||
$mform->addElement('hidden', 'update', true);
|
||||
$mform->setType('update', PARAM_BOOL);
|
||||
} else {
|
||||
$buttonlabel = get_string('registersite', 'hub',
|
||||
!empty($hubname) ? $hubname : $huburl);
|
||||
}
|
||||
|
||||
$this->add_action_buttons(false, $buttonlabel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+171
-84
@@ -15,112 +15,199 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
/*
|
||||
* @package moodle
|
||||
* @subpackage registration
|
||||
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
|
||||
* @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 for Moodle.net.
|
||||
* It handles redirection to the hub to continue the registration workflow process.
|
||||
* It also handles update operation by web service.
|
||||
* On this page the administrator selects which hub he wants to register (except for moodle.net)
|
||||
* Admins can register with moodle.net via the site admin menu "Registration" link.
|
||||
* On this page the administrator can also unregister from any hubs including moodle.net.
|
||||
*/
|
||||
|
||||
require_once('../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require('../../config.php');
|
||||
|
||||
admin_externalpage_setup('registrationmoodleorg');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/forms.php');
|
||||
require_once($CFG->dirroot . '/course/publish/lib.php');
|
||||
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
|
||||
|
||||
admin_externalpage_setup('registrationhubs');
|
||||
|
||||
$renderer = $PAGE->get_renderer('core', 'register');
|
||||
|
||||
$unregistration = optional_param('unregistration', 0, PARAM_INT);
|
||||
$cleanregdata = optional_param('cleanregdata', 0, PARAM_BOOL);
|
||||
$confirm = optional_param('confirm', 0, PARAM_INT);
|
||||
$huburl = optional_param('huburl', '', PARAM_URL);
|
||||
$cancel = optional_param('cancel', null, PARAM_ALPHA);
|
||||
|
||||
if ($unregistration && \core\hub\registration::is_registered()) {
|
||||
$siteunregistrationform = new \core\hub\site_unregistration_form();
|
||||
$registrationmanager = new registration_manager();
|
||||
$publicationmanager = new course_publish_manager();
|
||||
$errormessage = '';
|
||||
if (empty($cancel) and $unregistration and $confirm and confirm_sesskey()) {
|
||||
|
||||
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'));
|
||||
$hub = $registrationmanager->get_registeredhub($huburl);
|
||||
|
||||
//unpublish course and unregister the site by web service
|
||||
if (!$cleanregdata) {
|
||||
|
||||
//check if we need to unpublish courses
|
||||
//enrollable courses
|
||||
$unpublishalladvertisedcourses = optional_param('unpublishalladvertisedcourses', 0, PARAM_INT);
|
||||
$hubcourseids = array();
|
||||
if ($unpublishalladvertisedcourses) {
|
||||
$enrollablecourses = $publicationmanager->get_publications($huburl, null, 1);
|
||||
if (!empty($enrollablecourses)) {
|
||||
foreach ($enrollablecourses as $enrollablecourse) {
|
||||
$hubcourseids[] = $enrollablecourse->hubcourseid;
|
||||
}
|
||||
}
|
||||
}
|
||||
//downloadable courses
|
||||
$unpublishalluploadedcourses = optional_param('unpublishalluploadedcourses', 0, PARAM_INT);
|
||||
if ($unpublishalluploadedcourses) {
|
||||
$downloadablecourses = $publicationmanager->get_publications($huburl, null, 0);
|
||||
if (!empty($downloadablecourses)) {
|
||||
foreach ($downloadablecourses as $downloadablecourse) {
|
||||
$hubcourseids[] = $downloadablecourse->hubcourseid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//unpublish the courses by web service
|
||||
if (!empty($hubcourseids)) {
|
||||
$function = 'hub_unregister_courses';
|
||||
$params = array('courseids' => $hubcourseids);
|
||||
$serverurl = $huburl . "/local/hub/webservice/webservices.php";
|
||||
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
|
||||
try {
|
||||
$result = $xmlrpcclient->call($function, $params);
|
||||
//delete the published courses
|
||||
if (!empty($enrollablecourses)) {
|
||||
$publicationmanager->delete_hub_publications($huburl, 1);
|
||||
}
|
||||
if (!empty($downloadablecourses)) {
|
||||
$publicationmanager->delete_hub_publications($huburl, 0);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$errormessage = $e->getMessage();
|
||||
$errormessage .= html_writer::empty_tag('br') .
|
||||
get_string('errorunpublishcourses', 'hub');
|
||||
$confirm = false;
|
||||
$cleanregdata = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//course unpublish went ok, unregister the site now
|
||||
if ($confirm) {
|
||||
$function = 'hub_unregister_site';
|
||||
$params = array();
|
||||
$serverurl = $huburl . "/local/hub/webservice/webservices.php";
|
||||
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
|
||||
try {
|
||||
$result = $xmlrpcclient->call($function, $params);
|
||||
} catch (Exception $e) {
|
||||
if (!$cleanregdata) {
|
||||
$errormessage = $e->getMessage();
|
||||
$confirm = false;
|
||||
$cleanregdata = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check that we are still processing the unregistration,
|
||||
//it could have been unset if an exception were previsouly catched
|
||||
if ($confirm) {
|
||||
$registrationmanager->delete_registeredhub($huburl);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($cancel) and $unregistration and !$confirm) {
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
//do not check sesskey if confirm = false because this script is linked into email message
|
||||
if (!empty($errormessage)) {
|
||||
echo $OUTPUT->notification(get_string('unregistrationerror', 'hub', $errormessage));
|
||||
}
|
||||
|
||||
$hub = $registrationmanager->get_registeredhub($huburl);
|
||||
echo $OUTPUT->heading(get_string('unregisterfrom', 'hub', $hub->hubname), 3, 'main');
|
||||
if ($cleanregdata) {
|
||||
$siteunregistrationform = new site_clean_registration_data_form('',
|
||||
array('huburl' => $huburl, 'hubname' => $hub->hubname));
|
||||
} else {
|
||||
$siteunregistrationform = new site_unregistration_form('',
|
||||
array('huburl' => $huburl, 'hubname' => $hub->hubname));
|
||||
}
|
||||
|
||||
$siteunregistrationform->display();
|
||||
} else {
|
||||
$registeredonmoodleorg = false;
|
||||
$moodleorghub = $registrationmanager->get_registeredhub(HUB_MOODLEORGHUBURL);
|
||||
if (!empty($moodleorghub)) {
|
||||
$registeredonmoodleorg = true;
|
||||
}
|
||||
|
||||
// load the hub selector form
|
||||
$hubselectorform = new hub_selector_form();
|
||||
$fromform = $hubselectorform->get_data();
|
||||
$selectedhuburl = optional_param('publichub', false, PARAM_URL);
|
||||
$unlistedhuburl = optional_param('unlistedurl', false, PARAM_TEXT);
|
||||
$password = optional_param('password', '', PARAM_RAW);
|
||||
$registeringhuburl = null;
|
||||
if (!empty($unlistedhuburl)) {
|
||||
if (clean_param($unlistedhuburl, PARAM_URL) !== '') {
|
||||
$registeringhuburl = $unlistedhuburl;
|
||||
}
|
||||
} else if (!empty($selectedhuburl)) {
|
||||
$registeringhuburl = $selectedhuburl;
|
||||
}
|
||||
|
||||
// a hub has been selected, redirect to the hub registration page
|
||||
if (empty($cancel) and !empty($registeringhuburl) and confirm_sesskey()) {
|
||||
$hubname = optional_param(clean_param($registeringhuburl, PARAM_ALPHANUMEXT), '', PARAM_TEXT);
|
||||
$params = array('sesskey' => sesskey(), 'huburl' => $registeringhuburl,
|
||||
'password' => $password, 'hubname' => $hubname);
|
||||
redirect(new moodle_url($CFG->wwwroot . "/" . $CFG->admin . "/registration/register.php",
|
||||
$params));
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('unregisterfrom', 'hub', 'Moodle.net'), 3, 'main');
|
||||
$siteunregistrationform->display();
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
}
|
||||
|
||||
$isinitialregistration = \core\hub\registration::show_after_install(true);
|
||||
if (!$returnurl = optional_param('returnurl', null, PARAM_LOCALURL)) {
|
||||
$returnurl = $isinitialregistration ? '/admin/index.php' : '/admin/registration/index.php';
|
||||
}
|
||||
//check if the site is registered on Moodle.org and display a message about registering on MOOCH
|
||||
$registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
|
||||
if (empty($registered)) {
|
||||
$warningmsg = get_string('registermoochtips', 'hub');
|
||||
$warningmsg .= $renderer->single_button(new moodle_url('register.php', array('huburl' => HUB_MOODLEORGHUBURL
|
||||
, 'hubname' => 'Moodle.org')), get_string('register', 'admin'));
|
||||
echo $renderer->box($warningmsg, 'buttons mdl-align generalbox adminwarning');
|
||||
}
|
||||
|
||||
$siteregistrationform = new \core\hub\site_registration_form();
|
||||
$siteregistrationform->set_data(['returnurl' => $returnurl]);
|
||||
if ($fromform = $siteregistrationform->get_data()) {
|
||||
//do not check sesskey if confirm = false because this script is linked into email message
|
||||
if (!empty($errormessage)) {
|
||||
echo $OUTPUT->notification(get_string('unregistrationerror', 'hub', $errormessage));
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
\core\hub\registration::save_site_info($fromform);
|
||||
echo $OUTPUT->heading(get_string('registerwith', 'hub'));
|
||||
|
||||
if (\core\hub\registration::is_registered()) {
|
||||
if (\core\hub\registration::update_manual()) {
|
||||
redirect(new moodle_url($returnurl));
|
||||
$hubselectorform->display();
|
||||
|
||||
if (extension_loaded('xmlrpc')) {
|
||||
$hubs = $registrationmanager->get_registered_on_hubs();
|
||||
if (!empty($hubs)) {
|
||||
echo $OUTPUT->heading(get_string('registeredon', 'hub'), 3, 'main');
|
||||
echo $renderer->registeredonhublisting($hubs);
|
||||
}
|
||||
redirect(new moodle_url('/admin/registration/index.php', ['returnurl' => $returnurl]));
|
||||
} else {
|
||||
\core\hub\registration::register($returnurl);
|
||||
// This method will redirect away.
|
||||
} else { //display notice about xmlrpc
|
||||
$xmlrpcnotification = $OUTPUT->doc_link('admin/environment/php_extension/xmlrpc', '');
|
||||
$xmlrpcnotification .= get_string('xmlrpcdisabledregistration', 'hub');
|
||||
echo $OUTPUT->notification($xmlrpcnotification);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// OUTPUT SECTION.
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
// Current status of registration on Moodle.net.
|
||||
|
||||
$notificationtype = \core\output\notification::NOTIFY_ERROR;
|
||||
if (\core\hub\registration::is_registered()) {
|
||||
$lastupdated = \core\hub\registration::get_last_updated();
|
||||
if ($lastupdated == 0) {
|
||||
$registrationmessage = get_string('pleaserefreshregistrationunknown', 'admin');
|
||||
} else if (\core\hub\registration::get_new_registration_fields()) {
|
||||
$registrationmessage = get_string('pleaserefreshregistrationnewdata', 'admin');
|
||||
} else {
|
||||
$lastupdated = userdate($lastupdated, get_string('strftimedate', 'langconfig'));
|
||||
$registrationmessage = get_string('pleaserefreshregistration', 'admin', $lastupdated);
|
||||
$notificationtype = \core\output\notification::NOTIFY_INFO;
|
||||
}
|
||||
echo $OUTPUT->notification($registrationmessage, $notificationtype);
|
||||
} else if (!$isinitialregistration) {
|
||||
$registrationmessage = get_string('registrationwarning', 'admin');
|
||||
echo $OUTPUT->notification($registrationmessage, $notificationtype);
|
||||
}
|
||||
|
||||
// Heading.
|
||||
if (\core\hub\registration::is_registered()) {
|
||||
echo $OUTPUT->heading(get_string('updatesite', 'hub', 'Moodle.net'));
|
||||
} else if ($isinitialregistration) {
|
||||
echo $OUTPUT->heading(get_string('completeregistration', 'hub'));
|
||||
} else {
|
||||
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
|
||||
}
|
||||
|
||||
$renderer = $PAGE->get_renderer('core', 'admin');
|
||||
echo $renderer->moodleorg_registration_message();
|
||||
|
||||
$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');
|
||||
} else if ($isinitialregistration) {
|
||||
echo html_writer::div(html_writer::link(new moodle_url($returnurl), get_string('skipregistration', 'hub')), 'skipregistration');
|
||||
}
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
+295
-1
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
@@ -14,4 +15,297 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
|
||||
//// SITE PRIVACY /////
|
||||
|
||||
/**
|
||||
* Site privacy: private
|
||||
*/
|
||||
define('HUB_SITENOTPUBLISHED', 'notdisplayed');
|
||||
|
||||
/**
|
||||
* Site privacy: public
|
||||
*/
|
||||
define('HUB_SITENAMEPUBLISHED', 'named');
|
||||
|
||||
/**
|
||||
* Site privacy: public and global
|
||||
*/
|
||||
define('HUB_SITELINKPUBLISHED', 'linked');
|
||||
|
||||
/**
|
||||
*
|
||||
* Site registration library
|
||||
*
|
||||
* @package course
|
||||
* @copyright 2010 Moodle Pty Ltd (http://moodle.com)
|
||||
* @author Jerome Mouneyrac
|
||||
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class registration_manager {
|
||||
|
||||
/**
|
||||
* Automatically update the registration on all hubs
|
||||
*/
|
||||
public function cron() {
|
||||
global $CFG;
|
||||
if (extension_loaded('xmlrpc')) {
|
||||
$function = 'hub_update_site_info';
|
||||
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
|
||||
|
||||
// Update all hubs where the site is registered.
|
||||
$hubs = $this->get_registered_on_hubs();
|
||||
if (empty($hubs)) {
|
||||
mtrace(get_string('registrationwarning', 'admin'));
|
||||
}
|
||||
foreach ($hubs as $hub) {
|
||||
// Update the registration.
|
||||
$siteinfo = $this->get_site_info($hub->huburl);
|
||||
$params = array('siteinfo' => $siteinfo);
|
||||
$serverurl = $hub->huburl . "/local/hub/webservice/webservices.php";
|
||||
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
|
||||
try {
|
||||
$result = $xmlrpcclient->call($function, $params);
|
||||
$this->update_registeredhub($hub); // To update timemodified.
|
||||
mtrace(get_string('siteupdatedcron', 'hub', $hub->hubname));
|
||||
} catch (Exception $e) {
|
||||
$errorparam = new stdClass();
|
||||
$errorparam->errormessage = $e->getMessage();
|
||||
$errorparam->hubname = $hub->hubname;
|
||||
mtrace(get_string('errorcron', 'hub', $errorparam));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mtrace(get_string('errorcronnoxmlrpc', 'hub'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the site secret for a given hub
|
||||
* site identifier is assigned to Mooch
|
||||
* each hub has a unique and personal site secret.
|
||||
* @param string $huburl
|
||||
* @return string site secret
|
||||
*/
|
||||
public function get_site_secret_for_hub($huburl) {
|
||||
global $DB;
|
||||
|
||||
$existingregistration = $DB->get_record('registration_hubs',
|
||||
array('huburl' => $huburl));
|
||||
|
||||
if (!empty($existingregistration)) {
|
||||
return $existingregistration->secret;
|
||||
}
|
||||
|
||||
if ($huburl == HUB_MOODLEORGHUBURL) {
|
||||
$siteidentifier = get_site_identifier();
|
||||
} else {
|
||||
$siteidentifier = random_string(32) . $_SERVER['HTTP_HOST'];
|
||||
}
|
||||
|
||||
return $siteidentifier;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* When the site register on a hub, he must call this function
|
||||
* @param object $hub where the site is registered on
|
||||
* @return integer id of the record
|
||||
*/
|
||||
public function add_registeredhub($hub) {
|
||||
global $DB;
|
||||
$hub->timemodified = time();
|
||||
$id = $DB->insert_record('registration_hubs', $hub);
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* When a site unregister from a hub, he must call this function
|
||||
* @param string $huburl the huburl to delete
|
||||
*/
|
||||
public function delete_registeredhub($huburl) {
|
||||
global $DB;
|
||||
$DB->delete_records('registration_hubs', array('huburl' => $huburl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a hub on which the site is registered for a given url or token
|
||||
* Mostly use to check if the site is registered on a specific hub
|
||||
* @param string $huburl
|
||||
* @param string $token
|
||||
* @return object the hub
|
||||
*/
|
||||
public function get_registeredhub($huburl = null, $token = null) {
|
||||
global $DB;
|
||||
|
||||
$params = array();
|
||||
if (!empty($huburl)) {
|
||||
$params['huburl'] = $huburl;
|
||||
}
|
||||
if (!empty($token)) {
|
||||
$params['token'] = $token;
|
||||
}
|
||||
$params['confirmed'] = 1;
|
||||
$token = $DB->get_record('registration_hubs', $params);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hub which has not confirmed that the site is registered on,
|
||||
* but for which a request has been sent
|
||||
* @param string $huburl
|
||||
* @return object the hub
|
||||
*/
|
||||
public function get_unconfirmedhub($huburl) {
|
||||
global $DB;
|
||||
|
||||
$params = array();
|
||||
$params['huburl'] = $huburl;
|
||||
$params['confirmed'] = 0;
|
||||
$token = $DB->get_record('registration_hubs', $params);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a registered hub (mostly use to update the confirmation status)
|
||||
* @param object $hub the hub
|
||||
*/
|
||||
public function update_registeredhub($hub) {
|
||||
global $DB;
|
||||
$hub->timemodified = time();
|
||||
$DB->update_record('registration_hubs', $hub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all hubs where the site is registered
|
||||
*/
|
||||
public function get_registered_on_hubs() {
|
||||
global $DB;
|
||||
$hubs = $DB->get_records('registration_hubs', array('confirmed' => 1));
|
||||
return $hubs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return site information for a specific hub
|
||||
* @param string $huburl
|
||||
* @return array site info
|
||||
*/
|
||||
public function get_site_info($huburl) {
|
||||
global $CFG, $DB;
|
||||
|
||||
$siteinfo = array();
|
||||
$cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
|
||||
$siteinfo['name'] = get_config('hub', 'site_name_' . $cleanhuburl);
|
||||
$siteinfo['description'] = get_config('hub', 'site_description_' . $cleanhuburl);
|
||||
$siteinfo['contactname'] = get_config('hub', 'site_contactname_' . $cleanhuburl);
|
||||
$siteinfo['contactemail'] = get_config('hub', 'site_contactemail_' . $cleanhuburl);
|
||||
$siteinfo['contactphone'] = get_config('hub', 'site_contactphone_' . $cleanhuburl);
|
||||
$siteinfo['imageurl'] = get_config('hub', 'site_imageurl_' . $cleanhuburl);
|
||||
$siteinfo['privacy'] = get_config('hub', 'site_privacy_' . $cleanhuburl);
|
||||
$siteinfo['street'] = get_config('hub', 'site_address_' . $cleanhuburl);
|
||||
$siteinfo['regioncode'] = get_config('hub', 'site_region_' . $cleanhuburl);
|
||||
$siteinfo['countrycode'] = get_config('hub', 'site_country_' . $cleanhuburl);
|
||||
$siteinfo['geolocation'] = get_config('hub', 'site_geolocation_' . $cleanhuburl);
|
||||
$siteinfo['contactable'] = get_config('hub', 'site_contactable_' . $cleanhuburl);
|
||||
$siteinfo['emailalert'] = get_config('hub', 'site_emailalert_' . $cleanhuburl);
|
||||
if (get_config('hub', 'site_coursesnumber_' . $cleanhuburl) == -1) {
|
||||
$coursecount = -1;
|
||||
} else {
|
||||
$coursecount = $DB->count_records('course') - 1;
|
||||
}
|
||||
$siteinfo['courses'] = $coursecount;
|
||||
if (get_config('hub', 'site_usersnumber_' . $cleanhuburl) == -1) {
|
||||
$usercount = -1;
|
||||
} else {
|
||||
$usercount = $DB->count_records('user', array('deleted' => 0));
|
||||
}
|
||||
$siteinfo['users'] = $usercount;
|
||||
|
||||
if (get_config('hub', 'site_roleassignmentsnumber_' . $cleanhuburl) == -1) {
|
||||
$roleassigncount = -1;
|
||||
} else {
|
||||
$roleassigncount = $DB->count_records('role_assignments');
|
||||
}
|
||||
$siteinfo['enrolments'] = $roleassigncount;
|
||||
if (get_config('hub', 'site_postsnumber_' . $cleanhuburl) == -1) {
|
||||
$postcount = -1;
|
||||
} else {
|
||||
$postcount = $DB->count_records('forum_posts');
|
||||
}
|
||||
$siteinfo['posts'] = $postcount;
|
||||
if (get_config('hub', 'site_questionsnumber_' . $cleanhuburl) == -1) {
|
||||
$questioncount = -1;
|
||||
} else {
|
||||
$questioncount = $DB->count_records('question');
|
||||
}
|
||||
$siteinfo['questions'] = $questioncount;
|
||||
if (get_config('hub', 'site_resourcesnumber_' . $cleanhuburl) == -1) {
|
||||
$resourcecount = -1;
|
||||
} else {
|
||||
$resourcecount = $DB->count_records('resource');
|
||||
}
|
||||
$siteinfo['resources'] = $resourcecount;
|
||||
// Badge statistics.
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
if (get_config('hub', 'site_badges_' . $cleanhuburl) == -1) {
|
||||
$badges = -1;
|
||||
} else {
|
||||
$badges = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
|
||||
}
|
||||
$siteinfo['badges'] = $badges;
|
||||
if (get_config('hub', 'site_issuedbadges_' . $cleanhuburl) == -1) {
|
||||
$issuedbadges = -1;
|
||||
} else {
|
||||
$issuedbadges = $DB->count_records('badge_issued');
|
||||
}
|
||||
$siteinfo['issuedbadges'] = $issuedbadges;
|
||||
//TODO
|
||||
require_once($CFG->dirroot . "/course/lib.php");
|
||||
if (get_config('hub', 'site_participantnumberaverage_' . $cleanhuburl) == -1) {
|
||||
$participantnumberaverage = -1;
|
||||
} else {
|
||||
$participantnumberaverage = average_number_of_participants();
|
||||
}
|
||||
$siteinfo['participantnumberaverage'] = $participantnumberaverage;
|
||||
if (get_config('hub', 'site_modulenumberaverage_' . $cleanhuburl) == -1) {
|
||||
$modulenumberaverage = -1;
|
||||
} else {
|
||||
$modulenumberaverage = average_number_of_courses_modules();
|
||||
}
|
||||
$siteinfo['modulenumberaverage'] = $modulenumberaverage;
|
||||
$siteinfo['language'] = get_config('hub', 'site_language_' . $cleanhuburl);
|
||||
$siteinfo['moodleversion'] = $CFG->version;
|
||||
$siteinfo['moodlerelease'] = $CFG->release;
|
||||
$siteinfo['url'] = $CFG->wwwroot;
|
||||
|
||||
return $siteinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the site privacy string matching the define value
|
||||
* @param string $privacy must match the define into moodlelib.php
|
||||
* @return string
|
||||
*/
|
||||
public function get_site_privacy_string($privacy) {
|
||||
switch ($privacy) {
|
||||
case HUB_SITENOTPUBLISHED:
|
||||
$privacystring = get_string('siteprivacynotpublished', 'hub');
|
||||
break;
|
||||
case HUB_SITENAMEPUBLISHED:
|
||||
$privacystring = get_string('siteprivacypublished', 'hub');
|
||||
break;
|
||||
case HUB_SITELINKPUBLISHED:
|
||||
$privacystring = get_string('siteprivacylinked', 'hub');
|
||||
break;
|
||||
}
|
||||
if (empty($privacystring)) {
|
||||
throw new moodle_exception('unknownprivacy');
|
||||
}
|
||||
return $privacystring;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
/*
|
||||
* @package moodle
|
||||
* @subpackage registration
|
||||
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
|
||||
@@ -34,5 +34,168 @@
|
||||
|
||||
|
||||
require_once('../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/forms.php');
|
||||
require_once($CFG->dirroot . '/webservice/lib.php');
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
|
||||
|
||||
redirect(new moodle_url('/admin/registration/index.php'));
|
||||
require_sesskey();
|
||||
|
||||
$huburl = required_param('huburl', PARAM_URL);
|
||||
$huburl = rtrim($huburl, "/");
|
||||
|
||||
if ($huburl == HUB_MOODLEORGHUBURL) { // register to Moodle.org
|
||||
admin_externalpage_setup('registrationmoodleorg');
|
||||
} else { //register to a hub
|
||||
admin_externalpage_setup('registrationhub');
|
||||
}
|
||||
|
||||
$password = optional_param('password', '', PARAM_TEXT);
|
||||
$hubname = optional_param('hubname', '', PARAM_TEXT);
|
||||
|
||||
$registrationmanager = new registration_manager();
|
||||
|
||||
$registeredhub = $registrationmanager->get_registeredhub($huburl);
|
||||
|
||||
$siteregistrationform = new site_registration_form('',
|
||||
array('alreadyregistered' => !empty($registeredhub->token),
|
||||
'huburl' => $huburl, 'hubname' => $hubname,
|
||||
'password' => $password));
|
||||
$fromform = $siteregistrationform->get_data();
|
||||
|
||||
if (!empty($fromform) and confirm_sesskey()) {
|
||||
|
||||
// Set to -1 all optional data marked as "don't send" by the admin.
|
||||
// The function get_site_info() will not calculate the optional data if config is set to -1.
|
||||
$inputnames = array('courses', 'users', 'roleassignments', 'posts', 'questions', 'resources',
|
||||
'badges', 'issuedbadges', 'modulenumberaverage', 'participantnumberaverage');
|
||||
foreach ($inputnames as $inputname) {
|
||||
if (empty($fromform->{$inputname})) {
|
||||
$fromform->{$inputname} = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
$cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
|
||||
set_config('site_name_' . $cleanhuburl, $fromform->name, 'hub');
|
||||
set_config('site_description_' . $cleanhuburl, $fromform->description, 'hub');
|
||||
set_config('site_contactname_' . $cleanhuburl, $fromform->contactname, 'hub');
|
||||
set_config('site_contactemail_' . $cleanhuburl, $fromform->contactemail, 'hub');
|
||||
set_config('site_contactphone_' . $cleanhuburl, $fromform->contactphone, 'hub');
|
||||
set_config('site_imageurl_' . $cleanhuburl, $fromform->imageurl, 'hub');
|
||||
set_config('site_privacy_' . $cleanhuburl, $fromform->privacy, 'hub');
|
||||
set_config('site_address_' . $cleanhuburl, $fromform->address, 'hub');
|
||||
set_config('site_region_' . $cleanhuburl, $fromform->regioncode, 'hub');
|
||||
set_config('site_country_' . $cleanhuburl, $fromform->countrycode, 'hub');
|
||||
set_config('site_language_' . $cleanhuburl, $fromform->language, 'hub');
|
||||
set_config('site_geolocation_' . $cleanhuburl, $fromform->geolocation, 'hub');
|
||||
set_config('site_contactable_' . $cleanhuburl, $fromform->contactable, 'hub');
|
||||
set_config('site_emailalert_' . $cleanhuburl, $fromform->emailalert, 'hub');
|
||||
set_config('site_coursesnumber_' . $cleanhuburl, $fromform->courses, 'hub');
|
||||
set_config('site_usersnumber_' . $cleanhuburl, $fromform->users, 'hub');
|
||||
set_config('site_roleassignmentsnumber_' . $cleanhuburl, $fromform->roleassignments, 'hub');
|
||||
set_config('site_postsnumber_' . $cleanhuburl, $fromform->posts, 'hub');
|
||||
set_config('site_questionsnumber_' . $cleanhuburl, $fromform->questions, 'hub');
|
||||
set_config('site_resourcesnumber_' . $cleanhuburl, $fromform->resources, 'hub');
|
||||
set_config('site_badges_' . $cleanhuburl, $fromform->badges, 'hub');
|
||||
set_config('site_issuedbadges_' . $cleanhuburl, $fromform->issuedbadges, 'hub');
|
||||
set_config('site_modulenumberaverage_' . $cleanhuburl, $fromform->modulenumberaverage, 'hub');
|
||||
set_config('site_participantnumberaverage_' . $cleanhuburl, $fromform->participantnumberaverage, 'hub');
|
||||
}
|
||||
|
||||
/////// UPDATE ACTION ////////
|
||||
|
||||
// update the hub registration
|
||||
$update = optional_param('update', 0, PARAM_INT);
|
||||
if ($update and confirm_sesskey()) {
|
||||
|
||||
//update the registration
|
||||
$function = 'hub_update_site_info';
|
||||
$siteinfo = $registrationmanager->get_site_info($huburl);
|
||||
$params = array('siteinfo' => $siteinfo);
|
||||
$serverurl = $huburl . "/local/hub/webservice/webservices.php";
|
||||
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
|
||||
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $registeredhub->token);
|
||||
try {
|
||||
$result = $xmlrpcclient->call($function, $params);
|
||||
$registrationmanager->update_registeredhub($registeredhub); // To update timemodified.
|
||||
} catch (Exception $e) {
|
||||
$error = $OUTPUT->notification(get_string('errorregistration', 'hub', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/////// FORM REGISTRATION ACTION //////
|
||||
|
||||
if (!empty($fromform) and empty($update) and confirm_sesskey()) {
|
||||
|
||||
if (!empty($fromform) and confirm_sesskey()) { // if the register button has been clicked
|
||||
|
||||
// Retrieve the optional info (specially course number, user number, module number average...).
|
||||
$siteinfo = $registrationmanager->get_site_info($huburl);
|
||||
$fromform->courses = $siteinfo['courses'];
|
||||
$fromform->users = $siteinfo['users'];
|
||||
$fromform->enrolments = $siteinfo['enrolments'];
|
||||
$fromform->posts = $siteinfo['posts'];
|
||||
$fromform->questions = $siteinfo['questions'];
|
||||
$fromform->resources = $siteinfo['resources'];
|
||||
$fromform->badges = $siteinfo['badges'];
|
||||
$fromform->issuedbadges = $siteinfo['issuedbadges'];
|
||||
$fromform->modulenumberaverage = $siteinfo['modulenumberaverage'];
|
||||
$fromform->participantnumberaverage = $siteinfo['participantnumberaverage'];
|
||||
$fromform->street = $siteinfo['street'];
|
||||
|
||||
$params = (array) $fromform; //we are using the form input as the redirection parameters (token, url and name)
|
||||
|
||||
$unconfirmedhub = $registrationmanager->get_unconfirmedhub($huburl);
|
||||
if (empty($unconfirmedhub)) {
|
||||
//we save the token into the communication table in order to have a reference
|
||||
$unconfirmedhub = new stdClass();
|
||||
$unconfirmedhub->token = $registrationmanager->get_site_secret_for_hub($huburl);
|
||||
$unconfirmedhub->secret = $unconfirmedhub->token;
|
||||
$unconfirmedhub->huburl = $huburl;
|
||||
$unconfirmedhub->hubname = $hubname;
|
||||
$unconfirmedhub->confirmed = 0;
|
||||
$unconfirmedhub->id = $registrationmanager->add_registeredhub($unconfirmedhub);
|
||||
}
|
||||
|
||||
$params['token'] = $unconfirmedhub->token;
|
||||
$params['url'] = $CFG->wwwroot;
|
||||
redirect(new moodle_url($huburl . '/local/hub/siteregistration.php', $params));
|
||||
}
|
||||
}
|
||||
|
||||
/////// OUTPUT SECTION /////////////
|
||||
|
||||
echo $OUTPUT->header();
|
||||
//Display update notification result
|
||||
if (!empty($registeredhub->confirmed)) {
|
||||
if (!empty($result)) {
|
||||
echo $OUTPUT->notification(get_string('siteregistrationupdated', 'hub'), 'notifysuccess');
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($error)) {
|
||||
echo $error;
|
||||
}
|
||||
|
||||
// Some Moodle.org registration explanation.
|
||||
if ($huburl == HUB_MOODLEORGHUBURL) {
|
||||
if (!empty($registeredhub->token)) {
|
||||
if ($registeredhub->timemodified == 0) {
|
||||
$registrationmessage = get_string('pleaserefreshregistrationunknown', 'admin');
|
||||
} else {
|
||||
$lastupdated = userdate($registeredhub->timemodified, get_string('strftimedate', 'langconfig'));
|
||||
$registrationmessage = get_string('pleaserefreshregistration', 'admin', $lastupdated);
|
||||
}
|
||||
} else {
|
||||
$registrationmessage = get_string('registrationwarning', 'admin');
|
||||
}
|
||||
echo $OUTPUT->notification($registrationmessage);
|
||||
|
||||
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
|
||||
$renderer = $PAGE->get_renderer('core', 'register');
|
||||
echo $renderer->moodleorg_registration_message();
|
||||
}
|
||||
|
||||
$siteregistrationform->display();
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This file is part of Moodle - http://moodle.org/ //
|
||||
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
|
||||
// //
|
||||
// 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/>. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Registration renderer.
|
||||
* @package moodle
|
||||
* @subpackage registration
|
||||
* @copyright 2010 Moodle Pty Ltd (http://moodle.com)
|
||||
* @author Jerome Mouneyrac
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_register_renderer extends plugin_renderer_base {
|
||||
|
||||
/**
|
||||
* Display message about the benefits of registering on Moodle.org
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function moodleorg_registration_message() {
|
||||
$moodleorgstatslink = html_writer::link('http://moodle.net/stats',
|
||||
get_string('statsmoodleorg', 'admin'),
|
||||
array('target' => '_blank'));
|
||||
|
||||
$moodleorgregmsg = get_string('registermoodleorg', 'admin');
|
||||
$items = array(get_string('registermoodleorgli1', 'admin'),
|
||||
get_string('registermoodleorgli2', 'admin', $moodleorgstatslink));
|
||||
$moodleorgregmsg .= html_writer::alist($items);
|
||||
return $moodleorgregmsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a box message confirming a site registration (add or update)
|
||||
* @param string $confirmationmessage
|
||||
* @return string
|
||||
*/
|
||||
public function registration_confirmation($confirmationmessage) {
|
||||
$linktositelist = html_writer::tag('a', get_string('sitelist', 'hub'),
|
||||
array('href' => new moodle_url('/local/hub/index.php')));
|
||||
$message = $confirmationmessage . html_writer::empty_tag('br') . $linktositelist;
|
||||
return $this->output->box($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the listing of registered on hub
|
||||
*/
|
||||
public function registeredonhublisting($hubs) {
|
||||
global $CFG;
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('hub', 'hub'), get_string('operation', 'hub'));
|
||||
$table->size = array('80%', '20%');
|
||||
|
||||
foreach ($hubs as $hub) {
|
||||
if ($hub->huburl == HUB_MOODLEORGHUBURL) {
|
||||
$hub->hubname = get_string('registeredmoodleorg', 'hub', $hub->hubname);
|
||||
}
|
||||
$hublink = html_writer::tag('a', $hub->hubname, array('href' => $hub->huburl));
|
||||
$hublinkcell = html_writer::tag('div', $hublink, array('class' => 'registeredhubrow'));
|
||||
|
||||
$unregisterhuburl = new moodle_url("/" . $CFG->admin . "/registration/index.php",
|
||||
array('sesskey' => sesskey(), 'huburl' => $hub->huburl,
|
||||
'unregistration' => 1));
|
||||
$unregisterbutton = new single_button($unregisterhuburl,
|
||||
get_string('unregister', 'hub'));
|
||||
$unregisterbutton->class = 'centeredbutton';
|
||||
$unregisterbuttonhtml = $this->output->render($unregisterbutton);
|
||||
|
||||
//add button cells
|
||||
$cells = array($hublinkcell, $unregisterbuttonhtml);
|
||||
$row = new html_table_row($cells);
|
||||
$table->data[] = $row;
|
||||
}
|
||||
|
||||
return html_writer::table($table);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
/*
|
||||
* @package moodle
|
||||
* @subpackage registration
|
||||
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
|
||||
@@ -33,40 +33,44 @@
|
||||
|
||||
require('../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
|
||||
|
||||
$url = optional_param('url', '', PARAM_URL);
|
||||
$hubname = optional_param('hubname', '', PARAM_TEXT);
|
||||
$token = optional_param('token', '', PARAM_TEXT);
|
||||
|
||||
admin_externalpage_setup('registrationmoodleorg');
|
||||
admin_externalpage_setup('registrationhubs');
|
||||
|
||||
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) {
|
||||
foreach ($plugins as $plugin => $callback) {
|
||||
$callback('renew');
|
||||
}
|
||||
//check that we are waiting a confirmation from this hub, and check that the token is correct
|
||||
$registrationmanager = new registration_manager();
|
||||
$registeredhub = $registrationmanager->get_unconfirmedhub($url);
|
||||
if (!empty($registeredhub) and $registeredhub->token == $token) {
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('renewregistration', 'hub'), 3, 'main');
|
||||
$hublink = html_writer::tag('a', $hubname, array('href' => $url));
|
||||
|
||||
$registrationmanager->delete_registeredhub($url);
|
||||
|
||||
//Mooch case, need to recreate the siteidentifier
|
||||
if ($url == HUB_MOODLEORGHUBURL) {
|
||||
$CFG->siteidentifier = null;
|
||||
get_site_identifier();
|
||||
}
|
||||
throw new moodle_exception('errorotherhubsnotsupported', 'hub');
|
||||
|
||||
$deletedregmsg = get_string('previousregistrationdeleted', 'hub', $hublink);
|
||||
|
||||
$button = new single_button(new moodle_url('/admin/registration/index.php'),
|
||||
get_string('restartregistration', 'hub'));
|
||||
$button->class = 'restartregbutton';
|
||||
|
||||
echo html_writer::tag('div', $deletedregmsg . $OUTPUT->render($button),
|
||||
array('class' => 'mdl-align'));
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
} else {
|
||||
throw new moodle_exception('wrongtoken', 'hub',
|
||||
$CFG->wwwroot . '/' . $CFG->admin . '/registration/index.php');
|
||||
}
|
||||
|
||||
// Check that we are waiting a confirmation from this hub, and check that the token is correct.
|
||||
\core\hub\registration::reset_site_identifier($token);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('renewregistration', 'hub'), 3, 'main');
|
||||
$hublink = html_writer::tag('a', 'Moodle.net', array('href' => HUB_MOODLEORGHUBURL));
|
||||
|
||||
$deletedregmsg = get_string('previousregistrationdeleted', 'hub', $hublink);
|
||||
|
||||
$button = new single_button(new moodle_url('/admin/registration/index.php'),
|
||||
get_string('restartregistration', 'hub'));
|
||||
$button->class = 'restartregbutton';
|
||||
|
||||
echo html_writer::tag('div', $deletedregmsg . $OUTPUT->render($button),
|
||||
array('class' => 'mdl-align'));
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
|
||||
|
||||
+6
-108
@@ -276,19 +276,12 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
* @param int|null $availableupdatesfetch timestamp of the most recent updates fetch or null (unknown)
|
||||
* @param string[] $cachewarnings An array containing warnings from the Cache API.
|
||||
* @param array $eventshandlers Events 1 API handlers.
|
||||
* @param bool $themedesignermode Warn about the theme designer mode.
|
||||
* @param bool $devlibdir Warn about development libs directory presence.
|
||||
* @param bool $mobileconfigured Whether the mobile web services have been enabled
|
||||
* @param bool $overridetossl Whether or not ssl is being forced.
|
||||
* @param bool $invalidforgottenpasswordurl Whether the forgotten password URL does not link to a valid URL.
|
||||
*
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
public function admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
|
||||
$cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch,
|
||||
$buggyiconvnomb, $registered, array $cachewarnings = array(), $eventshandlers = 0,
|
||||
$themedesignermode = false, $devlibdir = false, $mobileconfigured = false,
|
||||
$overridetossl = false, $invalidforgottenpasswordurl = false) {
|
||||
$buggyiconvnomb, $registered, array $cachewarnings = array(), $eventshandlers = 0, $themedesignermode = false) {
|
||||
global $CFG;
|
||||
$output = '';
|
||||
|
||||
@@ -297,19 +290,15 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$output .= $this->legacy_log_store_writing_error();
|
||||
$output .= empty($CFG->disableupdatenotifications) ? $this->available_updates($availableupdates, $availableupdatesfetch) : '';
|
||||
$output .= $this->insecure_dataroot_warning($insecuredataroot);
|
||||
$output .= $this->development_libs_directories_warning($devlibdir);
|
||||
$output .= $this->themedesignermode_warning($themedesignermode);
|
||||
$output .= $this->display_errors_warning($errorsdisplayed);
|
||||
$output .= $this->buggy_iconv_warning($buggyiconvnomb);
|
||||
$output .= $this->cron_overdue_warning($cronoverdue);
|
||||
$output .= $this->db_problems($dbproblems);
|
||||
$output .= $this->maintenance_mode_warning($maintenancemode);
|
||||
$output .= $this->overridetossl_warning($overridetossl);
|
||||
$output .= $this->cache_warnings($cachewarnings);
|
||||
$output .= $this->events_handlers($eventshandlers);
|
||||
$output .= $this->registration_warning($registered);
|
||||
$output .= $this->mobile_configuration_warning($mobileconfigured);
|
||||
$output .= $this->forgotten_password_url_warning($invalidforgottenpasswordurl);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//// IT IS ILLEGAL AND A VIOLATION OF THE GPL TO HIDE, REMOVE OR MODIFY THIS COPYRIGHT NOTICE ///
|
||||
@@ -531,24 +520,6 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a warning that a directory with development libs is present.
|
||||
*
|
||||
* @param bool $devlibdir True if the warning should be displayed.
|
||||
* @return string
|
||||
*/
|
||||
protected function development_libs_directories_warning($devlibdir) {
|
||||
|
||||
if ($devlibdir) {
|
||||
$moreinfo = new moodle_url('/report/security/index.php');
|
||||
$warning = get_string('devlibdirpresent', 'core_admin', ['moreinfourl' => $moreinfo->out()]);
|
||||
return $this->warning($warning, 'error');
|
||||
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an appropriate message if dataroot is insecure.
|
||||
* @param bool $errorsdisplayed
|
||||
@@ -673,20 +644,6 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
return $this->warning(get_string('sitemaintenancewarning2', 'admin', $url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a warning that ssl is forced because the site was on loginhttps.
|
||||
*
|
||||
* @param bool $overridetossl Whether or not ssl is being forced.
|
||||
* @return string
|
||||
*/
|
||||
protected function overridetossl_warning($overridetossl) {
|
||||
if (!$overridetossl) {
|
||||
return '';
|
||||
}
|
||||
$warning = get_string('overridetossl', 'core_admin');
|
||||
return $this->warning($warning, 'warning');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a warning about installing development code if necesary.
|
||||
* @param int $maturity
|
||||
@@ -825,67 +782,17 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
|
||||
if (!$registered) {
|
||||
|
||||
if (has_capability('moodle/site:config', context_system::instance())) {
|
||||
$registerbutton = $this->single_button(new moodle_url('/admin/registration/index.php'),
|
||||
$registerbutton = $this->single_button(new moodle_url('/admin/registration/register.php',
|
||||
array('huburl' => HUB_MOODLEORGHUBURL, 'hubname' => 'Moodle.org')),
|
||||
get_string('register', 'admin'));
|
||||
$str = 'registrationwarning';
|
||||
} else {
|
||||
$registerbutton = '';
|
||||
$str = 'registrationwarningcontactadmin';
|
||||
}
|
||||
|
||||
return $this->warning( get_string($str, 'admin')
|
||||
. ' ' . $this->help_icon('registration', 'admin') . $registerbutton ,
|
||||
'error alert alert-danger');
|
||||
return $this->warning( get_string('registrationwarning', 'admin')
|
||||
. ' ' . $this->help_icon('registration', 'admin') . $registerbutton );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an admin page warning if site is not registered with moodle.org
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function warn_if_not_registered() {
|
||||
return $this->registration_warning(\core\hub\registration::is_registered());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a warning about the Mobile Web Services being disabled.
|
||||
*
|
||||
* @param boolean $mobileconfigured true if mobile web services are enabled
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
protected function mobile_configuration_warning($mobileconfigured) {
|
||||
$output = '';
|
||||
if (!$mobileconfigured) {
|
||||
$settingslink = new moodle_url('/admin/settings.php', ['section' => 'mobilesettings']);
|
||||
$configurebutton = $this->single_button($settingslink, get_string('enablemobilewebservice', 'admin'));
|
||||
$output .= $this->warning(get_string('mobilenotconfiguredwarning', 'admin') . ' ' . $configurebutton);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a warning about the forgotten password URL not linking to a valid URL.
|
||||
*
|
||||
* @param boolean $invalidforgottenpasswordurl true if the forgotten password URL is not valid
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
protected function forgotten_password_url_warning($invalidforgottenpasswordurl) {
|
||||
$output = '';
|
||||
if ($invalidforgottenpasswordurl) {
|
||||
$settingslink = new moodle_url('/admin/settings.php', ['section' => 'manageauths']);
|
||||
$configurebutton = $this->single_button($settingslink, get_string('check', 'moodle'));
|
||||
$output .= $this->warning(get_string('invalidforgottenpasswordurl', 'admin') . ' ' . $configurebutton,
|
||||
'error alert alert-danger');
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to render the information about the available Moodle update
|
||||
*
|
||||
@@ -1990,7 +1897,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));
|
||||
}
|
||||
// Enclose report text in div so feedback text will be displayed underneath it.
|
||||
$report = html_writer::div($report);
|
||||
@@ -2084,13 +1991,4 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
return $this->warning(get_string('legacylogginginuse'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display message about the benefits of registering on Moodle.org
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function moodleorg_registration_message() {
|
||||
return format_text(get_string('registermoodlenet', 'admin'), FORMAT_HTML, ['noclean' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ if ($roleid) {
|
||||
$select = new single_select($PAGE->url, 'roleid', $nameswithcounts, $roleid, null);
|
||||
$select->label = get_string('assignanotherrole', 'core_role');
|
||||
echo $OUTPUT->render($select);
|
||||
echo '<p><a href="' . $url . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
|
||||
echo '<p><a href="' . $PAGE->url . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
|
||||
echo '</div>';
|
||||
|
||||
} else if (empty($assignableroles)) {
|
||||
|
||||
@@ -183,14 +183,9 @@ abstract class core_role_capability_table_with_risks extends core_role_capabilit
|
||||
public function get_risk_icon($type) {
|
||||
global $OUTPUT;
|
||||
|
||||
$alt = get_string("{$type}short", "admin");
|
||||
$title = get_string($type, "admin");
|
||||
|
||||
$text = $OUTPUT->pix_icon('i/' . str_replace('risk', 'risk_', $type), $alt, 'moodle', [
|
||||
'title' => $title,
|
||||
]);
|
||||
$text = $OUTPUT->pix_icon('i/' . str_replace('risk', 'risk_', $type), get_string($type . 'short', 'admin'));
|
||||
$action = new popup_action('click', $this->risksurl, 'docspopup');
|
||||
$riskicon = $OUTPUT->action_link($this->risksurl, $text, $action);
|
||||
$riskicon = $OUTPUT->action_link($this->risksurl, $text, $action, array('title'=>get_string($type, 'admin')));
|
||||
|
||||
return $riskicon;
|
||||
}
|
||||
|
||||
@@ -100,8 +100,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
$this->role->shortname = core_text::strtolower(clean_param($this->role->shortname, PARAM_ALPHANUMEXT));
|
||||
if (empty($this->role->shortname)) {
|
||||
$this->errors['shortname'] = get_string('errorbadroleshortname', 'core_role');
|
||||
} else if (core_text::strlen($this->role->shortname) > 100) { // Check if it exceeds the max of 100 characters.
|
||||
$this->errors['shortname'] = get_string('errorroleshortnametoolong', 'core_role');
|
||||
}
|
||||
}
|
||||
if ($DB->record_exists_select('role', 'shortname = ? and id <> ?', array($this->role->shortname, $this->roleid))) {
|
||||
@@ -478,7 +476,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
}
|
||||
|
||||
protected function get_shortname_field($id) {
|
||||
return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="100" value="' . s($this->role->shortname) . '"' .
|
||||
return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->shortname) . '"' .
|
||||
' class="form-control"/>';
|
||||
}
|
||||
|
||||
|
||||
@@ -1,459 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for core_role.
|
||||
*
|
||||
* @package core_role
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_role\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use \core_privacy\local\metadata\collection;
|
||||
use \core_privacy\local\request\contextlist;
|
||||
use \core_privacy\local\request\approved_contextlist;
|
||||
use \core_privacy\local\request\transform;
|
||||
use \core_privacy\local\request\writer;
|
||||
use \core_privacy\local\request\userlist;
|
||||
use \core_privacy\local\request\approved_userlist;
|
||||
|
||||
/**
|
||||
* Privacy provider for core_role.
|
||||
*
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements
|
||||
\core_privacy\local\metadata\provider,
|
||||
\core_privacy\local\request\subsystem\provider,
|
||||
\core_privacy\local\request\subsystem\plugin_provider,
|
||||
\core_privacy\local\request\user_preference_provider,
|
||||
\core_privacy\local\request\core_userlist_provider {
|
||||
|
||||
/**
|
||||
* Get information about the user data stored by this plugin.
|
||||
*
|
||||
* @param collection $collection An object for storing metadata.
|
||||
* @return collection The metadata.
|
||||
*/
|
||||
public static function get_metadata(collection $collection) : collection {
|
||||
$rolecapabilities = [
|
||||
'roleid' => 'privacy:metadata:role_capabilities:roleid',
|
||||
'capability' => 'privacy:metadata:role_capabilities:capability',
|
||||
'permission' => 'privacy:metadata:role_capabilities:permission',
|
||||
'timemodified' => 'privacy:metadata:role_capabilities:timemodified',
|
||||
'modifierid' => 'privacy:metadata:role_capabilities:modifierid'
|
||||
];
|
||||
$roleassignments = [
|
||||
'roleid' => 'privacy:metadata:role_assignments:roleid',
|
||||
'userid' => 'privacy:metadata:role_assignments:userid',
|
||||
'timemodified' => 'privacy:metadata:role_assignments:timemodified',
|
||||
'modifierid' => 'privacy:metadata:role_assignments:modifierid',
|
||||
'component' => 'privacy:metadata:role_assignments:component',
|
||||
'itemid' => 'privacy:metadata:role_assignments:itemid'
|
||||
];
|
||||
$collection->add_database_table('role_capabilities', $rolecapabilities,
|
||||
'privacy:metadata:role_capabilities:tableexplanation');
|
||||
$collection->add_database_table('role_assignments', $roleassignments,
|
||||
'privacy:metadata:role_assignments:tableexplanation');
|
||||
|
||||
$collection->add_user_preference('definerole_showadvanced',
|
||||
'privacy:metadata:preference:showadvanced');
|
||||
|
||||
return $collection;
|
||||
}
|
||||
/**
|
||||
* Export all user preferences for the plugin.
|
||||
*
|
||||
* @param int $userid The userid of the user whose data is to be exported.
|
||||
*/
|
||||
public static function export_user_preferences(int $userid) {
|
||||
$showadvanced = get_user_preferences('definerole_showadvanced', null, $userid);
|
||||
if ($showadvanced !== null) {
|
||||
writer::export_user_preference('core_role',
|
||||
'definerole_showadvanced',
|
||||
transform::yesno($showadvanced),
|
||||
get_string('privacy:metadata:preference:showadvanced', 'core_role')
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Return all contexts for this userid.
|
||||
*
|
||||
* @param int $userid The user ID.
|
||||
* @return contextlist The list of context IDs.
|
||||
*/
|
||||
public static function get_contexts_for_userid(int $userid) : contextlist {
|
||||
global $DB;
|
||||
|
||||
$contextlist = new contextlist();
|
||||
|
||||
// The role_capabilities table contains user data.
|
||||
$contexts = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_USER,
|
||||
CONTEXT_COURSECAT,
|
||||
CONTEXT_COURSE,
|
||||
CONTEXT_MODULE,
|
||||
CONTEXT_BLOCK
|
||||
];
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
|
||||
$sql = "SELECT ctx.id
|
||||
FROM {context} ctx
|
||||
JOIN {role_capabilities} rc
|
||||
ON rc.contextid = ctx.id
|
||||
AND ((ctx.contextlevel {$insql} AND rc.modifierid = :modifierid)
|
||||
OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))";
|
||||
$params = [
|
||||
'modifierid' => $userid,
|
||||
'contextlevel' => CONTEXT_USER,
|
||||
'userid' => $userid
|
||||
];
|
||||
$params += $inparams;
|
||||
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
// The role_assignments table contains user data.
|
||||
$contexts = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_USER,
|
||||
CONTEXT_COURSECAT,
|
||||
CONTEXT_COURSE,
|
||||
CONTEXT_MODULE,
|
||||
CONTEXT_BLOCK
|
||||
];
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
'modifierid' => $userid
|
||||
];
|
||||
$params += $inparams;
|
||||
$sql = "SELECT ctx.id
|
||||
FROM {role_assignments} ra
|
||||
JOIN {context} ctx
|
||||
ON ctx.id = ra.contextid
|
||||
AND ctx.contextlevel {$insql}
|
||||
WHERE (ra.userid = :userid
|
||||
OR ra.modifierid = :modifierid)
|
||||
AND ra.component != 'tool_cohortroles'";
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
return $contextlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of users within a specific context.
|
||||
*
|
||||
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
|
||||
*/
|
||||
public static function get_users_in_context(userlist $userlist) {
|
||||
|
||||
if (empty($userlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$context = $userlist->get_context();
|
||||
|
||||
// Include users who created or modified role capabilities.
|
||||
$sql = "SELECT modifierid as userid
|
||||
FROM {role_capabilities}
|
||||
WHERE contextid = :contextid";
|
||||
|
||||
$params = [
|
||||
'contextid' => $context->id
|
||||
];
|
||||
|
||||
$userlist->add_from_sql('userid', $sql, $params);
|
||||
|
||||
// Include users that have a role assigned to them.
|
||||
$sql = "SELECT userid
|
||||
FROM {role_assignments}
|
||||
WHERE contextid = :contextid";
|
||||
|
||||
$userlist->add_from_sql('userid', $sql, $params);
|
||||
|
||||
// Include users who created or modified the role assignment.
|
||||
// Differentiate and exclude special cases where tool_cohortroles adds records through the
|
||||
// "Assign user roles to cohort" feature into the role_assignments table.
|
||||
// These records should be separately processed in tool_cohortroles.
|
||||
$sql = "SELECT modifierid as userid
|
||||
FROM {role_assignments}
|
||||
WHERE contextid = :contextid
|
||||
AND component != 'tool_cohortroles'";
|
||||
|
||||
$userlist->add_from_sql('userid', $sql, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The list of approved contexts for a user.
|
||||
*/
|
||||
public static function export_user_data(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
if (empty($contextlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$rolesnames = self::get_roles_name();
|
||||
$userid = $contextlist->get_user()->id;
|
||||
$ctxfields = \context_helper::get_preload_record_columns_sql('ctx');
|
||||
list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
|
||||
|
||||
// Role Assignments export data.
|
||||
$contexts = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_USER,
|
||||
CONTEXT_COURSECAT,
|
||||
CONTEXT_COURSE,
|
||||
CONTEXT_MODULE,
|
||||
CONTEXT_BLOCK
|
||||
];
|
||||
list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
|
||||
$sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, $ctxfields
|
||||
FROM {role_assignments} ra
|
||||
JOIN {context} ctx
|
||||
ON ctx.id = ra.contextid
|
||||
AND ctx.contextlevel {$inctxsql}
|
||||
AND (ra.userid = :userid OR ra.modifierid = :modifierid)
|
||||
AND ra.component != 'tool_cohortroles'
|
||||
JOIN {role} r
|
||||
ON r.id = ra.roleid
|
||||
WHERE ctx.id {$insql}";
|
||||
$params = ['userid' => $userid, 'modifierid' => $userid];
|
||||
$params += $inparams;
|
||||
$params += $ctxparams;
|
||||
$assignments = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($assignments as $assignment) {
|
||||
\context_helper::preload_from_record($assignment);
|
||||
$alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
|
||||
'timemodified' => transform::datetime($assignment->timemodified),
|
||||
'userid' => transform::user($assignment->userid),
|
||||
'modifierid' => transform::user($assignment->modifierid)
|
||||
];
|
||||
}
|
||||
$assignments->close();
|
||||
if (!empty($alldata)) {
|
||||
array_walk($alldata, function($roledata, $contextid) {
|
||||
$context = \context::instance_by_id($contextid);
|
||||
array_walk($roledata, function($data, $rolename) use ($context) {
|
||||
writer::with_context($context)->export_data(
|
||||
[get_string('privacy:metadata:role_assignments', 'core_role'), $rolename],
|
||||
(object)$data);
|
||||
});
|
||||
});
|
||||
unset($alldata);
|
||||
}
|
||||
|
||||
// Role Capabilities export data.
|
||||
$strpermissions = self::get_permissions_name();
|
||||
$contexts = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_USER,
|
||||
CONTEXT_COURSECAT,
|
||||
CONTEXT_COURSE,
|
||||
CONTEXT_MODULE,
|
||||
CONTEXT_BLOCK
|
||||
];
|
||||
list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
|
||||
$sql = "SELECT rc.id, rc.contextid, rc.capability, rc.permission, rc.timemodified, rc.roleid, $ctxfields
|
||||
FROM {context} ctx
|
||||
JOIN {role_capabilities} rc
|
||||
ON rc.contextid = ctx.id
|
||||
AND ((ctx.contextlevel {$inctxsql} AND rc.modifierid = :modifierid)
|
||||
OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))
|
||||
WHERE ctx.id {$insql}";
|
||||
$params = [
|
||||
'modifierid' => $userid,
|
||||
'contextlevel' => CONTEXT_USER,
|
||||
'userid' => $userid
|
||||
];
|
||||
$params += $inparams;
|
||||
$params += $ctxparams;
|
||||
$capabilities = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($capabilities as $capability) {
|
||||
\context_helper::preload_from_record($capability);
|
||||
$alldata[$capability->contextid][$rolesnames[$capability->roleid]][] = (object)[
|
||||
'timemodified' => transform::datetime($capability->timemodified),
|
||||
'capability' => $capability->capability,
|
||||
'permission' => $strpermissions[$capability->permission]
|
||||
];
|
||||
}
|
||||
$capabilities->close();
|
||||
if (!empty($alldata)) {
|
||||
array_walk($alldata, function($capdata, $contextid) {
|
||||
$context = \context::instance_by_id($contextid);
|
||||
array_walk($capdata, function($data, $rolename) use ($context) {
|
||||
writer::with_context($context)->export_data(
|
||||
[get_string('privacy:metadata:role_capabilities', 'core_role'), $rolename],
|
||||
(object)$data);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Exports the data relating to tool_cohortroles component on role assignments by
|
||||
* Assign user roles to cohort feature.
|
||||
*
|
||||
* @param int $userid The user ID.
|
||||
*/
|
||||
public static function export_user_role_to_cohort(int $userid) {
|
||||
global $DB;
|
||||
|
||||
$rolesnames = self::get_roles_name();
|
||||
$sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, r.id as roleid
|
||||
FROM {role_assignments} ra
|
||||
JOIN {context} ctx
|
||||
ON ctx.id = ra.contextid
|
||||
AND ctx.contextlevel = :contextlevel
|
||||
AND ra.component = 'tool_cohortroles'
|
||||
JOIN {role} r
|
||||
ON r.id = ra.roleid
|
||||
WHERE ctx.instanceid = :instanceid
|
||||
OR ra.userid = :userid";
|
||||
$params = ['userid' => $userid, 'instanceid' => $userid, 'contextlevel' => CONTEXT_USER];
|
||||
$assignments = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($assignments as $assignment) {
|
||||
$alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
|
||||
'timemodified' => transform::datetime($assignment->timemodified),
|
||||
'userid' => transform::user($assignment->userid),
|
||||
'modifierid' => transform::user($assignment->modifierid)
|
||||
];
|
||||
}
|
||||
$assignments->close();
|
||||
if (!empty($alldata)) {
|
||||
array_walk($alldata, function($roledata, $contextid) {
|
||||
$context = \context::instance_by_id($contextid);
|
||||
array_walk($roledata, function($data, $rolename) use ($context) {
|
||||
writer::with_context($context)->export_related_data(
|
||||
[get_string('privacy:metadata:role_cohortroles', 'core_role'), $rolename], 'cohortroles',
|
||||
(object)$data);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Delete all user data for this context.
|
||||
*
|
||||
* @param \context $context The context to delete data for.
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||
global $DB;
|
||||
|
||||
// Don't remove data from role_capabilities.
|
||||
// Because this data affects the whole Moodle, there are override capabilities.
|
||||
// Don't belong to the modifier user.
|
||||
|
||||
// Remove data from role_assignments.
|
||||
$DB->delete_records('role_assignments', ['contextid' => $context->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete multiple users within a single context.
|
||||
*
|
||||
* @param approved_userlist $userlist The approved context and user information to delete information for.
|
||||
*/
|
||||
public static function delete_data_for_users(approved_userlist $userlist) {
|
||||
global $DB;
|
||||
|
||||
// Don't remove data from role_capabilities.
|
||||
// Because this data affects the whole Moodle, there are override capabilities.
|
||||
// Don't belong to the modifier user.
|
||||
$context = $userlist->get_context();
|
||||
$userids = $userlist->get_userids();
|
||||
|
||||
if (empty($userids)) {
|
||||
return;
|
||||
}
|
||||
list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
|
||||
$params = ['contextid' => $context->id] + $userparams;
|
||||
|
||||
// Remove data from role_assignments.
|
||||
$DB->delete_records_select('role_assignments',
|
||||
"contextid = :contextid AND userid {$usersql}", $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all user data for this user only.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The list of approved contexts for a user.
|
||||
*/
|
||||
public static function delete_data_for_user(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
// Don't remove data from role_capabilities.
|
||||
// Because this data affects the whole Moodle, there are override capabilities.
|
||||
// Don't belong to the modifier user.
|
||||
|
||||
// Remove data from role_assignments.
|
||||
if (empty($contextlist->count())) {
|
||||
return;
|
||||
}
|
||||
$userid = $contextlist->get_user()->id;
|
||||
$contextids = $contextlist->get_contextids();
|
||||
|
||||
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
|
||||
$params = ['userid' => $userid] + $contextparams;
|
||||
|
||||
// Only delete the roles assignments where the user is assigned in all contexts.
|
||||
$DB->delete_records_select('role_assignments',
|
||||
"userid = :userid AND contextid {$contextsql}", $params);
|
||||
}
|
||||
/**
|
||||
* Delete user entries in role_assignments related to the feature
|
||||
* Assign user roles to cohort feature.
|
||||
*
|
||||
* @param int $userid The user ID.
|
||||
*/
|
||||
public static function delete_user_role_to_cohort(int $userid) {
|
||||
global $DB;
|
||||
|
||||
// Delete entries where userid is a mentor by tool_cohortroles.
|
||||
$DB->delete_records('role_assignments', ['userid' => $userid, 'component' => 'tool_cohortroles']);
|
||||
}
|
||||
/**
|
||||
* Get all the localised roles name in a simple array.
|
||||
*
|
||||
* @return array Array of name of the roles by roleid.
|
||||
*/
|
||||
protected static function get_roles_name() {
|
||||
$roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
|
||||
$rolesnames = array();
|
||||
foreach ($roles as $role) {
|
||||
$rolesnames[$role->id] = $role->localname;
|
||||
}
|
||||
return $rolesnames;
|
||||
}
|
||||
/**
|
||||
* Get all the permissions name in a simple array.
|
||||
*
|
||||
* @return array Array of permissions name.
|
||||
*/
|
||||
protected static function get_permissions_name() {
|
||||
$strpermissions = array(
|
||||
CAP_INHERIT => get_string('inherit', 'role'),
|
||||
CAP_ALLOW => get_string('allow', 'role'),
|
||||
CAP_PREVENT => get_string('prevent', 'role'),
|
||||
CAP_PROHIBIT => get_string('prohibit', 'role')
|
||||
);
|
||||
return $strpermissions;
|
||||
}
|
||||
}
|
||||
@@ -1,747 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy test for core_role
|
||||
*
|
||||
* @package core_role
|
||||
* @category test
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use \core_role\privacy\provider;
|
||||
use \core_privacy\local\request\approved_contextlist;
|
||||
use \core_privacy\local\request\writer;
|
||||
use \core_privacy\tests\provider_testcase;
|
||||
use \core_privacy\local\request\transform;
|
||||
use \tool_cohortroles\api;
|
||||
use \core_privacy\local\request\approved_userlist;
|
||||
|
||||
/**
|
||||
* Privacy test for core_role
|
||||
*
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_role_privacy_testcase extends provider_testcase {
|
||||
/**
|
||||
* Test to check export_user_preferences.
|
||||
* returns user preferences data.
|
||||
*/
|
||||
public function test_export_user_preferences() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$showadvanced = 1;
|
||||
set_user_preference('definerole_showadvanced', $showadvanced);
|
||||
provider::export_user_preferences($user->id);
|
||||
$writer = writer::with_context(\context_system::instance());
|
||||
$prefs = $writer->get_user_preferences('core_role');
|
||||
$this->assertEquals(transform::yesno($showadvanced), transform::yesno($prefs->definerole_showadvanced->value));
|
||||
$this->assertEquals(get_string('privacy:metadata:preference:showadvanced', 'core_role'),
|
||||
$prefs->definerole_showadvanced->description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all contexts are returned if there is any user data for this user.
|
||||
*/
|
||||
public function test_get_contexts_for_userid() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->assertEmpty(provider::get_contexts_for_userid($user->id));
|
||||
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$usercontext2 = \context_user::instance($user2->id);
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$course2 = $this->getDataGenerator()->create_course();
|
||||
$coursecat = $this->getDataGenerator()->create_category();
|
||||
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
|
||||
$cmcontext = \context_module::instance($cm->cmid);
|
||||
$page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
|
||||
$cmcontext2 = \context_module::instance($page->cmid);
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$coursecontext2 = \context_course::instance($course2->id);
|
||||
$coursecatcontext = \context_coursecat::instance($coursecat->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$block = $this->getDataGenerator()->create_block('online_users');
|
||||
$blockcontext = \context_block::instance($block->id);
|
||||
|
||||
$student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
|
||||
$manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
|
||||
|
||||
// Role assignments, where the user is assigned.
|
||||
role_assign($student->id, $user->id, $cmcontext2->id);
|
||||
role_assign($student->id, $user->id, $coursecontext2->id);
|
||||
role_assign($student->id, $user->id, $blockcontext->id);
|
||||
role_assign($manager->id, $user->id, $usercontext2->id);
|
||||
// Role assignments, where the user makes assignments.
|
||||
$this->setUser($user);
|
||||
role_assign($student->id, $user2->id, $coursecontext->id);
|
||||
role_assign($manager->id, $user2->id, $coursecatcontext->id);
|
||||
role_assign($manager->id, $user2->id, $systemcontext->id);
|
||||
|
||||
// Role capabilities.
|
||||
$this->setUser($user);
|
||||
$result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $cmcontext->id);
|
||||
|
||||
$contextlist = provider::get_contexts_for_userid($user->id)->get_contextids();
|
||||
$this->assertCount(8, $contextlist);
|
||||
$this->assertTrue(in_array($cmcontext->id, $contextlist));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that user data is exported correctly.
|
||||
*/
|
||||
public function test_export_user_data() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$usercontext2 = \context_user::instance($user2->id);
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$course2 = $this->getDataGenerator()->create_course();
|
||||
$coursecat = $this->getDataGenerator()->create_category();
|
||||
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
|
||||
$cmcontext = \context_module::instance($cm->cmid);
|
||||
$page = $this->getDataGenerator()->create_module('page', array('course' => $course->id));
|
||||
$cmcontext2 = \context_module::instance($page->cmid);
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$coursecontext2 = \context_course::instance($course2->id);
|
||||
$coursecatcontext = \context_coursecat::instance($coursecat->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$block = $this->getDataGenerator()->create_block('online_users');
|
||||
$blockcontext = \context_block::instance($block->id);
|
||||
|
||||
$student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
|
||||
$manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
|
||||
$rolesnames = self::get_roles_name();
|
||||
|
||||
$subcontextstudent = [
|
||||
get_string('privacy:metadata:role_assignments', 'core_role'),
|
||||
$rolesnames[$student->id]
|
||||
];
|
||||
$subcontextmanager = [
|
||||
get_string('privacy:metadata:role_assignments', 'core_role'),
|
||||
$rolesnames[$manager->id]
|
||||
];
|
||||
$subcontextrc = [
|
||||
get_string('privacy:metadata:role_capabilities', 'core_role'),
|
||||
$rolesnames[$student->id]
|
||||
];
|
||||
|
||||
// Test over role assignments.
|
||||
// Where the user is assigned.
|
||||
role_assign($student->id, $user->id, $cmcontext2->id);
|
||||
role_assign($student->id, $user->id, $coursecontext2->id);
|
||||
role_assign($student->id, $user->id, $blockcontext->id);
|
||||
role_assign($manager->id, $user->id, $usercontext2->id);
|
||||
// Where the user makes assignments.
|
||||
$this->setUser($user);
|
||||
role_assign($manager->id, $user2->id, $coursecatcontext->id);
|
||||
role_assign($manager->id, $user2->id, $systemcontext->id);
|
||||
|
||||
// Test overridable roles in module, course, category, user, system and block.
|
||||
assign_capability('moodle/backup:backupactivity', CAP_ALLOW, $student->id, $cmcontext->id, true);
|
||||
assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $coursecontext->id, true);
|
||||
assign_capability('moodle/category:manage', CAP_ALLOW, $student->id, $coursecatcontext->id, true);
|
||||
assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $systemcontext->id, true);
|
||||
assign_capability('moodle/block:edit', CAP_ALLOW, $student->id, $blockcontext->id, true);
|
||||
assign_capability('moodle/competency:evidencedelete', CAP_ALLOW, $student->id, $usercontext2->id, true);
|
||||
|
||||
// Retrieve the user's context ids.
|
||||
$contextlist = provider::get_contexts_for_userid($user->id);
|
||||
$approvedcontextlist = new approved_contextlist($user, 'core_role', $contextlist->get_contextids());
|
||||
|
||||
$strpermissions = array(
|
||||
CAP_INHERIT => get_string('inherit', 'role'),
|
||||
CAP_ALLOW => get_string('allow', 'role'),
|
||||
CAP_PREVENT => get_string('prevent', 'role'),
|
||||
CAP_PROHIBIT => get_string('prohibit', 'role')
|
||||
);
|
||||
// Retrieve role capabilities and role assignments.
|
||||
provider::export_user_data($approvedcontextlist);
|
||||
foreach ($contextlist as $context) {
|
||||
$writer = writer::with_context($context);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
if ($context->contextlevel == CONTEXT_MODULE) {
|
||||
if ($data = $writer->get_data($subcontextstudent)) {
|
||||
$this->assertEquals($user->id, reset($data)->userid);
|
||||
}
|
||||
if ($data = $writer->get_data($subcontextrc)) {
|
||||
$this->assertEquals('moodle/backup:backupactivity', reset($data)->capability);
|
||||
$this->assertEquals($strpermissions[CAP_ALLOW], reset($data)->permission);
|
||||
}
|
||||
}
|
||||
if ($context->contextlevel == CONTEXT_COURSE) {
|
||||
if ($data = $writer->get_data($subcontextstudent)) {
|
||||
$this->assertEquals($user->id, reset($data)->userid);
|
||||
}
|
||||
if ($data = $writer->get_data($subcontextrc)) {
|
||||
$this->assertEquals('moodle/backup:backupcourse', reset($data)->capability);
|
||||
}
|
||||
}
|
||||
if ($context->contextlevel == CONTEXT_COURSECAT) {
|
||||
if ($data = $writer->get_data($subcontextmanager)) {
|
||||
$this->assertEquals($user->id, reset($data)->modifierid);
|
||||
}
|
||||
if ($data = $writer->get_data($subcontextrc)) {
|
||||
$this->assertEquals('moodle/category:manage', reset($data)->capability);
|
||||
}
|
||||
}
|
||||
if ($context->contextlevel == CONTEXT_SYSTEM) {
|
||||
if ($data = $writer->get_data($subcontextmanager)) {
|
||||
$this->assertEquals($user->id, reset($data)->modifierid);
|
||||
}
|
||||
if ($data = $writer->get_data($subcontextrc)) {
|
||||
$this->assertEquals('moodle/backup:backupcourse', reset($data)->capability);
|
||||
}
|
||||
}
|
||||
if ($context->contextlevel == CONTEXT_BLOCK) {
|
||||
if ($data = $writer->get_data($subcontextstudent)) {
|
||||
$this->assertEquals($user->id, reset($data)->userid);
|
||||
}
|
||||
if ($data = $writer->get_data($subcontextrc)) {
|
||||
$this->assertEquals('moodle/block:edit', reset($data)->capability);
|
||||
}
|
||||
}
|
||||
if ($context->contextlevel == CONTEXT_USER) {
|
||||
if ($data = $writer->get_data($subcontextmanager)) {
|
||||
$this->assertEquals($user->id, reset($data)->userid);
|
||||
}
|
||||
if ($data = $writer->get_data($subcontextrc)) {
|
||||
$this->assertEquals('moodle/competency:evidencedelete', reset($data)->capability);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::delete_data_for_all_users_in_context().
|
||||
*/
|
||||
public function test_delete_data_for_all_users_in_context() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$usercontext2 = \context_user::instance($user2->id);
|
||||
$user3 = $this->getDataGenerator()->create_user();
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$coursecat = $this->getDataGenerator()->create_category();
|
||||
$coursecatcontext = \context_coursecat::instance($coursecat->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
|
||||
$cmcontext = \context_module::instance($cm->cmid);
|
||||
$student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
|
||||
$manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
|
||||
$block = $this->getDataGenerator()->create_block('online_users');
|
||||
$blockcontext = \context_block::instance($block->id);
|
||||
|
||||
// Role assignments CONTEXT_COURSE.
|
||||
role_assign($student->id, $user->id, $coursecontext->id);
|
||||
role_assign($student->id, $user2->id, $coursecontext->id);
|
||||
role_assign($student->id, $user3->id, $coursecontext->id);
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $coursecontext->id]);
|
||||
$this->assertEquals(3, $count);
|
||||
// Role assignments CONTEXT_COURSECAT.
|
||||
role_assign($student->id, $user2->id, $coursecatcontext->id);
|
||||
role_assign($student->id, $user3->id, $coursecatcontext->id);
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
|
||||
$this->assertEquals(2, $count);
|
||||
// Role assignments CONTEXT_SYSTEM.
|
||||
role_assign($student->id, $user->id, $systemcontext->id);
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
|
||||
$this->assertEquals(1, $count);
|
||||
// Role assignments CONTEXT_MODULE.
|
||||
role_assign($student->id, $user->id, $cmcontext->id);
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
|
||||
$this->assertEquals(1, $count);
|
||||
// Role assigments CONTEXT_BLOCK.
|
||||
role_assign($student->id, $user->id, $blockcontext->id);
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $blockcontext->id]);
|
||||
$this->assertEquals(1, $count);
|
||||
// Role assigments CONTEXT_USER.
|
||||
role_assign($manager->id, $user->id, $usercontext2->id);
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $usercontext2->id]);
|
||||
$this->assertEquals(1, $count);
|
||||
|
||||
// Delete data based on CONTEXT_COURSE context.
|
||||
provider::delete_data_for_all_users_in_context($coursecontext);
|
||||
// After deletion, the role_assignments entries for this context should have been deleted.
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $coursecontext->id]);
|
||||
$this->assertEquals(0, $count);
|
||||
// Check it is not removing data on other contexts.
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
|
||||
$this->assertEquals(2, $count);
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
|
||||
$this->assertEquals(1, $count);
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
|
||||
$this->assertEquals(1, $count);
|
||||
// Delete data based on CONTEXT_COURSECAT context.
|
||||
provider::delete_data_for_all_users_in_context($coursecatcontext);
|
||||
// After deletion, the role_assignments entries for this context should have been deleted.
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $coursecatcontext->id]);
|
||||
$this->assertEquals(0, $count);
|
||||
// Delete data based on CONTEXT_SYSTEM context.
|
||||
provider::delete_data_for_all_users_in_context($systemcontext);
|
||||
// After deletion, the role_assignments entries for this context should have been deleted.
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $systemcontext->id]);
|
||||
$this->assertEquals(0, $count);
|
||||
// Delete data based on CONTEXT_MODULE context.
|
||||
provider::delete_data_for_all_users_in_context($cmcontext);
|
||||
// After deletion, the role_assignments entries for this context should have been deleted.
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $cmcontext->id]);
|
||||
$this->assertEquals(0, $count);
|
||||
// Delete data based on CONTEXT_BLOCK context.
|
||||
provider::delete_data_for_all_users_in_context($usercontext2);
|
||||
// After deletion, the role_assignments entries for this context should have been deleted.
|
||||
$count = $DB->count_records('role_assignments', ['contextid' => $usercontext2->id]);
|
||||
$this->assertEquals(0, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::delete_data_for_user().
|
||||
*/
|
||||
public function test_delete_data_for_user() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$usercontext2 = \context_user::instance($user2->id);
|
||||
$user3 = $this->getDataGenerator()->create_user();
|
||||
$usercontext3 = \context_user::instance($user3->id);
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$course2 = $this->getDataGenerator()->create_course();
|
||||
$course3 = $this->getDataGenerator()->create_course();
|
||||
$coursecontext = \context_course::instance($course->id);
|
||||
$coursecontext2 = \context_course::instance($course2->id);
|
||||
$coursecontext3 = \context_course::instance($course3->id);
|
||||
$coursecat = $this->getDataGenerator()->create_category();
|
||||
$coursecatcontext = \context_coursecat::instance($coursecat->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course->id]);
|
||||
$cmcontext = \context_module::instance($cm->cmid);
|
||||
$student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
|
||||
$manager = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
|
||||
$block = $this->getDataGenerator()->create_block('online_users');
|
||||
$blockcontext = \context_block::instance($block->id);
|
||||
|
||||
// Role assignments, Where the user is assigned.
|
||||
role_assign($student->id, $user->id, $coursecontext->id);
|
||||
role_assign($student->id, $user->id, $coursecontext2->id);
|
||||
role_assign($student->id, $user->id, $coursecatcontext->id);
|
||||
role_assign($student->id, $user->id, $cmcontext->id);
|
||||
role_assign($student->id, $user->id, $systemcontext->id);
|
||||
role_assign($student->id, $user->id, $blockcontext->id);
|
||||
role_assign($manager->id, $user->id, $usercontext2->id);
|
||||
role_assign($manager->id, $user->id, $usercontext3->id);
|
||||
$count = $DB->count_records('role_assignments', ['userid' => $user->id]);
|
||||
$this->assertEquals(8, $count);
|
||||
// Role assignments, where the user makes assignments.
|
||||
$this->setUser($user);
|
||||
role_assign($student->id, $user2->id, $coursecontext3->id);
|
||||
role_assign($student->id, $user3->id, $coursecontext3->id);
|
||||
$count = $DB->count_records('role_assignments', ['modifierid' => $user->id]);
|
||||
$this->assertEquals(2, $count);
|
||||
|
||||
$contextlist = provider::get_contexts_for_userid($user->id);
|
||||
$approvedcontextlist = new approved_contextlist($user, 'core_role', $contextlist->get_contextids());
|
||||
provider::delete_data_for_user($approvedcontextlist);
|
||||
// After deletion, the role_assignments assigned to the user should have been deleted.
|
||||
$count = $DB->count_records('role_assignments', ['userid' => $user->id]);
|
||||
$this->assertEquals(0, $count);
|
||||
// After deletion, the role_assignments assigned by the user should not have been deleted.
|
||||
$count = $DB->count_records('role_assignments', ['modifierid' => $user->id]);
|
||||
$this->assertEquals(2, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export for a user with a key against a script where no instance is specified.
|
||||
*/
|
||||
public function test_export_user_role_to_cohort() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
// Assign user roles to cohort.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$contextuser = \context_user::instance($user->id);
|
||||
$teacher = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
|
||||
$cohort = $this->getDataGenerator()->create_cohort();
|
||||
$userassignover = $this->getDataGenerator()->create_user();
|
||||
$contextuserassignover = \context_user::instance($userassignover->id);
|
||||
cohort_add_member($cohort->id, $userassignover->id);
|
||||
$this->setAdminUser();
|
||||
$params = (object) array(
|
||||
'userid' => $user->id,
|
||||
'roleid' => $teacher->id,
|
||||
'cohortid' => $cohort->id
|
||||
);
|
||||
api::create_cohort_role_assignment($params);
|
||||
api::sync_all_cohort_roles();
|
||||
$rolesnames = self::get_roles_name();
|
||||
$subcontextteacher = [
|
||||
get_string('privacy:metadata:role_cohortroles', 'core_role'),
|
||||
$rolesnames[$teacher->id]
|
||||
];
|
||||
// Test User is assigned role teacher to cohort.
|
||||
provider::export_user_role_to_cohort($user->id);
|
||||
$writer = writer::with_context($contextuserassignover);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
$exported = $writer->get_related_data($subcontextteacher, 'cohortroles');
|
||||
$this->assertEquals($user->id, reset($exported)->userid);
|
||||
|
||||
// Test User is member of a cohort which User2 is assigned to role to this cohort.
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$cohort2 = $this->getDataGenerator()->create_cohort();
|
||||
cohort_add_member($cohort2->id, $user->id);
|
||||
$params = (object) array(
|
||||
'userid' => $user2->id,
|
||||
'roleid' => $teacher->id,
|
||||
'cohortid' => $cohort2->id
|
||||
);
|
||||
api::create_cohort_role_assignment($params);
|
||||
api::sync_all_cohort_roles();
|
||||
provider::export_user_role_to_cohort($user->id);
|
||||
$writer = writer::with_context($contextuser);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
$exported = $writer->get_related_data($subcontextteacher, 'cohortroles');
|
||||
$this->assertEquals($user2->id, reset($exported)->userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::delete_user_role_to_cohort().
|
||||
*/
|
||||
public function test_delete_user_role_to_cohort() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
// Assign user roles to cohort.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$user3 = $this->getDataGenerator()->create_user();
|
||||
$user4 = $this->getDataGenerator()->create_user();
|
||||
$teacher = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
|
||||
$cohort = $this->getDataGenerator()->create_cohort();
|
||||
cohort_add_member($cohort->id, $user2->id);
|
||||
cohort_add_member($cohort->id, $user3->id);
|
||||
cohort_add_member($cohort->id, $user4->id);
|
||||
$this->setAdminUser();
|
||||
$params = (object) array(
|
||||
'userid' => $user->id,
|
||||
'roleid' => $teacher->id,
|
||||
'cohortid' => $cohort->id
|
||||
);
|
||||
api::create_cohort_role_assignment($params);
|
||||
api::sync_all_cohort_roles();
|
||||
|
||||
$count = $DB->count_records('role_assignments', ['userid' => $user->id, 'component' => 'tool_cohortroles']);
|
||||
$this->assertEquals(3, $count);
|
||||
|
||||
provider::delete_user_role_to_cohort($user->id);
|
||||
$count = $DB->count_records('role_assignments', ['userid' => $user->id, 'component' => 'tool_cohortroles']);
|
||||
$this->assertEquals(0, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that only users within a course context are fetched.
|
||||
*/
|
||||
public function test_get_users_in_context() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$component = 'core_role';
|
||||
|
||||
$this->setAdminUser();
|
||||
$admin = \core_user::get_user_by_username('admin');
|
||||
// Create user1.
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$usercontext1 = \context_user::instance($user1->id);
|
||||
// Create user2.
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$usercontext2 = \context_user::instance($user2->id);
|
||||
// Create course1.
|
||||
$course1 = $this->getDataGenerator()->create_course();
|
||||
$coursecontext1 = \context_course::instance($course1->id);
|
||||
// Create course category.
|
||||
$coursecat = $this->getDataGenerator()->create_category();
|
||||
$coursecatcontext = \context_coursecat::instance($coursecat->id);
|
||||
// Create chat module.
|
||||
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course1->id]);
|
||||
$cmcontext = \context_module::instance($cm->cmid);
|
||||
|
||||
$systemcontext = \context_system::instance();
|
||||
// Create a block.
|
||||
$block = $this->getDataGenerator()->create_block('online_users');
|
||||
$blockcontext = \context_block::instance($block->id);
|
||||
|
||||
$studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
|
||||
$managerrole = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
|
||||
|
||||
// Role assignments CONTEXT_COURSE.
|
||||
role_assign($studentrole->id, $user1->id, $coursecontext1->id);
|
||||
role_assign($studentrole->id, $user2->id, $coursecontext1->id);
|
||||
// Role assignments CONTEXT_COURSECAT.
|
||||
role_assign($studentrole->id, $user2->id, $coursecatcontext->id);
|
||||
// Role assignments CONTEXT_SYSTEM.
|
||||
role_assign($studentrole->id, $user1->id, $systemcontext->id);
|
||||
// Role assignments CONTEXT_MODULE.
|
||||
role_assign($studentrole->id, $user2->id, $cmcontext->id);
|
||||
// Role assigments CONTEXT_BLOCK.
|
||||
role_assign($studentrole->id, $user1->id, $blockcontext->id);
|
||||
// Role assigments CONTEXT_USER.
|
||||
role_assign($managerrole->id, $user1->id, $usercontext2->id);
|
||||
|
||||
// Role capabilities.
|
||||
$this->setUser($user1);
|
||||
assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $studentrole->id, $cmcontext->id);
|
||||
|
||||
// The user list for usercontext1 should not return any users.
|
||||
$userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component);
|
||||
provider::get_users_in_context($userlist1);
|
||||
$this->assertCount(0, $userlist1);
|
||||
// The user list for usercontext2 should user1 and admin (role creator).
|
||||
$userlist2 = new \core_privacy\local\request\userlist($usercontext2, $component);
|
||||
provider::get_users_in_context($userlist2);
|
||||
$this->assertCount(2, $userlist2);
|
||||
$expected = [
|
||||
$user1->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEquals($expected, $userlist2->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for coursecontext1 should user1, user2 and admin (role creator).
|
||||
$userlist3 = new \core_privacy\local\request\userlist($coursecontext1, $component);
|
||||
provider::get_users_in_context($userlist3);
|
||||
$this->assertCount(3, $userlist3);
|
||||
$expected = [
|
||||
$user1->id,
|
||||
$user2->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEquals($expected, $userlist3->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for coursecatcontext should user2 and admin (role creator).
|
||||
$userlist4 = new \core_privacy\local\request\userlist($coursecatcontext, $component);
|
||||
provider::get_users_in_context($userlist4);
|
||||
$this->assertCount(2, $userlist4);
|
||||
$expected = [
|
||||
$user2->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEquals($expected, $userlist4->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for systemcontext should user1 and admin (role creator).
|
||||
$userlist6 = new \core_privacy\local\request\userlist($systemcontext, $component);
|
||||
provider::get_users_in_context($userlist6);
|
||||
$this->assertCount(2, $userlist6);
|
||||
$expected = [
|
||||
$user1->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEquals($expected, $userlist6->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for cmcontext should user1, user2 and admin (role creator).
|
||||
$userlist7 = new \core_privacy\local\request\userlist($cmcontext, $component);
|
||||
provider::get_users_in_context($userlist7);
|
||||
$this->assertCount(3, $userlist7);
|
||||
$expected = [
|
||||
$user1->id,
|
||||
$user2->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEquals($expected, $userlist7->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for blockcontext should user1 and admin (role creator).
|
||||
$userlist8 = new \core_privacy\local\request\userlist($blockcontext, $component);
|
||||
provider::get_users_in_context($userlist8);
|
||||
$this->assertCount(2, $userlist8);
|
||||
$expected = [
|
||||
$user1->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEquals($expected, $userlist8->get_userids(), '', 0.0, 10, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that data for users in approved userlist is deleted.
|
||||
*/
|
||||
public function test_delete_data_for_users() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
$component = 'core_role';
|
||||
|
||||
$this->setAdminUser();
|
||||
$admin = \core_user::get_user_by_username('admin');
|
||||
// Create user1.
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
// Create user2.
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$usercontext2 = \context_user::instance($user2->id);
|
||||
// Create course1.
|
||||
$course1 = $this->getDataGenerator()->create_course();
|
||||
$coursecontext1 = \context_course::instance($course1->id);
|
||||
// Create course category.
|
||||
$coursecat = $this->getDataGenerator()->create_category();
|
||||
$coursecatcontext = \context_coursecat::instance($coursecat->id);
|
||||
// Create chat module.
|
||||
$cm = $this->getDataGenerator()->create_module('chat', ['course' => $course1->id]);
|
||||
$cmcontext = \context_module::instance($cm->cmid);
|
||||
|
||||
$systemcontext = \context_system::instance();
|
||||
// Create a block.
|
||||
$block = $this->getDataGenerator()->create_block('online_users');
|
||||
$blockcontext = \context_block::instance($block->id);
|
||||
|
||||
$studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
|
||||
$managerrole = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
|
||||
|
||||
// Role assignments CONTEXT_COURSE.
|
||||
role_assign($studentrole->id, $user1->id, $coursecontext1->id);
|
||||
role_assign($studentrole->id, $user2->id, $coursecontext1->id);
|
||||
// Role assignments CONTEXT_COURSECAT.
|
||||
role_assign($studentrole->id, $user2->id, $coursecatcontext->id);
|
||||
// Role assignments CONTEXT_SYSTEM.
|
||||
role_assign($studentrole->id, $user1->id, $systemcontext->id);
|
||||
// Role assignments CONTEXT_MODULE.
|
||||
role_assign($studentrole->id, $user2->id, $cmcontext->id);
|
||||
// Role assigments CONTEXT_BLOCK.
|
||||
role_assign($studentrole->id, $user1->id, $blockcontext->id);
|
||||
// Role assigments CONTEXT_USER.
|
||||
role_assign($managerrole->id, $user1->id, $usercontext2->id);
|
||||
|
||||
// Role capabilities.
|
||||
$this->setUser($user1);
|
||||
assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $studentrole->id, $cmcontext->id);
|
||||
|
||||
// The user list for usercontext2 should user1 and admin (role creator).
|
||||
$userlist1 = new \core_privacy\local\request\userlist($usercontext2, $component);
|
||||
provider::get_users_in_context($userlist1);
|
||||
$this->assertCount(2, $userlist1);
|
||||
// The user list for coursecontext1 should user1, user2 and admin (role creator).
|
||||
$userlist2 = new \core_privacy\local\request\userlist($coursecontext1, $component);
|
||||
provider::get_users_in_context($userlist2);
|
||||
$this->assertCount(3, $userlist2);
|
||||
// The user list for coursecatcontext should user2 and admin (role creator).
|
||||
$userlist3 = new \core_privacy\local\request\userlist($coursecatcontext, $component);
|
||||
provider::get_users_in_context($userlist3);
|
||||
$this->assertCount(2, $userlist3);
|
||||
// The user list for systemcontext should user1 and admin (role creator).
|
||||
$userlist4 = new \core_privacy\local\request\userlist($systemcontext, $component);
|
||||
provider::get_users_in_context($userlist4);
|
||||
$this->assertCount(2, $userlist4);
|
||||
// The user list for cmcontext should user1, user2 and admin (role creator).
|
||||
$userlist5 = new \core_privacy\local\request\userlist($cmcontext, $component);
|
||||
provider::get_users_in_context($userlist5);
|
||||
$this->assertCount(3, $userlist5);
|
||||
// The user list for blockcontext should user1 and admin (role creator).
|
||||
$userlist6 = new \core_privacy\local\request\userlist($blockcontext, $component);
|
||||
provider::get_users_in_context($userlist6);
|
||||
$this->assertCount(2, $userlist6);
|
||||
|
||||
// Convert $userlist1 into an approved_contextlist.
|
||||
$approvedlist1 = new approved_userlist($usercontext2, $component, $userlist1->get_userids());
|
||||
// Delete using delete_data_for_user.
|
||||
provider::delete_data_for_users($approvedlist1);
|
||||
// Re-fetch users in usercontext2.
|
||||
$userlist1 = new \core_privacy\local\request\userlist($usercontext2, $component);
|
||||
provider::get_users_in_context($userlist1);
|
||||
$this->assertCount(0, $userlist1);
|
||||
|
||||
// Convert $userlist2 into an approved_contextlist.
|
||||
$approvedlist2 = new approved_userlist($coursecontext1, $component, $userlist2->get_userids());
|
||||
// Delete using delete_data_for_user.
|
||||
provider::delete_data_for_users($approvedlist2);
|
||||
// Re-fetch users in coursecontext1.
|
||||
$userlist2 = new \core_privacy\local\request\userlist($coursecontext1, $component);
|
||||
provider::get_users_in_context($userlist2);
|
||||
$this->assertCount(0, $userlist2);
|
||||
|
||||
// Convert $userlist3 into an approved_contextlist.
|
||||
$approvedlist3 = new approved_userlist($coursecatcontext, $component, $userlist3->get_userids());
|
||||
// Delete using delete_data_for_user.
|
||||
provider::delete_data_for_users($approvedlist3);
|
||||
// Re-fetch users in coursecatcontext.
|
||||
$userlist3 = new \core_privacy\local\request\userlist($coursecatcontext, $component);
|
||||
provider::get_users_in_context($userlist3);
|
||||
$this->assertCount(0, $userlist3);
|
||||
|
||||
// Convert $userlist4 into an approved_contextlist.
|
||||
$approvedlist4 = new approved_userlist($systemcontext, $component, $userlist4->get_userids());
|
||||
// Delete using delete_data_for_user.
|
||||
provider::delete_data_for_users($approvedlist4);
|
||||
// Re-fetch users in systemcontext.
|
||||
$userlist4 = new \core_privacy\local\request\userlist($systemcontext, $component);
|
||||
provider::get_users_in_context($userlist4);
|
||||
// The data from role_capabilities should still be present. The user list should return the admin user.
|
||||
$this->assertCount(1, $userlist4);
|
||||
$expected = [$admin->id];
|
||||
$this->assertEquals($expected, $userlist4->get_userids());
|
||||
|
||||
// Convert $userlist5 into an approved_contextlist.
|
||||
$approvedlist5 = new approved_userlist($cmcontext, $component, $userlist5->get_userids());
|
||||
// Delete using delete_data_for_user.
|
||||
provider::delete_data_for_users($approvedlist5);
|
||||
// Re-fetch users in cmcontext.
|
||||
$userlist5 = new \core_privacy\local\request\userlist($cmcontext, $component);
|
||||
provider::get_users_in_context($userlist5);
|
||||
// The data from role_capabilities should still be present. The user list should return user1.
|
||||
$this->assertCount(1, $userlist5);
|
||||
$expected = [$user1->id];
|
||||
$this->assertEquals($expected, $userlist5->get_userids());
|
||||
|
||||
// Convert $userlist6 into an approved_contextlist.
|
||||
$approvedlist6 = new approved_userlist($blockcontext, $component, $userlist6->get_userids());
|
||||
// Delete using delete_data_for_user.
|
||||
provider::delete_data_for_users($approvedlist6);
|
||||
// Re-fetch users in blockcontext.
|
||||
$userlist6 = new \core_privacy\local\request\userlist($blockcontext, $component);
|
||||
provider::get_users_in_context($userlist6);
|
||||
$this->assertCount(0, $userlist6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supoort function to get all the localised roles name
|
||||
* in a simple array for testing.
|
||||
*
|
||||
* @return array Array of name of the roles by roleid.
|
||||
*/
|
||||
protected static function get_roles_name() {
|
||||
$roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
|
||||
$rolesnames = array();
|
||||
foreach ($roles as $role) {
|
||||
$rolesnames[$role->id] = $role->localname;
|
||||
}
|
||||
return $rolesnames;
|
||||
}
|
||||
}
|
||||
+5
-23
@@ -5,22 +5,11 @@
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
redirect_if_major_upgrade_required();
|
||||
|
||||
$query = trim(optional_param('query', '', PARAM_NOTAGS)); // Search string
|
||||
|
||||
$context = context_system::instance();
|
||||
$PAGE->set_context($context);
|
||||
|
||||
$hassiteconfig = has_capability('moodle/site:config', $context);
|
||||
|
||||
if ($hassiteconfig && moodle_needs_upgrading()) {
|
||||
redirect(new moodle_url('/admin/index.php'));
|
||||
}
|
||||
|
||||
// If site registration needs updating, redirect.
|
||||
\core\hub\registration::registration_reminder('/admin/search.php');
|
||||
|
||||
admin_externalpage_setup('search', '', array('query' => $query)); // now hidden page
|
||||
|
||||
$adminroot = admin_get_root(); // need all settings here
|
||||
@@ -32,16 +21,15 @@ $focus = '';
|
||||
// now we'll deal with the case that the admin has submitted the form with changed settings
|
||||
if ($data = data_submitted() and confirm_sesskey() and isset($data->action) and $data->action == 'save-settings') {
|
||||
require_capability('moodle/site:config', $context);
|
||||
$count = admin_write_settings($data);
|
||||
if (admin_write_settings($data)) {
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
if (!empty($adminroot->errors)) {
|
||||
$errormsg = get_string('errorwithsettings', 'admin');
|
||||
$firsterror = reset($adminroot->errors);
|
||||
$focus = $firsterror->id;
|
||||
} else {
|
||||
// No errors. Did we change any setting? If so, then redirect with success.
|
||||
if ($count) {
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
}
|
||||
@@ -50,12 +38,6 @@ if ($data = data_submitted() and confirm_sesskey() and isset($data->action) and
|
||||
// to modify them
|
||||
echo $OUTPUT->header($focus);
|
||||
|
||||
// Display a warning if site is not registered.
|
||||
if (empty($query)) {
|
||||
$adminrenderer = $PAGE->get_renderer('core', 'admin');
|
||||
echo $adminrenderer->warn_if_not_registered();
|
||||
}
|
||||
|
||||
echo $OUTPUT->heading(get_string('administrationsite'));
|
||||
|
||||
if ($errormsg !== '') {
|
||||
@@ -67,7 +49,7 @@ if ($errormsg !== '') {
|
||||
|
||||
$showsettingslinks = true;
|
||||
|
||||
if ($hassiteconfig) {
|
||||
if (has_capability('moodle/site:config', $context)) {
|
||||
require_once("admin_settings_search_form.php");
|
||||
$form = new admin_settings_search_form();
|
||||
$form->display();
|
||||
|
||||
+57
-89
@@ -28,112 +28,85 @@ admin_externalpage_setup('searchareas');
|
||||
|
||||
$areaid = optional_param('areaid', null, PARAM_ALPHAEXT);
|
||||
$action = optional_param('action', null, PARAM_ALPHA);
|
||||
$indexingenabled = \core_search\manager::is_indexing_enabled(); // This restricts many of the actions on this page.
|
||||
|
||||
// Get a search manager instance, which we'll need for display and to handle some actions.
|
||||
try {
|
||||
$searchmanager = \core_search\manager::instance();
|
||||
} catch (core_search\engine_exception $searchmanagererror) {
|
||||
// In action cases, well throw this exception below. In non-action cases, we produce a lang string error.
|
||||
// Continue, we return an error later depending on the requested action.
|
||||
}
|
||||
|
||||
// Handle all the actions.
|
||||
echo $OUTPUT->header();
|
||||
|
||||
if ($action) {
|
||||
require_sesskey();
|
||||
|
||||
// If dealing with an areaid, we need to check that the area exists.
|
||||
if ($areaid) {
|
||||
// We need to check that the area exists.
|
||||
$area = \core_search\manager::get_search_area($areaid);
|
||||
if ($area === false) {
|
||||
throw new moodle_exception('invalidrequest');
|
||||
}
|
||||
}
|
||||
|
||||
// All the indexing actions.
|
||||
if (in_array($action, ['delete', 'indexall', 'reindexall', 'deleteall'])) {
|
||||
|
||||
// All of these actions require that indexing is enabled.
|
||||
if ($indexingenabled) {
|
||||
|
||||
// For all of these actions, we strictly need a manager instance.
|
||||
if (isset($searchmanagererror)) {
|
||||
throw $searchmanagererror;
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'delete':
|
||||
$searchmanager->delete_index($areaid);
|
||||
\core\notification::success(get_string('searchindexdeleted', 'admin'));
|
||||
break;
|
||||
case 'indexall':
|
||||
$searchmanager->index();
|
||||
\core\notification::success(get_string('searchindexupdated', 'admin'));
|
||||
break;
|
||||
case 'reindexall':
|
||||
$searchmanager->index(true);
|
||||
\core\notification::success(get_string('searchreindexed', 'admin'));
|
||||
break;
|
||||
case 'deleteall':
|
||||
$searchmanager->delete_index();
|
||||
\core\notification::success(get_string('searchalldeleted', 'admin'));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Redirect back to the main page after taking action.
|
||||
redirect(new moodle_url('/admin/searchareas.php'));
|
||||
}
|
||||
} else if (in_array($action, ['enable', 'disable'])) {
|
||||
switch ($action) {
|
||||
case 'enable':
|
||||
$area->set_enabled(true);
|
||||
\core\notification::success(get_string('searchareaenabled', 'admin'));
|
||||
break;
|
||||
case 'disable':
|
||||
$area->set_enabled(false);
|
||||
core\notification::success(get_string('searchareadisabled', 'admin'));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// All actions but enable/disable need the search engine to be ready.
|
||||
if ($action !== 'enable' && $action !== 'disable') {
|
||||
if (!empty($searchmanagererror)) {
|
||||
throw $searchmanagererror;
|
||||
}
|
||||
}
|
||||
|
||||
redirect(new moodle_url('/admin/searchareas.php'));
|
||||
} else {
|
||||
// Invalid action.
|
||||
throw new moodle_exception('invalidaction');
|
||||
switch ($action) {
|
||||
case 'enable':
|
||||
$area->set_enabled(true);
|
||||
echo $OUTPUT->notification(get_string('searchareaenabled', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'disable':
|
||||
$area->set_enabled(false);
|
||||
echo $OUTPUT->notification(get_string('searchareadisabled', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'delete':
|
||||
$search = \core_search\manager::instance();
|
||||
$search->delete_index($areaid);
|
||||
echo $OUTPUT->notification(get_string('searchindexdeleted', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'indexall':
|
||||
$searchmanager->index();
|
||||
echo $OUTPUT->notification(get_string('searchindexupdated', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'reindexall':
|
||||
$searchmanager->index(true);
|
||||
echo $OUTPUT->notification(get_string('searchreindexed', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
case 'deleteall':
|
||||
$searchmanager->delete_index();
|
||||
echo $OUTPUT->notification(get_string('searchalldeleted', 'admin'), \core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
default:
|
||||
throw new moodle_exception('invalidaction');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Display.
|
||||
if (isset($searchmanager) && $indexingenabled) {
|
||||
\core\notification::info(get_string('indexinginfo', 'admin'));
|
||||
} else if (isset($searchmanager)) {
|
||||
$params = (object) [
|
||||
'url' => (new moodle_url("/admin/settings.php?section=manageglobalsearch#admin-searchindexwhendisabled"))->out(false)
|
||||
];
|
||||
\core\notification::error(get_string('indexwhendisabledfullnotice', 'search', $params));
|
||||
$searchareas = \core_search\manager::get_search_areas_list();
|
||||
if (empty($searchmanagererror)) {
|
||||
$areasconfig = $searchmanager->get_areas_config($searchareas);
|
||||
} else {
|
||||
// In non-action cases, init errors are translated and displayed to the user as error notifications.
|
||||
$errorstr = get_string($searchmanagererror->errorcode, $searchmanagererror->module, $searchmanagererror->a);
|
||||
\core\notification::error($errorstr);
|
||||
$areasconfig = false;
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
if (!empty($searchmanagererror)) {
|
||||
$errorstr = get_string($searchmanagererror->errorcode, $searchmanagererror->module, $searchmanagererror->a);
|
||||
echo $OUTPUT->notification($errorstr, \core\output\notification::NOTIFY_ERROR);
|
||||
} else {
|
||||
echo $OUTPUT->notification(get_string('indexinginfo', 'admin'), \core\output\notification::NOTIFY_INFO);
|
||||
}
|
||||
|
||||
$table = new html_table();
|
||||
$table->id = 'core-search-areas';
|
||||
$table->head = [
|
||||
get_string('searcharea', 'search'),
|
||||
get_string('enable'),
|
||||
get_string('newestdocindexed', 'admin'),
|
||||
get_string('searchlastrun', 'admin'),
|
||||
get_string('searchindexactions', 'admin')
|
||||
];
|
||||
|
||||
$searchareas = \core_search\manager::get_search_areas_list();
|
||||
$areasconfig = isset($searchmanager) ? $searchmanager->get_areas_config($searchareas) : false;
|
||||
$table->head = array(get_string('searcharea', 'search'), get_string('enable'), get_string('newestdocindexed', 'admin'),
|
||||
get_string('searchlastrun', 'admin'), get_string('searchindexactions', 'admin'));
|
||||
|
||||
foreach ($searchareas as $area) {
|
||||
$areaid = $area->get_area_id();
|
||||
$columns = array(new html_table_cell($area->get_visible_name()));
|
||||
@@ -143,7 +116,7 @@ foreach ($searchareas as $area) {
|
||||
new pix_icon('t/hide', get_string('disable'), 'moodle', array('title' => '', 'class' => 'iconsmall')),
|
||||
null, array('title' => get_string('disable')));
|
||||
|
||||
if ($areasconfig && $indexingenabled) {
|
||||
if ($areasconfig) {
|
||||
$columns[] = $areasconfig[$areaid]->lastindexrun;
|
||||
|
||||
if ($areasconfig[$areaid]->indexingstart) {
|
||||
@@ -152,9 +125,6 @@ foreach ($searchareas as $area) {
|
||||
$areasconfig[$areaid]->docsprocessed . ' , ' .
|
||||
$areasconfig[$areaid]->recordsprocessed . ' , ' .
|
||||
$areasconfig[$areaid]->docsignored;
|
||||
if ($areasconfig[$areaid]->partial) {
|
||||
$laststatus .= ' ' . get_string('searchpartial', 'admin');
|
||||
}
|
||||
} else {
|
||||
$laststatus = '';
|
||||
}
|
||||
@@ -162,11 +132,7 @@ foreach ($searchareas as $area) {
|
||||
$columns[] = html_writer::link(admin_searcharea_action_url('delete', $areaid), 'Delete index');
|
||||
|
||||
} else {
|
||||
if (!$areasconfig) {
|
||||
$blankrow = new html_table_cell(get_string('searchnotavailable', 'admin'));
|
||||
} else {
|
||||
$blankrow = new html_table_cell(get_string('indexwhendisabledshortnotice', 'search'));
|
||||
}
|
||||
$blankrow = new html_table_cell(get_string('searchnotavailable', 'admin'));
|
||||
$blankrow->colspan = 3;
|
||||
$columns[] = $blankrow;
|
||||
}
|
||||
@@ -185,7 +151,10 @@ foreach ($searchareas as $area) {
|
||||
}
|
||||
|
||||
// Cross-search area tasks.
|
||||
$options = (isset($searchmanager) && $indexingenabled) ? [] : ['disabled' => true];
|
||||
$options = array();
|
||||
if (!empty($searchmanagererror)) {
|
||||
$options['disabled'] = true;
|
||||
}
|
||||
echo $OUTPUT->box_start('search-areas-actions');
|
||||
echo $OUTPUT->single_button(admin_searcharea_action_url('indexall'), get_string('searchupdateindex', 'admin'), 'get', $options);
|
||||
echo $OUTPUT->single_button(admin_searcharea_action_url('reindexall'), get_string('searchreindexindex', 'admin'), 'get', $options);
|
||||
@@ -193,7 +162,6 @@ echo $OUTPUT->single_button(admin_searcharea_action_url('deleteall'), get_string
|
||||
echo $OUTPUT->box_end();
|
||||
|
||||
echo html_writer::table($table);
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
/**
|
||||
|
||||
+4
-9
@@ -38,17 +38,12 @@ if (!($settingspage->check_access())) {
|
||||
$statusmsg = '';
|
||||
$errormsg = '';
|
||||
|
||||
// Form is submitted with changed settings. Do not want to execute when modifying a block.
|
||||
if ($data = data_submitted() and confirm_sesskey() and isset($data->action) and $data->action == 'save-settings') {
|
||||
if ($data = data_submitted() and confirm_sesskey()) {
|
||||
if (admin_write_settings($data)) {
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
$count = admin_write_settings($data);
|
||||
// Regardless of whether any setting change was written (a positive count), check validation errors for those that didn't.
|
||||
if (empty($adminroot->errors)) {
|
||||
// No errors. Did we change any setting? If so, then redirect with success.
|
||||
if ($count) {
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
// We didn't change a setting.
|
||||
switch ($return) {
|
||||
case 'site': redirect("$CFG->wwwroot/");
|
||||
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Adds settings links to admin tree.
|
||||
*
|
||||
* @package core_analytics
|
||||
* @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
if ($hassiteconfig) {
|
||||
$settings = new admin_settingpage('analyticssettings', new lang_string('analyticssettings', 'analytics'));
|
||||
$ADMIN->add('analytics', $settings);
|
||||
|
||||
if ($ADMIN->fulltree) {
|
||||
// Select the site prediction's processor.
|
||||
$predictionprocessors = \core_analytics\manager::get_all_prediction_processors();
|
||||
$predictors = array();
|
||||
foreach ($predictionprocessors as $fullclassname => $predictor) {
|
||||
$pluginname = substr($fullclassname, 1, strpos($fullclassname, '\\', 1) - 1);
|
||||
$predictors[$fullclassname] = new lang_string('pluginname', $pluginname);
|
||||
}
|
||||
$settings->add(new \core_analytics\admin_setting_predictor('analytics/predictionsprocessor',
|
||||
new lang_string('predictionsprocessor', 'analytics'), new lang_string('predictionsprocessor_help', 'analytics'),
|
||||
'\mlbackend_php\processor', $predictors)
|
||||
);
|
||||
|
||||
// Log store.
|
||||
$logmanager = get_log_manager();
|
||||
$readers = $logmanager->get_readers('core\log\sql_reader');
|
||||
$options = array();
|
||||
$defaultreader = null;
|
||||
foreach ($readers as $plugin => $reader) {
|
||||
if (!$reader->is_logging()) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($defaultreader)) {
|
||||
// The top one as default reader.
|
||||
$defaultreader = $plugin;
|
||||
}
|
||||
$options[$plugin] = $reader->get_name();
|
||||
}
|
||||
|
||||
if (empty($defaultreader)) {
|
||||
// We fall here during initial site installation because log stores are not
|
||||
// enabled until admin/tool/log/db/install.php is executed and get_readers
|
||||
// return nothing.
|
||||
|
||||
if ($enabledlogstores = get_config('tool_log', 'enabled_stores')) {
|
||||
$enabledlogstores = explode(',', $enabledlogstores);
|
||||
$defaultreader = reset($enabledlogstores);
|
||||
|
||||
// No need to set the correct name, just the value, this will not be displayed.
|
||||
$options[$defaultreader] = $defaultreader;
|
||||
}
|
||||
}
|
||||
$settings->add(new admin_setting_configselect('analytics/logstore',
|
||||
new lang_string('analyticslogstore', 'analytics'), new lang_string('analyticslogstore_help', 'analytics'),
|
||||
$defaultreader, $options));
|
||||
|
||||
// Enable/disable time splitting methods.
|
||||
$alltimesplittings = \core_analytics\manager::get_all_time_splittings();
|
||||
|
||||
$timesplittingoptions = array();
|
||||
$timesplittingdefaults = array('\core\analytics\time_splitting\quarters_accum',
|
||||
'\core\analytics\time_splitting\quarters', '\core\analytics\time_splitting\single_range');
|
||||
foreach ($alltimesplittings as $key => $timesplitting) {
|
||||
$timesplittingoptions[$key] = $timesplitting->get_name();
|
||||
}
|
||||
$settings->add(new admin_setting_configmultiselect('analytics/timesplittings',
|
||||
new lang_string('enabledtimesplittings', 'analytics'), new lang_string('timesplittingmethod_help', 'analytics'),
|
||||
$timesplittingdefaults, $timesplittingoptions)
|
||||
);
|
||||
|
||||
// Predictions processor output dir.
|
||||
$defaultmodeloutputdir = rtrim($CFG->dataroot, '/') . DIRECTORY_SEPARATOR . 'models';
|
||||
if (empty(get_config('analytics', 'modeloutputdir')) && !file_exists($defaultmodeloutputdir) &&
|
||||
is_writable($defaultmodeloutputdir)) {
|
||||
// Automatically create the dir for them so users don't see the invalid value red cross.
|
||||
mkdir($defaultmodeloutputdir, $CFG->directorypermissions, true);
|
||||
}
|
||||
$settings->add(new admin_setting_configdirectory('analytics/modeloutputdir', new lang_string('modeloutputdir', 'analytics'),
|
||||
new lang_string('modeloutputdirinfo', 'analytics'), $defaultmodeloutputdir));
|
||||
|
||||
// Disable web interface evaluation and get predictions.
|
||||
$settings->add(new admin_setting_configcheckbox('analytics/onlycli', new lang_string('onlycli', 'analytics'),
|
||||
new lang_string('onlycliinfo', 'analytics'), 1));
|
||||
|
||||
// Training and prediction time limit per model.
|
||||
$settings->add(new admin_setting_configduration('analytics/modeltimelimit', new lang_string('modeltimelimit', 'analytics'),
|
||||
new lang_string('modeltimelimitinfo', 'analytics'), 20 * MINSECS));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ preferences,moodle|/user/preferences.php|preferences',
|
||||
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));
|
||||
$temp->add(new admin_setting_configcheckbox('linkadmincategories', new lang_string('linkadmincategories', 'admin'), new lang_string('linkadmincategories_help', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('linkcoursesections', new lang_string('linkcoursesections', 'admin'), new lang_string('linkcoursesections_help', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('linkcoursesections', new lang_string('linkcoursesections', 'admin'), new lang_string('linkcoursesections_help', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('navshowfrontpagemods', new lang_string('navshowfrontpagemods', 'admin'), new lang_string('navshowfrontpagemods_help', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('navadduserpostslinks', new lang_string('navadduserpostslinks', 'admin'), new lang_string('navadduserpostslinks_help', 'admin'), 1));
|
||||
|
||||
@@ -199,7 +199,7 @@ preferences,moodle|/user/preferences.php|preferences',
|
||||
|
||||
// "documentation" settingpage
|
||||
$temp = new admin_settingpage('documentation', new lang_string('moodledocs'));
|
||||
$temp->add(new admin_setting_configtext('docroot', new lang_string('docroot', 'admin'), new lang_string('configdocroot', 'admin'), 'https://docs.moodle.org', PARAM_URL));
|
||||
$temp->add(new admin_setting_configtext('docroot', new lang_string('docroot', 'admin'), new lang_string('configdocroot', 'admin'), 'http://docs.moodle.org', PARAM_URL));
|
||||
$ltemp = array('' => get_string('forceno'));
|
||||
$ltemp += get_string_manager()->get_list_of_translations(true);
|
||||
$temp->add(new admin_setting_configselect('doclang', get_string('doclang', 'admin'), get_string('configdoclang', 'admin'), '', $ltemp));
|
||||
|
||||
@@ -92,9 +92,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configselect('moodlecourse/coursedisplay', new lang_string('coursedisplay'),
|
||||
new lang_string('coursedisplay_help'), COURSE_DISPLAY_SINGLEPAGE, $choices));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('moodlecourse/courseenddateenabled', get_string('courseenddateenabled'),
|
||||
get_string('courseenddateenabled_desc'), 1));
|
||||
|
||||
$temp->add(new admin_setting_configduration('moodlecourse/courseduration', get_string('courseduration'),
|
||||
get_string('courseduration_desc'), YEARSECS));
|
||||
|
||||
|
||||
@@ -28,9 +28,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$ADMIN->add('development', $temp);
|
||||
|
||||
// "Profiling" settingpage (conditionally if the 'xhprof' extension is available only).
|
||||
$xhprofenabled = extension_loaded('tideways_xhprof');
|
||||
$xhprofenabled = $xhprofenabled || extension_loaded('tideways');
|
||||
$xhprofenabled = $xhprofenabled || extension_loaded('xhprof');
|
||||
$xhprofenabled = extension_loaded('xhprof') || extension_loaded('tideways');
|
||||
$temp = new admin_settingpage('profiling', new lang_string('profiling', 'admin'), 'moodle/site:config', !$xhprofenabled);
|
||||
// Main profiling switch.
|
||||
$temp->add(new admin_setting_configcheckbox('profilingenabled', new lang_string('profilingenabled', 'admin'), new lang_string('profilingenabled_help', 'admin'), false));
|
||||
|
||||
@@ -102,7 +102,7 @@ if ($hassiteconfig) {
|
||||
$temp->add(new admin_setting_configtext('alternateloginurl', new lang_string('alternateloginurl', 'auth'),
|
||||
new lang_string('alternatelogin', 'auth', htmlspecialchars(get_login_url())), ''));
|
||||
$temp->add(new admin_setting_configtext('forgottenpasswordurl', new lang_string('forgottenpasswordurl', 'auth'),
|
||||
new lang_string('forgottenpassword', 'auth'), '', PARAM_URL));
|
||||
new lang_string('forgottenpassword', 'auth'), ''));
|
||||
$temp->add(new admin_setting_confightmleditor('auth_instructions', new lang_string('instructions', 'auth'),
|
||||
new lang_string('authinstructions', 'auth'), ''));
|
||||
$setting = new admin_setting_configtext('allowemailaddresses', new lang_string('allowemailaddresses', 'admin'),
|
||||
@@ -557,21 +557,6 @@ if ($hassiteconfig) {
|
||||
$temp->add(new admin_setting_heading('searchengineheading', new lang_string('searchengine', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configselect('searchengine',
|
||||
new lang_string('selectsearchengine', 'admin'), '', 'solr', $engines));
|
||||
$temp->add(new admin_setting_heading('searchoptionsheading', new lang_string('searchoptions', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configcheckbox('searchindexwhendisabled',
|
||||
new lang_string('searchindexwhendisabled', 'admin'), new lang_string('searchindexwhendisabled_desc', 'admin'),
|
||||
0));
|
||||
$temp->add(new admin_setting_configduration('searchindextime',
|
||||
new lang_string('searchindextime', 'admin'), new lang_string('searchindextime_desc', 'admin'),
|
||||
600));
|
||||
$options = [
|
||||
0 => new lang_string('searchallavailablecourses_off', 'admin'),
|
||||
1 => new lang_string('searchallavailablecourses_on', 'admin')
|
||||
];
|
||||
$temp->add(new admin_setting_configselect('searchallavailablecourses',
|
||||
new lang_string('searchallavailablecourses', 'admin'),
|
||||
new lang_string('searchallavailablecourses_desc', 'admin'),
|
||||
0, $options));
|
||||
|
||||
$ADMIN->add('searchplugins', $temp);
|
||||
$ADMIN->add('searchplugins', new admin_externalpage('searchareas', new lang_string('searchareas', 'admin'),
|
||||
|
||||
@@ -18,11 +18,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$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('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'),
|
||||
1 => new lang_string('allowindexingeverywhere', 'admin'),
|
||||
2 => new lang_string('allowindexingnowhere', 'admin'))));
|
||||
$temp->add(new admin_setting_pickroles('profileroles',
|
||||
new lang_string('profileroles','admin'),
|
||||
new lang_string('configprofileroles', 'admin'),
|
||||
@@ -54,7 +49,8 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
3600 => new lang_string('numminutes', '', 60))));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0));
|
||||
|
||||
$temp->add(new admin_setting_configtext('sitepolicy', new lang_string('sitepolicy', 'admin'), new lang_string('sitepolicy_help', 'admin'), '', PARAM_RAW));
|
||||
$temp->add(new admin_setting_configtext('sitepolicyguest', new lang_string('sitepolicyguest', 'admin'), new lang_string('sitepolicyguest_help', 'admin'), (isset($CFG->sitepolicy) ? $CFG->sitepolicy : ''), PARAM_RAW));
|
||||
$temp->add(new admin_setting_configcheckbox('extendedusernamechars', new lang_string('extendedusernamechars', 'admin'), new lang_string('configextendedusernamechars', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('keeptagnamecase', new lang_string('keeptagnamecase','admin'),new lang_string('configkeeptagnamecase', 'admin'),'1'));
|
||||
|
||||
@@ -107,10 +103,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
new lang_string('passwordchangetokendeletion', 'admin'),
|
||||
new lang_string('passwordchangetokendeletion_desc', 'admin'), 0));
|
||||
|
||||
$temp->add(new admin_setting_configduration('tokenduration',
|
||||
new lang_string('tokenduration', 'admin'),
|
||||
new lang_string('tokenduration_desc', 'admin'), 12 * WEEKSECS, WEEKSECS));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('groupenrolmentkeypolicy', new lang_string('groupenrolmentkeypolicy', 'admin'), new lang_string('groupenrolmentkeypolicy_desc', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('disableuserimages', new lang_string('disableuserimages', 'admin'), new lang_string('configdisableuserimages', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('emailchangeconfirmation', new lang_string('emailchangeconfirmation', 'admin'), new lang_string('configemailchangeconfirmation', 'admin'), 1));
|
||||
@@ -123,7 +115,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
|
||||
// "httpsecurity" settingpage
|
||||
$temp = new admin_settingpage('httpsecurity', new lang_string('httpsecurity', 'admin'));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('loginhttps', new lang_string('loginhttps', 'admin'), new lang_string('configloginhttps', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('cookiesecure', new lang_string('cookiesecure', 'admin'), new lang_string('configcookiesecure', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('cookiehttponly', new lang_string('cookiehttponly', 'admin'), new lang_string('configcookiehttponly', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowframembedding', new lang_string('allowframembedding', 'admin'), new lang_string('allowframembedding_help', 'admin'), 0));
|
||||
|
||||
@@ -12,8 +12,6 @@ $temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('patht
|
||||
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'), new lang_string('edhelpaspellpath'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'), new lang_string('pathtodot_help', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtogs', new lang_string('pathtogs', 'admin'), new lang_string('pathtogs_help', 'admin'), '/usr/bin/gs'));
|
||||
$temp->add(new admin_setting_configexecutable('pathtopython', new lang_string('pathtopython', 'admin'),
|
||||
new lang_string('pathtopythondesc', 'admin'), ''));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
|
||||
@@ -211,6 +209,9 @@ $temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
|
||||
$ADMIN->add('server', new admin_externalpage('adminregistration', new lang_string('hubs', 'admin'),
|
||||
"$CFG->wwwroot/$CFG->admin/registration/index.php"));
|
||||
|
||||
// E-mail settings.
|
||||
$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
|
||||
|
||||
|
||||
@@ -11,7 +11,14 @@ $hassiteconfig = has_capability('moodle/site:config', $systemcontext);
|
||||
$ADMIN->add('root', new admin_externalpage('adminnotifications', new lang_string('notifications'), "$CFG->wwwroot/$CFG->admin/index.php"));
|
||||
|
||||
$ADMIN->add('root', new admin_externalpage('registrationmoodleorg', new lang_string('registration', 'admin'),
|
||||
new moodle_url("/admin/registration/index.php")));
|
||||
"$CFG->wwwroot/$CFG->admin/registration/register.php?huburl=" . HUB_MOODLEORGHUBURL . "&hubname=Moodle.org&sesskey=" . sesskey()));
|
||||
$ADMIN->add('root', new admin_externalpage('registrationhub', new lang_string('registerwith', 'hub'),
|
||||
"$CFG->wwwroot/$CFG->admin/registration/register.php", 'moodle/site:config', true));
|
||||
$ADMIN->add('root', new admin_externalpage('registrationhubs', new lang_string('hubs', 'admin'),
|
||||
"$CFG->wwwroot/$CFG->admin/registration/index.php", 'moodle/site:config', true));
|
||||
$ADMIN->add('root', new admin_externalpage('siteregistrationconfirmed',
|
||||
new lang_string('registrationconfirmed', 'hub'),
|
||||
$CFG->wwwroot."/".$CFG->admin."/registration/confirmregistration.php", 'moodle/site:config', true));
|
||||
// hidden upgrade script
|
||||
$ADMIN->add('root', new admin_externalpage('upgradesettings', new lang_string('upgradesettings', 'admin'), "$CFG->wwwroot/$CFG->admin/upgradesettings.php", 'moodle/site:config', true));
|
||||
|
||||
@@ -23,7 +30,6 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('root', new admin_category('users', new lang_string('users','admin')));
|
||||
$ADMIN->add('root', new admin_category('courses', new lang_string('courses','admin')));
|
||||
$ADMIN->add('root', new admin_category('grades', new lang_string('grades')));
|
||||
$ADMIN->add('root', new admin_category('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('location', new lang_string('location','admin')));
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
$ADMIN->add('users', new admin_category('accounts', new lang_string('accounts', 'admin')));
|
||||
$ADMIN->add('users', new admin_category('roles', new lang_string('permissions', 'role')));
|
||||
$ADMIN->add('users', new admin_category('privacy', new lang_string('privacyandpolicies', 'admin')));
|
||||
|
||||
if ($hassiteconfig
|
||||
or has_capability('moodle/user:create', $systemcontext)
|
||||
@@ -16,10 +15,15 @@ if ($hassiteconfig
|
||||
or has_capability('moodle/cohort:view', $systemcontext)) { // speedup for non-admins, add all caps used on this page
|
||||
|
||||
|
||||
if (empty($CFG->loginhttps)) {
|
||||
$securewwwroot = $CFG->wwwroot;
|
||||
} else {
|
||||
$securewwwroot = str_replace('http:','https:',$CFG->wwwroot);
|
||||
}
|
||||
// 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'));
|
||||
$ADMIN->add('accounts', new admin_externalpage('addnewuser', new lang_string('addnewuser'), "$securewwwroot/user/editadvanced.php?id=-1", 'moodle/user:create'));
|
||||
|
||||
// "User default preferences" settingpage.
|
||||
$temp = new admin_settingpage('userdefaultpreferences', new lang_string('userdefaultpreferences', 'admin'));
|
||||
@@ -185,8 +189,6 @@ if ($hassiteconfig
|
||||
'phone2' => new lang_string('phone2'),
|
||||
'department' => new lang_string('department'),
|
||||
'institution' => new lang_string('institution'),
|
||||
'city' => new lang_string('city'),
|
||||
'country' => new lang_string('country'),
|
||||
)));
|
||||
$setting = new admin_setting_configtext('fullnamedisplay', new lang_string('fullnamedisplay', 'admin'),
|
||||
new lang_string('configfullnamedisplay', 'admin'), 'language', PARAM_TEXT, 50);
|
||||
@@ -210,48 +212,3 @@ if ($hassiteconfig
|
||||
$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
|
||||
|
||||
// Privacy settings.
|
||||
if ($hassiteconfig) {
|
||||
$temp = new admin_settingpage('privacysettings', new lang_string('privacysettings', 'admin'));
|
||||
|
||||
$options = array(
|
||||
0 => get_string('no'),
|
||||
1 => get_string('yes')
|
||||
);
|
||||
$url = new moodle_url('/admin/settings.php?section=supportcontact');
|
||||
$url = $url->out();
|
||||
$setting = new admin_setting_configselect('agedigitalconsentverification',
|
||||
new lang_string('agedigitalconsentverification', 'admin'),
|
||||
new lang_string('agedigitalconsentverification_desc', 'admin', $url), 0, $options);
|
||||
$setting->set_force_ltr(true);
|
||||
$temp->add($setting);
|
||||
|
||||
// See {@link https://gdpr-info.eu/art-8-gdpr/}.
|
||||
$ageofdigitalconsentmap = implode(PHP_EOL, [
|
||||
'*, 16',
|
||||
'AT, 14',
|
||||
'ES, 14',
|
||||
'US, 13'
|
||||
]);
|
||||
$setting = new admin_setting_agedigitalconsentmap('agedigitalconsentmap',
|
||||
new lang_string('ageofdigitalconsentmap', 'admin'),
|
||||
new lang_string('ageofdigitalconsentmap_desc', 'admin'),
|
||||
$ageofdigitalconsentmap,
|
||||
PARAM_RAW
|
||||
);
|
||||
$temp->add($setting);
|
||||
|
||||
$ADMIN->add('privacy', $temp);
|
||||
|
||||
// Policy settings.
|
||||
$temp = new admin_settingpage('policysettings', new lang_string('policysettings', 'admin'));
|
||||
$temp->add(new admin_settings_sitepolicy_handler_select('sitepolicyhandler', new lang_string('sitepolicyhandler', 'core_admin'),
|
||||
new lang_string('sitepolicyhandler_desc', 'core_admin')));
|
||||
$temp->add(new admin_setting_configtext('sitepolicy', new lang_string('sitepolicy', 'core_admin'),
|
||||
new lang_string('sitepolicy_help', 'core_admin'), '', PARAM_RAW));
|
||||
$temp->add(new admin_setting_configtext('sitepolicyguest', new lang_string('sitepolicyguest', 'core_admin'),
|
||||
new lang_string('sitepolicyguest_help', 'core_admin'), (isset($CFG->sitepolicy) ? $CFG->sitepolicy : ''), PARAM_RAW));
|
||||
|
||||
$ADMIN->add('privacy', $temp);
|
||||
}
|
||||
@@ -1,52 +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_filetypes
|
||||
|
||||
Renders the admin_setting_filetypes setting element.
|
||||
|
||||
Context variables required for this template:
|
||||
* id - element id
|
||||
* name - form element name
|
||||
* value - element value
|
||||
* descriptions - data for the core_form/filetypes-descriptions template
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"id": "test0",
|
||||
"name": "test",
|
||||
"value": ".jpg,.gif",
|
||||
"descriptions": {
|
||||
"hasdescriptions": true,
|
||||
"descriptions": [
|
||||
{
|
||||
"description": "Image (JPEG)",
|
||||
"extensions": ".jpeg .jpe .jpg"
|
||||
},
|
||||
{
|
||||
"description": "Image (GIF)",
|
||||
"extensions": ".gif"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}}
|
||||
<div class="form-text defaultsnext">
|
||||
<input type="text" name="{{name}}" value="{{value}}" size="30" id="{{id}}" class="text-ltr">
|
||||
<span data-filetypesbrowser="{{id}}"></span>
|
||||
<div data-filetypesdescriptions="{{id}}">{{#descriptions}}{{>core_form/filetypes-descriptions}}{{/descriptions}}</div>
|
||||
</div>
|
||||
@@ -40,7 +40,6 @@
|
||||
<div class="settingsform clearfix">
|
||||
{{#params}}
|
||||
<input type="hidden" name="{{name}}" value="{{value}}">
|
||||
<input type="hidden" name="action" value="save-settings">
|
||||
{{/params}}
|
||||
<input type="hidden" name="sesskey" value="{{sesskey}}">
|
||||
<input type="hidden" name="return" value="{{return}}">
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
@core @core_admin
|
||||
Feature: Manage tokens
|
||||
In order to manage webservice usage
|
||||
As an admin
|
||||
I need to be able to create and delete tokens
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | password | firstname | lastname |
|
||||
| testuser | testuser | Joe | Bloggs |
|
||||
| testuser2 | testuser2 | TestFirstname | TestLastname |
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
|
||||
@javascript
|
||||
Scenario: Add & delete a token
|
||||
Given I navigate to "Plugins > Web services > Manage tokens" in site administration
|
||||
And I follow "Add"
|
||||
And I set the field "User" to "Joe Bloggs"
|
||||
And I set the field "IP restriction" to "127.0.0.1"
|
||||
When I press "Save changes"
|
||||
Then I should see "Joe Bloggs"
|
||||
And I should see "127.0.0.1"
|
||||
And I follow "Delete"
|
||||
And I press "Delete"
|
||||
And I should not see "Joe Bloggs"
|
||||
@@ -1 +0,0 @@
|
||||
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
@@ -1 +0,0 @@
|
||||
define(["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events"],function(a,b,c,d,e,f){var g={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}}},h=function(b){return a(b.closest("tr")[0]).find("span.target-name").text()};return{confirmAction:function(i,j){a('[data-action-id="'+i+'"]').on("click",function(i){i.preventDefault();var k=a(i.currentTarget);if("undefined"==typeof g[j])return void c.error('Action "'+j+'" is not allowed.');var l=[g[j].title,g[j].body];l[1].param=h(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)})}}});
|
||||
@@ -1,56 +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/>.
|
||||
|
||||
/**
|
||||
* Shows a dialogue with info about this logs.
|
||||
*
|
||||
* @module tool_analytics/log_info
|
||||
* @class log_info
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/str', 'core/modal_factory', 'core/notification'], function($, str, ModalFactory, Notification) {
|
||||
|
||||
return /** @alias module:tool_analytics/log_info */ {
|
||||
|
||||
/**
|
||||
* Prepares a modal info for a log's results.
|
||||
*
|
||||
* @method loadInfo
|
||||
* @param {int} id
|
||||
* @param {string[]} info
|
||||
*/
|
||||
loadInfo: function(id, info) {
|
||||
|
||||
var link = $('[data-model-log-id="' + id + '"]');
|
||||
str.get_string('loginfo', 'tool_analytics').then(function(langString) {
|
||||
|
||||
var bodyInfo = $("<ul>");
|
||||
info.forEach(function(item) {
|
||||
bodyInfo.append('<li>' + item + '</li>');
|
||||
});
|
||||
bodyInfo.append("</ul>");
|
||||
|
||||
return ModalFactory.create({
|
||||
title: langString,
|
||||
body: bodyInfo.html(),
|
||||
large: true,
|
||||
}, link);
|
||||
|
||||
}).catch(Notification.exception);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,94 +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/>.
|
||||
|
||||
/**
|
||||
* AMD module for model actions confirmation.
|
||||
*
|
||||
* @module tool_analytics/model
|
||||
* @copyright 2017 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/str', 'core/log', 'core/notification', 'core/modal_factory', 'core/modal_events'],
|
||||
function($, Str, log, Notification, ModalFactory, ModalEvents) {
|
||||
|
||||
/**
|
||||
* List of actions that require confirmation and confirmation message.
|
||||
*/
|
||||
var actionsList = {
|
||||
clear: {
|
||||
title: {
|
||||
key: 'clearpredictions',
|
||||
component: 'tool_analytics'
|
||||
}, body: {
|
||||
key: 'clearmodelpredictions',
|
||||
component: 'tool_analytics'
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the model name.
|
||||
*
|
||||
* @param {Object} actionItem The action item DOM node.
|
||||
* @return {String}
|
||||
*/
|
||||
var getModelName = function(actionItem) {
|
||||
return $(actionItem.closest('tr')[0]).find('span.target-name').text();
|
||||
};
|
||||
|
||||
/** @alias module:tool_analytics/model */
|
||||
return {
|
||||
|
||||
/**
|
||||
* Displays a confirm modal window before executing the action.
|
||||
*
|
||||
* @param {String} actionId
|
||||
* @param {String} actionType
|
||||
*/
|
||||
confirmAction: function(actionId, actionType) {
|
||||
$('[data-action-id="' + actionId + '"]').on('click', function(ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
var a = $(ev.currentTarget);
|
||||
|
||||
if (typeof actionsList[actionType] === "undefined") {
|
||||
log.error('Action "' + actionType + '" is not allowed.');
|
||||
return;
|
||||
}
|
||||
|
||||
var reqStrings = [
|
||||
actionsList[actionType].title,
|
||||
actionsList[actionType].body
|
||||
];
|
||||
reqStrings[1].param = getModelName(a);
|
||||
|
||||
var stringsPromise = Str.get_strings(reqStrings);
|
||||
var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL});
|
||||
|
||||
$.when(stringsPromise, modalPromise).then(function(strings, modal) {
|
||||
modal.setTitle(strings[0]);
|
||||
modal.setBody(strings[1]);
|
||||
modal.setSaveButtonText(strings[0]);
|
||||
modal.getRoot().on(ModalEvents.save, function() {
|
||||
window.location.href = a.attr('href');
|
||||
});
|
||||
modal.show();
|
||||
return modal;
|
||||
}).fail(Notification.exception);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,119 +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/>.
|
||||
|
||||
/**
|
||||
* Model edit form.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_analytics\output\form;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot.'/lib/formslib.php');
|
||||
|
||||
/**
|
||||
* Model edit form.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class edit_model extends \moodleform {
|
||||
|
||||
/**
|
||||
* Form definition
|
||||
*/
|
||||
public function definition() {
|
||||
global $OUTPUT;
|
||||
|
||||
$mform = $this->_form;
|
||||
|
||||
if ($this->_customdata['model']->is_trained()) {
|
||||
$message = get_string('edittrainedwarning', 'tool_analytics');
|
||||
$mform->addElement('html', $OUTPUT->notification($message, \core\output\notification::NOTIFY_WARNING));
|
||||
}
|
||||
|
||||
$mform->addElement('advcheckbox', 'enabled', get_string('enabled', 'tool_analytics'));
|
||||
|
||||
$indicators = array();
|
||||
foreach ($this->_customdata['indicators'] as $classname => $indicator) {
|
||||
$optionname = \tool_analytics\output\helper::class_to_option($classname);
|
||||
$indicators[$optionname] = $indicator->get_name();
|
||||
}
|
||||
$options = array(
|
||||
'multiple' => true
|
||||
);
|
||||
$mform->addElement('autocomplete', 'indicators', get_string('indicators', 'tool_analytics'), $indicators, $options);
|
||||
$mform->setType('indicators', PARAM_ALPHANUMEXT);
|
||||
|
||||
$timesplittings = array('' => '');
|
||||
foreach ($this->_customdata['timesplittings'] as $classname => $timesplitting) {
|
||||
$optionname = \tool_analytics\output\helper::class_to_option($classname);
|
||||
$timesplittings[$optionname] = $timesplitting->get_name();
|
||||
}
|
||||
|
||||
$mform->addElement('select', 'timesplitting', get_string('timesplittingmethod', 'analytics'), $timesplittings);
|
||||
$mform->addHelpButton('timesplitting', 'timesplittingmethod', 'analytics');
|
||||
|
||||
$mform->addElement('hidden', 'id', $this->_customdata['id']);
|
||||
$mform->setType('id', PARAM_INT);
|
||||
|
||||
$mform->addElement('hidden', 'action', 'edit');
|
||||
$mform->setType('action', PARAM_ALPHANUMEXT);
|
||||
|
||||
$this->add_action_buttons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Form validation
|
||||
*
|
||||
* @param array $data data from the form.
|
||||
* @param array $files files uploaded.
|
||||
*
|
||||
* @return array of errors.
|
||||
*/
|
||||
public function validation($data, $files) {
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
if (!empty($data['timesplitting'])) {
|
||||
$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');
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($data['indicators'])) {
|
||||
$errors['indicators'] = get_string('errornoindicators', 'analytics');
|
||||
} else {
|
||||
foreach ($data['indicators'] as $indicator) {
|
||||
$realindicatorname = \tool_analytics\output\helper::option_to_class($indicator);
|
||||
if (\core_analytics\manager::is_valid($realindicatorname, '\core_analytics\local\indicator\base') === false) {
|
||||
$errors['indicators'] = get_string('errorinvalidindicator', 'analytics', $realindicatorname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['enabled']) && empty($data['timesplitting'])) {
|
||||
$errors['enabled'] = get_string('errorcantenablenotimesplitting', 'tool_analytics');
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +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/>.
|
||||
|
||||
/**
|
||||
* Typical crappy helper class with tiny functions.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 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();
|
||||
|
||||
/**
|
||||
* Helper class with general purpose tiny functions.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class helper {
|
||||
|
||||
/**
|
||||
* Converts a class full name to a select option key
|
||||
*
|
||||
* @param string $class
|
||||
* @return string
|
||||
*/
|
||||
public static function class_to_option($class) {
|
||||
// Form field is PARAM_ALPHANUMEXT and we are sending fully qualified class names
|
||||
// as option names, but replacing the backslash for a string that is really unlikely
|
||||
// to ever be part of a class name.
|
||||
return str_replace('\\', '2015102400ouuu', $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* option_to_class
|
||||
*
|
||||
* @param string $option
|
||||
* @return string
|
||||
*/
|
||||
public static function option_to_class($option) {
|
||||
// Really unlikely but yeah, I'm a bad booyyy.
|
||||
return str_replace('2015102400ouuu', '\\', $option);
|
||||
}
|
||||
}
|
||||
@@ -1,158 +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/>.
|
||||
|
||||
/**
|
||||
* Invalid analysables renderable.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 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;
|
||||
|
||||
/**
|
||||
* Invalid analysables renderable.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class invalid_analysables implements \renderable, \templatable {
|
||||
|
||||
/**
|
||||
* @var \core_analytics\model
|
||||
*/
|
||||
protected $model = null;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $page = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $perpage = 0;
|
||||
|
||||
/**
|
||||
* Inits the invalid analysables renderable.
|
||||
*
|
||||
* @param \core_analytics\model $model
|
||||
* @param int $page
|
||||
* @param int $perpage
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function __construct(\core_analytics\model $model, $page, $perpage) {
|
||||
|
||||
$this->model = $model;
|
||||
$this->page = $page;
|
||||
$this->perpage = $perpage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the data.
|
||||
*
|
||||
* @param \renderer_base $output
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output) {
|
||||
global $PAGE;
|
||||
|
||||
$offset = $this->page * $this->perpage;
|
||||
|
||||
$analysables = $this->model->get_analyser(['notimesplitting' => true])->get_analysables();
|
||||
|
||||
$skipped = 0;
|
||||
$enoughresults = false;
|
||||
$morepages = false;
|
||||
$results = array();
|
||||
foreach ($analysables as $key => $analysable) {
|
||||
|
||||
$validtraining = $this->model->get_target()->is_valid_analysable($analysable, true);
|
||||
if ($validtraining === true) {
|
||||
if ($this->model->is_static()) {
|
||||
// We still want to show this analysable if it is not valid to get predictions.
|
||||
$validtraining = get_string('notrainingbasedassumptions', 'analytics');
|
||||
} else {
|
||||
// We skip analysables that are valid for training or valid for prediction.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$validprediction = $this->model->get_target()->is_valid_analysable($analysable, false);
|
||||
if ($validprediction === true) {
|
||||
// We skip analysables that are valid for training or valid for prediction.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($offset && $skipped < $offset) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add a new results if we don't have enough yet.
|
||||
if (!$enoughresults) {
|
||||
$results[$analysable->get_id()] = array($analysable, $validtraining, $validprediction);
|
||||
if ($this->perpage && count($results) === $this->perpage) {
|
||||
$enoughresults = true;
|
||||
}
|
||||
} else {
|
||||
// Confirmed that we have results we can not fit into this page.
|
||||
$morepages = true;
|
||||
break;
|
||||
}
|
||||
|
||||
unset($analysables[$key]);
|
||||
}
|
||||
|
||||
// Prepare the context object.
|
||||
$data = new \stdClass();
|
||||
$data->modelname = $this->model->get_target()->get_name();
|
||||
|
||||
if ($this->page > 0) {
|
||||
$prev = clone $PAGE->url;
|
||||
$prev->param('page', $this->page - 1);
|
||||
$button = new \single_button($prev, get_string('previouspage', 'tool_analytics'), 'get');
|
||||
$data->prev = $button->export_for_template($output);
|
||||
}
|
||||
if ($morepages) {
|
||||
$next = clone $PAGE->url;
|
||||
$next->param('page', $this->page + 1);
|
||||
$button = new \single_button($next, get_string('nextpage', 'tool_analytics'), 'get');
|
||||
$data->next = $button->export_for_template($output);
|
||||
}
|
||||
|
||||
$data->analysables = [];
|
||||
foreach ($results as list($analysable, $validtraining, $validprediction)) {
|
||||
$obj = new \stdClass();
|
||||
$obj->url = \html_writer::link($analysable->get_context()->get_url(), $analysable->get_name(),
|
||||
array('target' => '_blank'));
|
||||
|
||||
if ($validtraining !== true) {
|
||||
$obj->validtraining = $validtraining;
|
||||
}
|
||||
if ($validprediction !== true) {
|
||||
$obj->validprediction = $validprediction;
|
||||
}
|
||||
$data->analysables[] = $obj;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -1,192 +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/>.
|
||||
|
||||
/**
|
||||
* Model logs table class.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 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;
|
||||
require_once($CFG->libdir . '/tablelib.php');
|
||||
|
||||
/**
|
||||
* Model logs table class.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class model_logs extends \table_sql {
|
||||
|
||||
/**
|
||||
* @var \core_analytics\model
|
||||
*/
|
||||
protected $model = null;
|
||||
|
||||
/**
|
||||
* Sets up the table_log parameters.
|
||||
*
|
||||
* @param string $uniqueid unique id of form.
|
||||
* @param \core_analytics\model $model
|
||||
*/
|
||||
public function __construct($uniqueid, $model) {
|
||||
global $PAGE;
|
||||
|
||||
parent::__construct($uniqueid);
|
||||
|
||||
$this->model = $model;
|
||||
|
||||
$this->set_attribute('class', 'modellog generaltable generalbox');
|
||||
$this->set_attribute('aria-live', 'polite');
|
||||
|
||||
$this->define_columns(array('time', 'version', 'indicators', 'timesplitting', 'accuracy', 'info', 'usermodified'));
|
||||
$this->define_headers(array(
|
||||
get_string('time'),
|
||||
get_string('version'),
|
||||
get_string('indicators', 'tool_analytics'),
|
||||
get_string('timesplittingmethod', 'analytics'),
|
||||
get_string('accuracy', 'tool_analytics'),
|
||||
get_string('info', 'tool_analytics'),
|
||||
get_string('fullnameuser'),
|
||||
));
|
||||
$this->pageable(true);
|
||||
$this->collapsible(false);
|
||||
$this->sortable(false);
|
||||
$this->is_downloadable(false);
|
||||
|
||||
$this->define_baseurl($PAGE->url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the version column.
|
||||
*
|
||||
* @param \stdClass $log log data.
|
||||
* @return string HTML for the version column
|
||||
*/
|
||||
public function col_version($log) {
|
||||
$recenttimestr = get_string('strftimerecent', 'core_langconfig');
|
||||
return userdate($log->version, $recenttimestr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the time column.
|
||||
*
|
||||
* @param \stdClass $log log data.
|
||||
* @return string HTML for the time column
|
||||
*/
|
||||
public function col_time($log) {
|
||||
$recenttimestr = get_string('strftimerecent', 'core_langconfig');
|
||||
return userdate($log->timecreated, $recenttimestr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the indicators column.
|
||||
*
|
||||
* @param \stdClass $log log data.
|
||||
* @return string HTML for the indicators column
|
||||
*/
|
||||
public function col_indicators($log) {
|
||||
$indicatorclasses = json_decode($log->indicators);
|
||||
$indicators = array();
|
||||
foreach ($indicatorclasses as $indicatorclass) {
|
||||
$indicator = \core_analytics\manager::get_indicator($indicatorclass);
|
||||
if ($indicator) {
|
||||
$indicators[] = $indicator->get_name();
|
||||
} else {
|
||||
debugging('Can\'t load ' . $indicatorclass . ' indicator', DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
return '<ul><li>' . implode('</li><li>', $indicators) . '</li></ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the context column.
|
||||
*
|
||||
* @param \stdClass $log log data.
|
||||
* @return string HTML for the context column
|
||||
*/
|
||||
public function col_timesplitting($log) {
|
||||
$timesplitting = \core_analytics\manager::get_time_splitting($log->timesplitting);
|
||||
return $timesplitting->get_name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the accuracy column.
|
||||
*
|
||||
* @param \stdClass $log log data.
|
||||
* @return string HTML for the accuracy column
|
||||
*/
|
||||
public function col_accuracy($log) {
|
||||
return strval(round($log->score * 100, 2)) . '%';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the info column.
|
||||
*
|
||||
* @param \stdClass $log log data.
|
||||
* @return string HTML for the score column
|
||||
*/
|
||||
public function col_info($log) {
|
||||
global $PAGE;
|
||||
|
||||
if (empty($log->info) && empty($log->dir)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$info = array();
|
||||
if (!empty($log->info)) {
|
||||
$info = json_decode($log->info);
|
||||
}
|
||||
if (!empty($log->dir)) {
|
||||
$info[] = get_string('predictorresultsin', 'tool_analytics', $log->dir);
|
||||
}
|
||||
$PAGE->requires->js_call_amd('tool_analytics/log_info', 'loadInfo', array($log->id, $info));
|
||||
return \html_writer::link('#', get_string('view'), array('data-model-log-id' => $log->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the usermodified column.
|
||||
*
|
||||
* @param \stdClass $log log data.
|
||||
* @return string HTML for the usermodified column
|
||||
*/
|
||||
public function col_usermodified($log) {
|
||||
$user = \core_user::get_user($log->usermodified);
|
||||
return fullname($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the logs table. Store results in the object for use by build_table.
|
||||
*
|
||||
* @param int $pagesize size of page for paginated displayed table.
|
||||
* @param bool $useinitialsbar do you want to use the initials bar.
|
||||
*/
|
||||
public function query_db($pagesize, $useinitialsbar = true) {
|
||||
$total = count($this->model->get_logs());
|
||||
$this->pagesize($pagesize, $total);
|
||||
$this->rawdata = $this->model->get_logs($this->get_page_start(), $this->get_page_size());
|
||||
|
||||
// Set initial bars.
|
||||
if ($useinitialsbar) {
|
||||
$this->initialbars($total > $pagesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,286 +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/>.
|
||||
|
||||
/**
|
||||
* Prediction models list page.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2016 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();
|
||||
|
||||
/**
|
||||
* Shows tool_analytics models list.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class models_list implements \renderable, \templatable {
|
||||
|
||||
/**
|
||||
* models
|
||||
*
|
||||
* @var \core_analytics\model[]
|
||||
*/
|
||||
protected $models = array();
|
||||
|
||||
/**
|
||||
* __construct
|
||||
*
|
||||
* @param \core_analytics\model[] $models
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($models) {
|
||||
$this->models = $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the data.
|
||||
*
|
||||
* @param \renderer_base $output
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output) {
|
||||
global $PAGE;
|
||||
|
||||
$data = new \stdClass();
|
||||
|
||||
$onlycli = get_config('analytics', 'onlycli');
|
||||
if ($onlycli === false) {
|
||||
// Default applied if no config found.
|
||||
$onlycli = 1;
|
||||
}
|
||||
|
||||
$data->models = array();
|
||||
foreach ($this->models as $model) {
|
||||
$modeldata = $model->export();
|
||||
|
||||
// Check if there is a help icon for the target to show.
|
||||
$identifier = $modeldata->target->get_identifier();
|
||||
$component = $modeldata->target->get_component();
|
||||
if (get_string_manager()->string_exists($identifier . '_help', $component)) {
|
||||
$helpicon = new \help_icon($identifier, $component);
|
||||
$modeldata->targethelp = $helpicon->export_for_template($output);
|
||||
} else {
|
||||
// We really want to encourage developers to add help to their targets.
|
||||
debugging("The target '{$modeldata->target}' should include a '{$identifier}_help' string to
|
||||
describe its purpose.", DEBUG_DEVELOPER);
|
||||
}
|
||||
|
||||
// Check if there is a help icon for the indicators to show.
|
||||
if (!empty($modeldata->indicators)) {
|
||||
$indicators = array();
|
||||
foreach ($modeldata->indicators as $ind) {
|
||||
// Create the indicator with the details we want for the context.
|
||||
$indicator = new \stdClass();
|
||||
$indicator->name = $ind->out();
|
||||
$identifier = $ind->get_identifier();
|
||||
$component = $ind->get_component();
|
||||
if (get_string_manager()->string_exists($identifier . '_help', $component)) {
|
||||
$helpicon = new \help_icon($identifier, $component);
|
||||
$indicator->help = $helpicon->export_for_template($output);
|
||||
} else {
|
||||
// We really want to encourage developers to add help to their indicators.
|
||||
debugging("The indicator '{$ind}' should include a '{$identifier}_help' string to
|
||||
describe its purpose.", DEBUG_DEVELOPER);
|
||||
}
|
||||
$indicators[] = $indicator;
|
||||
}
|
||||
$modeldata->indicators = $indicators;
|
||||
}
|
||||
|
||||
// Check if there is a help icon for the time splitting method.
|
||||
if (!empty($modeldata->timesplitting)) {
|
||||
$identifier = $modeldata->timesplitting->get_identifier();
|
||||
$component = $modeldata->timesplitting->get_component();
|
||||
if (get_string_manager()->string_exists($identifier . '_help', $component)) {
|
||||
$helpicon = new \help_icon($identifier, $component);
|
||||
$modeldata->timesplittinghelp = $helpicon->export_for_template($output);
|
||||
} else {
|
||||
// We really want to encourage developers to add help to their time splitting methods.
|
||||
debugging("The time splitting method '{$modeldata->timesplitting}' should include a '{$identifier}_help'
|
||||
string to describe its purpose.", DEBUG_DEVELOPER);
|
||||
}
|
||||
} else {
|
||||
$helpicon = new \help_icon('timesplittingnotdefined', 'tool_analytics');
|
||||
$modeldata->timesplittinghelp = $helpicon->export_for_template($output);
|
||||
}
|
||||
|
||||
// Has this model generated predictions?.
|
||||
$predictioncontexts = $model->get_predictions_contexts();
|
||||
|
||||
// Model predictions list.
|
||||
if (!$model->is_enabled()) {
|
||||
$modeldata->noinsights = get_string('disabledmodel', 'analytics');
|
||||
} else if ($model->uses_insights()) {
|
||||
if ($predictioncontexts) {
|
||||
|
||||
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(true, true), 90);
|
||||
}
|
||||
$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 ($model->any_prediction_obtained()) {
|
||||
$modeldata->noinsights = get_string('noinsights', 'analytics');
|
||||
} else {
|
||||
$modeldata->noinsights = get_string('nopredictionsyet', 'analytics');
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$modeldata->noinsights = get_string('noinsightsmodel', 'analytics');
|
||||
}
|
||||
|
||||
// Actions.
|
||||
$actionsmenu = new \action_menu();
|
||||
$actionsmenu->set_menu_trigger(get_string('actions'));
|
||||
$actionsmenu->set_owner_selector('model-actions-' . $model->get_id());
|
||||
$actionsmenu->set_alignment(\action_menu::TL, \action_menu::BL);
|
||||
|
||||
$urlparams = ['id' => $model->get_id(), 'sesskey' => sesskey()];
|
||||
|
||||
// Get predictions.
|
||||
if (!$onlycli && $modeldata->enabled && !empty($modeldata->timesplitting)) {
|
||||
$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);
|
||||
}
|
||||
|
||||
// Evaluate machine-learning-based models.
|
||||
if (!$onlycli && $model->get_indicators() && !$model->is_static()) {
|
||||
$urlparams['action'] = 'evaluate';
|
||||
$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'));
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
|
||||
// Machine-learning-based models evaluation log.
|
||||
if (!$model->is_static()) {
|
||||
$urlparams['action'] = 'log';
|
||||
$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);
|
||||
}
|
||||
|
||||
// Edit model.
|
||||
if (!$model->is_static()) {
|
||||
$urlparams['action'] = 'edit';
|
||||
$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);
|
||||
}
|
||||
|
||||
// Enable / disable.
|
||||
if ($model->is_enabled() || !empty($modeldata->timesplitting)) {
|
||||
// If there is no timesplitting method set, the model can not be enabled.
|
||||
if ($model->is_enabled()) {
|
||||
$action = 'disable';
|
||||
$text = get_string('disable');
|
||||
$icontype = 't/block';
|
||||
} else {
|
||||
$action = 'enable';
|
||||
$text = get_string('enable');
|
||||
$icontype = 'i/checked';
|
||||
}
|
||||
$urlparams['action'] = $action;
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon($icontype, $text), $text);
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
|
||||
// Export training data.
|
||||
if (!$model->is_static() && $model->is_trained()) {
|
||||
$urlparams['action'] = 'export';
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon('i/export',
|
||||
get_string('exporttrainingdata', 'tool_analytics')), get_string('export', '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('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($predictioncontexts)) {
|
||||
$actionid = 'clear-' . $model->get_id();
|
||||
$PAGE->requires->js_call_amd('tool_analytics/model', 'confirmAction', [$actionid, 'clear']);
|
||||
$urlparams['action'] = 'clear';
|
||||
$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]);
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
|
||||
$modeldata->actions = $actionsmenu->export_for_template($output);
|
||||
|
||||
$data->models[] = $modeldata;
|
||||
}
|
||||
|
||||
if (!$onlycli) {
|
||||
$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');
|
||||
|
||||
$langstrid = 'clievaluationandpredictionsnoadmin';
|
||||
if (is_siteadmin()) {
|
||||
$langstrid = 'clievaluationandpredictions';
|
||||
}
|
||||
$data->infos = array(
|
||||
(object)array('message' => get_string($langstrid, 'tool_analytics', $url->out()),
|
||||
'closebutton' => true)
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Renderer.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2016 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();
|
||||
|
||||
use plugin_renderer_base;
|
||||
use templatable;
|
||||
use renderable;
|
||||
|
||||
/**
|
||||
* Renderer class.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class renderer extends plugin_renderer_base {
|
||||
|
||||
/**
|
||||
* Defer to template.
|
||||
*
|
||||
* @param \tool_analytics\output\models_list $modelslist
|
||||
* @return string HTML
|
||||
*/
|
||||
protected function render_models_list(\tool_analytics\output\models_list $modelslist) {
|
||||
$data = $modelslist->export_for_template($this);
|
||||
return parent::render_from_template('tool_analytics/models_list', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a table.
|
||||
*
|
||||
* @param \table_sql $table
|
||||
* @return string HTML
|
||||
*/
|
||||
public function render_table(\table_sql $table) {
|
||||
|
||||
ob_start();
|
||||
$table->out(10, true);
|
||||
$output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Web interface evaluate results.
|
||||
*
|
||||
* @param \stdClass[] $results
|
||||
* @param string[] $logs
|
||||
* @return string HTML
|
||||
*/
|
||||
public function render_evaluate_results($results, $logs = array()) {
|
||||
global $OUTPUT;
|
||||
|
||||
$output = '';
|
||||
|
||||
foreach ($results as $timesplittingid => $result) {
|
||||
|
||||
if (!CLI_SCRIPT) {
|
||||
$output .= $OUTPUT->box_start('generalbox m-b-3');
|
||||
}
|
||||
|
||||
// Check that the array key is a string, not all results depend on time splitting methods (e.g. general errors).
|
||||
if (!is_numeric($timesplittingid)) {
|
||||
$timesplitting = \core_analytics\manager::get_time_splitting($timesplittingid);
|
||||
$langstrdata = (object)array('name' => $timesplitting->get_name(), 'id' => $timesplittingid);
|
||||
|
||||
if (CLI_SCRIPT) {
|
||||
$output .= $OUTPUT->heading(get_string('getpredictionsresultscli', 'tool_analytics', $langstrdata), 3);
|
||||
} else {
|
||||
$output .= $OUTPUT->heading(get_string('getpredictionsresults', 'tool_analytics', $langstrdata), 3);
|
||||
}
|
||||
}
|
||||
|
||||
if ($result->status == 0) {
|
||||
$output .= $OUTPUT->notification(get_string('goodmodel', 'tool_analytics'),
|
||||
\core\output\notification::NOTIFY_SUCCESS);
|
||||
} else if ($result->status === \core_analytics\model::NO_DATASET) {
|
||||
$output .= $OUTPUT->notification(get_string('nodatatoevaluate', 'tool_analytics'),
|
||||
\core\output\notification::NOTIFY_WARNING);
|
||||
}
|
||||
|
||||
if (isset($result->score)) {
|
||||
// Score.
|
||||
$output .= $OUTPUT->heading(get_string('accuracy', 'tool_analytics') . ': ' .
|
||||
round(floatval($result->score), 4) * 100 . '%', 4);
|
||||
}
|
||||
|
||||
if (!empty($result->info)) {
|
||||
foreach ($result->info as $message) {
|
||||
$output .= $OUTPUT->notification($message, \core\output\notification::NOTIFY_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
if (!CLI_SCRIPT) {
|
||||
$output .= $OUTPUT->box_end();
|
||||
}
|
||||
}
|
||||
|
||||
// Info logged during evaluation.
|
||||
if (!empty($logs) && debugging()) {
|
||||
$output .= $OUTPUT->heading(get_string('extrainfo', 'tool_analytics'), 3);
|
||||
foreach ($logs as $log) {
|
||||
$output .= $OUTPUT->notification($log, \core\output\notification::NOTIFY_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
if (!CLI_SCRIPT) {
|
||||
$output .= $OUTPUT->single_button(new \moodle_url('/admin/tool/analytics/index.php'), get_string('continue'), 'get');
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Web interface training & prediction results.
|
||||
*
|
||||
* @param \stdClass|false $trainresults
|
||||
* @param string[] $trainlogs
|
||||
* @param \stdClass|false $predictresults
|
||||
* @param string[] $predictlogs
|
||||
* @return string HTML
|
||||
*/
|
||||
public function render_get_predictions_results($trainresults = false, $trainlogs = array(), $predictresults = false, $predictlogs = array()) {
|
||||
global $OUTPUT;
|
||||
|
||||
$output = '';
|
||||
|
||||
if ($trainresults || (!empty($trainlogs) && debugging())) {
|
||||
$output .= $OUTPUT->heading(get_string('trainingresults', 'tool_analytics'), 3);
|
||||
}
|
||||
|
||||
if ($trainresults) {
|
||||
if ($trainresults->status == 0) {
|
||||
$output .= $OUTPUT->notification(get_string('trainingprocessfinished', 'tool_analytics'),
|
||||
\core\output\notification::NOTIFY_SUCCESS);
|
||||
} else if ($trainresults->status === \core_analytics\model::NO_DATASET ||
|
||||
$trainresults->status === \core_analytics\model::NOT_ENOUGH_DATA) {
|
||||
$output .= $OUTPUT->notification(get_string('nodatatotrain', 'tool_analytics'),
|
||||
\core\output\notification::NOTIFY_WARNING);
|
||||
} else {
|
||||
$output .= $OUTPUT->notification(get_string('generalerror', 'tool_analytics', $trainresults->status),
|
||||
\core\output\notification::NOTIFY_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($trainlogs) && debugging()) {
|
||||
$output .= $OUTPUT->heading(get_string('extrainfo', 'tool_analytics'), 4);
|
||||
foreach ($trainlogs as $log) {
|
||||
$output .= $OUTPUT->notification($log, \core\output\notification::NOTIFY_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
if ($predictresults || (!empty($predictlogs) && debugging())) {
|
||||
$output .= $OUTPUT->heading(get_string('predictionresults', 'tool_analytics'), 3, 'main m-t-3');
|
||||
}
|
||||
|
||||
if ($predictresults) {
|
||||
if ($predictresults->status == 0) {
|
||||
$output .= $OUTPUT->notification(get_string('predictionprocessfinished', 'tool_analytics'),
|
||||
\core\output\notification::NOTIFY_SUCCESS);
|
||||
} else if ($predictresults->status === \core_analytics\model::NO_DATASET ||
|
||||
$predictresults->status === \core_analytics\model::NOT_ENOUGH_DATA) {
|
||||
$output .= $OUTPUT->notification(get_string('nodatatopredict', 'tool_analytics'),
|
||||
\core\output\notification::NOTIFY_WARNING);
|
||||
} else {
|
||||
$output .= $OUTPUT->notification(get_string('generalerror', 'tool_analytics', $predictresults->status),
|
||||
\core\output\notification::NOTIFY_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($predictlogs) && debugging()) {
|
||||
$output .= $OUTPUT->heading(get_string('extrainfo', 'tool_analytics'), 4);
|
||||
foreach ($predictlogs as $log) {
|
||||
$output .= $OUTPUT->notification($log, \core\output\notification::NOTIFY_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
if (!CLI_SCRIPT) {
|
||||
$output .= $OUTPUT->single_button(new \moodle_url('/admin/tool/analytics/index.php'), get_string('continue'), 'get');
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer to template.
|
||||
*
|
||||
* @param \tool_analytics\output\invalid_analysables $invalidanalysables
|
||||
* @return string HTML
|
||||
*/
|
||||
protected function render_invalid_analysables(\tool_analytics\output\invalid_analysables $invalidanalysables) {
|
||||
$data = $invalidanalysables->export_for_template($this);
|
||||
return parent::render_from_template('tool_analytics/invalid_analysables', $data);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for tool_analytics.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_analytics\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for tool_analytics implementing null_provider.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -1,71 +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/>.
|
||||
|
||||
/**
|
||||
* Predict system models with new data available.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_analytics\task;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Predict system models with new data available.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class predict_models extends \core\task\scheduled_task {
|
||||
|
||||
/**
|
||||
* get_name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return get_string('predictmodels', 'tool_analytics');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the prediction task.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute() {
|
||||
global $OUTPUT, $PAGE;
|
||||
|
||||
$models = \core_analytics\manager::get_all_models(true, true);
|
||||
if (!$models) {
|
||||
mtrace(get_string('errornoenabledandtrainedmodels', 'tool_analytics'));
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($models as $model) {
|
||||
$result = $model->predict();
|
||||
if ($result) {
|
||||
echo $OUTPUT->heading(get_string('modelresults', 'tool_analytics', $model->get_target()->get_name()));
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_get_predictions_results(false, array(), $result, $model->get_analyser()->get_logs());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,82 +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/>.
|
||||
|
||||
/**
|
||||
* Train system models with new data available.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_analytics\task;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Train system models with new data available.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class train_models extends \core\task\scheduled_task {
|
||||
|
||||
/**
|
||||
* get_name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return get_string('trainmodels', 'tool_analytics');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the prediction task.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute() {
|
||||
global $OUTPUT, $PAGE;
|
||||
|
||||
$models = \core_analytics\manager::get_all_models(true);
|
||||
if (!$models) {
|
||||
mtrace(get_string('errornoenabledmodels', 'tool_analytics'));
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($models as $model) {
|
||||
|
||||
if ($model->is_static()) {
|
||||
// Skip models based on assumptions.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$model->get_time_splitting()) {
|
||||
// Can not train if there is no time splitting method selected.
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $model->train();
|
||||
if ($result) {
|
||||
echo $OUTPUT->heading(get_string('modelresults', 'tool_analytics', $model->get_target()->get_name()));
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_get_predictions_results($result, $model->get_analyser()->get_logs());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +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/>.
|
||||
|
||||
/**
|
||||
* Enables the provided model.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require_once(__DIR__ . '/../../../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
|
||||
$help = "Enables the provided model.
|
||||
|
||||
Options:
|
||||
--modelid Model id
|
||||
--timesplitting Time splitting method full class name
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$ 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,
|
||||
'modelid' => false,
|
||||
'timesplitting' => false
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
)
|
||||
);
|
||||
|
||||
if ($options['help']) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['modelid'] === false || $options['timesplitting'] === false) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// We need admin permissions.
|
||||
\core\session\manager::set_user(get_admin());
|
||||
|
||||
$model = new \core_analytics\model($options['modelid']);
|
||||
|
||||
// Evaluate its suitability to predict accurately.
|
||||
$model->enable($options['timesplitting']);
|
||||
|
||||
cli_heading(get_string('success'));
|
||||
exit(0);
|
||||
@@ -1,131 +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/>.
|
||||
|
||||
/**
|
||||
* Evaluates the provided model.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require_once(__DIR__ . '/../../../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
|
||||
$help = "Evaluates the provided model.
|
||||
|
||||
Options:
|
||||
--modelid Model id
|
||||
--non-interactive Not interactive questions
|
||||
--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)
|
||||
--reuse-prev-analysed Reuse recently analysed courses instead of analysing the whole site. Set it to false while" .
|
||||
" coding indicators. Defaults to true (Optional)" . "
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$ php admin/tool/analytics/cli/evaluate_model.php --modelid=1 --timesplitting='\\core\\analytics\\time_splitting\\quarters' --filter=123,321
|
||||
";
|
||||
|
||||
// Now get cli options.
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
array(
|
||||
'help' => false,
|
||||
'modelid' => false,
|
||||
'timesplitting' => false,
|
||||
'reuse-prev-analysed' => true,
|
||||
'non-interactive' => false,
|
||||
'filter' => false
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
)
|
||||
);
|
||||
|
||||
if ($options['help']) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['modelid'] === false) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Reformat them as an array.
|
||||
if ($options['filter'] !== false) {
|
||||
$options['filter'] = explode(',', $options['filter']);
|
||||
}
|
||||
|
||||
// We need admin permissions.
|
||||
\core\session\manager::set_user(get_admin());
|
||||
|
||||
$model = new \core_analytics\model($options['modelid']);
|
||||
|
||||
mtrace(get_string('analysingsitedata', 'tool_analytics'));
|
||||
|
||||
if ($options['reuse-prev-analysed']) {
|
||||
mtrace(get_string('evaluationinbatches', 'tool_analytics'));
|
||||
}
|
||||
|
||||
$analyseroptions = array(
|
||||
'filter' => $options['filter'],
|
||||
'timesplitting' => $options['timesplitting'],
|
||||
'reuseprevanalysed' => $options['reuse-prev-analysed'],
|
||||
);
|
||||
// Evaluate its suitability to predict accurately.
|
||||
$results = $model->evaluate($analyseroptions);
|
||||
|
||||
$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.
|
||||
foreach ($results as $result) {
|
||||
if ($result->status !== \core_analytics\model::NO_DATASET &&
|
||||
$result->status !== \core_analytics\model::GENERAL_ERROR) {
|
||||
$validdatasets = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($validdatasets) && !$model->is_enabled() && $options['non-interactive'] === false) {
|
||||
|
||||
// Select a dataset, train and enable the model.
|
||||
$input = cli_input(get_string('clienablemodel', 'tool_analytics'));
|
||||
while (!\core_analytics\manager::is_valid($input, '\core_analytics\local\time_splitting\base') && $input !== 'none') {
|
||||
mtrace(get_string('errorunexistingtimesplitting', 'analytics'));
|
||||
$input = cli_input(get_string('clienablemodel', 'tool_analytics'));
|
||||
}
|
||||
|
||||
if ($input === 'none') {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Refresh the instance to prevent unexpected issues.
|
||||
$model = new \core_analytics\model($modelobj);
|
||||
|
||||
// Set the time splitting method file and enable it.
|
||||
$model->enable($input);
|
||||
|
||||
mtrace(get_string('trainandpredictmodel', 'tool_analytics'));
|
||||
|
||||
// Train the model with the selected time splitting method and start predicting.
|
||||
$model->train();
|
||||
$model->predict();
|
||||
}
|
||||
|
||||
exit(0);
|
||||
@@ -1,228 +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/>.
|
||||
|
||||
/**
|
||||
* Guesses course start and end dates based on activity logs.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require_once(__DIR__ . '/../../../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
|
||||
require_once($CFG->dirroot . '/course/lib.php');
|
||||
require_once($CFG->dirroot . '/course/format/weeks/lib.php');
|
||||
|
||||
$help = "Guesses course start and end dates based on activity logs.
|
||||
|
||||
IMPORTANT: Don't use this script if you keep previous academic years users enrolled in courses. Guesses would not be accurate.
|
||||
|
||||
Options:
|
||||
--guessstart Guess the course start date (default to true)
|
||||
--guessend Guess the course end date (default to true)
|
||||
--guessall Guess all start and end dates, even if they are already set (default to false)
|
||||
--update Update the db or just notify the guess (default to false)
|
||||
--filter Analyser dependant. e.g. A courseid would evaluate the model using a single course (Optional)
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$ php admin/tool/analytics/cli/guess_course_start_and_end_dates.php --update=1 --filter=123,321
|
||||
";
|
||||
|
||||
// Now get cli options.
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
array(
|
||||
'help' => false,
|
||||
'guessstart' => true,
|
||||
'guessend' => true,
|
||||
'guessall' => false,
|
||||
'update' => false,
|
||||
'filter' => false
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
)
|
||||
);
|
||||
|
||||
if ($options['help']) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['guessstart'] === false && $options['guessend'] === false && $options['guessall'] === false) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Reformat them as an array.
|
||||
if ($options['filter'] !== false) {
|
||||
$options['filter'] = explode(',', clean_param($options['filter'], PARAM_SEQUENCE));
|
||||
}
|
||||
|
||||
// We need admin permissions.
|
||||
\core\session\manager::set_user(get_admin());
|
||||
|
||||
$conditions = array('id != 1');
|
||||
if (!$options['guessall']) {
|
||||
if ($options['guessstart']) {
|
||||
$conditions[] = '(startdate is null or startdate = 0)';
|
||||
}
|
||||
if ($options['guessend']) {
|
||||
$conditions[] = '(enddate is null or enddate = 0)';
|
||||
}
|
||||
}
|
||||
|
||||
$coursessql = '';
|
||||
$params = null;
|
||||
if ($options['filter']) {
|
||||
list($coursessql, $params) = $DB->get_in_or_equal($options['filter'], SQL_PARAMS_NAMED);
|
||||
$conditions[] = 'id ' . $coursessql;
|
||||
}
|
||||
|
||||
$courses = $DB->get_recordset_select('course', implode(' AND ', $conditions), $params, 'sortorder ASC');
|
||||
foreach ($courses as $course) {
|
||||
tool_analytics_calculate_course_dates($course, $options);
|
||||
}
|
||||
$courses->close();
|
||||
|
||||
|
||||
/**
|
||||
* tool_analytics_calculate_course_dates
|
||||
*
|
||||
* @param stdClass $course
|
||||
* @param array $options CLI options
|
||||
* @return void
|
||||
*/
|
||||
function tool_analytics_calculate_course_dates($course, $options) {
|
||||
global $DB, $OUTPUT;
|
||||
|
||||
$courseman = new \core_analytics\course($course);
|
||||
|
||||
$notification = $course->shortname . ' (id = ' . $course->id . '): ';
|
||||
|
||||
$originalenddate = null;
|
||||
$guessedstartdate = null;
|
||||
$guessedenddate = null;
|
||||
$samestartdate = null;
|
||||
$lowerenddate = null;
|
||||
|
||||
if ($options['guessstart'] || $options['guessall']) {
|
||||
|
||||
$originalstartdate = $course->startdate;
|
||||
|
||||
$guessedstartdate = $courseman->guess_start();
|
||||
$samestartdate = ($guessedstartdate == $originalstartdate);
|
||||
$lowerenddate = ($course->enddate && ($course->enddate < $guessedstartdate));
|
||||
|
||||
if ($samestartdate) {
|
||||
if (!$guessedstartdate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('cantguessstartdate', 'tool_analytics');
|
||||
} else {
|
||||
// No need to update.
|
||||
$notification .= PHP_EOL . ' ' . get_string('samestartdate', 'tool_analytics') . ': ' . userdate($guessedstartdate);
|
||||
}
|
||||
} else if (!$guessedstartdate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('cantguessstartdate', 'tool_analytics');
|
||||
} else if ($lowerenddate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('cantguessstartdate', 'tool_analytics') . ': ' .
|
||||
get_string('enddatebeforestartdate', 'error') . ' - ' . userdate($guessedstartdate);
|
||||
} else {
|
||||
// Update it to something we guess.
|
||||
|
||||
// We set it to $course even if we don't update because may be needed to guess the end one.
|
||||
$course->startdate = $guessedstartdate;
|
||||
$notification .= PHP_EOL . ' ' . get_string('startdate') . ': ' . userdate($guessedstartdate);
|
||||
|
||||
// Two different course updates because week's end date may be recalculated after setting the start date.
|
||||
if ($options['update']) {
|
||||
update_course($course);
|
||||
|
||||
// Refresh course data as end date may have been updated.
|
||||
$course = $DB->get_record('course', array('id' => $course->id));
|
||||
$courseman = new \core_analytics\course($course);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($options['guessend'] || $options['guessall']) {
|
||||
|
||||
if (!empty($lowerenddate) && !empty($guessedstartdate)) {
|
||||
$course->startdate = $guessedstartdate;
|
||||
}
|
||||
|
||||
$originalenddate = $course->enddate;
|
||||
|
||||
$format = course_get_format($course);
|
||||
$formatoptions = $format->get_format_options();
|
||||
|
||||
// Change this for a course formats API level call in MDL-60702.
|
||||
if (method_exists($format, 'update_end_date') && $formatoptions['automaticenddate']) {
|
||||
// Special treatment for weeks-based formats with automatic end date.
|
||||
|
||||
if ($options['update']) {
|
||||
$format::update_end_date($course->id);
|
||||
$course->enddate = $DB->get_field('course', 'enddate', array('id' => $course->id));
|
||||
$notification .= PHP_EOL . ' ' . get_string('weeksenddateautomaticallyset', 'tool_analytics') . ': ' .
|
||||
userdate($course->enddate);
|
||||
} else {
|
||||
// We can't provide more info without actually updating it in db.
|
||||
$notification .= PHP_EOL . ' ' . get_string('weeksenddatedefault', 'tool_analytics');
|
||||
}
|
||||
} else {
|
||||
$guessedenddate = $courseman->guess_end();
|
||||
|
||||
if ($guessedenddate == $originalenddate) {
|
||||
if (!$guessedenddate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('cantguessenddate', 'tool_analytics');
|
||||
} else {
|
||||
// No need to update.
|
||||
$notification .= PHP_EOL . ' ' . get_string('sameenddate', 'tool_analytics') . ': ' . userdate($guessedenddate);
|
||||
}
|
||||
} else if (!$guessedenddate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('cantguessenddate', 'tool_analytics');
|
||||
} else {
|
||||
// Update it to something we guess.
|
||||
|
||||
$course->enddate = $guessedenddate;
|
||||
|
||||
$updateit = false;
|
||||
if ($course->enddate < $course->startdate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('errorendbeforestart', 'analytics', userdate($course->enddate));
|
||||
} else if ($course->startdate + (YEARSECS + (WEEKSECS * 4)) > $course->enddate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('coursetoolong', 'analytics');
|
||||
} else {
|
||||
$notification .= PHP_EOL . ' ' . get_string('enddate') . ': ' . userdate($course->enddate);
|
||||
$updateit = true;
|
||||
}
|
||||
|
||||
if ($options['update'] && $updateit) {
|
||||
update_course($course);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mtrace($notification);
|
||||
}
|
||||
|
||||
mtrace(get_string('success'));
|
||||
|
||||
exit(0);
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Prediction models tool frontend.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
admin_externalpage_setup('analyticmodels', '', null, '', array('pagelayout' => 'report'));
|
||||
|
||||
$models = \core_analytics\manager::get_all_models();
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$templatable = new \tool_analytics\output\models_list($models);
|
||||
echo $PAGE->get_renderer('tool_analytics')->render($templatable);
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Strings for tool_analytics.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['accuracy'] = 'Accuracy';
|
||||
$string['allpredictions'] = 'All predictions';
|
||||
$string['analysingsitedata'] = 'Analysing the site';
|
||||
$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';
|
||||
$string['cantguessenddate'] = 'Can\'t guess the end date';
|
||||
$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 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['editmodel'] = 'Edit "{$a}" model';
|
||||
$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 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';
|
||||
$string['errornostaticedit'] = 'Models based on assumptions cannot be edited.';
|
||||
$string['errornostaticevaluated'] = 'Models based on assumptions cannot be evaluated. They are always 100% correct according to how they were defined.';
|
||||
$string['errornostaticlog'] = 'Models based on assumptions cannot be evaluated because there is no performance log.';
|
||||
$string['erroronlycli'] = 'Execution only allowed via command line';
|
||||
$string['errortrainingdataexport'] = 'The model training data could not be exported';
|
||||
$string['evaluate'] = 'Evaluate';
|
||||
$string['evaluatemodel'] = 'Evaluate model';
|
||||
$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['export'] = 'Export';
|
||||
$string['exporttrainingdata'] = 'Export training data';
|
||||
$string['getpredictionsresultscli'] = 'Results using {$a->name} (id: {$a->id}) course duration splitting';
|
||||
$string['getpredictionsresults'] = 'Results using {$a->name} course duration splitting';
|
||||
$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['indicators'] = 'Indicators';
|
||||
$string['info'] = 'Info';
|
||||
$string['insights'] = 'Insights';
|
||||
$string['invalidanalysables'] = 'Invalid site elements';
|
||||
$string['invalidanalysablesinfo'] = 'This pages lists this site analysable elements that can not be used by this prediction model. The listed elements can not be used neither to train the prediction model nor the prediction model can get predictions for them.';
|
||||
$string['invalidanalysablestable'] = 'Invalid site analysable elements table';
|
||||
$string['invalidprediction'] = 'Invalid to get predictions';
|
||||
$string['invalidtraining'] = 'Invalid to train the model';
|
||||
$string['loginfo'] = 'Log extra info';
|
||||
$string['modelinvalidanalysables'] = 'Invalid analysable elements for "{$a}" model';
|
||||
$string['modelresults'] = '{$a} results';
|
||||
$string['modeltimesplitting'] = 'Time splitting';
|
||||
$string['nextpage'] = 'Next page';
|
||||
$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['notdefined'] = 'Not yet defined';
|
||||
$string['pluginname'] = 'Analytic models';
|
||||
$string['predictionresults'] = 'Prediction results';
|
||||
$string['predictmodels'] = 'Predict models';
|
||||
$string['predictorresultsin'] = 'Predictor logged information in {$a} directory';
|
||||
$string['predictionprocessfinished'] = 'Prediction process finished';
|
||||
$string['previouspage'] = 'Previous page';
|
||||
$string['samestartdate'] = 'Current start date is good';
|
||||
$string['sameenddate'] = 'Current end date is good';
|
||||
$string['target'] = 'Target';
|
||||
$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';
|
||||
$string['trainmodels'] = 'Train models';
|
||||
$string['viewlog'] = '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.';
|
||||
@@ -1,241 +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/>.
|
||||
|
||||
/**
|
||||
* Model-related actions.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
|
||||
$id = required_param('id', PARAM_INT);
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
|
||||
$context = context_system::instance();
|
||||
|
||||
require_login();
|
||||
|
||||
$model = new \core_analytics\model($id);
|
||||
\core_analytics\manager::check_can_manage_models();
|
||||
|
||||
$params = array('id' => $id, 'action' => $action);
|
||||
$url = new \moodle_url('/admin/tool/analytics/model.php', $params);
|
||||
|
||||
switch ($action) {
|
||||
|
||||
case 'edit':
|
||||
$title = get_string('editmodel', 'tool_analytics', $model->get_target()->get_name());
|
||||
break;
|
||||
case 'evaluate':
|
||||
$title = get_string('evaluatemodel', 'tool_analytics');
|
||||
break;
|
||||
case 'getpredictions':
|
||||
$title = get_string('getpredictions', 'tool_analytics');
|
||||
break;
|
||||
case 'log':
|
||||
$title = get_string('viewlog', 'tool_analytics');
|
||||
break;
|
||||
case 'enable':
|
||||
$title = get_string('enable');
|
||||
break;
|
||||
case 'disable':
|
||||
$title = get_string('disable');
|
||||
break;
|
||||
case 'export':
|
||||
$title = get_string('export', 'tool_analytics');
|
||||
break;
|
||||
case 'clear':
|
||||
$title = get_string('clearpredictions', 'tool_analytics');
|
||||
break;
|
||||
case 'invalidanalysables':
|
||||
$title = get_string('invalidanalysables', 'tool_analytics');
|
||||
break;
|
||||
default:
|
||||
throw new moodle_exception('errorunknownaction', 'analytics');
|
||||
}
|
||||
|
||||
$PAGE->set_context($context);
|
||||
$PAGE->set_url($url);
|
||||
$PAGE->set_pagelayout('report');
|
||||
$PAGE->set_title($title);
|
||||
$PAGE->set_heading($title);
|
||||
|
||||
$onlycli = get_config('analytics', 'onlycli');
|
||||
if ($onlycli === false) {
|
||||
// Default applied if no config found.
|
||||
$onlycli = 1;
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
|
||||
case 'enable':
|
||||
confirm_sesskey();
|
||||
|
||||
$model->enable();
|
||||
redirect(new \moodle_url('/admin/tool/analytics/index.php'));
|
||||
break;
|
||||
|
||||
case 'disable':
|
||||
confirm_sesskey();
|
||||
|
||||
$model->update(0, false, false);
|
||||
redirect(new \moodle_url('/admin/tool/analytics/index.php'));
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
confirm_sesskey();
|
||||
|
||||
if ($model->is_static()) {
|
||||
echo $OUTPUT->header();
|
||||
throw new moodle_exception('errornostaticedit', 'tool_analytics');
|
||||
}
|
||||
|
||||
$customdata = array(
|
||||
'id' => $model->get_id(),
|
||||
'model' => $model,
|
||||
'indicators' => $model->get_potential_indicators(),
|
||||
'timesplittings' => \core_analytics\manager::get_enabled_time_splitting_methods()
|
||||
);
|
||||
$mform = new \tool_analytics\output\form\edit_model(null, $customdata);
|
||||
|
||||
if ($mform->is_cancelled()) {
|
||||
redirect(new \moodle_url('/admin/tool/analytics/index.php'));
|
||||
|
||||
} else if ($data = $mform->get_data()) {
|
||||
|
||||
// Converting option names to class names.
|
||||
$indicators = array();
|
||||
foreach ($data->indicators as $indicator) {
|
||||
$indicatorclass = \tool_analytics\output\helper::option_to_class($indicator);
|
||||
$indicators[] = \core_analytics\manager::get_indicator($indicatorclass);
|
||||
}
|
||||
$timesplitting = \tool_analytics\output\helper::option_to_class($data->timesplitting);
|
||||
$model->update($data->enabled, $indicators, $timesplitting);
|
||||
redirect(new \moodle_url('/admin/tool/analytics/index.php'));
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$modelobj = $model->get_model_obj();
|
||||
|
||||
$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);
|
||||
$mform->set_data($modelobj);
|
||||
$mform->display();
|
||||
break;
|
||||
|
||||
case 'evaluate':
|
||||
confirm_sesskey();
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
if ($model->is_static()) {
|
||||
throw new moodle_exception('errornostaticevaluate', 'tool_analytics');
|
||||
}
|
||||
|
||||
if ($onlycli) {
|
||||
throw new moodle_exception('erroronlycli', 'tool_analytics');
|
||||
}
|
||||
|
||||
// Web interface is used by people who can not use CLI nor code stuff, always use
|
||||
// cached stuff as they will change the model through the web interface as well
|
||||
// which invalidates the previously analysed stuff.
|
||||
$results = $model->evaluate(array('reuseprevanalysed' => true));
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_evaluate_results($results, $model->get_analyser()->get_logs());
|
||||
break;
|
||||
|
||||
case 'getpredictions':
|
||||
confirm_sesskey();
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
if ($onlycli) {
|
||||
throw new moodle_exception('erroronlycli', 'tool_analytics');
|
||||
}
|
||||
|
||||
$trainresults = $model->train();
|
||||
$trainlogs = $model->get_analyser()->get_logs();
|
||||
|
||||
// Looks dumb to get a new instance but better be conservative.
|
||||
$model = new \core_analytics\model($model->get_model_obj());
|
||||
if ($model->is_trained()) {
|
||||
$predictresults = $model->predict();
|
||||
$predictlogs = $model->get_analyser()->get_logs();
|
||||
} else {
|
||||
$predictresults = false;
|
||||
$predictlogs = array();
|
||||
}
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render_get_predictions_results($trainresults, $trainlogs, $predictresults, $predictlogs);
|
||||
break;
|
||||
|
||||
case 'log':
|
||||
echo $OUTPUT->header();
|
||||
|
||||
if ($model->is_static()) {
|
||||
throw new moodle_exception('errornostaticlog', 'tool_analytics');
|
||||
}
|
||||
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
$modellogstable = new \tool_analytics\output\model_logs('model-' . $model->get_id(), $model);
|
||||
echo $renderer->render_table($modellogstable);
|
||||
break;
|
||||
|
||||
case 'export':
|
||||
|
||||
if ($model->is_static() || !$model->is_trained()) {
|
||||
throw new moodle_exception('errornoexport', 'tool_analytics');
|
||||
}
|
||||
|
||||
$file = $model->get_training_data();
|
||||
if (!$file) {
|
||||
redirect(new \moodle_url('/admin/tool/analytics/index.php'), get_string('errortrainingdataexport', 'tool_analytics'),
|
||||
null, \core\output\notification::NOTIFY_ERROR);
|
||||
}
|
||||
|
||||
$filename = 'training-data.' . $model->get_id() . '.' . time() . '.csv';
|
||||
send_file($file, $filename, null, 0, false, true);
|
||||
break;
|
||||
|
||||
case 'clear':
|
||||
confirm_sesskey();
|
||||
|
||||
$model->clear();
|
||||
redirect(new \moodle_url('/admin/tool/analytics/index.php'));
|
||||
break;
|
||||
|
||||
case 'invalidanalysables':
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
// No option in the UI to change this, only for url hackers ;).
|
||||
$perpage = optional_param('perpage', 10, PARAM_INT);
|
||||
|
||||
$renderable = new \tool_analytics\output\invalid_analysables($model, $page, $perpage);
|
||||
$renderer = $PAGE->get_renderer('tool_analytics');
|
||||
echo $renderer->render($renderable);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Adds settings links to admin tree.
|
||||
*
|
||||
* @package tool_analytics
|
||||
* @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$ADMIN->add('analytics', new admin_externalpage('analyticmodels', get_string('analyticmodels', 'tool_analytics'),
|
||||
"$CFG->wwwroot/$CFG->admin/tool/analytics/index.php", 'moodle/analytics:managemodels'));
|
||||
@@ -1,78 +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/invalid_analysables
|
||||
|
||||
Template for invalid analysables.
|
||||
|
||||
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",
|
||||
"analysables": [
|
||||
{
|
||||
"url": "<a href=\"#\">Maths</a>",
|
||||
"validtraining": "Ongoing course",
|
||||
"validprediction": "Not enough students activity"
|
||||
}, {
|
||||
"url": "<a href=\"#\">Psichology</a>",
|
||||
"validtraining": "No students",
|
||||
"validprediction": "No students"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
|
||||
<div class="box">
|
||||
<h3>{{#str}}modelinvalidanalysables, tool_analytics, {{modelname}}{{/str}}</h3>
|
||||
<div>{{#str}}invalidanalysablesinfo, tool_analytics{{/str}}</div>
|
||||
<div class="m-t-2 m-b-1">
|
||||
<span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
|
||||
<span>{{#next}}{{> core/single_button}}{{/next}}</span>
|
||||
</div>
|
||||
<table class="generaltable fullwidth">
|
||||
<caption class="accesshide">{{#str}}invalidanalysablestable, tool_analytics{{/str}}</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{#str}}name{{/str}}</th>
|
||||
<th scope="col">{{#str}}invalidtraining, tool_analytics{{/str}}</th>
|
||||
<th scope="col">{{#str}}invalidprediction, tool_analytics{{/str}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#analysables}}
|
||||
<tr>
|
||||
<td>{{{url}}}</td>
|
||||
<td>{{validtraining}}</td>
|
||||
<td>{{validprediction}}</td>
|
||||
</tr>
|
||||
{{/analysables}}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="m-t-1 m-b-2">
|
||||
<span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
|
||||
<span>{{#next}}{{> core/single_button}}{{/next}}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,186 +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/models_list
|
||||
|
||||
Template for models list.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"models": [
|
||||
{
|
||||
"target": "Prevent devs at risk",
|
||||
"targethelp": [
|
||||
{
|
||||
"title": "Help with something",
|
||||
"url": "http://example.org/help",
|
||||
"linktext": "",
|
||||
"icon":{
|
||||
"extraclasses": "iconhelp",
|
||||
"attributes": [
|
||||
{"name": "src", "value": "../../../pix/help.svg"},
|
||||
{"name": "alt", "value": "Help icon"}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"enabled": 1,
|
||||
"indicators": [{
|
||||
"name": "Indicator 1",
|
||||
"help": [{
|
||||
"title": "Help with something",
|
||||
"url": "http://example.org/help",
|
||||
"linktext": "",
|
||||
"icon":{
|
||||
"extraclasses": "iconhelp",
|
||||
"attributes": [
|
||||
{"name": "src", "value": "../../../pix/help.svg"},
|
||||
{"name": "alt", "value": "Help icon"}
|
||||
]
|
||||
}
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Indicator 2",
|
||||
"help": [{
|
||||
"title": "Help with something",
|
||||
"url": "http://example.org/help",
|
||||
"linktext": "",
|
||||
"icon":{
|
||||
"extraclasses": "iconhelp",
|
||||
"attributes": [
|
||||
{"name": "src", "value": "../../../pix/help.svg"},
|
||||
{"name": "alt", "value": "Help icon"}
|
||||
]
|
||||
}
|
||||
}]
|
||||
}],
|
||||
"timesplitting": "Quarters",
|
||||
"timesplittinghelp": [
|
||||
{
|
||||
"title": "Help with something",
|
||||
"url": "http://example.org/help",
|
||||
"linktext": "",
|
||||
"icon":{
|
||||
"extraclasses": "iconhelp",
|
||||
"attributes": [
|
||||
{"name": "src", "value": "../../../pix/help.svg"},
|
||||
{"name": "alt", "value": "Help icon"}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"noinsights": "No insights available yet"
|
||||
}
|
||||
],
|
||||
"warnings": {
|
||||
"message": "Hey, this is a warning"
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
{{#warnings}}
|
||||
{{> core/notification_warning}}
|
||||
{{/warnings}}
|
||||
{{#infos}}
|
||||
{{> core/notification_info}}
|
||||
{{/infos}}
|
||||
|
||||
<div class="box">
|
||||
<table class="generaltable fullwidth">
|
||||
<caption>{{#str}}analyticmodels, tool_analytics{{/str}}</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{#str}}target, tool_analytics{{/str}}</th>
|
||||
<th scope="col">{{#str}}enabled, tool_analytics{{/str}}</th>
|
||||
<th scope="col">{{#str}}indicators, tool_analytics{{/str}}</th>
|
||||
<th scope="col">{{#str}}modeltimesplitting, tool_analytics{{/str}}</th>
|
||||
<th scope="col">{{#str}}insights, tool_analytics{{/str}}</th>
|
||||
<th scope="col">{{#str}}actions{{/str}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#models}}
|
||||
<tr>
|
||||
<td>
|
||||
<span class="target-name">{{target}}</span>
|
||||
{{#targethelp}}
|
||||
{{>core/help_icon}}
|
||||
{{/targethelp}}
|
||||
</td>
|
||||
<td>
|
||||
{{#enabled}}
|
||||
{{#pix}}i/checked, core, {{#str}}yes{{/str}}{{/pix}}
|
||||
{{/enabled}}
|
||||
{{^enabled}}
|
||||
{{#str}}no{{/str}}
|
||||
{{/enabled}}
|
||||
</td>
|
||||
<td>
|
||||
<ul>
|
||||
{{#indicators}}
|
||||
<li>
|
||||
{{name}}
|
||||
{{#help}}
|
||||
{{>core/help_icon}}
|
||||
{{/help}}
|
||||
</li>
|
||||
{{/indicators}}
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
{{#timesplitting}}
|
||||
{{timesplitting}}
|
||||
{{#timesplittinghelp}}
|
||||
{{>core/help_icon}}
|
||||
{{/timesplittinghelp}}
|
||||
{{/timesplitting}}
|
||||
{{^timesplitting}}
|
||||
{{#str}}notdefined, tool_analytics{{/str}}
|
||||
{{#timesplittinghelp}}
|
||||
{{>core/help_icon}}
|
||||
{{/timesplittinghelp}}
|
||||
{{/timesplitting}}
|
||||
</td>
|
||||
<td>
|
||||
{{! models_list renderer is responsible of sending one or the other}}
|
||||
{{#insights}}
|
||||
{{> core/single_select }}
|
||||
{{/insights}}
|
||||
{{#noinsights}}
|
||||
{{.}}
|
||||
{{/noinsights}}
|
||||
</td>
|
||||
<td>
|
||||
{{#actions}}
|
||||
{{> core/action_menu}}
|
||||
{{/actions}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/models}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -1,73 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for tool_assignmentupgrade.
|
||||
*
|
||||
* @package tool_assignmentupgrade
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_assignmentupgrade\privacy;
|
||||
|
||||
use core_privacy\local\metadata\collection;
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for tool_assignmentupgrade implementing metadata, plugin, and user_preference providers.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements
|
||||
\core_privacy\local\metadata\provider,
|
||||
\core_privacy\local\request\user_preference_provider {
|
||||
|
||||
/**
|
||||
* Returns meta data about this system.
|
||||
*
|
||||
* @param collection $collection The initialised collection to add items to.
|
||||
* @return collection A listing of user data stored through this system.
|
||||
*/
|
||||
public static function get_metadata(collection $collection) : collection {
|
||||
$collection->add_user_preference(
|
||||
'tool_assignmentupgrade_perpage',
|
||||
'privacy:metadata:preference:perpage'
|
||||
);
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all user preferences for the plugin.
|
||||
*
|
||||
* @param int $userid The userid of the user whose data is to be exported.
|
||||
*/
|
||||
public static function export_user_preferences(int $userid) {
|
||||
$perpage = get_user_preferences('tool_assignmentupgrade_perpage', null, $userid);
|
||||
if ($perpage !== null) {
|
||||
writer::export_user_preference(
|
||||
'tool_assignmentupgrade',
|
||||
'perpage',
|
||||
$perpage,
|
||||
get_string('privacy:metadata:preference:perpage', 'tool_assignmentupgrade')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -58,4 +58,3 @@ $string['upgradeallconfirm'] = 'Upgrade all assignments?';
|
||||
$string['upgradeprogress'] = 'Upgrade assignment {$a->current} of {$a->total}';
|
||||
$string['upgradesingle'] = 'Upgrade single assignment';
|
||||
$string['viewcourse'] = 'View the course with the converted assignment';
|
||||
$string['privacy:metadata:preference:perpage'] = 'The assignment upgrade records per page preference set for the user.';
|
||||
|
||||
@@ -1,75 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy tests for tool_assignmentupgrade.
|
||||
*
|
||||
* @package tool_assignmentupgrade
|
||||
* @category test
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use \core_privacy\tests\provider_testcase;
|
||||
use \core_privacy\local\request\writer;
|
||||
use \tool_assignmentupgrade\privacy\provider;
|
||||
|
||||
/**
|
||||
* Unit tests for tool_assignmentupgrade/classes/privacy/policy
|
||||
*
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_assignmentupgrade_privacy_testcase extends provider_testcase {
|
||||
|
||||
/**
|
||||
* Overriding setUp() function to always reset after tests.
|
||||
*/
|
||||
public function setUp() {
|
||||
$this->resetAfterTest(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::test_export_user_preferences().
|
||||
*/
|
||||
public function test_export_user_preferences() {
|
||||
// Test setup.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
// Add a user home page preference for the User.
|
||||
set_user_preference('tool_assignmentupgrade_perpage', '100', $user);
|
||||
|
||||
// Test the user preference exists.
|
||||
$params = [
|
||||
'userid' => $user->id,
|
||||
'name' => 'tool_assignmentupgrade_perpage'
|
||||
];
|
||||
|
||||
// Test the user preferences export contains 1 user preference record for the User.
|
||||
provider::export_user_preferences($user->id);
|
||||
$contextuser = context_user::instance($user->id);
|
||||
$writer = writer::with_context($contextuser);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
|
||||
$exportedpreferences = $writer->get_user_preferences('tool_assignmentupgrade');
|
||||
$this->assertCount(1, (array) $exportedpreferences);
|
||||
$this->assertEquals('100', $exportedpreferences->perpage->value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->component = 'tool_assignmentupgrade';
|
||||
$plugin->dependencies = array('mod_assign' => 2017110800);
|
||||
$plugin->dependencies = array('mod_assign' => 2017050500);
|
||||
|
||||
@@ -1,46 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for tool_availabilityconditions.
|
||||
*
|
||||
* @package tool_availabilityconditions
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_availabilityconditions\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for tool_availabilityconditions implementing null_provider.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -24,4 +24,3 @@
|
||||
|
||||
$string['manageplugins'] = 'Manage restrictions';
|
||||
$string['pluginname'] = 'Availability condition management';
|
||||
$string['privacy:metadata'] = 'The Availability condition management plugin does not store any personal data.';
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->component = 'tool_availabilityconditions';
|
||||
|
||||
@@ -1,46 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for tool_behat.
|
||||
*
|
||||
* @package tool_behat
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_behat\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for tool_behat implementing null_provider.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -109,17 +109,6 @@ require_once(__DIR__ . '/../../../../lib/behat/lib.php');
|
||||
require_once(__DIR__ . '/../../../../lib/behat/classes/behat_command.php');
|
||||
require_once(__DIR__ . '/../../../../lib/behat/classes/behat_config_manager.php');
|
||||
|
||||
// Remove error handling overrides done in config.php. This is consistent with admin/tool/behat/cli/util_single_run.php.
|
||||
$CFG->debug = (E_ALL | E_STRICT);
|
||||
$CFG->debugdisplay = 1;
|
||||
error_reporting($CFG->debug);
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('log_errors', '1');
|
||||
|
||||
// Import the necessary libraries.
|
||||
require_once($CFG->libdir . '/setuplib.php');
|
||||
require_once($CFG->libdir . '/behat/classes/util.php');
|
||||
|
||||
// For drop option check if parallel site.
|
||||
if ((empty($options['parallel'])) && ($options['drop']) || $options['updatesteps']) {
|
||||
$options['parallel'] = behat_config_manager::get_behat_run_config_value('parallel');
|
||||
@@ -409,7 +398,7 @@ function print_combined_install_output($processes) {
|
||||
// Show process name in first row.
|
||||
foreach ($processes as $name => $process) {
|
||||
// If we don't have enough space to show full run name then show runX.
|
||||
if ($lengthofprocessline < strlen($name) + 2) {
|
||||
if ($lengthofprocessline < strlen($name + 2)) {
|
||||
$name = substr($name, -5);
|
||||
}
|
||||
// One extra padding as we are adding | separator for rest of the data.
|
||||
|
||||
@@ -23,31 +23,30 @@
|
||||
*/
|
||||
|
||||
$string['aim'] = 'This administration tool helps developers and test writers to create .feature files describing Moodle\'s functionalities and run them automatically. Step definitions available for use in .feature files are listed below.';
|
||||
$string['allavailablesteps'] = 'All available step definitions';
|
||||
$string['allavailablesteps'] = 'All the available steps definitions';
|
||||
$string['errorbehatcommand'] = 'Error running behat CLI command. Try running "{$a} --help" manually from CLI to find out more about the problem.';
|
||||
$string['errorcomposer'] = 'Composer dependencies are not installed.';
|
||||
$string['errordataroot'] = '$CFG->behat_dataroot is not set or is invalid.';
|
||||
$string['errorsetconfig'] = '$CFG->behat_dataroot, $CFG->behat_prefix and $CFG->behat_wwwroot need to be set in config.php.';
|
||||
$string['erroruniqueconfig'] = '$CFG->behat_dataroot, $CFG->behat_prefix and $CFG->behat_wwwroot values need to be different than $CFG->dataroot, $CFG->prefix, $CFG->wwwroot, $CFG->phpunit_dataroot and $CFG->phpunit_prefix values.';
|
||||
$string['fieldvalueargument'] = 'Field value arguments';
|
||||
$string['fieldvalueargument_help'] = 'This argument should be completed by a field value. There are many field types, including simple ones like checkboxes, selects or textareas, or complex ones like date selectors. See the dev documentation <a href="http://docs.moodle.org/dev/Acceptance_testing" target="_blank">Acceptance_testing</a> for details of expected field values.';
|
||||
$string['fieldvalueargument_help'] = 'This argument should be completed by a field value, there are many field types, simple ones like checkboxes, selects or textareas or complex ones like date selectors. You can check <a href="http://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps" target="_blank">Field values</a> to see the expected field value depending on the field type you provide.';
|
||||
$string['giveninfo'] = 'Given. Processes to set up the environment';
|
||||
$string['infoheading'] = 'Info';
|
||||
$string['installinfo'] = 'Read {$a} for installation and tests execution info';
|
||||
$string['newstepsinfo'] = 'Read {$a} for info about how to add new step definitions';
|
||||
$string['newstepsinfo'] = 'Read {$a} for info about how to add new steps definitions';
|
||||
$string['newtestsinfo'] = 'Read {$a} for info about how to write new tests';
|
||||
$string['nostepsdefinitions'] = 'There aren\'t any step definitions matching this filter';
|
||||
$string['nostepsdefinitions'] = 'There aren\'t steps definitions matching this filters';
|
||||
$string['pluginname'] = 'Acceptance testing';
|
||||
$string['stepsdefinitionscomponent'] = 'Area';
|
||||
$string['stepsdefinitionscontains'] = 'Contains';
|
||||
$string['stepsdefinitionsfilters'] = 'Step definitions';
|
||||
$string['stepsdefinitionsfilters'] = 'Steps definitions';
|
||||
$string['stepsdefinitionstype'] = 'Type';
|
||||
$string['theninfo'] = 'Then. Checkings to ensure the outcomes are the expected ones';
|
||||
$string['unknownexceptioninfo'] = 'There was a problem with Selenium or your browser. Please ensure you are using the latest version of Selenium. Error:';
|
||||
$string['viewsteps'] = 'Filter';
|
||||
$string['wheninfo'] = 'When. Action that provokes an event';
|
||||
$string['wheninfo'] = 'When. Actions that provokes an event';
|
||||
$string['wrongbehatsetup'] = 'Something is wrong with the behat setup and so step definitions cannot be listed: <b>{$a->errormsg}</b><br/><br/>Please check:<ul>
|
||||
<li>$CFG->behat_dataroot, $CFG->behat_prefix and $CFG->behat_wwwroot are set in config.php with different values from $CFG->dataroot, $CFG->prefix and $CFG->wwwroot.</li>
|
||||
<li>You ran "{$a->behatinit}" from your Moodle root directory.</li>
|
||||
<li>Dependencies are installed in vendor/ and {$a->behatcommand} file has execution permissions.</li></ul>';
|
||||
$string['privacy:metadata'] = 'The Acceptance testing plugin does not store any personal data.';
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/behat/classes/behat_selectors.php');
|
||||
|
||||
/**
|
||||
* Renderer for behat tool web features
|
||||
*
|
||||
@@ -41,8 +44,6 @@ class tool_behat_renderer extends plugin_renderer_base {
|
||||
* @return string HTML code
|
||||
*/
|
||||
public function render_stepsdefinitions($stepsdefinitions, $form) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/behat/classes/behat_selectors.php');
|
||||
|
||||
$html = $this->generic_info();
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ Feature: Set up contextual data for tests
|
||||
And I should see "Test workshop name"
|
||||
And I follow "Test assignment name"
|
||||
And I should see "Test assignment description"
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "C1"
|
||||
And I follow "Test assignment name with scale"
|
||||
And I follow "Edit settings"
|
||||
And the field "Type" matches value "Scale"
|
||||
@@ -312,6 +312,7 @@ Feature: Set up contextual data for tests
|
||||
| fullname | course | gradecategory |
|
||||
| Grade sub category 2 | C1 | Grade category 1 |
|
||||
When I log in as "admin"
|
||||
And I am on course index
|
||||
And I am on "Course 1" course homepage
|
||||
And I navigate to "View > Grader report" in the course gradebook
|
||||
Then I should see "Grade category 1"
|
||||
|
||||
@@ -11,7 +11,7 @@ Feature: List the system steps definitions
|
||||
|
||||
@javascript
|
||||
Scenario: Accessing the list
|
||||
Then I should see "Step definitions"
|
||||
Then I should see "Steps definitions"
|
||||
And I should not see "There aren't steps definitions matching this filter"
|
||||
|
||||
@javascript
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -1,46 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for tool_capability.
|
||||
*
|
||||
* @package tool_capability
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_capability\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for tool_capability implementing null_provider.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -34,4 +34,3 @@ $string['pluginname'] = 'Capability overview';
|
||||
$string['reportforcapability'] = 'Report for capability \'{$a}\'';
|
||||
$string['reportsettings'] = 'Report settings';
|
||||
$string['roleslabel'] = 'Roles:';
|
||||
$string['privacy:metadata'] = 'The Capability overview plugin does not store any personal data.';
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -167,7 +167,7 @@ class api {
|
||||
$params['roleid'] = $roleid;
|
||||
$params['userid'] = $userid;
|
||||
|
||||
$sql = 'SELECT DISTINCT u.id AS userid, ra.id, ctx.id AS contextid
|
||||
$sql = 'SELECT u.id AS userid, ra.id, ctx.id AS contextid
|
||||
FROM {user} u
|
||||
JOIN {cohort_members} cm ON u.id = cm.userid
|
||||
JOIN {context} ctx ON u.id = ctx.instanceid AND ctx.contextlevel = :usercontext
|
||||
|
||||
@@ -98,7 +98,7 @@ class cohort_role_assignments_table extends table_sql {
|
||||
);
|
||||
$context = context_helper::instance_by_id($data->cohortcontextid);
|
||||
|
||||
$exporter = new \core_cohort\external\cohort_summary_exporter($record, array('context' => $context));
|
||||
$exporter = new \tool_lp\external\cohort_summary_exporter($record, array('context' => $context));
|
||||
$cohort = $exporter->export($OUTPUT);
|
||||
|
||||
$html = $OUTPUT->render_from_template('tool_cohortroles/cohort-in-list', $cohort);
|
||||
|
||||
@@ -1,328 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for tool_cohortroles.
|
||||
*
|
||||
* @package tool_cohortroles
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_cohortroles\privacy;
|
||||
|
||||
use core_privacy\local\metadata\collection;
|
||||
use core_privacy\local\request\approved_contextlist;
|
||||
use core_privacy\local\request\context;
|
||||
use core_privacy\local\request\contextlist;
|
||||
use core_privacy\local\request\transform;
|
||||
use core_privacy\local\request\writer;
|
||||
use core_privacy\local\request\userlist;
|
||||
use \core_privacy\local\request\approved_userlist;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for tool_cohortroles implementing metadata and plugin providers.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements
|
||||
\core_privacy\local\metadata\provider,
|
||||
\core_privacy\local\request\core_userlist_provider,
|
||||
\core_privacy\local\request\plugin\provider {
|
||||
|
||||
/**
|
||||
* Returns meta data about this system.
|
||||
*
|
||||
* @param collection $collection The initialised collection to add items to.
|
||||
* @return collection A listing of user data stored through this system.
|
||||
*/
|
||||
public static function get_metadata(collection $collection) : collection {
|
||||
// The tool_cohortroles plugin utilises the mdl_tool_cohortroles table.
|
||||
$collection->add_database_table(
|
||||
'tool_cohortroles',
|
||||
[
|
||||
'id' => 'privacy:metadata:tool_cohortroles:id',
|
||||
'cohortid' => 'privacy:metadata:tool_cohortroles:cohortid',
|
||||
'roleid' => 'privacy:metadata:tool_cohortroles:roleid',
|
||||
'userid' => 'privacy:metadata:tool_cohortroles:userid',
|
||||
'timecreated' => 'privacy:metadata:tool_cohortroles:timecreated',
|
||||
'timemodified' => 'privacy:metadata:tool_cohortroles:timemodified',
|
||||
'usermodified' => 'privacy:metadata:tool_cohortroles:usermodified'
|
||||
],
|
||||
'privacy:metadata:tool_cohortroles'
|
||||
);
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of contexts that contain user information for the specified user.
|
||||
*
|
||||
* @param int $userid The user to search.
|
||||
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
|
||||
*/
|
||||
public static function get_contexts_for_userid(int $userid) : contextlist {
|
||||
$contextlist = new contextlist();
|
||||
|
||||
// When we process user deletions and expiries, we always delete from the user context.
|
||||
// As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
|
||||
// as roles may change and data may be removed earlier than it should be.
|
||||
|
||||
// Retrieve the context associated with tool_cohortroles records.
|
||||
$sql = "SELECT DISTINCT c.contextid
|
||||
FROM {tool_cohortroles} tc
|
||||
JOIN {cohort} c
|
||||
ON tc.cohortid = c.id
|
||||
JOIN {context} ctx
|
||||
ON ctx.id = c.contextid
|
||||
WHERE tc.userid = :userid
|
||||
AND (ctx.contextlevel = :contextlevel1
|
||||
OR ctx.contextlevel = :contextlevel2)";
|
||||
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
'contextlevel1' => CONTEXT_SYSTEM,
|
||||
'contextlevel2' => CONTEXT_COURSECAT
|
||||
];
|
||||
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
return $contextlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of users within a specific context.
|
||||
*
|
||||
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
|
||||
*/
|
||||
public static function get_users_in_context(userlist $userlist) {
|
||||
$context = $userlist->get_context();
|
||||
|
||||
// When we process user deletions and expiries, we always delete from the user context.
|
||||
// As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
|
||||
// as roles may change and data may be removed earlier than it should be.
|
||||
|
||||
$allowedcontextlevels = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_COURSECAT
|
||||
];
|
||||
|
||||
if (!in_array($context->contextlevel, $allowedcontextlevels)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = "SELECT tc.userid as userid
|
||||
FROM {tool_cohortroles} tc
|
||||
JOIN {cohort} c
|
||||
ON tc.cohortid = c.id
|
||||
WHERE c.contextid = :contextid";
|
||||
|
||||
$params = [
|
||||
'contextid' => $context->id
|
||||
];
|
||||
|
||||
$userlist->add_from_sql('userid', $sql, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts to export information for.
|
||||
*/
|
||||
public static function export_user_data(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
// Remove contexts different from SYSTEM or COURSECAT.
|
||||
$contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
|
||||
if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT) {
|
||||
$carry[] = $context->id;
|
||||
}
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
if (empty($contextids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$userid = $contextlist->get_user()->id;
|
||||
|
||||
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
|
||||
|
||||
// Retrieve the tool_cohortroles records created for the user.
|
||||
$sql = "SELECT cr.id as cohortroleid,
|
||||
c.name as cohortname,
|
||||
c.idnumber as cohortidnumber,
|
||||
c.description as cohortdescription,
|
||||
c.contextid as contextid,
|
||||
r.shortname as roleshortname,
|
||||
cr.userid as userid,
|
||||
cr.timecreated as timecreated,
|
||||
cr.timemodified as timemodified
|
||||
FROM {tool_cohortroles} cr
|
||||
JOIN {cohort} c ON c.id = cr.cohortid
|
||||
JOIN {role} r ON r.id = cr.roleid
|
||||
WHERE cr.userid = :userid
|
||||
AND c.contextid {$contextsql}";
|
||||
|
||||
$params = ['userid' => $userid] + $contextparams;
|
||||
|
||||
$cohortroles = $DB->get_records_sql($sql, $params);
|
||||
|
||||
foreach ($cohortroles as $cohortrole) {
|
||||
// The tool_cohortroles data export is organised in:
|
||||
// {User Context}/Cohort roles management/{cohort name}/{role shortname}/data.json.
|
||||
$subcontext = [
|
||||
get_string('pluginname', 'tool_cohortroles'),
|
||||
$cohortrole->cohortname,
|
||||
$cohortrole->roleshortname
|
||||
];
|
||||
|
||||
$data = (object) [
|
||||
'cohortname' => $cohortrole->cohortname,
|
||||
'cohortidnumber' => $cohortrole->cohortidnumber,
|
||||
'cohortdescription' => $cohortrole->cohortdescription,
|
||||
'roleshortname' => $cohortrole->roleshortname,
|
||||
'userid' => transform::user($cohortrole->userid),
|
||||
'timecreated' => transform::datetime($cohortrole->timecreated),
|
||||
'timemodified' => transform::datetime($cohortrole->timemodified)
|
||||
];
|
||||
|
||||
$context = \context::instance_by_id($cohortrole->contextid);
|
||||
|
||||
writer::with_context($context)->export_data($subcontext, $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data for all users in the specified context.
|
||||
*
|
||||
* @param context $context The specific context to delete data for.
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||
global $DB;
|
||||
|
||||
// When we process user deletions and expiries, we always delete from the user context.
|
||||
// As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
|
||||
// as roles may change and data may be removed earlier than it should be.
|
||||
|
||||
$allowedcontextlevels = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_COURSECAT
|
||||
];
|
||||
|
||||
if (!in_array($context->contextlevel, $allowedcontextlevels)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cohortids = $DB->get_fieldset_select('cohort', 'id', 'contextid = :contextid',
|
||||
['contextid' => $context->id]);
|
||||
|
||||
// Delete the tool_cohortroles records created in the specific context.
|
||||
$DB->delete_records_list('tool_cohortroles', 'cohortid', $cohortids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete multiple users within a single context.
|
||||
*
|
||||
* @param approved_userlist $userlist The approved context and user information to delete information for.
|
||||
*/
|
||||
public static function delete_data_for_users(approved_userlist $userlist) {
|
||||
global $DB;
|
||||
|
||||
// When we process user deletions and expiries, we always delete from the user context.
|
||||
// As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
|
||||
// as roles may change and data may be removed earlier than it should be.
|
||||
|
||||
$userids = $userlist->get_userids();
|
||||
|
||||
if (empty($userids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$context = $userlist->get_context();
|
||||
|
||||
$allowedcontextlevels = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_COURSECAT
|
||||
];
|
||||
|
||||
if (!in_array($context->contextlevel, $allowedcontextlevels)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cohortids = $DB->get_fieldset_select('cohort', 'id', 'contextid = :contextid',
|
||||
['contextid' => $context->id]);
|
||||
|
||||
if (empty($cohortids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
list($cohortsql, $cohortparams) = $DB->get_in_or_equal($cohortids, SQL_PARAMS_NAMED);
|
||||
list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
|
||||
|
||||
$params = $cohortparams + $userparams;
|
||||
$select = "cohortid {$cohortsql} AND userid {$usersql}";
|
||||
|
||||
// Delete the tool_cohortroles records created in the specific context for an approved list of users.
|
||||
$DB->delete_records_select('tool_cohortroles', $select, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
|
||||
*/
|
||||
public static function delete_data_for_user(approved_contextlist $contextlist) {
|
||||
global $DB;
|
||||
|
||||
// When we process user deletions and expiries, we always delete from the user context.
|
||||
// As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
|
||||
// as roles may change and data may be removed earlier than it should be.
|
||||
|
||||
// Remove contexts different from SYSTEM or COURSECAT.
|
||||
$contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
|
||||
if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT) {
|
||||
$carry[] = $context->id;
|
||||
}
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
if (empty($contextids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$userid = $contextlist->get_user()->id;
|
||||
|
||||
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
|
||||
$selectcontext = "contextid {$contextsql}";
|
||||
// Get the cohorts in the specified contexts.
|
||||
$cohortids = $DB->get_fieldset_select('cohort', 'id', $selectcontext, $contextparams);
|
||||
|
||||
if (empty($cohortids)) {
|
||||
return;
|
||||
}
|
||||
|
||||
list($cohortsql, $cohortparams) = $DB->get_in_or_equal($cohortids, SQL_PARAMS_NAMED);
|
||||
$selectcohort = "cohortid {$cohortsql} AND userid = :userid";
|
||||
$params = ['userid' => $userid] + $cohortparams;
|
||||
|
||||
// Delete the tool_cohortroles records created for the userid.
|
||||
$DB->delete_records_select('tool_cohortroles', $selectcohort, $params);
|
||||
}
|
||||
}
|
||||
@@ -42,11 +42,3 @@ $string['selectrole'] = 'Select role';
|
||||
$string['selectusers'] = 'Select users to assign role';
|
||||
$string['taskname'] = 'Sync cohort role assignments';
|
||||
$string['thisuserroles'] = 'Roles assigned relative to this user';
|
||||
$string['privacy:metadata:tool_cohortroles'] = 'The Cohort roles management plugin stores user cohort role mappings.';
|
||||
$string['privacy:metadata:tool_cohortroles:id'] = 'The ID of the cohort role mapping record';
|
||||
$string['privacy:metadata:tool_cohortroles:cohortid'] = 'The ID of the cohort';
|
||||
$string['privacy:metadata:tool_cohortroles:roleid'] = 'The ID of the role';
|
||||
$string['privacy:metadata:tool_cohortroles:userid'] = 'The ID of the user';
|
||||
$string['privacy:metadata:tool_cohortroles:timecreated'] = 'The time when the cohort role mapping was created';
|
||||
$string['privacy:metadata:tool_cohortroles:timemodified'] = 'The time when the cohort role mapping was modified';
|
||||
$string['privacy:metadata:tool_cohortroles:usermodified'] = 'The ID of the user who last modified the cohort role mapping';
|
||||
|
||||
@@ -1,379 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the tool_cohortroles implementation of the privacy API.
|
||||
*
|
||||
* @package tool_cohortroles
|
||||
* @category test
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
global $CFG;
|
||||
|
||||
use \core_privacy\local\request\writer;
|
||||
use \core_privacy\local\request\approved_contextlist;
|
||||
use \tool_cohortroles\api;
|
||||
use \tool_cohortroles\privacy\provider;
|
||||
use core_privacy\local\request\approved_userlist;
|
||||
|
||||
/**
|
||||
* Unit tests for the tool_cohortroles implementation of the privacy API.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_cohortroles_privacy_testcase extends \core_privacy\tests\provider_testcase {
|
||||
|
||||
/**
|
||||
* Overriding setUp() function to always reset after tests.
|
||||
*/
|
||||
public function setUp() {
|
||||
$this->resetAfterTest(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::get_contexts_for_userid().
|
||||
*/
|
||||
public function test_get_contexts_for_userid() {
|
||||
global $DB;
|
||||
|
||||
// Test setup.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create course category.
|
||||
$coursecategory = $this->getDataGenerator()->create_category();
|
||||
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
|
||||
$systemctx = context_system::instance();
|
||||
// Create course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursectx = \context_course::instance($course->id);
|
||||
|
||||
$this->setup_test_scenario_data($user->id, $systemctx, 1);
|
||||
$this->setup_test_scenario_data($user->id, $coursecategoryctx, 1, 'Sausage roll 2',
|
||||
'sausageroll2');
|
||||
$this->setup_test_scenario_data($user->id, $coursectx, 1, 'Sausage roll 3',
|
||||
'sausageroll3');
|
||||
|
||||
// Test the User's assigned cohortroles matches 3.
|
||||
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
|
||||
$this->assertCount(3, $cohortroles);
|
||||
|
||||
// Test the User's retrieved contextlist returns only the system and course category context.
|
||||
$contextlist = provider::get_contexts_for_userid($user->id);
|
||||
$contexts = $contextlist->get_contexts();
|
||||
$this->assertCount(2, $contexts);
|
||||
|
||||
$contextlevels = array_column($contexts, 'contextlevel');
|
||||
$expected = [
|
||||
CONTEXT_SYSTEM,
|
||||
CONTEXT_COURSECAT
|
||||
];
|
||||
// Test the User's contexts equal the system and course category context.
|
||||
$this->assertEquals($expected, $contextlevels, '', 0, 10, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::export_user_data().
|
||||
*/
|
||||
public function test_export_user_data() {
|
||||
// Test setup.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create course category.
|
||||
$coursecategory = $this->getDataGenerator()->create_category();
|
||||
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
|
||||
$systemctx = context_system::instance();
|
||||
// Create course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$coursectx = \context_course::instance($course->id);
|
||||
|
||||
$this->setup_test_scenario_data($user->id, $systemctx, 1);
|
||||
$this->setup_test_scenario_data($user->id, $coursecategoryctx, 1, 'Sausage roll 2',
|
||||
'sausageroll2');
|
||||
$this->setup_test_scenario_data($user->id, $coursectx, 1, 'Sausage roll 3',
|
||||
'sausageroll3');
|
||||
|
||||
// Test the User's retrieved contextlist contains two contexts.
|
||||
$contextlist = provider::get_contexts_for_userid($user->id);
|
||||
$contexts = $contextlist->get_contexts();
|
||||
$this->assertCount(2, $contexts);
|
||||
|
||||
// Add a system, course category and course context to the approved context list.
|
||||
$approvedcontextids = [
|
||||
$systemctx->id,
|
||||
$coursecategoryctx->id,
|
||||
$coursectx->id
|
||||
];
|
||||
|
||||
// Retrieve the User's tool_cohortroles data.
|
||||
$approvedcontextlist = new approved_contextlist($user, 'tool_cohortroles', $approvedcontextids);
|
||||
provider::export_user_data($approvedcontextlist);
|
||||
|
||||
// Test the tool_cohortroles data is exported at the system context level.
|
||||
$writer = writer::with_context($systemctx);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
// Test the tool_cohortroles data is exported at the course category context level.
|
||||
$writer = writer::with_context($coursecategoryctx);
|
||||
$this->assertTrue($writer->has_any_data());
|
||||
// Test the tool_cohortroles data is not exported at the course context level.
|
||||
$writer = writer::with_context($coursectx);
|
||||
$this->assertFalse($writer->has_any_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::delete_data_for_all_users_in_context().
|
||||
*/
|
||||
public function test_delete_data_for_all_users_in_context() {
|
||||
global $DB;
|
||||
|
||||
// Test setup.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create course category.
|
||||
$coursecategory = $this->getDataGenerator()->create_category();
|
||||
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
|
||||
$systemctx = context_system::instance();
|
||||
|
||||
$this->setup_test_scenario_data($user->id, $systemctx, 1);
|
||||
$this->setup_test_scenario_data($user->id, $coursecategoryctx, 1, 'Sausage roll 2',
|
||||
'sausageroll2');
|
||||
|
||||
// Test the User's assigned cohortroles matches 2.
|
||||
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
|
||||
$this->assertCount(2, $cohortroles);
|
||||
|
||||
// Test the User's retrieved contextlist contains two contexts.
|
||||
$contextlist = provider::get_contexts_for_userid($user->id);
|
||||
$contexts = $contextlist->get_contexts();
|
||||
$this->assertCount(2, $contexts);
|
||||
|
||||
// Make sure the user data is only being deleted in within the system and course category context.
|
||||
$usercontext = context_user::instance($user->id);
|
||||
// Delete all the User's records in mdl_tool_cohortroles table by the user context.
|
||||
provider::delete_data_for_all_users_in_context($usercontext);
|
||||
|
||||
// Test the cohort roles records in mdl_tool_cohortroles table is still present.
|
||||
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
|
||||
$this->assertCount(2, $cohortroles);
|
||||
|
||||
// Delete all the User's records in mdl_tool_cohortroles table by the specified system context.
|
||||
provider::delete_data_for_all_users_in_context($systemctx);
|
||||
|
||||
// The user data in the system context should be deleted.
|
||||
// Test the User's retrieved contextlist contains one context (course category).
|
||||
$contextlist = provider::get_contexts_for_userid($user->id);
|
||||
$contexts = $contextlist->get_contexts();
|
||||
$this->assertCount(1, $contexts);
|
||||
|
||||
// Delete all the User's records in mdl_tool_cohortroles table by the specified course category context.
|
||||
provider::delete_data_for_all_users_in_context($coursecategoryctx);
|
||||
|
||||
// Test the cohort roles records in mdl_tool_cohortroles table is equals zero.
|
||||
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
|
||||
$this->assertCount(0, $cohortroles);
|
||||
|
||||
$contextlist = provider::get_contexts_for_userid($user->id);
|
||||
$contexts = $contextlist->get_contexts();
|
||||
$this->assertCount(0, $contexts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::delete_data_for_user().
|
||||
*/
|
||||
public function test_delete_data_for_user() {
|
||||
global $DB;
|
||||
|
||||
// Test setup.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$this->setAdminUser();
|
||||
|
||||
// Create course category.
|
||||
$coursecategory = $this->getDataGenerator()->create_category();
|
||||
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
|
||||
$systemctx = context_system::instance();
|
||||
|
||||
$this->setup_test_scenario_data($user->id, $systemctx, 1);
|
||||
$this->setup_test_scenario_data($user->id, $coursecategoryctx, 1, 'Sausage roll 2',
|
||||
'sausageroll2');
|
||||
|
||||
// Test the User's assigned cohortroles matches 2.
|
||||
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
|
||||
$this->assertCount(2, $cohortroles);
|
||||
|
||||
// Test the User's retrieved contextlist contains two contexts.
|
||||
$contextlist = provider::get_contexts_for_userid($user->id);
|
||||
$contexts = $contextlist->get_contexts();
|
||||
$this->assertCount(2, $contexts);
|
||||
|
||||
// Make sure the user data is only being deleted in within the system and the course category contexts.
|
||||
$usercontext = context_user::instance($user->id);
|
||||
// Delete all the User's records in mdl_tool_cohortroles table by the specified approved context list.
|
||||
$approvedcontextlist = new approved_contextlist($user, 'tool_cohortroles', [$usercontext->id]);
|
||||
provider::delete_data_for_user($approvedcontextlist);
|
||||
|
||||
// Test the cohort roles records in mdl_tool_cohortroles table are still present.
|
||||
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
|
||||
$this->assertCount(2, $cohortroles);
|
||||
|
||||
// Delete all the User's records in mdl_tool_cohortroles table by the specified approved context list.
|
||||
$approvedcontextlist = new approved_contextlist($user, 'tool_cohortroles', $contextlist->get_contextids());
|
||||
provider::delete_data_for_user($approvedcontextlist);
|
||||
|
||||
// Test the records in mdl_tool_cohortroles table is equals zero.
|
||||
$cohortroles = $DB->get_records('tool_cohortroles', ['userid' => $user->id]);
|
||||
$this->assertCount(0, $cohortroles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that only users within a course context are fetched.
|
||||
*/
|
||||
public function test_get_users_in_context() {
|
||||
$component = 'tool_cohortroles';
|
||||
|
||||
// Create a user.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$usercontext = context_user::instance($user->id);
|
||||
|
||||
// Create course category.
|
||||
$coursecategory = $this->getDataGenerator()->create_category();
|
||||
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
|
||||
$systemctx = context_system::instance();
|
||||
|
||||
$this->setAdminUser();
|
||||
|
||||
$userlist = new \core_privacy\local\request\userlist($systemctx, $component);
|
||||
provider::get_users_in_context($userlist);
|
||||
$this->assertCount(0, $userlist);
|
||||
|
||||
$this->setup_test_scenario_data($user->id, $systemctx, 1);
|
||||
$this->setup_test_scenario_data($user->id, $coursecategoryctx, 1, 'Sausage roll 2',
|
||||
'sausageroll2');
|
||||
|
||||
// The list of users within the system context should contain user.
|
||||
provider::get_users_in_context($userlist);
|
||||
$this->assertCount(1, $userlist);
|
||||
$this->assertTrue(in_array($user->id, $userlist->get_userids()));
|
||||
|
||||
// The list of users within the course category context should contain user.
|
||||
$userlist = new \core_privacy\local\request\userlist($coursecategoryctx, $component);
|
||||
provider::get_users_in_context($userlist);
|
||||
$this->assertCount(1, $userlist);
|
||||
$this->assertTrue(in_array($user->id, $userlist->get_userids()));
|
||||
|
||||
// The list of users within the user context should be empty.
|
||||
$userlist2 = new \core_privacy\local\request\userlist($usercontext, $component);
|
||||
provider::get_users_in_context($userlist2);
|
||||
$this->assertCount(0, $userlist2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that data for users in approved userlist is deleted.
|
||||
*/
|
||||
public function test_delete_data_for_users() {
|
||||
$component = 'tool_cohortroles';
|
||||
|
||||
// Create user1.
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
// Create user2.
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
// Create user3.
|
||||
$user3 = $this->getDataGenerator()->create_user();
|
||||
$usercontext3 = context_user::instance($user3->id);
|
||||
|
||||
// Create course category.
|
||||
$coursecategory = $this->getDataGenerator()->create_category();
|
||||
$coursecategoryctx = \context_coursecat::instance($coursecategory->id);
|
||||
$systemctx = context_system::instance();
|
||||
|
||||
$this->setAdminUser();
|
||||
|
||||
$this->setup_test_scenario_data($user1->id, $systemctx, 1);
|
||||
$this->setup_test_scenario_data($user2->id, $systemctx, 1, 'Sausage roll 2',
|
||||
'sausageroll2');
|
||||
$this->setup_test_scenario_data($user3->id, $coursecategoryctx, 1, 'Sausage roll 3',
|
||||
'sausageroll3');
|
||||
|
||||
$userlist1 = new \core_privacy\local\request\userlist($systemctx, $component);
|
||||
provider::get_users_in_context($userlist1);
|
||||
$this->assertCount(2, $userlist1);
|
||||
$this->assertTrue(in_array($user1->id, $userlist1->get_userids()));
|
||||
$this->assertTrue(in_array($user2->id, $userlist1->get_userids()));
|
||||
|
||||
// Convert $userlist1 into an approved_contextlist.
|
||||
$approvedlist1 = new approved_userlist($systemctx, $component, [$user1->id]);
|
||||
// Delete using delete_data_for_user.
|
||||
provider::delete_data_for_users($approvedlist1);
|
||||
|
||||
// Re-fetch users in systemcontext.
|
||||
$userlist1 = new \core_privacy\local\request\userlist($systemctx, $component);
|
||||
provider::get_users_in_context($userlist1);
|
||||
// The user data of user1in systemcontext should be deleted.
|
||||
// The user data of user2 in systemcontext should be still present.
|
||||
$this->assertCount(1, $userlist1);
|
||||
$this->assertTrue(in_array($user2->id, $userlist1->get_userids()));
|
||||
|
||||
// Convert $userlist1 into an approved_contextlist in the user context.
|
||||
$approvedlist2 = new approved_userlist($usercontext3, $component, $userlist1->get_userids());
|
||||
// Delete using delete_data_for_user.
|
||||
provider::delete_data_for_users($approvedlist2);
|
||||
// Re-fetch users in systemcontext.
|
||||
$userlist1 = new \core_privacy\local\request\userlist($systemctx, $component);
|
||||
provider::get_users_in_context($userlist1);
|
||||
// The user data in systemcontext should not be deleted.
|
||||
$this->assertCount(1, $userlist1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to setup tool_cohortroles records for testing a specific user.
|
||||
*
|
||||
* @param int $userid The ID of the user used for testing.
|
||||
* @param int $nocohortroles The number of tool_cohortroles to create for the user.
|
||||
* @param string $rolename The name of the role to be created.
|
||||
* @param string $roleshortname The short name of the role to be created.
|
||||
* @throws \core_competency\invalid_persistent_exception
|
||||
* @throws coding_exception
|
||||
*/
|
||||
protected function setup_test_scenario_data($userid, $context, $nocohortroles, $rolename = 'Sausage Roll',
|
||||
$roleshortname = 'sausageroll') {
|
||||
$roleid = create_role($rolename, $roleshortname, 'mmmm');
|
||||
|
||||
$result = new \stdClass();
|
||||
$result->contextid = $context->id;
|
||||
|
||||
for ($c = 0; $c < $nocohortroles; $c++) {
|
||||
$cohort = $this->getDataGenerator()->create_cohort($result);
|
||||
|
||||
$params = (object)array(
|
||||
'userid' => $userid,
|
||||
'roleid' => $roleid,
|
||||
'cohortid' => $cohort->id
|
||||
);
|
||||
|
||||
api::create_cohort_role_assignment($params);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,8 +25,8 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_cohortroles'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
$plugin->dependencies = array(
|
||||
|
||||
@@ -1,46 +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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for tool_customlang.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_customlang\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for tool_customlang implementing null_provider.
|
||||
*
|
||||
* @copyright 2018 Zig Tan <zig@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,15 @@ defined('MOODLE_INTERNAL') || die();
|
||||
function xmldb_tool_customlang_upgrade($oldversion) {
|
||||
global $CFG;
|
||||
|
||||
// Moodle v2.8.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Moodle v2.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Moodle v3.0.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Moodle v3.1.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
@@ -38,8 +47,5 @@ function xmldb_tool_customlang_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ $string['checkin'] = 'Save strings to language pack';
|
||||
$string['checkout'] = 'Open language pack for editing';
|
||||
$string['checkoutdone'] = 'Language pack loaded';
|
||||
$string['checkoutinprogress'] = 'Loading language pack';
|
||||
$string['confirmcheckin'] = 'You are about to save modifications to your local language pack. This will export the customised strings from the translator into your site data directory and your site will start using the modified strings. Press \'Continue\' to proceed with saving.';
|
||||
$string['confirmcheckin'] = 'You are about to save modifications to your local language pack. This will export the customised strings from the translator into you Moodle data directory and Moodle will start using the modified strings. Press \'Continue\' to proceed with saving.';
|
||||
$string['customlang:edit'] = 'Edit local translation';
|
||||
$string['customlang:view'] = 'View local translation';
|
||||
$string['filter'] = 'Filter strings';
|
||||
@@ -59,4 +59,3 @@ $string['placeholderwarning'] = 'string contains a placeholder';
|
||||
$string['pluginname'] = 'Language customisation';
|
||||
$string['savecheckin'] = 'Save changes to the language pack';
|
||||
$string['savecontinue'] = 'Apply changes and continue editing';
|
||||
$string['privacy:metadata'] = 'The Language customisation plugin does not store any personal data.';
|
||||
|
||||
@@ -159,11 +159,6 @@ class tool_customlang_utils {
|
||||
$needsupdate = true;
|
||||
$current[$stringid]->local = $stringlocal;
|
||||
$current[$stringid]->timecustomized = $now;
|
||||
} else if (isset($currentlocal) && $stringlocal !== $currentlocal) {
|
||||
// If local string has been removed, we need to remove also the old local value from DB.
|
||||
$needsupdate = true;
|
||||
$current[$stringid]->local = null;
|
||||
$current[$stringid]->timecustomized = $now;
|
||||
}
|
||||
|
||||
if ($needsupdate) {
|
||||
|
||||
@@ -134,13 +134,11 @@ class tool_customlang_renderer extends plugin_renderer_base {
|
||||
$output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'translatorsubmitted', 'value'=>1));
|
||||
$output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=>sesskey()));
|
||||
$output .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'p', 'value'=>$translator->currentpage));
|
||||
$save1 = html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'savecontinue',
|
||||
'value' => get_string('savecontinue', 'tool_customlang'), 'class' => 'btn btn-secondary'));
|
||||
$save2 = html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'savecheckin',
|
||||
'value' => get_string('savecheckin', 'tool_customlang'), 'class' => 'btn btn-secondary'));
|
||||
$output .= html_writer::tag('fieldset', $save1 . ' ' . $save2, array('class' => 'buttonsbar'));
|
||||
$save1 = html_writer::empty_tag('input', array('type'=>'submit', 'name'=>'savecontinue', 'value'=>get_string('savecontinue', 'tool_customlang')));
|
||||
$save2 = html_writer::empty_tag('input', array('type'=>'submit', 'name'=>'savecheckin', 'value'=>get_string('savecheckin', 'tool_customlang')));
|
||||
$output .= html_writer::tag('fieldset', $save1.$save2, array('class'=>'buttonsbar'));
|
||||
$output .= html_writer::table($table);
|
||||
$output .= html_writer::tag('fieldset', $save1 . ' ' . $save2, array('class' => 'buttonsbar'));
|
||||
$output .= html_writer::tag('fieldset', $save1.$save2, array('class'=>'buttonsbar'));
|
||||
$output .= html_writer::end_tag('div');
|
||||
$output .= html_writer::end_tag('form');
|
||||
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->component = 'tool_customlang'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user