Compare commits
544 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d7496dacd | |||
| 253eece808 | |||
| 65e7470b92 | |||
| bd115c5e1a | |||
| 3b680fa554 | |||
| 0b0f121e89 | |||
| 7c98470586 | |||
| 6807076172 | |||
| b34c006bfd | |||
| 9555192935 | |||
| e25bcf9ede | |||
| 311adf5f6f | |||
| 6fb1e19c1e | |||
| 585780a182 | |||
| 52ce316caa | |||
| bb31fe88fb | |||
| 4fdafd4263 | |||
| 6374ec5013 | |||
| 329357ccff | |||
| 2d69b8442e | |||
| 953d1b8254 | |||
| 693115bebb | |||
| 76d24aed1e | |||
| 3d51aed3e2 | |||
| 7a16d88a4e | |||
| eaa25cf51b | |||
| 249bc5b8f9 | |||
| c519d282f4 | |||
| 660bdcc5ec | |||
| 3e906fea06 | |||
| 6f07919b5f | |||
| 89e9b922aa | |||
| 3087133bb6 | |||
| 364460d796 | |||
| 7cde7d004f | |||
| 644b843a94 | |||
| ddade6e964 | |||
| 672602d1e7 | |||
| 60a0d854ba | |||
| 925c451f1a | |||
| dc92cc0e20 | |||
| 3c8b723fdb | |||
| 24d86db351 | |||
| 68b4f0ea52 | |||
| 319efddb99 | |||
| b0496fb383 | |||
| a6117d4b44 | |||
| f7d43b77b1 | |||
| cae79de01c | |||
| 8ce983c55b | |||
| 84d15d73a5 | |||
| c783413759 | |||
| e3c328c91f | |||
| 8b772d1436 | |||
| a29d0ee99c | |||
| fd5ddee7ed | |||
| ba88242f5f | |||
| 0c9999bd22 | |||
| 29dc0bb3f6 | |||
| d56aa41e9e | |||
| 5778558dae | |||
| b7bf868042 | |||
| 06c20c4675 | |||
| f30a2bb18e | |||
| 5733851176 | |||
| 92a2dcc96a | |||
| 3a694fd6bf | |||
| bb6a65da42 | |||
| a11ffea697 | |||
| 90d7307872 | |||
| 453dfc4f94 | |||
| 75bffe9d96 | |||
| 22dc6301f0 | |||
| 7266fa1524 | |||
| e0a09f31b1 | |||
| 72526c6f49 | |||
| 5c0f33209e | |||
| 943ee4d484 | |||
| acd31294f4 | |||
| b409287479 | |||
| 13d98b9f6e | |||
| 2b19e45d49 | |||
| 7bde04468b | |||
| 80b23a2afd | |||
| da8e201e17 | |||
| d6950db0d9 | |||
| 661d66b452 | |||
| 74a5cc0965 | |||
| 768a82b583 | |||
| 04d3db34ee | |||
| c871b4d5f8 | |||
| d3749a82ab | |||
| d7610a257f | |||
| 62b840648d | |||
| 5f93e6ab03 | |||
| 69beec3d2a | |||
| d2c9c79c0e | |||
| 1ce15ab9b1 | |||
| a24d8a0d2a | |||
| 8835ecef16 | |||
| 86c79ed091 | |||
| d4f5e92ee1 | |||
| 2c58f9533b | |||
| 34077a9190 | |||
| 42726d645c | |||
| 02d08d2e4d | |||
| 9b90cf6584 | |||
| bdbc077efc | |||
| fb06894e75 | |||
| 6b4946e0a8 | |||
| 057f63909f | |||
| ea84a13152 | |||
| 9639feb9a3 | |||
| f009e2621e | |||
| 3449379bca | |||
| c77d6a79ec | |||
| d8558b1d42 | |||
| b8614dee98 | |||
| b852d34285 | |||
| 250ef211f0 | |||
| 2ebcdda606 | |||
| ce89c63b0b | |||
| 8acc343fb8 | |||
| 15a54747b9 | |||
| 7666131199 | |||
| 8b54213ad0 | |||
| 561a371423 | |||
| 6cc39f8e94 | |||
| 58e54a3d33 | |||
| eb1c1e79a1 | |||
| e7c973a195 | |||
| a982ebad0c | |||
| 27692e70b5 | |||
| 05db16c24d | |||
| 0aaf7fe953 | |||
| aea9770cfc | |||
| 05fe39a88f | |||
| 44305df587 | |||
| 638caa1355 | |||
| 6d29dc587e | |||
| 0f03ac03b5 | |||
| a11b849ebe | |||
| 4cfa5bca7c | |||
| 19ad8459d7 | |||
| 3f6919adc7 | |||
| 5d2ce59559 | |||
| e08dd90c32 | |||
| 26d7f16686 | |||
| 5b168b055f | |||
| 7ad936dcbf | |||
| 29ab56c4d2 | |||
| 6c640dacf4 | |||
| 234d24dfea | |||
| 835505681c | |||
| e930abfcf8 | |||
| cb06a0a271 | |||
| f8f19a4d8e | |||
| e2a8d063ee | |||
| 1fd2f0364c | |||
| 7f450dcea3 | |||
| c39a3357ed | |||
| cc10212366 | |||
| df2b3113d9 | |||
| d4f428311a | |||
| e2c677c3e8 | |||
| 80b3cb4951 | |||
| dfa5124909 | |||
| d3a6c97a43 | |||
| 316a50f2b7 | |||
| 2883fd28e4 | |||
| aa7f8f9e09 | |||
| c4b56bb393 | |||
| 156d214635 | |||
| 31b07a6298 | |||
| 2c82466444 | |||
| 91e70280a2 | |||
| 68e93dbfee | |||
| c12d07d9d4 | |||
| a29ef48500 | |||
| 0fae681a7c | |||
| 149df44e29 | |||
| da1fafe59d | |||
| 3821c707b8 | |||
| 1c7a5d9972 | |||
| 0fdbf26fd0 | |||
| 4f3c3432cd | |||
| b6715bb1ae | |||
| 40094ddbe0 | |||
| 8535c32bf3 | |||
| 6b90c69bda | |||
| 6f3337dcba | |||
| ff33f82ac2 | |||
| bf6cf572ca | |||
| 433109e2ac | |||
| 07bfca9041 | |||
| b2320ccd71 | |||
| 5e4ba1f036 | |||
| 7e17945088 | |||
| 535e970ad3 | |||
| dd8595035f | |||
| 06ae387ca5 | |||
| df48a73c5c | |||
| 70bbb44030 | |||
| 70ab78478f | |||
| 8a66b2b99a | |||
| ee5ac3f1f3 | |||
| 9e71503ab3 | |||
| 651ecb52d9 | |||
| 85845b13d7 | |||
| 7b0946129c | |||
| 7d7cfee0b7 | |||
| 6751ba6500 | |||
| 6d387e4b2b | |||
| ed3b73d9fc | |||
| f95b010ec5 | |||
| 97060da478 | |||
| 9715fd56da | |||
| 7e3d7fb02d | |||
| a9cc2ebb6e | |||
| 1a7ec4cf3d | |||
| 7715c626ad | |||
| 1c9098aeb8 | |||
| 5d18431087 | |||
| 0d27c76e34 | |||
| 8deeed9771 | |||
| 7893a34171 | |||
| e6966b7ae7 | |||
| 3e81ebecb6 | |||
| f9c5802f4e | |||
| e6ee7a5b1c | |||
| 17081ee902 | |||
| e817dd70db | |||
| bc30a904f4 | |||
| b2d9c6ff81 | |||
| 18dae18e20 | |||
| 18c7f3cdf3 | |||
| f0b462209a | |||
| 974db25816 | |||
| 7a02ae5644 | |||
| a9f24ce125 | |||
| a68fcabc65 | |||
| 2978ffc4a5 | |||
| a694661d5c | |||
| 7d77854fd6 | |||
| 17124e62a9 | |||
| d9ae012d15 | |||
| c03706fafb | |||
| f77aa8c4a7 | |||
| 4044abd156 | |||
| 6164556c85 | |||
| 69a8f920d4 | |||
| ff263b6dbc | |||
| 763c71194b | |||
| 19ac0728f2 | |||
| 39cb2a03e5 | |||
| c8c84b4af1 | |||
| 5ec01a7226 | |||
| f878e05d62 | |||
| aa0e2cffdd | |||
| c18b59808c | |||
| a0d8c025f7 | |||
| 137d311fd1 | |||
| 57f20b6cb3 | |||
| a10506b8d7 | |||
| 28b8fc9896 | |||
| f55b829f44 | |||
| 836b2c23a2 | |||
| 0068701bc6 | |||
| 83a978d1cd | |||
| d05795db8e | |||
| 629a7066be | |||
| 058b11e57b | |||
| aa230649d9 | |||
| f8cce391b2 | |||
| a7d476c35f | |||
| 5425fb3d79 | |||
| 587d737690 | |||
| 31b68a2b5d | |||
| a48f00d940 | |||
| f7da739ea0 | |||
| ebb346cd8e | |||
| b39d8d5027 | |||
| cf48f359ad | |||
| 8ac29c9422 | |||
| 7f3617860c | |||
| b35f70ce14 | |||
| 77d0c0caa9 | |||
| c2193308a6 | |||
| 9456911fe9 | |||
| bd2c8fdd54 | |||
| 234d81e39b | |||
| 9747b5b26b | |||
| 508d462fa7 | |||
| f687e02dec | |||
| 72c3038925 | |||
| d393030c58 | |||
| d68ea84924 | |||
| 85825dcc55 | |||
| 80f152296c | |||
| 48aa9aae56 | |||
| 025065daf5 | |||
| 49be0febdc | |||
| 73f57aab98 | |||
| 457f0e9384 | |||
| 4b15c803e2 | |||
| 50aff515b7 | |||
| 5b33398f07 | |||
| 47568f31c5 | |||
| eba83406da | |||
| 137c6f36bb | |||
| d9043b324d | |||
| e57e560385 | |||
| eebd5742b6 | |||
| 0837a24c05 | |||
| f2e48b39f6 | |||
| 5060c53176 | |||
| 3f392e934e | |||
| c1e4679ed5 | |||
| 9254b7e75a | |||
| 1d609ca0ee | |||
| 61fabd3e73 | |||
| e8d03fdae4 | |||
| c8922328b2 | |||
| 19635ef720 | |||
| 9d5a4746ab | |||
| e4406472f0 | |||
| cf2f67272a | |||
| 2ebac5604c | |||
| c5f48698da | |||
| c2a043f50d | |||
| 001c78285f | |||
| af90bb572e | |||
| 882a660f7e | |||
| adc1de569d | |||
| 607716f206 | |||
| 5358ce28ee | |||
| fef8dda150 | |||
| b049731dfb | |||
| 5277dca108 | |||
| 4be4d0d489 | |||
| 3d0bcb7172 | |||
| 7dac3707fd | |||
| 037a7d5d6c | |||
| f5587cf881 | |||
| a18c0b7c8b | |||
| 097a879e1a | |||
| 58acb96ee6 | |||
| 1901cd3fdf | |||
| 2c9a5c009f | |||
| b564a40d74 | |||
| 179bfdf5c5 | |||
| eb975467bd | |||
| 5efbd6e0e1 | |||
| fa20b1790f | |||
| 7d579dd4bb | |||
| 6b0661b9ea | |||
| afd57ca9a0 | |||
| c14e75a017 | |||
| 318e2344c0 | |||
| 17ed404ccc | |||
| 5b54a87858 | |||
| ea49be1e61 | |||
| 0f3d3b2d77 | |||
| dee41e0648 | |||
| c11b1c6b3f | |||
| e2362b0a7a | |||
| d63721cb15 | |||
| 66b1733bda | |||
| 81821e6833 | |||
| 965a5fdb27 | |||
| 6aa2828161 | |||
| d46a37ebd4 | |||
| 8c358aefd9 | |||
| 40aceb0256 | |||
| f64240ce94 | |||
| 10c7926c0f | |||
| 8a26315686 | |||
| 0e8d4d8e2a | |||
| 5ac11701ac | |||
| dc65317ba6 | |||
| f0ae7c4343 | |||
| b52c1855fa | |||
| 6e1e63cc6b | |||
| 50ae525be9 | |||
| a700d119df | |||
| 9ccd794b36 | |||
| 49673645ea | |||
| e6316e6b9b | |||
| 5003afbe48 | |||
| 7e1bbaaf20 | |||
| d1111bc3e8 | |||
| 8de03684ac | |||
| 2db07c4d0a | |||
| 3ac3d942dd | |||
| 84308c7dfc | |||
| 24a0e76ebf | |||
| 2444b2b787 | |||
| b704fa7dda | |||
| 9d3d193f29 | |||
| 43c7557e84 | |||
| da74ac4987 | |||
| 1e5bc3a393 | |||
| 7c20cd1b81 | |||
| edf1a1ac8c | |||
| 5a2acac1ed | |||
| 719c95009e | |||
| 860b4b941a | |||
| 26ed48ec40 | |||
| 58ba1a9448 | |||
| 40d2b4de39 | |||
| bce1d7ff85 | |||
| 3f439ff9d4 | |||
| 0c34355c85 | |||
| ab118d48f5 | |||
| 6df3213c9b | |||
| 6dbd0e938f | |||
| 8889f6f26f | |||
| 36aa09726b | |||
| 196c2ae7a5 | |||
| 4d217e3a1a | |||
| 09e3db1aa6 | |||
| 8815ecb3fd | |||
| 8482210209 | |||
| 281ef7ef8d | |||
| 6970580b4c | |||
| 652633b467 | |||
| 5a7963d9f5 | |||
| 56ff5e78f1 | |||
| e31db928b5 | |||
| 03fcd81892 | |||
| 05a41b6e32 | |||
| 8a38a37f1f | |||
| 4ea1bd3537 | |||
| 35b7cbf027 | |||
| 87eb0fdf21 | |||
| c8aef2e4ba | |||
| fa72ebc155 | |||
| 6d7f162df0 | |||
| 97d64fb809 | |||
| fd3c586992 | |||
| 61fb8ee988 | |||
| 44f8c11123 | |||
| e5b9510af2 | |||
| ab151f86ab | |||
| e36e40f530 | |||
| 3a8a8c8463 | |||
| 2f811e6acf | |||
| fb7da9c74f | |||
| d27862e2ca | |||
| c7fde934c7 | |||
| be50fbe20c | |||
| 74bf7382dd | |||
| cb075f6257 | |||
| 8a1b5fc2b0 | |||
| bd22abe778 | |||
| b3867e7422 | |||
| 8c298f14bb | |||
| 58bd2ed8e4 | |||
| 36ca488c06 | |||
| bca28b03a9 | |||
| a6216bb890 | |||
| 94b14df11d | |||
| 0dc60026c8 | |||
| 63a1ec81c4 | |||
| 150fc0837a | |||
| 72958879c6 | |||
| d8d560b7fe | |||
| 917dd49db2 | |||
| 80691cf5a3 | |||
| e20720ce0e | |||
| f976349b95 | |||
| 312a166f1e | |||
| f16ca8fa7a | |||
| 846a8b6568 | |||
| 692d3090fa | |||
| 8092eb95c4 | |||
| 2b864ceec3 | |||
| 80083244b6 | |||
| 560f4d895b | |||
| 95c3017da4 | |||
| 8fffc08ee8 | |||
| 364230d6f8 | |||
| 45f674e8cb | |||
| 4ba166cf80 | |||
| 3a779663aa | |||
| ca7b24f6d0 | |||
| 35a2a34a7d | |||
| 603c794190 | |||
| 38c4d51947 | |||
| a86228f547 | |||
| b30033c6c0 | |||
| 5661849a02 | |||
| 66e8ce9976 | |||
| cf92eaeb0b | |||
| f7f40e54e6 | |||
| 627177855a | |||
| 8c7983a43f | |||
| 0d0aa11e19 | |||
| eb0439b5da | |||
| 37101f0698 | |||
| 4b8a001bb0 | |||
| a9cf9d5519 | |||
| 53275e5b8f | |||
| 518e5799e4 | |||
| 6a610605f6 | |||
| e4eb16bd9f | |||
| 3e831cc8c5 | |||
| 5ecca13a6f | |||
| 278f58dae0 | |||
| 73cf6fb65c | |||
| 6483b5d68f | |||
| 6c24b8289f | |||
| e2e00a9dd4 | |||
| 8168155e17 | |||
| d6650b63bf | |||
| 174389cc26 | |||
| 03454c2262 | |||
| e591ddc4e8 | |||
| e1767fa80f | |||
| e25033e42d | |||
| dd2c19eb09 | |||
| 3b8b8d7d84 | |||
| 5378285a9a | |||
| 3a098250f1 | |||
| 148ddd26e7 | |||
| cdf432ee17 | |||
| b1e918edd8 | |||
| f58df6fa88 | |||
| eae562817d | |||
| 033a59f9c5 | |||
| a34a8636be | |||
| 08d2e7c136 | |||
| 886bbcbdb8 | |||
| 0c3e759d98 | |||
| 607a452a74 | |||
| 3ef6e04f3c | |||
| dfc7dcd062 | |||
| 80d773868c | |||
| eb127cc93b | |||
| e5eb66e405 | |||
| 67f869a081 | |||
| a11a9ca5aa | |||
| 3fe8dbd027 | |||
| 6aeecbdf46 |
@@ -1,8 +1,12 @@
|
||||
{
|
||||
'plugins': [
|
||||
'babel',
|
||||
'@babel',
|
||||
'promise',
|
||||
'jsdoc',
|
||||
'jsdoc'
|
||||
],
|
||||
'extends': [
|
||||
'eslint:recommended',
|
||||
'plugin:promise/recommended'
|
||||
],
|
||||
'env': {
|
||||
'browser': true,
|
||||
@@ -16,42 +20,19 @@
|
||||
'M': true,
|
||||
'Y': true
|
||||
},
|
||||
// Warn about unused eslint-disable statements.
|
||||
'reportUnusedDisableDirectives': true,
|
||||
'rules': {
|
||||
// See http://eslint.org/docs/rules/ for all rules and explanations of all
|
||||
// rules.
|
||||
|
||||
// === Possible Errors ===
|
||||
'comma-dangle': 'off',
|
||||
'no-compare-neg-zero': 'error',
|
||||
'no-cond-assign': 'error',
|
||||
'no-console': 'error',
|
||||
'no-constant-condition': 'error',
|
||||
'no-control-regex': 'error',
|
||||
'no-debugger': 'error',
|
||||
'no-dupe-args': 'error',
|
||||
'no-dupe-keys': 'error',
|
||||
'no-duplicate-case': 'error',
|
||||
'no-empty': 'warn',
|
||||
'no-empty-character-class': 'error',
|
||||
'no-ex-assign': 'error',
|
||||
'no-extra-boolean-cast': 'error',
|
||||
'no-extra-parens': 'off',
|
||||
'no-extra-semi': 'error',
|
||||
'no-func-assign': 'error',
|
||||
'no-inner-declarations': 'error',
|
||||
'no-invalid-regexp': 'error',
|
||||
'no-irregular-whitespace': 'error',
|
||||
'no-obj-calls': 'error',
|
||||
'no-prototype-builtins': 'off',
|
||||
'no-regex-spaces': 'error',
|
||||
'no-sparse-arrays': 'error',
|
||||
'no-unexpected-multiline': 'error',
|
||||
'no-unreachable': 'warn',
|
||||
'no-unsafe-finally': 'error',
|
||||
'no-unsafe-negation': 'error',
|
||||
'use-isnan': 'error',
|
||||
'valid-jsdoc': ['warn', { 'requireReturn': false, 'requireParamDescription': false, 'requireReturnDescription': false }],
|
||||
'valid-typeof': 'error',
|
||||
|
||||
// === Best Practices ===
|
||||
// (these mostly match our jshint config)
|
||||
@@ -63,15 +44,12 @@
|
||||
'dot-notation': 'warn',
|
||||
'no-alert': 'warn',
|
||||
'no-caller': 'error',
|
||||
'no-case-declarations': 'error',
|
||||
'no-div-regex': 'error',
|
||||
'no-empty-pattern': 'error',
|
||||
'no-empty-function': 'warn',
|
||||
'no-eq-null': 'error',
|
||||
'no-eval': 'error',
|
||||
'no-extend-native': 'error',
|
||||
'no-extra-bind': 'warn',
|
||||
'no-fallthrough': 'error',
|
||||
'no-floating-decimal': 'warn',
|
||||
'no-global-assign': 'warn',
|
||||
'no-implied-eval': 'error',
|
||||
@@ -83,28 +61,22 @@
|
||||
'no-multi-str': 'error',
|
||||
'no-new-func': 'error',
|
||||
'no-new-wrappers': 'error',
|
||||
'no-octal': 'error',
|
||||
'no-octal-escape': 'error',
|
||||
'no-proto': 'error',
|
||||
'no-redeclare': 'warn',
|
||||
'no-restricted-globals': ['error', { 'name': 'Notification' }],
|
||||
'no-return-assign': 'error',
|
||||
'no-script-url': 'error',
|
||||
'no-self-assign': 'error',
|
||||
'no-self-compare': 'error',
|
||||
'no-sequences': 'warn',
|
||||
'no-throw-literal': 'warn',
|
||||
'no-unmodified-loop-condition': 'error',
|
||||
'no-unused-expressions': 'error',
|
||||
'no-unused-labels': 'error',
|
||||
'no-useless-call': 'warn',
|
||||
'no-useless-escape': 'warn',
|
||||
'no-with': 'error',
|
||||
'wrap-iife': ['error', 'any'],
|
||||
|
||||
// === Variables ===
|
||||
'no-delete-var': 'error',
|
||||
'no-undef': 'error',
|
||||
'no-undef-init': 'error',
|
||||
'no-unused-vars': ['error', { 'caughtErrors': 'none' }],
|
||||
|
||||
@@ -137,8 +109,6 @@
|
||||
'max-statements-per-line': ['warn', { max: 2 }],
|
||||
'new-cap': ['warn', { 'properties': false }],
|
||||
'new-parens': 'warn',
|
||||
'newline-after-var': 'off',
|
||||
'newline-before-return': 'off',
|
||||
'newline-per-chained-call': 'off',
|
||||
'no-array-constructor': 'off',
|
||||
'no-bitwise': 'error',
|
||||
@@ -146,7 +116,6 @@
|
||||
'no-inline-comments': 'off',
|
||||
'no-lonely-if': 'off',
|
||||
'no-mixed-operators': 'off',
|
||||
'no-mixed-spaces-and-tabs': 'error',
|
||||
'no-multiple-empty-lines': 'warn',
|
||||
'no-negated-condition': 'off',
|
||||
'no-nested-ternary': 'warn',
|
||||
@@ -168,7 +137,6 @@
|
||||
'padded-blocks': 'off',
|
||||
'quote-props': ['warn', 'as-needed', {'unnecessary': false, 'keywords': true, 'numbers': true}],
|
||||
'quotes': 'off',
|
||||
'require-jsdoc': 'warn',
|
||||
'semi': 'error',
|
||||
'semi-spacing': ['warn', {'before': false, 'after': true}],
|
||||
'sort-vars': 'off',
|
||||
@@ -181,21 +149,19 @@
|
||||
'unicode-bom': 'error',
|
||||
'wrap-regex': 'off',
|
||||
|
||||
// === Promises ===
|
||||
// === Promises (override plugin:promise/recommended) ===
|
||||
'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()'
|
||||
'message': 'Use "core/str" module or M.util.get_string()'
|
||||
}],
|
||||
},
|
||||
overrides: [
|
||||
@@ -235,7 +201,6 @@
|
||||
parser: '@babel/eslint-parser',
|
||||
// Check AMD with some slightly stricter rules.
|
||||
rules: {
|
||||
'no-unused-vars': 'error',
|
||||
'no-implicit-globals': 'error',
|
||||
// Disable all of the rules that have babel versions.
|
||||
'new-cap': 'off',
|
||||
@@ -247,65 +212,37 @@
|
||||
'semi': 'off',
|
||||
'no-unused-expressions': 'off',
|
||||
// Enable all of the babel version of these rules.
|
||||
'babel/new-cap': ['warn', { 'properties': false }],
|
||||
'@babel/new-cap': ['warn', { 'properties': false }],
|
||||
// Not using this rule for the time being because it isn't
|
||||
// compatible with jQuery and ES6.
|
||||
'babel/no-invalid-this': 'off',
|
||||
'babel/object-curly-spacing': 'warn',
|
||||
// This is off in the original style int.
|
||||
'babel/quotes': 'off',
|
||||
'babel/semi': 'error',
|
||||
'babel/no-unused-expressions': 'error',
|
||||
'@babel/no-invalid-this': 'off',
|
||||
'@babel/object-curly-spacing': 'warn',
|
||||
'@babel/semi': 'error',
|
||||
'@babel/no-unused-expressions': 'error',
|
||||
// === Promises ===
|
||||
// We have Promise now that we're using ES6.
|
||||
'promise/no-native': 'off',
|
||||
'promise/avoid-new': 'off',
|
||||
|
||||
// === JSDocs ===
|
||||
"jsdoc/check-access": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/check-alignment": 1, // Recommended.
|
||||
"jsdoc/check-param-names": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/check-property-names": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/empty-tags": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/implements-on-classes": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/multiline-blocks": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-jsdoc": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-param": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-param-name": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-param-type": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-property": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-property-name": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-property-type": [
|
||||
'error',
|
||||
],
|
||||
'jsdoc/check-access': 'error',
|
||||
'jsdoc/check-alignment': 1, // Recommended.
|
||||
'jsdoc/check-param-names': 'error',
|
||||
'jsdoc/check-property-names': 'error',
|
||||
'jsdoc/empty-tags': 'error',
|
||||
'jsdoc/implements-on-classes': 'error',
|
||||
'jsdoc/multiline-blocks': 'error',
|
||||
'jsdoc/require-jsdoc': 'error',
|
||||
'jsdoc/require-param': 'error',
|
||||
'jsdoc/require-param-name': 'error',
|
||||
'jsdoc/require-param-type': 'error',
|
||||
'jsdoc/require-property': 'error',
|
||||
'jsdoc/require-property-name': 'error',
|
||||
'jsdoc/require-property-type': 'error'
|
||||
},
|
||||
parserOptions: {
|
||||
'sourceType': 'module',
|
||||
'requireConfigFile': false,
|
||||
'requireConfigFile': false
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -3,7 +3,7 @@ name: Core
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- master
|
||||
- main
|
||||
- MOODLE_[0-9]+_STABLE
|
||||
tags-ignore:
|
||||
- v[0-9]+.[0-9]+.[0-9]+*
|
||||
@@ -23,10 +23,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checking out code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Configuring node & npm
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
@@ -103,7 +103,7 @@ jobs:
|
||||
coverage: none
|
||||
|
||||
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setting up PHPUnit
|
||||
env:
|
||||
|
||||
@@ -16,10 +16,10 @@ jobs:
|
||||
git config --global core.eol lf
|
||||
|
||||
- name: Checking out code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Configuring node & npm
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
@@ -112,7 +112,7 @@ jobs:
|
||||
git config --global core.eol lf
|
||||
|
||||
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Needs to be done after php is available, git configured and Moodle checkout has happened.
|
||||
- name: Setting up moodle-exttests service
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function to generate the destination for the uglify task
|
||||
* Function to generate the destination for the minification task
|
||||
* (e.g. build/file.min.js). This function will be passed to
|
||||
* the rename property of files array when building dynamically:
|
||||
* http://gruntjs.com/configuring-tasks#building-the-files-object-dynamically
|
||||
@@ -60,7 +60,6 @@ module.exports = grunt => {
|
||||
grunt.registerTask('js', ['amd', 'yui']);
|
||||
|
||||
// Register NPM tasks.
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-rollup');
|
||||
|
||||
@@ -104,6 +103,7 @@ module.exports = grunt => {
|
||||
// The queue runner will run the next `size` items in the queue.
|
||||
const runQueue = (size = 1) => {
|
||||
queue.splice(0, size).forEach(resolve => {
|
||||
grunt.log.debug(`Item resolved. Kicking off next one.`);
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
@@ -113,15 +113,17 @@ module.exports = grunt => {
|
||||
|
||||
// The options hook is run in parallel.
|
||||
// We can return an unresolved Promise which is queued for later resolution.
|
||||
options: async() => {
|
||||
options: async(options) => {
|
||||
return new Promise(resolve => {
|
||||
queue.push(resolve);
|
||||
startQueue();
|
||||
return options;
|
||||
});
|
||||
},
|
||||
|
||||
// When an item in the queue completes, start the next item in the queue.
|
||||
buildEnd: () => {
|
||||
generateBundle: (options, bundle) => {
|
||||
grunt.log.debug(`Finished output phase for ${Object.keys(bundle).join(', ')}`);
|
||||
runQueue();
|
||||
},
|
||||
};
|
||||
@@ -151,24 +153,10 @@ module.exports = grunt => {
|
||||
//
|
||||
// It also adds the Moodle plugin name to the AMD module definition
|
||||
// so that it can be imported as expected in other modules.
|
||||
path.resolve('.grunt/babel-plugin-add-module-to-define.js'),
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-syntax-import-meta',
|
||||
['@babel/plugin-proposal-class-properties', {'loose': false}],
|
||||
'@babel/plugin-proposal-json-strings'
|
||||
path.resolve('.grunt/babel-plugin-add-module-to-define.js')
|
||||
],
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: [
|
||||
">0.3%",
|
||||
"last 2 versions",
|
||||
"not ie >= 0",
|
||||
"not op_mini all",
|
||||
"not Opera > 0",
|
||||
"not dead"
|
||||
]
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: false
|
||||
}]
|
||||
|
||||
+28
-12
@@ -20,17 +20,33 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
// Project configuration.
|
||||
grunt.config.merge({
|
||||
jsdoc: {
|
||||
dist: {
|
||||
options: {
|
||||
configure: ".grunt/jsdoc/jsdoc.conf.js",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
module.exports = (grunt) => {
|
||||
const path = require('path');
|
||||
|
||||
grunt.loadNpmTasks('grunt-jsdoc');
|
||||
grunt.registerTask('jsdoc', 'Generate JavaScript documentation using jsdoc', function() {
|
||||
const done = this.async();
|
||||
const configuration = path.resolve('.grunt/jsdoc/jsdoc.conf.js');
|
||||
|
||||
grunt.util.spawn({
|
||||
cmd: 'jsdoc',
|
||||
args: [
|
||||
'--configure',
|
||||
configuration,
|
||||
]
|
||||
}, function(error, result, code) {
|
||||
if (result.stdout) {
|
||||
grunt.log.write(result.stdout);
|
||||
}
|
||||
|
||||
if (result.stderr) {
|
||||
grunt.log.error(result.stderr);
|
||||
}
|
||||
if (error) {
|
||||
grunt.fail.fatal(`JSDoc failed with error code ${code}`);
|
||||
} else {
|
||||
grunt.log.write('JSDoc completed successfully'.green);
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@ module.exports = grunt => {
|
||||
// Use a fully-qualified path.
|
||||
src: files,
|
||||
options: {
|
||||
quietDeprecationWarnings: true,
|
||||
configOverrides: {
|
||||
rules: {
|
||||
// These rules have to be disabled in .stylelintrc for scss compat.
|
||||
@@ -45,7 +46,10 @@ module.exports = grunt => {
|
||||
return {
|
||||
stylelint: {
|
||||
scss: {
|
||||
options: {syntax: 'scss'},
|
||||
options: {
|
||||
quietDeprecationWarnings: true,
|
||||
customSyntax: 'postcss-scss',
|
||||
},
|
||||
src: files,
|
||||
},
|
||||
},
|
||||
|
||||
+16
-4
@@ -1,9 +1,14 @@
|
||||
{
|
||||
"customSyntax": "postcss-scss",
|
||||
"plugins": [
|
||||
"stylelint-csstree-validator"
|
||||
],
|
||||
"rules": {
|
||||
"csstree/validator": true,
|
||||
"csstree/validator": {
|
||||
"syntaxExtensions": [
|
||||
"sass"
|
||||
]
|
||||
},
|
||||
"at-rule-empty-line-before": [ "always",
|
||||
{"except": [ "blockless-after-blockless"], ignore: ["after-comment", "inside-block"]}
|
||||
],
|
||||
@@ -45,7 +50,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-scheme-disallowed-list": ["data"],
|
||||
"function-whitespace-after": "always",
|
||||
"indentation": 4,
|
||||
"keyframe-declaration-no-important": true,
|
||||
@@ -84,12 +89,19 @@
|
||||
"selector-type-no-unknown": true,
|
||||
"string-no-newline": true,
|
||||
"time-min-milliseconds": 100,
|
||||
"unit-blacklist": ["pt"],
|
||||
"unit-disallowed-list": ["pt"],
|
||||
"unit-case": "lower",
|
||||
"unit-no-unknown": true,
|
||||
"value-keyword-case": ["lower", {"ignoreKeywords": ["/(@|$)/"]}],
|
||||
"value-list-comma-newline-after": "always-multi-line",
|
||||
"value-list-comma-space-after": "always-single-line",
|
||||
"value-list-comma-space-before": "never",
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/yui/**/*.css"],
|
||||
"rules": {
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3923,6 +3923,8 @@
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_oracle_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.2" requires="3.11.8">
|
||||
@@ -3939,6 +3941,7 @@
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="8.0.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_83" message="unsupportedphpversion83" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -4112,6 +4115,8 @@
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_oracle_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.3" requires="3.11.8">
|
||||
@@ -4128,6 +4133,7 @@
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="8.0.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_83" message="unsupportedphpversion83" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -4303,6 +4309,8 @@
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_db_prefix_length" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_oracle_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.4" requires="4.1.2">
|
||||
@@ -4494,6 +4502,400 @@
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_db_prefix_length" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_oracle_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_async_backup" level="recommended">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.5" requires="4.1.2">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.6.7" />
|
||||
<VENDOR name="mysql" version="8.0" />
|
||||
<VENDOR name="postgres" version="13" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="8.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="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="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_EXTENSION name="sodium" level="required"/>
|
||||
<PHP_EXTENSION name="exif" level="optional"/>
|
||||
</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="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="sixtyfourbitsrequired" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="iscustomadminwarnings" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_db_prefix_length" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_oracle_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_async_backup" level="recommended">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="5.0" requires="4.2.3">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.11.0" />
|
||||
<VENDOR name="mysql" version="8.4" />
|
||||
<VENDOR name="postgres" version="14" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="8.2.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="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_EXTENSION name="sodium" level="required"/>
|
||||
<PHP_EXTENSION name="exif" level="optional"/>
|
||||
</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="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="sixtyfourbitsrequired" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="iscustomadminwarnings" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_db_prefix_length" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_oracle_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_async_backup" level="recommended">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
@@ -180,7 +180,7 @@ class generator_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function create_preset_provider(): array {
|
||||
public static function create_preset_provider(): array {
|
||||
return [
|
||||
'Default values' => [
|
||||
],
|
||||
|
||||
@@ -84,7 +84,7 @@ class helper_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function create_preset_provider(): array {
|
||||
public static function create_preset_provider(): array {
|
||||
return [
|
||||
'Default values' => [
|
||||
],
|
||||
@@ -177,7 +177,7 @@ class helper_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_item_provider(): array {
|
||||
public static function add_item_provider(): array {
|
||||
return [
|
||||
'Setting without plugin' => [
|
||||
'name' => 'settingname',
|
||||
@@ -239,7 +239,7 @@ class helper_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_plugin_provider(): array {
|
||||
public static function add_plugin_provider(): array {
|
||||
return [
|
||||
'Plugin: enabled (using int)' => [
|
||||
'type' => 'plugintype',
|
||||
@@ -321,7 +321,7 @@ class helper_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function change_default_preset_provider(): array {
|
||||
public static function change_default_preset_provider(): array {
|
||||
return [
|
||||
'Starter preset' => [
|
||||
'preset' => 'starter',
|
||||
|
||||
@@ -72,7 +72,7 @@ class adminpresets_admin_setting_bloglevel_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function save_value_provider(): array {
|
||||
public static function save_value_provider(): array {
|
||||
return [
|
||||
'Save the bloglevel and set blog_menu block visibility to true' => [
|
||||
'setttingvalue' => BLOG_USER_LEVEL,
|
||||
|
||||
@@ -66,7 +66,7 @@ class adminpresets_admin_setting_sitesettext_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function save_value_provider(): array {
|
||||
public static function save_value_provider(): array {
|
||||
return [
|
||||
'Fullname: different value' => [
|
||||
'settingname' => 'fullname',
|
||||
|
||||
@@ -77,7 +77,7 @@ class adminpresets_setting_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function save_value_provider(): array {
|
||||
public static function save_value_provider(): array {
|
||||
return [
|
||||
'Core setting with the same value is not saved' => [
|
||||
'category' => 'optionalsubsystems',
|
||||
@@ -167,7 +167,7 @@ class adminpresets_setting_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function save_attributes_values_provider(): array {
|
||||
public static function save_attributes_values_provider(): array {
|
||||
return [
|
||||
'Plugin setting with the same value is not saved' => [
|
||||
'category' => 'modsettinglesson',
|
||||
|
||||
@@ -358,7 +358,7 @@ class manager_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function export_preset_provider(): array {
|
||||
public static function export_preset_provider(): array {
|
||||
return [
|
||||
'Export settings and plugins, excluding sensible' => [
|
||||
'includesensible' => false,
|
||||
@@ -521,7 +521,7 @@ class manager_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function import_preset_provider(): array {
|
||||
public static function import_preset_provider(): array {
|
||||
return [
|
||||
'Import settings from an empty file' => [
|
||||
'filecontents' => '',
|
||||
|
||||
+5
-2
@@ -2052,8 +2052,10 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
// We are checking installed & enabled things
|
||||
if ($environment_result->getLevel() == 'required') {
|
||||
$stringtouse = 'environmentrequirecustomcheck';
|
||||
} else {
|
||||
} else if ($environment_result->getLevel() == 'optional') {
|
||||
$stringtouse = 'environmentrecommendcustomcheck';
|
||||
} else {
|
||||
$stringtouse = 'environmentshouldfixcustomcheck';
|
||||
}
|
||||
|
||||
} else if ($environment_result->getPart() == 'php_setting') {
|
||||
@@ -2084,7 +2086,8 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
if ($status) { //Handle ok result (ok)
|
||||
$status = get_string('statusok');
|
||||
} else {
|
||||
if ($environment_result->getLevel() == 'optional') {//Handle check result (warning)
|
||||
// Handle check result (warning).
|
||||
if (in_array($environment_result->getLevel(), ['optional', 'recommended'])) {
|
||||
$status = get_string('check');
|
||||
$warningline = true;
|
||||
} else { //Handle error result (error)
|
||||
|
||||
@@ -152,7 +152,8 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$sensiblesettingsdefault .= 'server_password@@search_solr, ssl_keypassword@@search_solr, ';
|
||||
$sensiblesettingsdefault .= 'alternateserver_password@@search_solr, alternatessl_keypassword@@search_solr, ';
|
||||
$sensiblesettingsdefault .= 'test_password@@cachestore_redis, password@@mlbackend_python, ';
|
||||
$sensiblesettingsdefault .= 'badges_badgesalt@@none, calendar_exportsalt@@none';
|
||||
$sensiblesettingsdefault .= 'badges_badgesalt@@none, calendar_exportsalt@@none, ';
|
||||
$sensiblesettingsdefault .= 'bigbluebuttonbn_shared_secret@@none';
|
||||
$temp->add(new admin_setting_configtextarea('adminpresets/sensiblesettings',
|
||||
get_string('sensiblesettings', 'core_adminpresets'),
|
||||
get_string('sensiblesettingstext', 'core_adminpresets'),
|
||||
|
||||
@@ -18,7 +18,7 @@ Feature: An administrator can browse user accounts
|
||||
When I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
# Name field always present, email field is default for showidentity.
|
||||
Then the following should exist in the "users" table:
|
||||
| First name / Last name | Email address |
|
||||
| First name | Email address |
|
||||
| User One | one@example.com |
|
||||
| User Two | two@example.com |
|
||||
# Should not see other identity fields or non-default name fields.
|
||||
@@ -34,7 +34,7 @@ Feature: An administrator can browse user accounts
|
||||
| alternativefullnameformat | firstnamephonetic lastname |
|
||||
When I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
Then the following should exist in the "users" table:
|
||||
| First name - phonetic / Last name | Email address |
|
||||
| First name - phonetic | Email address |
|
||||
| Yewzer One | one@example.com |
|
||||
| Yoozare Two | two@example.com |
|
||||
|
||||
@@ -43,7 +43,7 @@ Feature: An administrator can browse user accounts
|
||||
| showuseridentity | department,profile_field_frog |
|
||||
When I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
Then the following should exist in the "users" table:
|
||||
| First name / Last name | Favourite frog | Department |
|
||||
| First name | Favourite frog | Department |
|
||||
| User One | Kermit | Attack |
|
||||
| User Two | Tree | Defence |
|
||||
And I should not see "Email address" in the "table" "css_element"
|
||||
|
||||
@@ -48,25 +48,3 @@ Feature: View task logs report and use its filters
|
||||
| operator | shouldornotsee |
|
||||
| Less than | should not see |
|
||||
| Greater than | should see |
|
||||
|
||||
@javascript
|
||||
Scenario: Reset task log filters
|
||||
Given I log in as "admin"
|
||||
And I change window size to "large"
|
||||
And I navigate to "Server > Tasks > Task logs" in site administration
|
||||
When I click on "Filters" "button"
|
||||
And I set the following fields in the "Result" "core_reportbuilder > Filter" to these values:
|
||||
| Result operator | Is equal to |
|
||||
| Result value | Fail |
|
||||
And I click on "Apply" "button" in the "[data-region='report-filters']" "css_element"
|
||||
Then I should see "Filters applied"
|
||||
And I should see "Filters (1)" in the "#dropdownFiltersButton" "css_element"
|
||||
And I should see "Nothing to display"
|
||||
And I click on "Reset all" "button" in the "[data-region='report-filters']" "css_element"
|
||||
And I should see "Filters reset"
|
||||
And I should not see "Filters (1)" in the "#dropdownFiltersButton" "css_element"
|
||||
And I should see "Filters" in the "#dropdownFiltersButton" "css_element"
|
||||
And "[data-region='report-filters']" "css_element" should be visible
|
||||
And the following fields in the "Result" "core_reportbuilder > Filter" match these values:
|
||||
| Result operator | Is any value |
|
||||
And I should not see "Nothing to display"
|
||||
|
||||
@@ -103,7 +103,7 @@ class task_logs_test extends core_reportbuilder_testcase {
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function datasource_filters_provider(): array {
|
||||
public static function datasource_filters_provider(): array {
|
||||
return [
|
||||
'Filter name' => ['task_log:name', [
|
||||
'task_log:name_values' => [send_schedules::class],
|
||||
|
||||
@@ -64,7 +64,7 @@ class delete extends base {
|
||||
* Delete the DB preset
|
||||
*/
|
||||
public function execute(): void {
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
$this->manager->delete_preset($this->id);
|
||||
|
||||
|
||||
@@ -52,8 +52,6 @@ class export extends base {
|
||||
* Stores a preset into the DB.
|
||||
*/
|
||||
public function execute(): void {
|
||||
confirm_sesskey();
|
||||
|
||||
$url = new \moodle_url('/admin/tool/admin_presets/index.php', ['action' => 'export', 'mode' => 'execute']);
|
||||
$this->moodleform = new export_form($url);
|
||||
|
||||
@@ -87,7 +85,7 @@ class export extends base {
|
||||
* @throws xml_writer_exception
|
||||
*/
|
||||
public function download_xml(): void {
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
list($xmlstr, $filename) = $this->manager->download_preset($this->id);
|
||||
|
||||
|
||||
@@ -40,8 +40,6 @@ class import extends base {
|
||||
* Imports the xmlfile into DB
|
||||
*/
|
||||
public function execute(): void {
|
||||
confirm_sesskey();
|
||||
|
||||
$url = new \moodle_url('/admin/tool/admin_presets/index.php', ['action' => 'import', 'mode' => 'execute']);
|
||||
$this->moodleform = new import_form($url);
|
||||
|
||||
|
||||
@@ -38,8 +38,6 @@ class load extends base {
|
||||
public function execute(): void {
|
||||
global $OUTPUT;
|
||||
|
||||
confirm_sesskey();
|
||||
|
||||
$url = new \moodle_url('/admin/tool/admin_presets/index.php', ['action' => 'load', 'mode' => 'execute']);
|
||||
$this->moodleform = new load_form($url);
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class rollback extends base {
|
||||
public function execute(): void {
|
||||
global $OUTPUT;
|
||||
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
list($presetapp, $rollback, $failures) = $this->manager->revert_preset($this->id);
|
||||
|
||||
|
||||
@@ -5,16 +5,18 @@ Feature: I can download a preset
|
||||
| name |
|
||||
| Custom preset |
|
||||
|
||||
@javascript
|
||||
Scenario: Custom preset settings can be downloaded
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Site admin presets" in site administration
|
||||
When I open the action menu in "Custom preset" "table_row"
|
||||
Then following "Download" "link" in the "Custom preset" "table_row" should download between "0" and "5000" bytes
|
||||
Then following "Download" in the "Custom preset" "table_row" should download a file that:
|
||||
| Has mimetype | text/xml |
|
||||
| Contains text in xml element | Custom preset |
|
||||
|
||||
@javascript
|
||||
Scenario: Core preset settings can be downloaded
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Site admin presets" in site administration
|
||||
When I open the action menu in "Starter" "table_row"
|
||||
Then following "Download" "link" in the "Starter" "table_row" should download between "0" and "5000" bytes
|
||||
Then following "Download" in the "Starter" "table_row" should download a file that:
|
||||
| Has mimetype | text/xml |
|
||||
| Contains text in xml element | Starter |
|
||||
|
||||
@@ -70,7 +70,7 @@ class base_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function log_provider(): array {
|
||||
public static function log_provider(): array {
|
||||
return [
|
||||
// Action = base.
|
||||
'action=base and mode = show' => [
|
||||
|
||||
@@ -156,7 +156,7 @@ class export_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function export_execute_provider(): array {
|
||||
public static function export_execute_provider(): array {
|
||||
return [
|
||||
'Export settings and plugins, excluding sensible' => [
|
||||
'includesensible' => false,
|
||||
|
||||
@@ -190,7 +190,7 @@ class import_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function import_execute_provider(): array {
|
||||
public static function import_execute_provider(): array {
|
||||
$fixturesfolder = __DIR__ . '/../../../../../presets/tests/fixtures/';
|
||||
|
||||
return [
|
||||
|
||||
@@ -97,28 +97,28 @@ if ($onlycli === false) {
|
||||
switch ($action) {
|
||||
|
||||
case 'enable':
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
$model->enable();
|
||||
redirect($returnurl);
|
||||
break;
|
||||
|
||||
case 'disable':
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
$model->update(0, false, false);
|
||||
redirect($returnurl);
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
$model->delete();
|
||||
redirect($returnurl);
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
$invalidcurrenttimesplitting = $model->invalid_timesplitting_selected();
|
||||
$potentialtimesplittings = $model->get_potential_timesplittings();
|
||||
@@ -183,7 +183,7 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'evaluate':
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
if ($model->is_static()) {
|
||||
throw new moodle_exception('errornostaticevaluate', 'tool_analytics');
|
||||
@@ -226,7 +226,7 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'scheduledanalysis':
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
if ($onlycli) {
|
||||
throw new moodle_exception('erroronlycli', 'tool_analytics');
|
||||
@@ -292,7 +292,7 @@ switch ($action) {
|
||||
break;
|
||||
|
||||
case 'clear':
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
$model->clear();
|
||||
redirect($returnurl);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
@tool_behat
|
||||
Feature: Confirm that we can open multiple browser tabs
|
||||
In order to use multiple browser tabs
|
||||
As a test writer
|
||||
I need the relevant Behat steps to work
|
||||
|
||||
@javascript @_switch_window
|
||||
Scenario: Open multiple browser tabs
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname |
|
||||
| Course 1 | C1 |
|
||||
| Course 2 | C2 |
|
||||
| Course 3 | C3 |
|
||||
And I am on the "C1" "Course" page logged in as "admin"
|
||||
|
||||
# Open a new tab on the same page.
|
||||
When I open a tab named "CourseViewer1" on the current page
|
||||
And I should see "Course 1" in the "h1" "css_element"
|
||||
And I am on the "C2" "Course" page
|
||||
|
||||
# Open new tab for specified page with identifier.
|
||||
And I open a tab named "CourseViewer2" on the "C3" "Course" page
|
||||
|
||||
# And for a specified page without identifier.
|
||||
And I open a tab named "CourseViewer4" on the "My courses" page
|
||||
|
||||
# Switch between all the tabs and confirm their different contents.
|
||||
Then I should see "No courses"
|
||||
And I switch to "CourseViewer2" tab
|
||||
And "Course 3" "heading" should exist
|
||||
And I switch to "CourseViewer1" tab
|
||||
And "Course 2" "heading" should exist
|
||||
And I switch to the main tab
|
||||
And "Course 1" "heading" should exist
|
||||
@@ -53,7 +53,7 @@ class behat_form_text_test extends \basic_testcase {
|
||||
*
|
||||
* @return array of value and expectation pairs to be tested.
|
||||
*/
|
||||
public function provider_test_set_get_value() {
|
||||
public static function provider_test_set_get_value(): array {
|
||||
return [
|
||||
'null' => [null, null],
|
||||
'int' => [3, 3],
|
||||
@@ -68,7 +68,7 @@ class behat_form_text_test extends \basic_testcase {
|
||||
*
|
||||
* @param mixed $value value to be set.
|
||||
* @param mixed $expectation value to be checked.
|
||||
* @dataProvider provider_test_set_get_value()
|
||||
* @dataProvider provider_test_set_get_value
|
||||
*/
|
||||
public function test_set_get_value($value, $expectation) {
|
||||
$session = $this->createMock(Session::class);
|
||||
@@ -85,7 +85,7 @@ class behat_form_text_test extends \basic_testcase {
|
||||
*
|
||||
* @return array of decsep, value, match and result pairs to be tested.
|
||||
*/
|
||||
public function provider_test_matches() {
|
||||
public static function provider_test_matches(): array {
|
||||
return [
|
||||
'lazy true' => ['.', 'hello', 'hello', true],
|
||||
'lazy false' => ['.', 'hello', 'bye', false],
|
||||
@@ -113,7 +113,7 @@ class behat_form_text_test extends \basic_testcase {
|
||||
* @param mixed $value value to be set.
|
||||
* @param mixed $match value to be matched.
|
||||
* @param bool $result expected return status of the function.
|
||||
* @dataProvider provider_test_matches()
|
||||
* @dataProvider provider_test_matches
|
||||
*/
|
||||
public function test_matches($decsep, $value, $match, $result) {
|
||||
global $CFG;
|
||||
|
||||
@@ -30,7 +30,7 @@ use tool_brickfield\local\tool\tool;
|
||||
class tool_test extends \advanced_testcase {
|
||||
|
||||
/** @var string base 64 image */
|
||||
protected $base64img = <<<EOF
|
||||
protected static string $base64img = <<<EOF
|
||||
<img src="data:image/gif;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/
|
||||
8mJl+fn/9ZWb8/PzWlwv///6wWGbImAPgTEMImIN9gUFCEm/gDALULDN8PAD6atYdCTX9gUNKlj8wZAKUsAOzZz+UMAOsJAP/Z2ccMDA8PD/95eX5N
|
||||
WvsJCOVNQPtfX/8zM8+QePLl38MGBr8JCP+zs9myn/8GBqwpAP/GxgwJCPny78lzYLgjAJ8vAP9fX/+MjMUcAN8zM/9wcM8ZGcATEL+QePdZWf/29u
|
||||
@@ -118,11 +118,11 @@ EOF;
|
||||
* Base64 image provider.
|
||||
* @return array
|
||||
*/
|
||||
public function base64_img_provider(): array {
|
||||
public static function base64_img_provider(): array {
|
||||
$img = '<img src="myimage.jpg" />';
|
||||
return [
|
||||
'Image tag alone (base64)' => [
|
||||
$this->base64img,
|
||||
self::$base64img,
|
||||
true,
|
||||
],
|
||||
'Image tag alone (link)' => [
|
||||
@@ -130,7 +130,7 @@ EOF;
|
||||
false,
|
||||
],
|
||||
'Image tag in string (base64)' => [
|
||||
"This is my image {$this->base64img}.",
|
||||
"This is my image " . self::$base64img,
|
||||
true,
|
||||
],
|
||||
'Image tag in string (link)' => [
|
||||
@@ -162,7 +162,7 @@ EOF;
|
||||
}
|
||||
|
||||
public function test_truncate_base64() {
|
||||
$truncated = tool::truncate_base64($this->base64img);
|
||||
$truncated = tool::truncate_base64(self::$base64img);
|
||||
$this->assertStringContainsString('<img src="data:image/gif;base64..."', $truncated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class langstring_test extends advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function fix_syntax_data() : array {
|
||||
public static function fix_syntax_data(): array {
|
||||
return [
|
||||
// Syntax sanity v1 strings.
|
||||
[
|
||||
|
||||
@@ -79,7 +79,7 @@ class phpparser_test extends advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parse_provider() : array {
|
||||
public static function parse_provider(): array {
|
||||
return [
|
||||
'Invalid PHP code' => [
|
||||
'No PHP code', [], false
|
||||
|
||||
@@ -155,9 +155,9 @@ class data_request extends persistent {
|
||||
case api::DATAREQUEST_STATUS_EXPIRED:
|
||||
$result = true;
|
||||
break;
|
||||
// Complete requests are expired if the expiry time has elapsed.
|
||||
// Complete requests are expired if the expiry time is a positive value, and has elapsed.
|
||||
case api::DATAREQUEST_STATUS_DOWNLOAD_READY:
|
||||
$expiryseconds = get_config('tool_dataprivacy', 'privacyrequestexpiry');
|
||||
$expiryseconds = (int) get_config('tool_dataprivacy', 'privacyrequestexpiry');
|
||||
if ($expiryseconds > 0 && time() >= ($request->get('timemodified') + $expiryseconds)) {
|
||||
$result = true;
|
||||
}
|
||||
@@ -178,7 +178,12 @@ class data_request extends persistent {
|
||||
public static function get_expired_requests($userid = 0) {
|
||||
global $DB;
|
||||
|
||||
$expiryseconds = get_config('tool_dataprivacy', 'privacyrequestexpiry');
|
||||
// Complete requests are expired if the expiry time is a positive value, and has elapsed.
|
||||
$expiryseconds = (int) get_config('tool_dataprivacy', 'privacyrequestexpiry');
|
||||
if ($expiryseconds <= 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$expirytime = strtotime("-{$expiryseconds} second");
|
||||
$table = self::TABLE;
|
||||
$sqlwhere = 'type = :export_type AND status = :completestatus AND timemodified <= :expirytime';
|
||||
|
||||
@@ -545,7 +545,7 @@ class api_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data_request_creation_provider() {
|
||||
public static function data_request_creation_provider(): array {
|
||||
return [
|
||||
'Export request by user, automatic approval off' => [
|
||||
false, api::DATAREQUEST_TYPE_EXPORT, 'automaticdataexportapproval', false, 0,
|
||||
@@ -705,7 +705,7 @@ class api_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_data_requests_provider() {
|
||||
public static function get_data_requests_provider(): array {
|
||||
$completeonly = [api::DATAREQUEST_STATUS_COMPLETE, api::DATAREQUEST_STATUS_DOWNLOAD_READY, api::DATAREQUEST_STATUS_DELETED];
|
||||
$completeandcancelled = array_merge($completeonly, [api::DATAREQUEST_STATUS_CANCELLED]);
|
||||
|
||||
@@ -842,7 +842,7 @@ class api_test extends \advanced_testcase {
|
||||
/**
|
||||
* Data provider for test_has_ongoing_request.
|
||||
*/
|
||||
public function status_provider() {
|
||||
public static function status_provider(): array {
|
||||
return [
|
||||
[api::DATAREQUEST_STATUS_AWAITING_APPROVAL, true],
|
||||
[api::DATAREQUEST_STATUS_APPROVED, true],
|
||||
@@ -932,7 +932,7 @@ class api_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function notify_dpo_provider() {
|
||||
public static function notify_dpo_provider(): array {
|
||||
return [
|
||||
[false, api::DATAREQUEST_TYPE_EXPORT, 'requesttypeexport', 'Export my user data'],
|
||||
[false, api::DATAREQUEST_TYPE_DELETE, 'requesttypedelete', 'Delete my user data'],
|
||||
@@ -1284,7 +1284,7 @@ class api_test extends \advanced_testcase {
|
||||
/**
|
||||
* Data provider for invalid contextlevel fetchers.
|
||||
*/
|
||||
public function invalid_effective_contextlevel_provider() {
|
||||
public static function invalid_effective_contextlevel_provider(): array {
|
||||
return [
|
||||
[CONTEXT_COURSECAT],
|
||||
[CONTEXT_COURSE],
|
||||
@@ -1844,7 +1844,7 @@ class api_test extends \advanced_testcase {
|
||||
/**
|
||||
* Data provider for \tool_dataprivacy_api_testcase::test_set_context_defaults
|
||||
*/
|
||||
public function set_context_defaults_provider() {
|
||||
public static function set_context_defaults_provider(): array {
|
||||
$contextlevels = [
|
||||
[CONTEXT_COURSECAT],
|
||||
[CONTEXT_COURSE],
|
||||
@@ -2319,7 +2319,7 @@ class api_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function queue_data_request_task_provider() {
|
||||
public static function queue_data_request_task_provider(): array {
|
||||
return [
|
||||
'With user ID provided' => [true],
|
||||
'Without user ID provided' => [false],
|
||||
@@ -2356,7 +2356,7 @@ class api_test extends \advanced_testcase {
|
||||
/**
|
||||
* Data provider for test_is_automatic_request_approval_on().
|
||||
*/
|
||||
public function automatic_request_approval_setting_provider() {
|
||||
public static function automatic_request_approval_setting_provider(): array {
|
||||
return [
|
||||
'Data export, not set' => [
|
||||
'automaticdataexportapproval', api::DATAREQUEST_TYPE_EXPORT, null, false
|
||||
|
||||
@@ -54,6 +54,7 @@ Feature: Data delete from the privacy API
|
||||
And I should see "Awaiting approval" in the "Victim User 1" "table_row"
|
||||
And I open the action menu in "Victim User 1" "table_row"
|
||||
And I follow "Approve request"
|
||||
And I wait until "Approve request" "button" exists
|
||||
And I press "Approve request"
|
||||
And I should see "Approved" in the "Victim User 1" "table_row"
|
||||
And I run all adhoc tasks
|
||||
@@ -80,6 +81,7 @@ Feature: Data delete from the privacy API
|
||||
And I navigate to "Users > Privacy and policies > Data requests" in site administration
|
||||
And I open the action menu in "Victim User 1" "table_row"
|
||||
And I follow "Approve request"
|
||||
And I wait until "Approve request" "button" exists
|
||||
And I press "Approve request"
|
||||
|
||||
And I log out
|
||||
@@ -115,6 +117,7 @@ Feature: Data delete from the privacy API
|
||||
And I navigate to "Users > Privacy and policies > Data requests" in site administration
|
||||
And I open the action menu in "Victim User 1" "table_row"
|
||||
And I follow "Approve request"
|
||||
And I wait until "Approve request" "button" exists
|
||||
And I press "Approve request"
|
||||
|
||||
And I log out
|
||||
|
||||
@@ -48,13 +48,15 @@ Feature: Data export from the privacy API
|
||||
And I should see "Awaiting approval" in the "Victim User 1" "table_row"
|
||||
And I open the action menu in "Victim User 1" "table_row"
|
||||
And I follow "Approve request"
|
||||
And I wait until "Approve request" "button" exists
|
||||
And I press "Approve request"
|
||||
And I should see "Approved" in the "Victim User 1" "table_row"
|
||||
And I run all adhoc tasks
|
||||
And I reload the page
|
||||
And I should see "Download ready" in the "Victim User 1" "table_row"
|
||||
And I open the action menu in "Victim User 1" "table_row"
|
||||
And following "Download" should download between "1" and "150000" bytes
|
||||
And following "Download" should download a file that:
|
||||
| Contains file in zip | index.html |
|
||||
And the following config values are set as admin:
|
||||
| privacyrequestexpiry | 1 | tool_dataprivacy |
|
||||
And I wait "1" seconds
|
||||
@@ -89,7 +91,8 @@ Feature: Data export from the privacy API
|
||||
And I reload the page
|
||||
And I should see "Download ready" in the "Export all of my personal data" "table_row"
|
||||
And I open the action menu in "Victim User 1" "table_row"
|
||||
And following "Download" should download between "1" and "155000" bytes
|
||||
And following "Download" should download a file that:
|
||||
| Contains file in zip | index.html |
|
||||
|
||||
And the following config values are set as admin:
|
||||
| privacyrequestexpiry | 1 | tool_dataprivacy |
|
||||
@@ -115,6 +118,7 @@ Feature: Data export from the privacy API
|
||||
And I navigate to "Users > Privacy and policies > Data requests" in site administration
|
||||
And I open the action menu in "Victim User 1" "table_row"
|
||||
And I follow "Approve request"
|
||||
And I wait until "Approve request" "button" exists
|
||||
And I press "Approve request"
|
||||
|
||||
And I log out
|
||||
@@ -126,7 +130,8 @@ Feature: Data export from the privacy API
|
||||
And I reload the page
|
||||
And I should see "Download ready" in the "Victim User 1" "table_row"
|
||||
And I open the action menu in "Victim User 1" "table_row"
|
||||
And following "Download" should download between "1" and "150000" bytes
|
||||
And following "Download" should download a file that:
|
||||
| Contains file in zip | index.html |
|
||||
|
||||
And the following config values are set as admin:
|
||||
| privacyrequestexpiry | 1 | tool_dataprivacy |
|
||||
|
||||
@@ -35,7 +35,7 @@ class data_request_test extends data_privacy_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function status_state_provider() : array {
|
||||
public static function status_state_provider(): array {
|
||||
return [
|
||||
[
|
||||
'state' => api::DATAREQUEST_STATUS_PENDING,
|
||||
@@ -138,9 +138,9 @@ class data_request_test extends data_privacy_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function non_resettable_provider() : array {
|
||||
public static function non_resettable_provider(): array {
|
||||
$states = [];
|
||||
foreach ($this->status_state_provider() as $thisstatus) {
|
||||
foreach (self::status_state_provider() as $thisstatus) {
|
||||
if (!$thisstatus['resettable']) {
|
||||
$states[] = $thisstatus;
|
||||
}
|
||||
|
||||
@@ -1918,7 +1918,7 @@ class expired_contexts_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function can_process_deletion_provider() : array {
|
||||
public static function can_process_deletion_provider(): array {
|
||||
return [
|
||||
'Pending' => [
|
||||
expired_context::STATUS_EXPIRED,
|
||||
@@ -1956,7 +1956,7 @@ class expired_contexts_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function is_complete_provider() : array {
|
||||
public static function is_complete_provider(): array {
|
||||
return [
|
||||
'Pending' => [
|
||||
expired_context::STATUS_EXPIRED,
|
||||
@@ -1991,7 +1991,7 @@ class expired_contexts_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function is_fully_expired_provider() : array {
|
||||
public static function is_fully_expired_provider(): array {
|
||||
return [
|
||||
'Fully expired' => [
|
||||
[
|
||||
|
||||
@@ -26,10 +26,11 @@ require_once('data_privacy_testcase.php');
|
||||
* Expired data requests tests.
|
||||
*
|
||||
* @package tool_dataprivacy
|
||||
* @covers \tool_dataprivacy\data_request
|
||||
* @copyright 2018 Michael Hawkins
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class expired_data_requests_test extends data_privacy_testcase {
|
||||
final class expired_data_requests_test extends data_privacy_testcase {
|
||||
|
||||
/**
|
||||
* Test tearDown.
|
||||
@@ -107,6 +108,52 @@ class expired_data_requests_test extends data_privacy_testcase {
|
||||
$this->assertEquals(0, $DB->count_records('files', $fileconditions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that data requests are not expired when expiration is disabled (set to zero)
|
||||
*/
|
||||
public function test_data_request_expiry_never(): void {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
\core_privacy\local\request\writer::setup_real_writer_instance();
|
||||
|
||||
// Disable request expiry.
|
||||
set_config('privacyrequestexpiry', 0, 'tool_dataprivacy');
|
||||
|
||||
// Create and approve data request.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$usercontext = \context_user::instance($user->id);
|
||||
|
||||
$this->setUser($user->id);
|
||||
$datarequest = api::create_data_request($user->id, api::DATAREQUEST_TYPE_EXPORT);
|
||||
$requestid = $datarequest->get('id');
|
||||
|
||||
$this->setAdminUser();
|
||||
api::approve_data_request($requestid);
|
||||
|
||||
ob_start();
|
||||
$this->runAdhocTasks('\tool_dataprivacy\task\process_data_request_task');
|
||||
ob_end_clean();
|
||||
|
||||
// Run expiry deletion - should not affect test export.
|
||||
$expiredrequests = data_request::get_expired_requests();
|
||||
$this->assertEmpty($expiredrequests);
|
||||
data_request::expire($expiredrequests);
|
||||
|
||||
// Confirm approved and exported.
|
||||
$request = new data_request($requestid);
|
||||
$this->assertEquals(api::DATAREQUEST_STATUS_DOWNLOAD_READY, $request->get('status'));
|
||||
$fileconditions = [
|
||||
'userid' => $user->id,
|
||||
'component' => 'tool_dataprivacy',
|
||||
'filearea' => 'export',
|
||||
'itemid' => $requestid,
|
||||
'contextid' => $usercontext->id,
|
||||
];
|
||||
$this->assertEquals(2, $DB->count_records('files', $fileconditions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for \tool_dataprivacy\data_request::is_expired()
|
||||
* Tests for the expected request status to protect from false positive/negative,
|
||||
|
||||
+2
-2
@@ -578,7 +578,7 @@ class external_test extends externallib_advanced_testcase {
|
||||
/**
|
||||
* Data provider for \tool_dataprivacy_external_testcase::test_XX_options().
|
||||
*/
|
||||
public function get_options_provider() {
|
||||
public static function get_options_provider(): array {
|
||||
return [
|
||||
[false, false],
|
||||
[false, true],
|
||||
@@ -703,7 +703,7 @@ class external_test extends externallib_advanced_testcase {
|
||||
/**
|
||||
* Data provider for \tool_dataprivacy_external_testcase::get_activity_options().
|
||||
*/
|
||||
public function get_activity_options_provider() {
|
||||
public static function get_activity_options_provider(): array {
|
||||
return [
|
||||
[false, false, true],
|
||||
[false, true, true],
|
||||
|
||||
@@ -58,7 +58,7 @@ class filtered_userlist_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function apply_expired_contexts_filters_provider() : array {
|
||||
public static function apply_expired_contexts_filters_provider(): array {
|
||||
return [
|
||||
// Entire list should be preserved.
|
||||
'No overrides' => [
|
||||
|
||||
@@ -120,8 +120,7 @@ Feature: Add customised file types
|
||||
| Custom description | Froggy file |
|
||||
And I press "Save changes"
|
||||
# Create a resource activity and add it to a course
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
When I add a "File" to section "1"
|
||||
When I add a resource activity to course "Course 1" section "1"
|
||||
And I set the following fields to these values:
|
||||
| Name | An example of customised file type |
|
||||
| Description | File description |
|
||||
|
||||
@@ -38,20 +38,20 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
/**
|
||||
* Data provider for test_upgrade_http_links
|
||||
*/
|
||||
public function upgrade_http_links_provider() {
|
||||
public static function upgrade_http_links_provider(): array {
|
||||
global $CFG;
|
||||
// Get the http url, since the default test wwwroot is https.
|
||||
$wwwroothttp = preg_replace('/^https:/', 'http:', $CFG->wwwroot);
|
||||
return [
|
||||
"Test image from another site should be replaced" => [
|
||||
"content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">',
|
||||
"content" => '<img src="' . self::getExternalTestFileUrl('/test.jpg', false) . '">',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<img src="' . $this->get_converted_http_link('/test.jpg') . '">',
|
||||
"expectedcontent" => '<img src="' . self::get_converted_http_link('/test.jpg') . '">',
|
||||
],
|
||||
"Test object from another site should be replaced" => [
|
||||
"content" => '<object data="' . $this->getExternalTestFileUrl('/test.swf', false) . '">',
|
||||
"content" => '<object data="' . self::getExternalTestFileUrl('/test.swf', false) . '">',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<object data="' . $this->get_converted_http_link('/test.swf') . '">',
|
||||
"expectedcontent" => '<object data="' . self::get_converted_http_link('/test.swf') . '">',
|
||||
],
|
||||
"Test image from a site with international name should be replaced" => [
|
||||
"content" => '<img src="http://中国互联网络信息中心.中国/logosy/201706/W01.png">',
|
||||
@@ -79,9 +79,9 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
"expectedcontent" => '<img src="https://anothersite.com?param=http://asdf.com">',
|
||||
],
|
||||
"Search for params should be case insensitive" => [
|
||||
"content" => '<object DATA="' . $this->getExternalTestFileUrl('/test.swf', false) . '">',
|
||||
"content" => '<object DATA="' . self::getExternalTestFileUrl('/test.swf', false) . '">',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<object DATA="' . $this->get_converted_http_link('/test.swf') . '">',
|
||||
"expectedcontent" => '<object DATA="' . self::get_converted_http_link('/test.swf') . '">',
|
||||
],
|
||||
"URL should be case insensitive" => [
|
||||
"content" => '<object data="HTTP://some.site/path?query">',
|
||||
@@ -89,30 +89,30 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
"expectedcontent" => '<object data="https://some.site/path?query">',
|
||||
],
|
||||
"More params should not interfere" => [
|
||||
"content" => '<img alt="A picture" src="' . $this->getExternalTestFileUrl('/test.png', false) .
|
||||
"content" => '<img alt="A picture" src="' . self::getExternalTestFileUrl('/test.png', false) .
|
||||
'" width="1”><p style="font-size: \'20px\'"></p>',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<img alt="A picture" src="' . $this->get_converted_http_link('/test.png') .
|
||||
"expectedcontent" => '<img alt="A picture" src="' . self::get_converted_http_link('/test.png') .
|
||||
'" width="1”><p style="font-size: \'20px\'"></p>',
|
||||
],
|
||||
"Broken URL should not be changed" => [
|
||||
"content" => '<img src="broken.' . $this->getExternalTestFileUrl('/test.png', false) . '">',
|
||||
"content" => '<img src="broken.' . self::getExternalTestFileUrl('/test.png', false) . '">',
|
||||
"outputregex" => '/^$/',
|
||||
"expectedcontent" => '<img src="broken.' . $this->getExternalTestFileUrl('/test.png', false) . '">',
|
||||
"expectedcontent" => '<img src="broken.' . self::getExternalTestFileUrl('/test.png', false) . '">',
|
||||
],
|
||||
"Link URL should not be changed" => [
|
||||
"content" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '">' .
|
||||
$this->getExternalTestFileUrl('/test.png', false) . '</a>',
|
||||
"content" => '<a href="' . self::getExternalTestFileUrl('/test.png', false) . '">' .
|
||||
self::getExternalTestFileUrl('/test.png', false) . '</a>',
|
||||
"outputregex" => '/^$/',
|
||||
"expectedcontent" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '">' .
|
||||
$this->getExternalTestFileUrl('/test.png', false) . '</a>',
|
||||
"expectedcontent" => '<a href="' . self::getExternalTestFileUrl('/test.png', false) . '">' .
|
||||
self::getExternalTestFileUrl('/test.png', false) . '</a>',
|
||||
],
|
||||
"Test image from another site should be replaced but link should not" => [
|
||||
"content" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '"><img src="' .
|
||||
$this->getExternalTestFileUrl('/test.jpg', false) . '"></a>',
|
||||
"content" => '<a href="' . self::getExternalTestFileUrl('/test.png', false) . '"><img src="' .
|
||||
self::getExternalTestFileUrl('/test.jpg', false) . '"></a>',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '"><img src="' .
|
||||
$this->get_converted_http_link('/test.jpg') . '"></a>',
|
||||
"expectedcontent" => '<a href="' . self::getExternalTestFileUrl('/test.png', false) . '"><img src="' .
|
||||
self::get_converted_http_link('/test.jpg') . '"></a>',
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -127,8 +127,8 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
* @param string $path Path to be rewritten
|
||||
* @return string
|
||||
*/
|
||||
protected function get_converted_http_link($path) {
|
||||
return preg_replace('/^http:/', 'https:', $this->getExternalTestFileUrl($path, false));
|
||||
protected static function get_converted_http_link($path) {
|
||||
return preg_replace('/^http:/', 'https:', self::getExternalTestFileUrl($path, false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,15 +160,15 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
/**
|
||||
* Data provider for test_http_link_stats
|
||||
*/
|
||||
public function http_link_stats_provider() {
|
||||
public static function http_link_stats_provider(): array {
|
||||
global $CFG;
|
||||
// Get the http url, since the default test wwwroot is https.
|
||||
$wwwrootdomain = 'www.example.com';
|
||||
$wwwroothttp = preg_replace('/^https:/', 'http:', $CFG->wwwroot);
|
||||
$testdomain = $this->get_converted_http_link('');
|
||||
$testdomain = self::get_converted_http_link('');
|
||||
return [
|
||||
"Test image from an available site so shouldn't be reported" => [
|
||||
"content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">',
|
||||
"content" => '<img src="' . self::getExternalTestFileUrl('/test.jpg', false) . '">',
|
||||
"domain" => $testdomain,
|
||||
"expectedcount" => 0,
|
||||
],
|
||||
|
||||
@@ -114,7 +114,7 @@ if ($mode == DELETION_OF_SELECTED_LANG and (!empty($uninstalllang) or !empty($co
|
||||
}
|
||||
}
|
||||
|
||||
if ($mode == UPDATE_ALL_LANG) {
|
||||
if ($mode == UPDATE_ALL_LANG && confirm_sesskey()) {
|
||||
core_php_time_limit::raise();
|
||||
$controller->update_all_installed_languages();
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
<div>
|
||||
<form id="updateform" action="{{updateurl}}" method="post">
|
||||
<fieldset>
|
||||
<input type="hidden" name="sesskey" value="{{sesskey}}">
|
||||
<input type="submit" value="{{#str}}updatelangs, tool_langimport{{/str}}" class="btn btn-secondary">
|
||||
{{#hasmanyinstalledlanguages}}
|
||||
<p class="mt-2 small">{{#str}} updatelangsnote, tool_langimport, {"taskname": {{#quote}}{{updatelangstaskname}}{{/quote}} }{{/str}}</p>
|
||||
|
||||
@@ -48,7 +48,7 @@ class controller_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function uninstall_lang_invalid_provider(): array {
|
||||
public static function uninstall_lang_invalid_provider(): array {
|
||||
return [
|
||||
'Empty string' => [''],
|
||||
'Meaningless empty string' => [' '],
|
||||
|
||||
@@ -389,7 +389,7 @@ class store_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array Array of parameters
|
||||
*/
|
||||
public function decode_other_provider(): array {
|
||||
public static function decode_other_provider(): array {
|
||||
return [
|
||||
[['info' => 'd2819896', 'logurl' => 'discuss.php?d=2819896']],
|
||||
[null],
|
||||
|
||||
@@ -14,6 +14,6 @@ Feature: In a report, admin can see logstore visibility changes
|
||||
And I click on "Enable" "icon" in the "External database log" "table_row"
|
||||
And I navigate to "Reports > Config changes" in site administration
|
||||
Then the following should exist in the "reportbuilder-table" table:
|
||||
| User | Plugin | Setting | New value | Original value |
|
||||
| First name | Plugin | Setting | New value | Original value |
|
||||
| Admin User | logstore_standard | tool_logstore_visibility | 0 | 1 |
|
||||
| Admin User | logstore_database | tool_logstore_visibility | 1 | 0 |
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -71,14 +71,12 @@ define(['jquery'], function($) {
|
||||
return null;
|
||||
};
|
||||
|
||||
// eslint-disable-line valid-jsdoc
|
||||
/**
|
||||
* Return the type of the module.
|
||||
*
|
||||
* @return {String}
|
||||
* @method getType
|
||||
*/
|
||||
// eslint-enable-line valid-jsdoc
|
||||
Rule.prototype.getType = function() {
|
||||
throw new Error('Not implemented');
|
||||
};
|
||||
|
||||
@@ -873,6 +873,8 @@ class external extends external_api {
|
||||
|
||||
$context = context_system::instance();
|
||||
self::validate_context($context);
|
||||
require_capability('moodle/competency:templatemanage', $context);
|
||||
|
||||
$output = $PAGE->get_renderer('tool_lp');
|
||||
|
||||
list($filtercapsql, $filtercapparams) = api::filter_users_with_capability_on_user_context_sql($cap,
|
||||
|
||||
@@ -128,7 +128,7 @@ $functions = array(
|
||||
'classpath' => '',
|
||||
'description' => 'Search for users.',
|
||||
'type' => 'read',
|
||||
'capabilities' => '',
|
||||
'capabilities' => 'moodle/competency:templatemanage',
|
||||
'ajax' => true,
|
||||
),
|
||||
// This function was originally in this plugin but has been moved to core.
|
||||
|
||||
@@ -149,17 +149,14 @@ class externallib_test extends externallib_advanced_testcase {
|
||||
'email' => 'bobbyyy@dyyylan.com', 'phone1' => '123456', 'phone2' => '78910', 'department' => 'Marketing',
|
||||
'institution' => 'HQ'));
|
||||
|
||||
// First we search with no capability assigned.
|
||||
// Assign capability required to perform the search.
|
||||
$this->setUser($ux);
|
||||
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
|
||||
$result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
|
||||
$this->assertCount(0, $result['users']);
|
||||
$this->assertEquals(0, $result['count']);
|
||||
$systemcontext = \context_system::instance();
|
||||
$customrole = $this->assignUserCapability('moodle/competency:templatemanage', $systemcontext->id);
|
||||
|
||||
// Now we assign a different capability.
|
||||
$usercontext = \context_user::instance($u1->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
$customrole = $this->assignUserCapability('moodle/competency:planview', $usercontext->id);
|
||||
$this->assignUserCapability('moodle/competency:templatemanage', $usercontext->id, $customrole);
|
||||
|
||||
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
|
||||
$result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
|
||||
@@ -195,6 +192,8 @@ class externallib_test extends externallib_advanced_testcase {
|
||||
$ux3 = $dg->create_user();
|
||||
role_assign($this->creatorrole, $ux3->id, $usercontext->id);
|
||||
$this->setUser($ux3);
|
||||
$systemcontext = \context_system::instance();
|
||||
$customrole = $this->assignUserCapability('moodle/competency:templatemanage', $systemcontext->id, $customrole);
|
||||
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
|
||||
$result = \external_api::clean_returnvalue(external::search_users_returns(), $result);
|
||||
$this->assertCount(1, $result['users']);
|
||||
@@ -270,6 +269,7 @@ class externallib_test extends externallib_advanced_testcase {
|
||||
|
||||
// Now do the test.
|
||||
$this->setUser($master);
|
||||
$dummyrole = $this->assignUserCapability('moodle/competency:templatemanage', $syscontext->id);
|
||||
$result = external::search_users('MOODLER', 'moodle/site:config');
|
||||
$this->assertCount(2, $result['users']);
|
||||
$this->assertEquals(2, $result['count']);
|
||||
@@ -277,6 +277,7 @@ class externallib_test extends externallib_advanced_testcase {
|
||||
$this->assertArrayHasKey($slave3->id, $result['users']);
|
||||
|
||||
$this->setUser($manager);
|
||||
$this->assignUserCapability('moodle/competency:templatemanage', $syscontext->id, $dummyrole);
|
||||
$result = external::search_users('MOODLER', 'moodle/site:config');
|
||||
$this->assertCount(1, $result['users']);
|
||||
$this->assertEquals(1, $result['count']);
|
||||
@@ -385,6 +386,8 @@ class externallib_test extends externallib_advanced_testcase {
|
||||
|
||||
// Switch to a user that cannot view identity fields.
|
||||
$this->setUser($ux);
|
||||
$systemcontext = \context_system::instance();
|
||||
$this->assignUserCapability('moodle/competency:templatemanage', $systemcontext->id, $dummyrole);
|
||||
$CFG->showuseridentity = 'idnumber,email,phone1,phone2,department,institution';
|
||||
|
||||
// Only names are included.
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
$plugin->version = 2022112800; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2022112801; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2022111800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -419,13 +419,13 @@ class api {
|
||||
public static function get_qrlogin_key(stdClass $mobilesettings) {
|
||||
global $USER;
|
||||
// Delete previous keys.
|
||||
delete_user_key('tool_mobile', $USER->id);
|
||||
delete_user_key('tool_mobile/qrlogin', $USER->id);
|
||||
|
||||
// Create a new key.
|
||||
$iprestriction = !empty($mobilesettings->qrsameipcheck) ? getremoteaddr(null) : null;
|
||||
$qrkeyttl = !empty($mobilesettings->qrkeyttl) ? $mobilesettings->qrkeyttl : self::LOGIN_QR_KEY_TTL;
|
||||
$validuntil = time() + $qrkeyttl;
|
||||
return create_user_key('tool_mobile', $USER->id, null, $iprestriction, $validuntil);
|
||||
return create_user_key('tool_mobile/qrlogin', $USER->id, null, $iprestriction, $validuntil);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?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/>.
|
||||
|
||||
namespace tool_mobile;
|
||||
|
||||
use core\session\utility\cookie_helper;
|
||||
use core\event\user_loggedin;
|
||||
|
||||
/**
|
||||
* Event handler for tool_mobile.
|
||||
*
|
||||
* @package tool_mobile
|
||||
* @copyright 2024 Juan Leyva
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class event_handler {
|
||||
|
||||
/**
|
||||
* Allows the plugin to augment Set-Cookie headers when the user_loggedin event is fired as part of complete_user_login() calls.
|
||||
*
|
||||
* @param user_loggedin $event the event
|
||||
* @return void
|
||||
*/
|
||||
public static function handle_user_loggedin(user_loggedin $event): void {
|
||||
global $CFG;
|
||||
|
||||
// Set Partitioned and Secure attributes to the MoodleSession cookie if the user is using the Moodle app.
|
||||
if (\core_useragent::is_moodle_app()) {
|
||||
cookie_helper::add_attributes_to_cookie_response_header('MoodleSession'.$CFG->sessioncookie, ['Secure', 'Partitioned']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -649,8 +649,8 @@ class external extends external_api {
|
||||
api::check_autologin_prerequisites($params['userid']); // Checks https, avoid site admins using this...
|
||||
|
||||
// Validate and delete the key.
|
||||
$key = validate_user_key($params['qrloginkey'], 'tool_mobile', null);
|
||||
delete_user_key('tool_mobile', $params['userid']);
|
||||
$key = validate_user_key($params['qrloginkey'], 'tool_mobile/qrlogin', null);
|
||||
delete_user_key('tool_mobile/qrlogin', $params['userid']);
|
||||
|
||||
// Double check key belong to user.
|
||||
if ($key->userid != $params['userid']) {
|
||||
|
||||
@@ -66,7 +66,7 @@ class provider implements
|
||||
FROM {user_private_key} k
|
||||
JOIN {user} u ON k.userid = u.id
|
||||
JOIN {context} ctx ON ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel
|
||||
WHERE k.userid = :userid AND k.script = 'tool_mobile'";
|
||||
WHERE k.userid = :userid AND (k.script = 'tool_mobile' OR k.script = 'tool_mobile/qrlogin')";
|
||||
$params = ['userid' => $userid, 'contextlevel' => CONTEXT_USER];
|
||||
$contextlist = new contextlist();
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
@@ -88,6 +88,7 @@ class provider implements
|
||||
|
||||
// Add users based on userkey.
|
||||
\core_userkey\privacy\provider::get_user_contexts_with_script($userlist, $context, 'tool_mobile');
|
||||
\core_userkey\privacy\provider::get_user_contexts_with_script($userlist, $context, 'tool_mobile/qrlogin');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,6 +109,7 @@ class provider implements
|
||||
}
|
||||
// Export associated userkeys.
|
||||
\core_userkey\privacy\provider::export_userkeys($context, [], 'tool_mobile');
|
||||
\core_userkey\privacy\provider::export_userkeys($context, [], 'tool_mobile/qrlogin');
|
||||
}
|
||||
/**
|
||||
* Export all user preferences for the plugin.
|
||||
@@ -138,6 +140,7 @@ class provider implements
|
||||
$userid = $context->instanceid;
|
||||
// Delete all the userkeys.
|
||||
\core_userkey\privacy\provider::delete_userkeys('tool_mobile', $userid);
|
||||
\core_userkey\privacy\provider::delete_userkeys('tool_mobile/qrlogin', $userid);
|
||||
}
|
||||
/**
|
||||
* Delete all user data for the specified user, in the specified contexts.
|
||||
@@ -158,6 +161,7 @@ class provider implements
|
||||
$userid = $context->instanceid;
|
||||
// Delete all the userkeys.
|
||||
\core_userkey\privacy\provider::delete_userkeys('tool_mobile', $userid);
|
||||
\core_userkey\privacy\provider::delete_userkeys('tool_mobile/qrlogin', $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,5 +182,6 @@ class provider implements
|
||||
|
||||
// Delete all the userkeys.
|
||||
\core_userkey\privacy\provider::delete_userkeys('tool_mobile', $userid);
|
||||
\core_userkey\privacy\provider::delete_userkeys('tool_mobile/qrlogin', $userid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* tool_mobile plugin event handler definition.
|
||||
*
|
||||
* @package tool_mobile
|
||||
* @category event
|
||||
* @copyright 2024 Juan Leyva
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$observers = [
|
||||
[
|
||||
'eventname' => '\core\event\user_loggedin',
|
||||
'callback' => '\tool_mobile\event_handler::handle_user_loggedin',
|
||||
],
|
||||
];
|
||||
@@ -69,6 +69,14 @@ if (empty($service)) {
|
||||
throw new moodle_exception('servicenotavailable', 'webservice');
|
||||
}
|
||||
|
||||
// If the user is using the inapp (embedded) browser, we need to set the Secure and Partitioned attributes to the session cookie.
|
||||
if (\core_useragent::is_moodle_app()) {
|
||||
\core\session\utility\cookie_helper::add_attributes_to_cookie_response_header(
|
||||
"MoodleSession{$CFG->sessioncookie}",
|
||||
['Secure', 'Partitioned'],
|
||||
);
|
||||
}
|
||||
|
||||
require_login(0, false);
|
||||
|
||||
// Require an active user: not guest, not suspended.
|
||||
|
||||
@@ -265,3 +265,16 @@ function tool_mobile_pre_processor_message_send($procname, $data) {
|
||||
$data->fullmessagehtml .= html_writer::tag('p', get_string('readingthisemailgettheapp', 'tool_mobile', $url->out()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to add headers before the HTTP headers are sent.
|
||||
*
|
||||
*/
|
||||
function tool_mobile_before_http_headers() {
|
||||
global $CFG;
|
||||
|
||||
// Set Partitioned and Secure attributes to the MoodleSession cookie if the user is using the Moodle app.
|
||||
if (\core_useragent::is_moodle_app()) {
|
||||
\core\session\utility\cookie_helper::add_attributes_to_cookie_response_header('MoodleSession'.$CFG->sessioncookie, ['Secure', 'Partitioned']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,8 @@ class provider_test extends \core_privacy\tests\provider_testcase {
|
||||
$context1 = \context_user::instance($user1->id);
|
||||
$context2 = \context_user::instance($user2->id);
|
||||
$key1 = get_user_key('tool_mobile', $user1->id);
|
||||
$key2 = get_user_key('tool_mobile', $user2->id);
|
||||
$key2 = get_user_key('tool_mobile/qrlogin', $user1->id);
|
||||
$key3 = get_user_key('tool_mobile', $user2->id);
|
||||
|
||||
// Ensure only user1 is found in context1.
|
||||
$userlist = new \core_privacy\local\request\userlist($context1, $component);
|
||||
@@ -174,12 +175,15 @@ class provider_test extends \core_privacy\tests\provider_testcase {
|
||||
$context1 = \context_user::instance($user1->id);
|
||||
$context2 = \context_user::instance($user2->id);
|
||||
$keyvalue1 = get_user_key('tool_mobile', $user1->id);
|
||||
$keyvalue2 = get_user_key('tool_mobile', $user2->id);
|
||||
$keyvalue2 = get_user_key('tool_mobile/qrlogin', $user1->id);
|
||||
$keyvalue3 = get_user_key('tool_mobile', $user2->id);
|
||||
$key1 = $DB->get_record('user_private_key', ['value' => $keyvalue1]);
|
||||
|
||||
// Before deletion, we should have 2 user_private_keys.
|
||||
// Before deletion, we should have 2 user_private_keys for tool_mobile and one for tool_mobile/qrlogin.
|
||||
$count = $DB->count_records('user_private_key', ['script' => 'tool_mobile']);
|
||||
$this->assertEquals(2, $count);
|
||||
$count = $DB->count_records('user_private_key', ['script' => 'tool_mobile/qrlogin']);
|
||||
$this->assertEquals(1, $count);
|
||||
|
||||
// Ensure deleting wrong user in the user context does nothing.
|
||||
$approveduserids = [$user2->id];
|
||||
@@ -197,6 +201,8 @@ class provider_test extends \core_privacy\tests\provider_testcase {
|
||||
// Ensure only user1's data is deleted, user2's remains.
|
||||
$count = $DB->count_records('user_private_key', ['script' => 'tool_mobile']);
|
||||
$this->assertEquals(1, $count);
|
||||
$count = $DB->count_records('user_private_key', ['script' => 'tool_mobile/qrlogin']);
|
||||
$this->assertEquals(0, $count);
|
||||
|
||||
$params = ['script' => $component];
|
||||
$userid = $DB->get_field_select('user_private_key', 'userid', 'script = :script', $params);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
$plugin->version = 2022112800; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2022112801; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2022111800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_mobile'; // Full name of the plugin (used for diagnostics).
|
||||
$plugin->dependencies = array(
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -121,7 +121,6 @@ define(['tool_moodlenet/validator',
|
||||
});
|
||||
// Trigger the transition between 'pages'.
|
||||
carousel.carousel(2);
|
||||
// eslint-disable-next-line max-len
|
||||
modal.setFooter(Templates.render('tool_moodlenet/chooser_footer_close_mnet', {}));
|
||||
};
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ if ($cancel) {
|
||||
}
|
||||
redirect($url);
|
||||
} else if ($continue) {
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
// Handle backups.
|
||||
if (strtolower($importinfo->get_resource()->get_extension()) == 'mbz') {
|
||||
|
||||
@@ -81,7 +81,7 @@ switch ($config->type) {
|
||||
}
|
||||
|
||||
if ($import && $module) {
|
||||
confirm_sesskey();
|
||||
require_sesskey();
|
||||
|
||||
$handlerinfo = $handlerregistry->get_resource_handler_for_mod_and_strategy($importinfo->get_resource(), $module, $strategy);
|
||||
if (is_null($handlerinfo)) {
|
||||
|
||||
@@ -52,7 +52,7 @@ class lib_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_endpoints_provider() {
|
||||
public static function get_endpoints_provider(): array {
|
||||
global $CFG;
|
||||
return [
|
||||
[
|
||||
|
||||
@@ -59,7 +59,7 @@ class import_handler_info_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array the data for creation of the info object.
|
||||
*/
|
||||
public function handler_info_data_provider() {
|
||||
public static function handler_info_data_provider(): array {
|
||||
return [
|
||||
'All data present' => ['label', 'Add a label to the course', false],
|
||||
'Empty module name' => ['', 'Add a file resource to the course', true],
|
||||
|
||||
@@ -53,10 +53,10 @@ class remote_resource_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function remote_resource_data_provider() {
|
||||
public static function remote_resource_data_provider(): array {
|
||||
return [
|
||||
'With filename and extension' => [
|
||||
$this->getExternalTestFileUrl('/test.html'),
|
||||
self::getExternalTestFileUrl('/test.html'),
|
||||
(object) [
|
||||
'name' => 'Test html file',
|
||||
'description' => 'Full description of the html file'
|
||||
@@ -77,9 +77,9 @@ class remote_resource_test extends \advanced_testcase {
|
||||
/**
|
||||
* Test confirming the network based operations of a remote_resource.
|
||||
*/
|
||||
public function test_network_features() {
|
||||
$url = $this->getExternalTestFileUrl('/test.html');
|
||||
$nonexistenturl = $this->getExternalTestFileUrl('/test.htmlzz');
|
||||
public function test_network_features(): void {
|
||||
$url = self::getExternalTestFileUrl('/test.html');
|
||||
$nonexistenturl = self::getExternalTestFileUrl('/test.htmlzz');
|
||||
|
||||
$remoteres = new remote_resource(
|
||||
new \curl(),
|
||||
|
||||
@@ -55,7 +55,7 @@ class url_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function url_provider() {
|
||||
public static function url_provider(): array {
|
||||
return [
|
||||
'No path' => [
|
||||
'url' => 'https://example.moodle.net',
|
||||
|
||||
@@ -50,12 +50,10 @@ list($options, $unrecognized) = cli_get_params(
|
||||
)
|
||||
);
|
||||
|
||||
if (file_exists(__DIR__.'/../../../../vendor/phpunit/phpunit/composer.json')) {
|
||||
// Composer packages present.
|
||||
require_once(__DIR__.'/../../../../vendor/autoload.php');
|
||||
|
||||
} else {
|
||||
// Note: installation via PEAR is not supported any more.
|
||||
// Basic check to see if phpunit is installed.
|
||||
if (!file_exists(__DIR__.'/../../../../vendor/phpunit/phpunit/composer.json') ||
|
||||
!file_exists(__DIR__.'/../../../../vendor/bin/phpunit') ||
|
||||
!file_exists(__DIR__.'/../../../../vendor/autoload.php')) {
|
||||
phpunit_bootstrap_error(PHPUNIT_EXITCODE_PHPUNITMISSING);
|
||||
}
|
||||
|
||||
@@ -74,12 +72,13 @@ if ($options['run']) {
|
||||
}
|
||||
}
|
||||
$_SERVER['argv'] = array_values($_SERVER['argv']);
|
||||
PHPUnit\TextUI\Command::main();
|
||||
require(__DIR__ . '/../../../../vendor/bin/phpunit');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
define('PHPUNIT_UTIL', true);
|
||||
|
||||
require(__DIR__.'/../../../../vendor/autoload.php');
|
||||
require(__DIR__ . '/../../../../lib/phpunit/bootstrap.php');
|
||||
|
||||
// from now on this is a regular moodle CLI_SCRIPT
|
||||
|
||||
@@ -170,6 +170,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
|
||||
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
|
||||
And I click on "Actions" "link_or_button" in the "This privacy policy" "table_row"
|
||||
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
|
||||
And I wait until "Activate" "button" exists
|
||||
And I press "Activate"
|
||||
And I log out
|
||||
When I log in as "manager"
|
||||
@@ -260,6 +261,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
|
||||
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
|
||||
And I click on "Actions" "link_or_button" in the "This privacy policy" "table_row"
|
||||
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
|
||||
And I wait until "Activate" "button" exists
|
||||
And I press "Activate"
|
||||
And I log out
|
||||
When I log in as "manager"
|
||||
|
||||
@@ -175,7 +175,7 @@ class category_bin_test extends \advanced_testcase {
|
||||
* Used to verify that recycle bin is immune to various settings. Provides plugin, name, value for
|
||||
* direct usage with set_config()
|
||||
*/
|
||||
public function recycle_bin_settings_provider() {
|
||||
public static function recycle_bin_settings_provider(): array {
|
||||
return [
|
||||
'backup/backup_auto_storage moodle' => [[
|
||||
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 0],
|
||||
|
||||
@@ -172,7 +172,7 @@ class course_bin_test extends \advanced_testcase {
|
||||
* Used to verify that recycle bin is immune to various settings. Provides plugin, name, value for
|
||||
* direct usage with set_config()
|
||||
*/
|
||||
public function recycle_bin_settings_provider() {
|
||||
public static function recycle_bin_settings_provider(): array {
|
||||
return [
|
||||
'backup/backup_auto_storage moodle' => [[
|
||||
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 0],
|
||||
|
||||
@@ -87,7 +87,8 @@ require_sesskey();
|
||||
|
||||
// Prepare to handle output via mtrace.
|
||||
echo html_writer::start_tag('pre');
|
||||
require('lib.php');
|
||||
|
||||
require_once("{$CFG->dirroot}/{$CFG->admin}/tool/task/lib.php");
|
||||
$CFG->mtrace_wrapper = 'tool_task_mtrace_wrapper';
|
||||
|
||||
// Run the specified task (this will output an error if it doesn't exist).
|
||||
|
||||
@@ -62,8 +62,8 @@ Feature: Manage scheduled tasks
|
||||
And I press "Save changes"
|
||||
Then I should see "Changes saved"
|
||||
And the following should not exist in the "admintable" table:
|
||||
| Name | Component | Minute | Hour | Day | Day of week | Month |
|
||||
| Log table cleanup | Standard log | */5 | 1 | 2 | 4 | 3 |
|
||||
| Name | Minute | Hour | Day | Day of week | Month |
|
||||
| Log table cleanup | */5 | 1 | 2 | 4 | 3 |
|
||||
And I should see "Log table cleanup" in the "tr.table-primary" "css_element"
|
||||
|
||||
Scenario: Disabled plugin's tasks are labelled as disabled too
|
||||
|
||||
@@ -1182,7 +1182,7 @@ class course_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function enrolment_uploaddata_error_provider(): array {
|
||||
public static function enrolment_uploaddata_error_provider(): array {
|
||||
return [
|
||||
['errorcannotcreateorupdateenrolment', [
|
||||
'shortname' => 'C1',
|
||||
|
||||
@@ -30,7 +30,7 @@ class field_value_validators_test extends \advanced_testcase {
|
||||
/**
|
||||
* Data provider for \field_value_validators_testcase::test_validate_theme().
|
||||
*/
|
||||
public function themes_provider() {
|
||||
public static function themes_provider(): array {
|
||||
return [
|
||||
'User themes disabled' => [
|
||||
false, 'boost', 'warning', get_string('userthemesnotallowed', 'tool_uploaduser')
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -36,6 +36,7 @@ import {dispatchEvent} from 'core/event_dispatcher';
|
||||
import {eventTypes} from './events';
|
||||
import {get_string as getString} from 'core/str';
|
||||
import {prefetchStrings} from 'core/prefetch';
|
||||
import PendingPromise from 'core/pending';
|
||||
|
||||
/**
|
||||
* The minimum spacing for tour step to display.
|
||||
@@ -485,14 +486,22 @@ const Tour = class {
|
||||
return this.endTour();
|
||||
}
|
||||
|
||||
const pendingPromise = new PendingPromise(`tool_usertours/tour:_gotoStep-${stepConfig.stepNumber}`);
|
||||
|
||||
if (typeof stepConfig.delay !== 'undefined' && stepConfig.delay && !stepConfig.delayed) {
|
||||
stepConfig.delayed = true;
|
||||
window.setTimeout(this._gotoStep.bind(this), stepConfig.delay, stepConfig, direction);
|
||||
window.setTimeout(function(stepConfig, direction) {
|
||||
this._gotoStep(stepConfig, direction);
|
||||
pendingPromise.resolve();
|
||||
}, stepConfig.delay, stepConfig, direction);
|
||||
|
||||
return this;
|
||||
} else if (!stepConfig.orphan && !this.isStepActuallyVisible(stepConfig)) {
|
||||
let fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';
|
||||
return this.gotoStep(this[fn](stepConfig.stepNumber), direction);
|
||||
const fn = direction == -1 ? 'getPreviousStepNumber' : 'getNextStepNumber';
|
||||
this.gotoStep(this[fn](stepConfig.stepNumber), direction);
|
||||
|
||||
pendingPromise.resolve();
|
||||
return this;
|
||||
}
|
||||
|
||||
this.hide();
|
||||
@@ -503,6 +512,7 @@ const Tour = class {
|
||||
this.dispatchEvent(eventTypes.stepRendered, {stepConfig});
|
||||
}
|
||||
|
||||
pendingPromise.resolve();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -820,12 +830,14 @@ const Tour = class {
|
||||
left: 0,
|
||||
});
|
||||
|
||||
const pendingPromise = new PendingPromise(`tool_usertours/tour:addStepToPage-${stepConfig.stepNumber}`);
|
||||
animationTarget
|
||||
.animate({
|
||||
scrollTop: this.calculateScrollTop(stepConfig),
|
||||
}).promise().then(function() {
|
||||
this.positionStep(stepConfig);
|
||||
this.revealStep(stepConfig);
|
||||
pendingPromise.resolve();
|
||||
return;
|
||||
}.bind(this))
|
||||
.catch(function() {
|
||||
@@ -897,6 +909,7 @@ const Tour = class {
|
||||
*/
|
||||
revealStep(stepConfig) {
|
||||
// Fade the step in.
|
||||
const pendingPromise = new PendingPromise(`tool_usertours/tour:revealStep-${stepConfig.stepNumber}`);
|
||||
this.currentStepNode.fadeIn('', $.proxy(function() {
|
||||
// Announce via ARIA.
|
||||
this.announceStep(stepConfig);
|
||||
@@ -910,6 +923,7 @@ const Tour = class {
|
||||
if (this.currentStepNode) {
|
||||
this.currentStepNode.focus();
|
||||
}
|
||||
pendingPromise.resolve();
|
||||
}, this), 100);
|
||||
|
||||
}, this));
|
||||
@@ -1157,6 +1171,7 @@ const Tour = class {
|
||||
return this;
|
||||
}
|
||||
|
||||
const pendingPromise = new PendingPromise('tool_usertours/tour:hide');
|
||||
if (this.currentStepNode && this.currentStepNode.length) {
|
||||
this.currentStepNode.hide();
|
||||
if (this.currentStepPopper) {
|
||||
@@ -1191,17 +1206,22 @@ const Tour = class {
|
||||
this.currentStepConfig = null;
|
||||
}
|
||||
|
||||
let fadeTime = 0;
|
||||
if (transition) {
|
||||
fadeTime = 400;
|
||||
}
|
||||
|
||||
// Remove the backdrop features.
|
||||
$('[data-flexitour="step-background"]').remove();
|
||||
$('[data-flexitour="step-backdrop"]').removeAttr('data-flexitour');
|
||||
$('[data-flexitour="backdrop"]').fadeOut(fadeTime, function() {
|
||||
$(this).remove();
|
||||
});
|
||||
|
||||
const backdrop = $('[data-flexitour="backdrop"]');
|
||||
if (backdrop.length) {
|
||||
if (transition) {
|
||||
const backdropRemovalPromise = new PendingPromise('tool_usertours/tour:hide:backdrop');
|
||||
backdrop.fadeOut(400, function() {
|
||||
$(this).remove();
|
||||
backdropRemovalPromise.resolve();
|
||||
});
|
||||
} else {
|
||||
backdrop.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove aria-describedby and tabindex attributes.
|
||||
if (this.currentStepNode && this.currentStepNode.length) {
|
||||
@@ -1222,6 +1242,8 @@ const Tour = class {
|
||||
|
||||
this.currentStepNode = null;
|
||||
this.currentStepPopper = null;
|
||||
|
||||
pendingPromise.resolve();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class accessdate_filter_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filter_matches_provider() {
|
||||
public static function filter_matches_provider(): array {
|
||||
return [
|
||||
'No config set; Matches' => [
|
||||
[],
|
||||
|
||||
@@ -126,7 +126,7 @@ class cache_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_matching_tourdata_provider() {
|
||||
public static function get_matching_tourdata_provider(): array {
|
||||
$tourconfigs = [
|
||||
(object) [
|
||||
'name' => 'my_exact_1',
|
||||
|
||||
@@ -42,7 +42,7 @@ class helper_test extends advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_string_from_input_provider(): array {
|
||||
public static function get_string_from_input_provider(): array {
|
||||
return [
|
||||
'Text' => [
|
||||
'example',
|
||||
|
||||
@@ -74,7 +74,7 @@ class manager_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sesskey_required_provider() {
|
||||
public static function sesskey_required_provider(): array {
|
||||
$tourid = rand(1, 100);
|
||||
$stepid = rand(1, 100);
|
||||
|
||||
@@ -121,7 +121,7 @@ class manager_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function move_tour_provider() {
|
||||
public static function move_tour_provider(): array {
|
||||
$alltours = [
|
||||
['name' => 'Tour 1'],
|
||||
['name' => 'Tour 2'],
|
||||
@@ -198,7 +198,7 @@ class manager_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_matching_tours_provider() {
|
||||
public static function get_matching_tours_provider(): array {
|
||||
global $CFG;
|
||||
|
||||
$alltours = [
|
||||
|
||||
@@ -73,7 +73,7 @@ class step_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dirty_value_provider() {
|
||||
public static function dirty_value_provider(): array {
|
||||
return [
|
||||
'tourid' => [
|
||||
'tourid',
|
||||
@@ -160,7 +160,7 @@ class step_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function step_sortorder_provider() {
|
||||
public static function step_sortorder_provider(): array {
|
||||
return [
|
||||
[0, 5, true, false],
|
||||
[1, 5, false, false],
|
||||
@@ -254,7 +254,7 @@ class step_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_config_provider() {
|
||||
public static function get_config_provider(): array {
|
||||
$allvalues = (object) [
|
||||
'some' => 'value',
|
||||
'another' => 42,
|
||||
@@ -410,7 +410,7 @@ class step_test extends \advanced_testcase {
|
||||
/**
|
||||
* Data provider for set_config.
|
||||
*/
|
||||
public function set_config_provider() {
|
||||
public static function set_config_provider(): array {
|
||||
$allvalues = (object) [
|
||||
'some' => 'value',
|
||||
'another' => 42,
|
||||
@@ -764,7 +764,7 @@ class step_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getter_provider() {
|
||||
public static function getter_provider(): array {
|
||||
return [
|
||||
'id' => [
|
||||
'id',
|
||||
|
||||
@@ -30,7 +30,7 @@ class theme_filter_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filter_matches_provider() {
|
||||
public static function filter_matches_provider(): array {
|
||||
return [
|
||||
'No config set; Matches' => [
|
||||
null,
|
||||
|
||||
@@ -73,7 +73,7 @@ class tour_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dirty_value_provider() {
|
||||
public static function dirty_value_provider(): array {
|
||||
return [
|
||||
'name' => [
|
||||
'name',
|
||||
@@ -126,7 +126,7 @@ class tour_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getter_provider() {
|
||||
public static function getter_provider(): array {
|
||||
return [
|
||||
'id' => [
|
||||
'id',
|
||||
@@ -430,7 +430,7 @@ class tour_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_config_provider() {
|
||||
public static function get_config_provider(): array {
|
||||
$allvalues = (object) [
|
||||
'some' => 'value',
|
||||
'another' => 42,
|
||||
@@ -624,7 +624,7 @@ class tour_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function should_show_for_user_provider() {
|
||||
public static function should_show_for_user_provider(): array {
|
||||
$time = time();
|
||||
return [
|
||||
'Not seen by user at all' => [
|
||||
@@ -715,7 +715,7 @@ class tour_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_tour_key_provider() {
|
||||
public static function get_tour_key_provider(): array {
|
||||
$id = rand(1, 100);
|
||||
$time = time();
|
||||
|
||||
@@ -723,7 +723,7 @@ class tour_test extends \advanced_testcase {
|
||||
'No initial values' => [
|
||||
$id,
|
||||
[null, $time],
|
||||
$this->greaterThanOrEqual($time),
|
||||
self::greaterThanOrEqual($time),
|
||||
true,
|
||||
null,
|
||||
sprintf('tool_usertours_\d_%d_%s', $id, $time),
|
||||
@@ -879,7 +879,7 @@ class tour_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sortorder_first_last_provider() {
|
||||
public static function sortorder_first_last_provider(): array {
|
||||
$topcount = rand(10, 100);
|
||||
return [
|
||||
'Only tour => first + last' => [
|
||||
@@ -987,7 +987,7 @@ class tour_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_filter_values_provider() {
|
||||
public static function get_filter_values_provider(): array {
|
||||
$cheese = ['cheddar', 'boursin', 'mozzarella'];
|
||||
$horses = ['coolie', 'dakota', 'leo', 'twiggy'];
|
||||
return [
|
||||
@@ -1046,7 +1046,7 @@ class tour_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function set_filter_values_provider() {
|
||||
public static function set_filter_values_provider(): array {
|
||||
$cheese = ['cheddar', 'boursin', 'mozzarella'];
|
||||
$horses = ['coolie', 'dakota', 'leo', 'twiggy'];
|
||||
|
||||
|
||||
@@ -36,6 +36,11 @@ class new_table_from_mysql extends XMLDBAction {
|
||||
function init() {
|
||||
parent::init();
|
||||
|
||||
global $DB;
|
||||
if ($DB->get_dbfamily() !== 'mysql') {
|
||||
throw new moodle_exception('DB family not supported');
|
||||
}
|
||||
|
||||
// Set own custom attributes
|
||||
|
||||
// Get needed strings
|
||||
@@ -55,8 +60,6 @@ class new_table_from_mysql extends XMLDBAction {
|
||||
function invoke() {
|
||||
parent::invoke();
|
||||
|
||||
$result = true;
|
||||
|
||||
// Set own core attributes
|
||||
$this->does_generate = ACTION_GENERATE_HTML;
|
||||
|
||||
@@ -125,11 +128,15 @@ class new_table_from_mysql extends XMLDBAction {
|
||||
// If table, retrofit information and, if everything works,
|
||||
// go to the table edit action
|
||||
} else {
|
||||
// Get some params (table is mandatory here)
|
||||
$tableparam = required_param('table', PARAM_CLEAN);
|
||||
$afterparam = required_param('after', PARAM_CLEAN);
|
||||
// Get some params (table is mandatory here).
|
||||
$tableparam = required_param('table', PARAM_ALPHANUMEXT);
|
||||
$afterparam = required_param('after', PARAM_ALPHANUMEXT);
|
||||
|
||||
// Create one new xmldb_table
|
||||
if (empty($tableparam) || empty($afterparam)) {
|
||||
throw new moodle_exception('Invalid param value detected.');
|
||||
}
|
||||
|
||||
// Create one new xmldb_table.
|
||||
$table = new xmldb_table(strtolower(trim($tableparam)));
|
||||
$table->setComment($table->getName() . ' table retrofitted from MySQL');
|
||||
// Get fields info from ADODb
|
||||
@@ -147,7 +154,6 @@ class new_table_from_mysql extends XMLDBAction {
|
||||
// Get PK, UK and indexes info from ADODb
|
||||
$dbindexes = $DB->get_indexes($tableparam);
|
||||
if ($dbindexes) {
|
||||
$lastkey = NULL; //To temp store the last key processed
|
||||
foreach ($dbindexes as $indexname => $dbindex) {
|
||||
// Add the indexname to the array
|
||||
$dbindex['name'] = $indexname;
|
||||
@@ -156,9 +162,6 @@ class new_table_from_mysql extends XMLDBAction {
|
||||
$key = new xmldb_key(strtolower($dbindex['name']));
|
||||
// Set key with info retrofitted
|
||||
$key->setFromADOKey($dbindex);
|
||||
// Set default comment to PKs
|
||||
if ($key->getType() == XMLDB_KEY_PRIMARY) {
|
||||
}
|
||||
// Add key to the table
|
||||
$table->addKey($key);
|
||||
|
||||
@@ -172,18 +175,17 @@ class new_table_from_mysql extends XMLDBAction {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Finally, add the whole retroffited table to the structure
|
||||
// in the place specified
|
||||
// Finally, add the whole retrofitted table to the structure in the place specified.
|
||||
$structure->addTable($table, $afterparam);
|
||||
}
|
||||
|
||||
// Launch postaction if exists (leave this here!)
|
||||
if ($this->getPostAction() && $result) {
|
||||
if ($this->getPostAction()) {
|
||||
return $this->launch($this->getPostAction());
|
||||
}
|
||||
|
||||
// Return ok if arrived here
|
||||
return $result;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ Feature: Manage analytics models
|
||||
And I should see "Read actions amount"
|
||||
And I click on "Select Student 6 for bulk action" "checkbox" in the "Student 6" "table_row"
|
||||
And I click on "Accept" "button"
|
||||
And I wait until "Confirm" "button" exists
|
||||
And I click on "Confirm" "button" in the "Accept" "dialogue"
|
||||
And I click on "View prediction details" "icon" in the "Student 5" "table_row"
|
||||
And I click on "Select Student 5 for bulk action" "checkbox" in the "Student 5" "table_row"
|
||||
@@ -145,7 +146,8 @@ Feature: Manage analytics models
|
||||
When I open the action menu in "Students at risk of not meeting the course completion conditions" "table_row"
|
||||
And I choose "Export" in the open action menu
|
||||
And I click on "Actions" "link" in the "Students at risk of not meeting the course completion conditions" "table_row"
|
||||
And following "Export" should download between "100" and "500" bytes
|
||||
And following "Export" should download a file that:
|
||||
| Contains file in zip | model-config.json |
|
||||
|
||||
Scenario: Check invalid site elements
|
||||
When I open the action menu in "Students at risk of not meeting the course completion conditions" "table_row"
|
||||
|
||||
@@ -23,8 +23,7 @@ namespace core_analytics;
|
||||
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class calculation_info_test extends \advanced_testcase {
|
||||
|
||||
final class calculation_info_test extends \advanced_testcase {
|
||||
/**
|
||||
* test_calculation_info description
|
||||
*
|
||||
@@ -88,7 +87,7 @@ class calculation_info_test extends \advanced_testcase {
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function provider_test_calculation_info_add_pull() {
|
||||
public static function provider_test_calculation_info_add_pull(): array {
|
||||
return [
|
||||
'mixed-types' => ['asd', true, [123, 123, 123], (object)['asd' => 'fgfg']],
|
||||
];
|
||||
|
||||
+9
-11
@@ -14,31 +14,29 @@
|
||||
// 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 activities completed by classification.
|
||||
*
|
||||
* @package core_analytics
|
||||
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_analytics;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use advanced_testcase;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Unit tests for activities completed by classification.
|
||||
*
|
||||
* @package core_analytics
|
||||
* @covers \core_analytics\local\indicator\community_of_inquiry_activity
|
||||
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class community_of_inquiry_activities_completed_by_testcase extends advanced_testcase {
|
||||
final class community_of_inquiry_activities_completed_by_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* availability_levels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function availability_levels() {
|
||||
public static function availability_levels(): array {
|
||||
return array(
|
||||
'activity' => array('activity'),
|
||||
'section' => array('section'),
|
||||
@@ -148,7 +146,7 @@ class community_of_inquiry_activities_completed_by_testcase extends advanced_tes
|
||||
$second = $startdate + WEEKSECS;
|
||||
$third = $startdate + (WEEKSECS * 2);
|
||||
$forth = $startdate + (WEEKSECS * 3);
|
||||
$this->assertCount(1, $method->invoke($indicator, $first, $first + WEEKSECS, $stu1));
|
||||
$this->assertCount(2, $method->invoke($indicator, $first, $first + WEEKSECS, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $second, $second + WEEKSECS, $stu1));
|
||||
$this->assertCount(0, $method->invoke($indicator, $third, $third + WEEKSECS, $stu1));
|
||||
$this->assertCount(2, $method->invoke($indicator, $forth, $forth + WEEKSECS, $stu1));
|
||||
@@ -29,8 +29,7 @@ require_once(__DIR__ . '/fixtures/test_indicator_min.php');
|
||||
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class indicator_test extends \advanced_testcase {
|
||||
|
||||
final class indicator_test extends \advanced_testcase {
|
||||
/**
|
||||
* test_validate_calculated_value
|
||||
*
|
||||
@@ -50,7 +49,7 @@ class indicator_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function validate_calculated_value() {
|
||||
public static function validate_calculated_value(): array {
|
||||
return [
|
||||
'max' => ['test_indicator_max', [1]],
|
||||
'min' => ['test_indicator_min', [-1]],
|
||||
@@ -83,7 +82,7 @@ class indicator_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function validate_calculated_value_exceptions() {
|
||||
public static function validate_calculated_value_exceptions(): array {
|
||||
return [
|
||||
'max' => ['test_indicator_max', 2],
|
||||
'min' => ['test_indicator_min', -2],
|
||||
|
||||
@@ -31,8 +31,7 @@ require_once(__DIR__ . '/fixtures/test_target_course_level_shortname.php');
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \core_analytics\manager
|
||||
*/
|
||||
class manager_test extends \advanced_testcase {
|
||||
|
||||
final class manager_test extends \advanced_testcase {
|
||||
/**
|
||||
* test_deleted_context
|
||||
*/
|
||||
@@ -44,7 +43,7 @@ class manager_test extends \advanced_testcase {
|
||||
set_config('enabled_stores', 'logstore_standard', 'tool_log');
|
||||
|
||||
$target = \core_analytics\manager::get_target('test_target_course_level_shortname');
|
||||
$indicators = array('test_indicator_max', 'test_indicator_min', 'test_indicator_fullname');
|
||||
$indicators = ['test_indicator_max', 'test_indicator_min', 'test_indicator_fullname'];
|
||||
foreach ($indicators as $key => $indicator) {
|
||||
$indicators[$key] = \core_analytics\manager::get_indicator($indicator);
|
||||
}
|
||||
@@ -52,10 +51,10 @@ class manager_test extends \advanced_testcase {
|
||||
$model = \core_analytics\model::create($target, $indicators);
|
||||
$modelobj = $model->get_model_obj();
|
||||
|
||||
$coursepredict1 = $this->getDataGenerator()->create_course(array('visible' => 0));
|
||||
$coursepredict2 = $this->getDataGenerator()->create_course(array('visible' => 0));
|
||||
$coursetrain1 = $this->getDataGenerator()->create_course(array('visible' => 1));
|
||||
$coursetrain2 = $this->getDataGenerator()->create_course(array('visible' => 1));
|
||||
$coursepredict1 = $this->getDataGenerator()->create_course(['visible' => 0]);
|
||||
$coursepredict2 = $this->getDataGenerator()->create_course(['visible' => 0]);
|
||||
$coursetrain1 = $this->getDataGenerator()->create_course(['visible' => 1]);
|
||||
$coursetrain2 = $this->getDataGenerator()->create_course(['visible' => 1]);
|
||||
|
||||
$model->enable('\core\analytics\time_splitting\no_splitting');
|
||||
|
||||
@@ -65,25 +64,33 @@ class manager_test extends \advanced_testcase {
|
||||
// Generate a prediction action to confirm that it is deleted when there is an important update.
|
||||
$predictions = $DB->get_records('analytics_predictions');
|
||||
$prediction = reset($predictions);
|
||||
$prediction = new \core_analytics\prediction($prediction, array('whatever' => 'not used'));
|
||||
$prediction = new \core_analytics\prediction($prediction, ['whatever' => 'not used']);
|
||||
$prediction->action_executed(\core_analytics\prediction::ACTION_USEFUL, $model->get_target());
|
||||
|
||||
$predictioncontextid = $prediction->get_prediction_data()->contextid;
|
||||
|
||||
$npredictions = $DB->count_records('analytics_predictions', array('contextid' => $predictioncontextid));
|
||||
$npredictionactions = $DB->count_records('analytics_prediction_actions',
|
||||
array('predictionid' => $prediction->get_prediction_data()->id));
|
||||
$nindicatorcalc = $DB->count_records('analytics_indicator_calc', array('contextid' => $predictioncontextid));
|
||||
$npredictions = $DB->count_records('analytics_predictions', ['contextid' => $predictioncontextid]);
|
||||
$npredictionactions = $DB->count_records(
|
||||
'analytics_prediction_actions',
|
||||
['predictionid' => $prediction->get_prediction_data()->id]
|
||||
);
|
||||
$nindicatorcalc = $DB->count_records('analytics_indicator_calc', ['contextid' => $predictioncontextid]);
|
||||
|
||||
\core_analytics\manager::cleanup();
|
||||
|
||||
// Nothing is incorrectly deleted.
|
||||
$this->assertEquals($npredictions, $DB->count_records('analytics_predictions',
|
||||
array('contextid' => $predictioncontextid)));
|
||||
$this->assertEquals($npredictionactions, $DB->count_records('analytics_prediction_actions',
|
||||
array('predictionid' => $prediction->get_prediction_data()->id)));
|
||||
$this->assertEquals($nindicatorcalc, $DB->count_records('analytics_indicator_calc',
|
||||
array('contextid' => $predictioncontextid)));
|
||||
$this->assertEquals($npredictions, $DB->count_records(
|
||||
'analytics_predictions',
|
||||
['contextid' => $predictioncontextid]
|
||||
));
|
||||
$this->assertEquals($npredictionactions, $DB->count_records(
|
||||
'analytics_prediction_actions',
|
||||
['predictionid' => $prediction->get_prediction_data()->id]
|
||||
));
|
||||
$this->assertEquals($nindicatorcalc, $DB->count_records(
|
||||
'analytics_indicator_calc',
|
||||
['contextid' => $predictioncontextid]
|
||||
));
|
||||
|
||||
// Now we delete a context, the course predictions and prediction actions should be deleted.
|
||||
$deletedcontext = \context::instance_by_id($predictioncontextid);
|
||||
@@ -91,10 +98,12 @@ class manager_test extends \advanced_testcase {
|
||||
|
||||
\core_analytics\manager::cleanup();
|
||||
|
||||
$this->assertEmpty($DB->count_records('analytics_predictions', array('contextid' => $predictioncontextid)));
|
||||
$this->assertEmpty($DB->count_records('analytics_prediction_actions',
|
||||
array('predictionid' => $prediction->get_prediction_data()->id)));
|
||||
$this->assertEmpty($DB->count_records('analytics_indicator_calc', array('contextid' => $predictioncontextid)));
|
||||
$this->assertEmpty($DB->count_records('analytics_predictions', ['contextid' => $predictioncontextid]));
|
||||
$this->assertEmpty($DB->count_records(
|
||||
'analytics_prediction_actions',
|
||||
['predictionid' => $prediction->get_prediction_data()->id]
|
||||
));
|
||||
$this->assertEmpty($DB->count_records('analytics_indicator_calc', ['contextid' => $predictioncontextid]));
|
||||
|
||||
set_config('enabled_stores', '', 'tool_log');
|
||||
get_log_manager(true);
|
||||
@@ -111,7 +120,7 @@ class manager_test extends \advanced_testcase {
|
||||
set_config('enabled_stores', 'logstore_standard', 'tool_log');
|
||||
|
||||
$target = \core_analytics\manager::get_target('test_target_course_level_shortname');
|
||||
$indicators = array('test_indicator_max', 'test_indicator_min', 'test_indicator_fullname');
|
||||
$indicators = ['test_indicator_max', 'test_indicator_min', 'test_indicator_fullname'];
|
||||
foreach ($indicators as $key => $indicator) {
|
||||
$indicators[$key] = \core_analytics\manager::get_indicator($indicator);
|
||||
}
|
||||
@@ -119,10 +128,10 @@ class manager_test extends \advanced_testcase {
|
||||
$model = \core_analytics\model::create($target, $indicators);
|
||||
$modelobj = $model->get_model_obj();
|
||||
|
||||
$coursepredict1 = $this->getDataGenerator()->create_course(array('visible' => 0));
|
||||
$coursepredict2 = $this->getDataGenerator()->create_course(array('visible' => 0));
|
||||
$coursetrain1 = $this->getDataGenerator()->create_course(array('visible' => 1));
|
||||
$coursetrain2 = $this->getDataGenerator()->create_course(array('visible' => 1));
|
||||
$coursepredict1 = $this->getDataGenerator()->create_course(['visible' => 0]);
|
||||
$coursepredict2 = $this->getDataGenerator()->create_course(['visible' => 0]);
|
||||
$coursetrain1 = $this->getDataGenerator()->create_course(['visible' => 1]);
|
||||
$coursetrain2 = $this->getDataGenerator()->create_course(['visible' => 1]);
|
||||
|
||||
$model->enable('\core\analytics\time_splitting\no_splitting');
|
||||
|
||||
@@ -139,9 +148,9 @@ class manager_test extends \advanced_testcase {
|
||||
|
||||
\core_analytics\manager::cleanup();
|
||||
|
||||
$this->assertEmpty($DB->count_records('analytics_predict_samples', array('analysableid' => $coursepredict1->id)));
|
||||
$this->assertEmpty($DB->count_records('analytics_train_samples', array('analysableid' => $coursepredict1->id)));
|
||||
$this->assertEmpty($DB->count_records('analytics_used_analysables', array('analysableid' => $coursepredict1->id)));
|
||||
$this->assertEmpty($DB->count_records('analytics_predict_samples', ['analysableid' => $coursepredict1->id]));
|
||||
$this->assertEmpty($DB->count_records('analytics_train_samples', ['analysableid' => $coursepredict1->id]));
|
||||
$this->assertEmpty($DB->count_records('analytics_used_analysables', ['analysableid' => $coursepredict1->id]));
|
||||
|
||||
set_config('enabled_stores', '', 'tool_log');
|
||||
get_log_manager(true);
|
||||
@@ -190,7 +199,7 @@ class manager_test extends \advanced_testcase {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// This is expected to run without an exception.
|
||||
$models = $this->load_models_from_fixture_file('no_teaching');
|
||||
$models = self::load_models_from_fixture_file('no_teaching');
|
||||
\core_analytics\manager::validate_models_declaration($models);
|
||||
}
|
||||
|
||||
@@ -214,34 +223,34 @@ class manager_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array of (string)testcase => [(array)models, (string)expected exception message]
|
||||
*/
|
||||
public function validate_models_declaration_exceptions_provider() {
|
||||
public static function validate_models_declaration_exceptions_provider(): array {
|
||||
return [
|
||||
'missing_target' => [
|
||||
$this->load_models_from_fixture_file('missing_target'),
|
||||
self::load_models_from_fixture_file('missing_target'),
|
||||
'Missing target declaration',
|
||||
],
|
||||
'invalid_target' => [
|
||||
$this->load_models_from_fixture_file('invalid_target'),
|
||||
self::load_models_from_fixture_file('invalid_target'),
|
||||
'Invalid target classname',
|
||||
],
|
||||
'missing_indicators' => [
|
||||
$this->load_models_from_fixture_file('missing_indicators'),
|
||||
self::load_models_from_fixture_file('missing_indicators'),
|
||||
'Missing indicators declaration',
|
||||
],
|
||||
'invalid_indicators' => [
|
||||
$this->load_models_from_fixture_file('invalid_indicators'),
|
||||
self::load_models_from_fixture_file('invalid_indicators'),
|
||||
'Invalid indicator classname',
|
||||
],
|
||||
'invalid_time_splitting' => [
|
||||
$this->load_models_from_fixture_file('invalid_time_splitting'),
|
||||
self::load_models_from_fixture_file('invalid_time_splitting'),
|
||||
'Invalid time splitting classname',
|
||||
],
|
||||
'invalid_time_splitting_fq' => [
|
||||
$this->load_models_from_fixture_file('invalid_time_splitting_fq'),
|
||||
self::load_models_from_fixture_file('invalid_time_splitting_fq'),
|
||||
'Expecting fully qualified time splitting classname',
|
||||
],
|
||||
'invalid_enabled' => [
|
||||
$this->load_models_from_fixture_file('invalid_enabled'),
|
||||
self::load_models_from_fixture_file('invalid_enabled'),
|
||||
'Cannot enable a model without time splitting method specified',
|
||||
],
|
||||
];
|
||||
@@ -253,12 +262,12 @@ class manager_test extends \advanced_testcase {
|
||||
* @param string $filename
|
||||
* @return array
|
||||
*/
|
||||
protected function load_models_from_fixture_file(string $filename) {
|
||||
protected static function load_models_from_fixture_file(string $filename) {
|
||||
global $CFG;
|
||||
|
||||
$models = null;
|
||||
|
||||
require($CFG->dirroot.'/analytics/tests/fixtures/db_analytics_php/'.$filename.'.php');
|
||||
require("{$CFG->dirroot}/analytics/tests/fixtures/db_analytics_php/{$filename}.php");
|
||||
|
||||
return $models;
|
||||
}
|
||||
@@ -430,9 +439,9 @@ class manager_test extends \advanced_testcase {
|
||||
*/
|
||||
public function test_model_declaration_identifier() {
|
||||
|
||||
$noteaching1 = $this->load_models_from_fixture_file('no_teaching');
|
||||
$noteaching2 = $this->load_models_from_fixture_file('no_teaching');
|
||||
$noteaching3 = $this->load_models_from_fixture_file('no_teaching');
|
||||
$noteaching1 = self::load_models_from_fixture_file('no_teaching');
|
||||
$noteaching2 = self::load_models_from_fixture_file('no_teaching');
|
||||
$noteaching3 = self::load_models_from_fixture_file('no_teaching');
|
||||
|
||||
// Same model declaration should always lead to same identifier.
|
||||
$this->assertEquals(
|
||||
@@ -474,9 +483,9 @@ class manager_test extends \advanced_testcase {
|
||||
public function test_get_declared_target_and_indicators_instances() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$definition = $this->load_models_from_fixture_file('no_teaching');
|
||||
$definition = self::load_models_from_fixture_file('no_teaching');
|
||||
|
||||
list($target, $indicators) = \core_analytics\manager::get_declared_target_and_indicators_instances($definition[0]);
|
||||
[$target, $indicators] = \core_analytics\manager::get_declared_target_and_indicators_instances($definition[0]);
|
||||
|
||||
$this->assertTrue($target instanceof \core_analytics\local\target\base);
|
||||
$this->assertNotEmpty($indicators);
|
||||
|
||||
@@ -111,7 +111,7 @@ class prediction_actions_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function execute_actions_provider(): array {
|
||||
public static function execute_actions_provider(): array {
|
||||
return [
|
||||
'Empty actions with no filter' => [
|
||||
[],
|
||||
|
||||
@@ -341,14 +341,14 @@ class prediction_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_ml_training_and_prediction() {
|
||||
public static function provider_ml_training_and_prediction(): array {
|
||||
$cases = array(
|
||||
'no_splitting' => array('\core\analytics\time_splitting\no_splitting', 0, 1),
|
||||
'quarters' => array('\core\analytics\time_splitting\quarters', 3, 4)
|
||||
);
|
||||
|
||||
// We need to test all system prediction processors.
|
||||
return $this->add_prediction_processors($cases);
|
||||
return static::add_prediction_processors($cases);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,13 +417,13 @@ class prediction_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_ml_processors() {
|
||||
public static function provider_ml_processors(): array {
|
||||
$cases = [
|
||||
'case' => [],
|
||||
];
|
||||
|
||||
// We need to test all system prediction processors.
|
||||
return $this->add_prediction_processors($cases);
|
||||
return static::add_prediction_processors($cases);
|
||||
}
|
||||
/**
|
||||
* Test the system classifiers returns.
|
||||
@@ -507,7 +507,7 @@ class prediction_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_ml_classifiers_return() {
|
||||
public static function provider_ml_classifiers_return(): array {
|
||||
// Using verbose options as the first argument for readability.
|
||||
$cases = array(
|
||||
'1-samples' => array('maybe', 1, [0]),
|
||||
@@ -517,7 +517,7 @@ class prediction_test extends \advanced_testcase {
|
||||
);
|
||||
|
||||
// We need to test all system prediction processors.
|
||||
return $this->add_prediction_processors($cases);
|
||||
return static::add_prediction_processors($cases);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -581,13 +581,13 @@ class prediction_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_test_multi_classifier() {
|
||||
public static function provider_test_multi_classifier(): array {
|
||||
$cases = array(
|
||||
'notimesplitting' => array('\core\analytics\time_splitting\no_splitting'),
|
||||
);
|
||||
|
||||
// Add all system prediction processors.
|
||||
return $this->add_prediction_processors($cases);
|
||||
return static::add_prediction_processors($cases);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -777,8 +777,7 @@ class prediction_test extends \advanced_testcase {
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provider_ml_test_evaluation_configuration() {
|
||||
|
||||
public static function provider_ml_test_evaluation_configuration(): array {
|
||||
$cases = array(
|
||||
'bad' => array(
|
||||
'modelquality' => 'random',
|
||||
@@ -797,7 +796,7 @@ class prediction_test extends \advanced_testcase {
|
||||
)
|
||||
)
|
||||
);
|
||||
return $this->add_prediction_processors($cases);
|
||||
return static::add_prediction_processors($cases);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -955,8 +954,7 @@ class prediction_test extends \advanced_testcase {
|
||||
* @param array $cases
|
||||
* @return array
|
||||
*/
|
||||
protected function add_prediction_processors($cases) {
|
||||
|
||||
protected static function add_prediction_processors($cases): array {
|
||||
$return = array();
|
||||
|
||||
if (defined('TEST_MLBACKEND_PYTHON_HOST') && defined('TEST_MLBACKEND_PYTHON_PORT')
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user