Compare commits
1274 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 773e7cd612 | |||
| ce059497ac | |||
| 6c712c9caf | |||
| 6cfed9eebb | |||
| 7cae4c7570 | |||
| 86f6671fe6 | |||
| 91a40ccce5 | |||
| 62ee8fd5c8 | |||
| 35c6838f14 | |||
| 596e7c7b0c | |||
| 47d87f7243 | |||
| 56f849dcc6 | |||
| 2ad3d1a7f1 | |||
| 3265a02f6c | |||
| bbf96cb595 | |||
| 918d45dfbd | |||
| 35b29cf219 | |||
| 6f5266c717 | |||
| 841fd94499 | |||
| 3c8abccaaa | |||
| 23cc13e8ef | |||
| 5fc3b83497 | |||
| 56fdffa68e | |||
| 2b442c2fb7 | |||
| 7215c71486 | |||
| 9b3a8f7bd1 | |||
| 51b2acfae3 | |||
| 5dbf93200a | |||
| 4b987e5f7a | |||
| 337704e555 | |||
| 9f01cf6122 | |||
| 8872202049 | |||
| 855b9e504b | |||
| f253fa7f7e | |||
| 8ee6f49384 | |||
| f4f6534b40 | |||
| 1d70790168 | |||
| 17a5e73a9b | |||
| 5987bed350 | |||
| b6d0dec01e | |||
| c0d519b426 | |||
| 05c66fcebd | |||
| 5c545ca2ff | |||
| 4037bdd825 | |||
| c211e62465 | |||
| ff27bc6c5a | |||
| 02a2e649e9 | |||
| 8dcc813d0b | |||
| 329a5109b8 | |||
| 108bfe3f52 | |||
| 4501c37045 | |||
| b0679c1103 | |||
| b8322f7dd1 | |||
| a2221d6d8d | |||
| 472fdf0603 | |||
| a5edc8cb89 | |||
| c2cddf3c25 | |||
| 8d748b3401 | |||
| 6feb10dd53 | |||
| ff431a76cd | |||
| e49f38f6d2 | |||
| 7381719f54 | |||
| ddb31238a1 | |||
| 009b90a43b | |||
| 7afca3b34a | |||
| 882734c99f | |||
| c0c9be6d03 | |||
| 226a690c0d | |||
| f702707ef7 | |||
| d1bec1e23b | |||
| 497c016518 | |||
| 078f59faf8 | |||
| df4f869af7 | |||
| 0a4092bc27 | |||
| 31a7410a90 | |||
| 793289f905 | |||
| cd009c0c51 | |||
| 60900a8066 | |||
| dde73f5fb5 | |||
| 44fe2370b7 | |||
| 5d09a5f6b0 | |||
| 3944872103 | |||
| 5db25124ef | |||
| b17f7fd443 | |||
| 787485d9eb | |||
| 299fb2f158 | |||
| 71f444e82d | |||
| 1e0f448b3e | |||
| d1a71ec909 | |||
| 9c4f2a55b6 | |||
| a0ec66dc6b | |||
| b08b4a2bdc | |||
| 0d355a0e8d | |||
| 382250e60e | |||
| 71bb7f306e | |||
| 6864463dc4 | |||
| b5db1d43f6 | |||
| c50c1fd745 | |||
| 9aad72e85b | |||
| 2e4198ab76 | |||
| dc6da3f20e | |||
| 52777e6a56 | |||
| 4b53207d34 | |||
| 6d0a928b64 | |||
| 616935475b | |||
| 8d6cbcb248 | |||
| 35d42cc6a7 | |||
| 6030e5ce3d | |||
| 1d0b0ebb15 | |||
| 2a2d658d84 | |||
| 1e1c3622e3 | |||
| 68242c6a84 | |||
| eae9427f8f | |||
| f906c7cadc | |||
| c302886845 | |||
| 3afaa0d81c | |||
| ba69ad868a | |||
| bc509f6d8c | |||
| 120b877cb6 | |||
| f32754319e | |||
| 3e91d27f5e | |||
| d6adfa6446 | |||
| 58bdf28392 | |||
| bde3b82720 | |||
| 7111921105 | |||
| 67e1e3107a | |||
| fac00d7e8c | |||
| bbbb211c71 | |||
| 54beada930 | |||
| af3e51fa82 | |||
| 78adf434d4 | |||
| cc7bc38cc1 | |||
| 4c4c74c13b | |||
| cb13db88a3 | |||
| 31b1a9601f | |||
| 1e10d9328e | |||
| cf3b76b980 | |||
| f1f578cd7a | |||
| 8b16724fef | |||
| ecdd8bf487 | |||
| 713b28c2a5 | |||
| c2d1a1eb60 | |||
| d76dddea87 | |||
| 28fca52bd4 | |||
| 4d3c0a9d82 | |||
| 5334972a73 | |||
| d62a536a2c | |||
| 240d414aba | |||
| 8d4930ab11 | |||
| 41cf8a2f42 | |||
| 80223d703c | |||
| 0782c3c18d | |||
| cf1546a472 | |||
| 6d1ec7c38d | |||
| 379d21c8cb | |||
| d2f7b36caa | |||
| b70b06bc61 | |||
| 96f41c3d99 | |||
| 8eb4a14e44 | |||
| f8811d5661 | |||
| a3f78dbd7a | |||
| 1d17c73e9e | |||
| b21076309d | |||
| c34c00a762 | |||
| 3d87e93f02 | |||
| 76f2dc1f14 | |||
| 77e578a91a | |||
| eb0e5a1297 | |||
| 8844095259 | |||
| 4b58966938 | |||
| 69ec780e95 | |||
| e539a0aa30 | |||
| 7116f5fde8 | |||
| aba0e6b70d | |||
| 37136525d9 | |||
| 8e6d2ba38d | |||
| f418bf8c96 | |||
| 8a40250c49 | |||
| e516a662c5 | |||
| 4adfbf3cba | |||
| ecafdc45d0 | |||
| 499bf7df7d | |||
| 378725c05f | |||
| e3142ca2e2 | |||
| 23ed4c4440 | |||
| 4ac8ae1be7 | |||
| 254aa09f40 | |||
| d27c60a90a | |||
| 5fae9c213d | |||
| e7a160da9a | |||
| ac1402d552 | |||
| 2c5adf1c5b | |||
| 4d54712518 | |||
| 853cbc5973 | |||
| 630325a4e4 | |||
| 842e7aa041 | |||
| 46916975a2 | |||
| 8fc5c6214a | |||
| 263419e10d | |||
| f4024153e1 | |||
| 61752e9e0f | |||
| d9e13438d1 | |||
| 6a7750a141 | |||
| f025935c1c | |||
| 4640d8f9ca | |||
| c420408522 | |||
| 2020498bd5 | |||
| 6ad9b1314f | |||
| 994e833c20 | |||
| ab3f29f739 | |||
| fb298c2209 | |||
| 10126a1325 | |||
| 6bd3ffdf25 | |||
| d1f40013d9 | |||
| 2386b44490 | |||
| dffd5de050 | |||
| fdf5ac3dfb | |||
| 70cfba0496 | |||
| 92e4d6c028 | |||
| 3a88c22eb1 | |||
| ac4fe16003 | |||
| 0e0a753346 | |||
| 0f21f23c05 | |||
| 7171c9fc0a | |||
| 0322232dd4 | |||
| f5590ad1c0 | |||
| dcaf627cfe | |||
| 6aa1c3dfcb | |||
| 6c97f9d1f5 | |||
| 8a2a5f1a89 | |||
| 9bce6baf62 | |||
| f7f7755067 | |||
| 9ac848c738 | |||
| db9934a625 | |||
| 6b3cb904d0 | |||
| c43f9136f3 | |||
| 01fc4b40f0 | |||
| f5152d30c3 | |||
| 3827885984 | |||
| bc84eabfc6 | |||
| 6735a694e2 | |||
| 186fd5b847 | |||
| 0f1f18d8a4 | |||
| c3589fee83 | |||
| 6e74df2344 | |||
| 42bb84db9f | |||
| 6d38633c3c | |||
| ff1877c738 | |||
| 6e7c0d9686 | |||
| 40edd91ddb | |||
| 9d7343074d | |||
| feea5e5cbd | |||
| 78855e618c | |||
| 01f6f99349 | |||
| 63a322b0e7 | |||
| 9a92ca5e75 | |||
| 209768c9bc | |||
| 8e1f02568a | |||
| 8039e01ef7 | |||
| 1dc927aea7 | |||
| f03fd2f6b7 | |||
| ea17a4cbd6 | |||
| 9a9fde8aa5 | |||
| aa741e8795 | |||
| 1ca2e36ecf | |||
| 99b37e2c3b | |||
| 2d7f1d7470 | |||
| ff146ed37d | |||
| 2b9db93f78 | |||
| 985f4d1e48 | |||
| 77475c93fd | |||
| 6a9f05742e | |||
| 1116c64d44 | |||
| 5d211ff68a | |||
| aac9d82e12 | |||
| f11f91a1e0 | |||
| ad85ffb55a | |||
| 6d21e94213 | |||
| 52eb636ebe | |||
| 915339039a | |||
| cbd016e620 | |||
| 8a76c2a9a1 | |||
| 9ccd5030d8 | |||
| 3489bb1f30 | |||
| e4a649d0f9 | |||
| 59a09e2e3f | |||
| ec20642963 | |||
| 34ba550138 | |||
| a248c359cc | |||
| 18d5ddf01d | |||
| deaab14bf9 | |||
| 4e00a821cf | |||
| 496ef9b0a8 | |||
| e5b1fc8083 | |||
| c2c71b28eb | |||
| db6d34630f | |||
| 88a9d4cff1 | |||
| 96c8ad66f9 | |||
| fbb0428179 | |||
| 82592f0c84 | |||
| aa3118999a | |||
| 80de5d08ee | |||
| 1d457c78f5 | |||
| de301d4237 | |||
| e2c94750fb | |||
| e2c8f4ad1b | |||
| 8c1455d220 | |||
| 7b85e141da | |||
| cd744ba504 | |||
| 974c63505b | |||
| 724210c4f7 | |||
| ae9d510288 | |||
| 981f750b81 | |||
| e49f9e46aa | |||
| 721d57228f | |||
| 3c25c373d9 | |||
| 17eb41c270 | |||
| af6e65f221 | |||
| 8bbc064e29 | |||
| 78b18c00bf | |||
| 4b3b4b7d78 | |||
| 557d1c8820 | |||
| 698e1f7823 | |||
| 5b4702a6b6 | |||
| 77c0b16613 | |||
| 9adef8af21 | |||
| cc45df637f | |||
| 9055c9e213 | |||
| 13655cd5ea | |||
| ea3f1d19b9 | |||
| 8256ebd431 | |||
| 8ba97d0104 | |||
| 71ee378a69 | |||
| 8208453a14 | |||
| 7c6e9b37b3 | |||
| 19dc872bca | |||
| 0a51214fb3 | |||
| 6910afa56f | |||
| 5e5e82621c | |||
| 2edff57e63 | |||
| 3b8bb4d4c1 | |||
| 920763ad00 | |||
| 1acd3cac07 | |||
| 7de4119fe2 | |||
| 6fb2fa9859 | |||
| 1d54d21ec0 | |||
| c87ed01b17 | |||
| 23541c936a | |||
| b7490a205f | |||
| 8415e0461b | |||
| 9ee41118b0 | |||
| 137b10b378 | |||
| bb9e3ec1ff | |||
| 7152b05700 | |||
| 087ccaff4f | |||
| 3fb245f481 | |||
| 8de31cf961 | |||
| 88e7da61cd | |||
| 3648b629ed | |||
| 0d833e248a | |||
| 783fba428f | |||
| 514c7ee639 | |||
| fa35b9506f | |||
| 29f7630b75 | |||
| 7a2a47d9e8 | |||
| 17211224a1 | |||
| 2394a675dd | |||
| 449c835fe2 | |||
| 322afa9f4f | |||
| 1d0777dbe4 | |||
| cd94f2bc2e | |||
| e899fd5c02 | |||
| 438b2ac8c2 | |||
| f6ae03bf41 | |||
| fc52aaf319 | |||
| ef8eb8ef1a | |||
| f1c6cf8b26 | |||
| e68cea5747 | |||
| 3f797704ea | |||
| aae57db8d2 | |||
| 8c3091e5f3 | |||
| b52ad05038 | |||
| ec5d807139 | |||
| 1f00b5d9bb | |||
| 0f53bd6b8e | |||
| bf29fea4bb | |||
| 8a733bc85f | |||
| 1b87f634a8 | |||
| 9260dad3b3 | |||
| 6002a1454f | |||
| cef3216f2a | |||
| bed6bfe7d4 | |||
| 1c39517553 | |||
| e92846ce18 | |||
| 31d0ccb078 | |||
| fc7fa7f72c | |||
| 6994f63eef | |||
| c28c0ed466 | |||
| 479b0f0eaa | |||
| 7b96e8a413 | |||
| 2321fe4da9 | |||
| 3aa05048cf | |||
| 17d6ecd26d | |||
| 7d5c5fad77 | |||
| c1296560bf | |||
| 93e25f8657 | |||
| f43de821c6 | |||
| 1b0690a7f1 | |||
| e003e8a6ff | |||
| 1e8f432437 | |||
| 51d7849f08 | |||
| ede7d22dc7 | |||
| 4355451e2f | |||
| 5e102fa8c3 | |||
| 1925b641e2 | |||
| 377da86151 | |||
| 9a2db9e2ec | |||
| 844637b880 | |||
| 9e597d3658 | |||
| 0e25936c0d | |||
| 627e14727e | |||
| ffe84e977f | |||
| 7bc67e92e2 | |||
| dd96341354 | |||
| 1714cb74b3 | |||
| c94c579aa6 | |||
| 16bcd8f057 | |||
| 5e65d02eab | |||
| 1b8bfedaa9 | |||
| 7b920d2d7b | |||
| 63b0a865dd | |||
| 7766af18a5 | |||
| 14d68d98b5 | |||
| 8676a67888 | |||
| 8af16c5709 | |||
| 7f74dc1c16 | |||
| 5bdc07a3b6 | |||
| bccfc48b94 | |||
| 95c3de0877 | |||
| d833fc2131 | |||
| 6e04f9f294 | |||
| 7f45f9ab3e | |||
| 547a6dcdde | |||
| 28fff43d2b | |||
| 7565cda9c6 | |||
| 90fa490de7 | |||
| 5f9ddb348e | |||
| ff8da7e008 | |||
| dde5a7882c | |||
| a6ab91786f | |||
| 0a43bdcc6c | |||
| b1a4bd579a | |||
| 4825c139ef | |||
| d207a2ad02 | |||
| ccc6b4d00b | |||
| cc3a909810 | |||
| c93de36436 | |||
| da3ebf216e | |||
| 7c8fd0d417 | |||
| 558ace5997 | |||
| 98254ccd1a | |||
| 5be02868af | |||
| a36b3ec48f | |||
| ea4e0ae3cb | |||
| 68c3eb8aa9 | |||
| 331b9947a3 | |||
| 4e8d58374e | |||
| 86669b0564 | |||
| e80e613f65 | |||
| 81410615ed | |||
| 1d0bd0cfdf | |||
| b4f40ae78e | |||
| 556611a864 | |||
| 7ce8e4cde2 | |||
| bde7f5d734 | |||
| e08f640061 | |||
| 4f01d454a7 | |||
| 35cc7cad05 | |||
| 7b5fa603dd | |||
| 4e72b72720 | |||
| eaf24d71f2 | |||
| ed46bff4ae | |||
| 87bcff8c6e | |||
| 81c2fe97a3 | |||
| 8b53812c8f | |||
| 78aeaf17e7 | |||
| 662d20869a | |||
| f66c4fa42d | |||
| 76a830b058 | |||
| 2f9582d754 | |||
| 12d4c82f98 | |||
| 3648ffdc8e | |||
| 1194dde152 | |||
| f727dad657 | |||
| 985d5a5824 | |||
| 0210ab0005 | |||
| 99cf35e681 | |||
| 61d0134488 | |||
| 2369ad7737 | |||
| 71dcd85182 | |||
| f5d19447e0 | |||
| b276f33850 | |||
| b932b798f1 | |||
| 14cecfa4c0 | |||
| 9582b85c16 | |||
| f920fdced0 | |||
| 53836d2035 | |||
| ff2b655928 | |||
| 706f6c93ae | |||
| 6028dc3924 | |||
| fd34a36514 | |||
| 27da8851f6 | |||
| 248ab7a4b3 | |||
| fcf07d64c8 | |||
| 897cfd7c81 | |||
| 193aa32b88 | |||
| 78908d7757 | |||
| 896c962160 | |||
| 1178406516 | |||
| 409f92b75d | |||
| 6ea0b003d7 | |||
| 918b60d700 | |||
| b997786180 | |||
| 3e8447fe9a | |||
| 28a1f0943d | |||
| 7a2d0fb5dc | |||
| 28de3d7db9 | |||
| 9fa04e3f2e | |||
| 1d41237ae8 | |||
| b0a9faf1c6 | |||
| e9961085eb | |||
| 766376261a | |||
| 8e2e459daa | |||
| fedd703ce1 | |||
| a1216eb05b | |||
| e49e58a924 | |||
| 97a03ba74d | |||
| ba43374d96 | |||
| 09d078c3b8 | |||
| a8e089a8c8 | |||
| 3e8043f3f4 | |||
| 70f695d068 | |||
| e83cad80b1 | |||
| d727c1eafd | |||
| 463b232453 | |||
| 02a8be1f80 | |||
| 7bc714ac09 | |||
| 3accc543ec | |||
| 481c57cabe | |||
| c0256a7351 | |||
| f8287cb170 | |||
| 621cd70b4c | |||
| 7e2acbfb55 | |||
| c87ccd3111 | |||
| 06be826b2e | |||
| 06a4390060 | |||
| 126cbbff7c | |||
| f252b08433 | |||
| fae048b402 | |||
| 0408008fbe | |||
| 0ff5242a3c | |||
| 2488fe37ca | |||
| 4edad07619 | |||
| 6cdcee7a65 | |||
| 28fbba8b3c | |||
| 90fde2b40d | |||
| d8bfd5b747 | |||
| 0d9c49d8d6 | |||
| 4d9ffaae34 | |||
| 21cfc35074 | |||
| 5d0b569ba1 | |||
| fd7db38d8b | |||
| 2f9f0b0fcc | |||
| 14aaba1b72 | |||
| 629657363d | |||
| 498c54d1de | |||
| a3f72b3972 | |||
| 098f09b638 | |||
| 99732c4c3b | |||
| 905d3939f5 | |||
| 051cad238b | |||
| 6a4bf785cc | |||
| 223f7cc0b4 | |||
| 287ed73429 | |||
| db1368926a | |||
| ec19837b79 | |||
| 3b0d958065 | |||
| 6722a6b105 | |||
| 920b4dd6ab | |||
| 898bdfdd67 | |||
| ed7485277e | |||
| eb238722da | |||
| da1f204a0a | |||
| 5dd385d522 | |||
| dca6513b8a | |||
| 6484e89188 | |||
| 9312e7389a | |||
| 0218859c3e | |||
| 18702b5869 | |||
| d0ab1d1540 | |||
| 7d25143979 | |||
| a067cc5ada | |||
| ea68407895 | |||
| 03f5e32712 | |||
| c0b0649582 | |||
| 72cd24d3c9 | |||
| d16aa74359 | |||
| 7e52e95d8d | |||
| 42f3862b91 | |||
| 556648db0b | |||
| 6026aa7b3c | |||
| 8e5782b848 | |||
| f38e17f16f | |||
| 465cc9e91a | |||
| faa76ee29a | |||
| d6491a67c8 | |||
| 27db5c5024 | |||
| e6b274a542 | |||
| 6f317a983e | |||
| a5293c4ed8 | |||
| 66e77f8173 | |||
| 4ba58ac02f | |||
| 21f5c148fc | |||
| 2e026689c6 | |||
| 3a718d620e | |||
| beff06190a | |||
| 975081c367 | |||
| 9417cedd78 | |||
| 19343c7bd1 | |||
| 64dd473559 | |||
| 9e4a19af6c | |||
| eeba9c1dc5 | |||
| 55a465c445 | |||
| d1d52a3399 | |||
| ad7b38f3ff | |||
| a22b74872c | |||
| 1af998d32c | |||
| 4d9ab4ca48 | |||
| 55189f02ee | |||
| 115f703440 | |||
| 5cd7b5cad0 | |||
| fb81664dc3 | |||
| 8cbc470f2a | |||
| 1bc92d37f2 | |||
| 348e338a21 | |||
| bf854f5f24 | |||
| b861165753 | |||
| 3c2208cc24 | |||
| 2d1fcf6cce | |||
| 2f502066cb | |||
| 41cd0c4d3a | |||
| 0efc7095e3 | |||
| 6178388d94 | |||
| f0e9fa2a7b | |||
| c651779095 | |||
| ce5efbc1da | |||
| e9506c638b | |||
| bb3f9ee492 | |||
| 14017f40b9 | |||
| 413736095b | |||
| f78101f638 | |||
| 105e40d377 | |||
| ce2f6179cd | |||
| 47ff67ec29 | |||
| 3fb1660734 | |||
| 6e7c392d84 | |||
| 806e6bec59 | |||
| 8d7fe960a0 | |||
| 8d1cbe3a35 | |||
| 197ec7e822 | |||
| fbab65f86b | |||
| cd054d77f1 | |||
| 6168569323 | |||
| 5da2fa002e | |||
| 4b137eb20c | |||
| 34ffdc2c81 | |||
| 83d478ce93 | |||
| 565bc965b1 | |||
| e2cdcc563d | |||
| ae61985191 | |||
| 2b169e9b31 | |||
| ccbd35915c | |||
| 114d1a051e | |||
| 856c31cc32 | |||
| 25049f4f19 | |||
| 00a46671fa | |||
| d008aa7c99 | |||
| 2d462ee8bd | |||
| 3f50f83dc1 | |||
| 41121d705f | |||
| cc2faa2c90 | |||
| ae4f9b31f7 | |||
| 01f3495a46 | |||
| c4c328565d | |||
| 7961a36b76 | |||
| eda7eb44b3 | |||
| 6589c3cdd6 | |||
| eeb76ddd3f | |||
| 14ea69c07c | |||
| 9f0400b74d | |||
| f68a64d50b | |||
| d82acd309b | |||
| 22f34e807d | |||
| 31d3a656d6 | |||
| 3d41104fab | |||
| 523f308a9a | |||
| e4d03a9257 | |||
| cedf141cc3 | |||
| b4d51d67a9 | |||
| 9763c99f87 | |||
| 56be61d4f6 | |||
| 6de6fe9590 | |||
| 754440d796 | |||
| 1ddaad70ad | |||
| c954e18a99 | |||
| e0a366fa0a | |||
| 2e5daf9108 | |||
| 5281e10e77 | |||
| aae7a2b206 | |||
| 419ff44b78 | |||
| c4a8787574 | |||
| 834a1d64c5 | |||
| 496e6ac804 | |||
| 7eb0f97113 | |||
| 9f1df0f2e4 | |||
| 8fc60dd25d | |||
| 558a30dc7d | |||
| 9773b4b079 | |||
| d686ee8faa | |||
| 5cb1cf7695 | |||
| 465f3b477b | |||
| ad00d91851 | |||
| 1eed96dec7 | |||
| 2e21c78006 | |||
| aba9644393 | |||
| 4aa6b89ead | |||
| f8bce36ef2 | |||
| fce2b0008c | |||
| c2bd0a7d31 | |||
| 2d7a59d060 | |||
| 57e0a20dec | |||
| 3fe455fab4 | |||
| ca743b6a95 | |||
| 5ea37637b7 | |||
| 75bae1a55b | |||
| f3db3d30e0 | |||
| 7714ea42ec | |||
| 12c103b21a | |||
| ec157a3052 | |||
| 57bb2fdaac | |||
| e437183098 | |||
| 3af8f89e58 | |||
| 52b1184468 | |||
| 99d0308e4b | |||
| 3ae46b2a93 | |||
| 5fce0b3f5d | |||
| b3ebbb61f4 | |||
| 16689245e8 | |||
| 98280a4c8c | |||
| 171e55f304 | |||
| f1fed72bda | |||
| 07674eb12f | |||
| 2308a02324 | |||
| 1da6703d6d | |||
| 27a62292ad | |||
| 271b94ff4f | |||
| 315ec3bad6 | |||
| 4cb342ef34 | |||
| e7bb7aa9a2 | |||
| 7aca3ebb3c | |||
| 61bb2c70c2 | |||
| d84da184c5 | |||
| f612465b53 | |||
| 4727970abd | |||
| 88c700bd2c | |||
| b354694012 | |||
| a9bccc9dbc | |||
| 7c52a27375 | |||
| 300d9ca23d | |||
| 00b2219fd4 | |||
| 8b9d73dad8 | |||
| 9029eb0e71 | |||
| d54b3447e6 | |||
| 39d542eeb4 | |||
| 2cf6b7cc41 | |||
| 5651e88dc9 | |||
| 5a90580646 | |||
| c98428aab3 | |||
| dc780e3eb1 | |||
| d75844ea12 | |||
| 11e5003bd6 | |||
| a348c5f420 | |||
| 4b651226d5 | |||
| e33c554aaa | |||
| 31937c4b0e | |||
| 141216f94c | |||
| fba96f096b | |||
| 7148c9d35e | |||
| 8193ba9da9 | |||
| 6bf314500a | |||
| ee034c39e5 | |||
| 46aea33b69 | |||
| e0f9ca6787 | |||
| 976f8f0c52 | |||
| 767be5d8c1 | |||
| 94140b11e8 | |||
| a45e6838ef | |||
| ae17678a1c | |||
| 3ae39301b9 | |||
| 422fcb70ca | |||
| 29a396fe4e | |||
| af777f92a0 | |||
| 6f35d6536d | |||
| 36cde1e295 | |||
| 05a1532e88 | |||
| 91ae4ab5db | |||
| 2cc3588b77 | |||
| 222aefb456 | |||
| 94160c9ad0 | |||
| 9c7ab777d9 | |||
| 7818990010 | |||
| 17a035ac59 | |||
| abe11a9ace | |||
| bfab0d603c | |||
| 070454489f | |||
| e32a114998 | |||
| 3db28cdebd | |||
| ccd4ef8ddd | |||
| 51b0a67bd2 | |||
| b9371d7bf6 | |||
| 1ec406cbd7 | |||
| b1c1119743 | |||
| 3d45f2c083 | |||
| 1f5da975e2 | |||
| 7156a01a0c | |||
| db22846df6 | |||
| ef6e3bfd77 | |||
| ee0106f70b | |||
| 36ee886a12 | |||
| 97e0452344 | |||
| 874bdf2035 | |||
| ab43412ae9 | |||
| 3d01fc77de | |||
| 08d7552f4d | |||
| 8983d50bd1 | |||
| 9fb8221fb3 | |||
| 4b60cede1e | |||
| 4514918c33 | |||
| 86d6bdf079 | |||
| f5d75c8e24 | |||
| bfeb6f3bac | |||
| ec52cca8b1 | |||
| 6bbb402129 | |||
| 7375466f51 | |||
| 8635e2cefa | |||
| 52bad33356 | |||
| 5c155ba8f7 | |||
| ffa17ad17d | |||
| 5d6fcc67cf | |||
| a37dc94598 | |||
| 1e08e046e2 | |||
| 4ff5d5ef17 | |||
| 84ef6eb8d9 | |||
| 3b45e0db41 | |||
| 535523f21f | |||
| 9c50ccbf7e | |||
| 6c39b7890e | |||
| b676817a64 | |||
| 8eca15c5f1 | |||
| 1bb4c59adc | |||
| 2332ac5f87 | |||
| 0700b8510f | |||
| 7bc82ad672 | |||
| 92b9900d6e | |||
| 312ca07bb7 | |||
| bea621d6c6 | |||
| 28a8eb3856 | |||
| fb39317a64 | |||
| 6e7f80363b | |||
| 82bd2ff5a9 | |||
| e657192d31 | |||
| 85782cffd7 | |||
| fac004cfe9 | |||
| 221c293ac7 | |||
| 5ad20a0633 | |||
| d63bdf9bb9 | |||
| bc29f1c98a | |||
| 4830f55122 | |||
| 48508e4ecc | |||
| fbb2d6592d | |||
| 581a497189 | |||
| 3d3314d433 | |||
| a1f21bad0d | |||
| 189810269a | |||
| e592c6dd9d | |||
| 563cfa0e1e | |||
| 863fb96ffa | |||
| 10f03d2a99 | |||
| b3b04e083b | |||
| 9262b490ee | |||
| f37d0629ea | |||
| 6d9518cf56 | |||
| 0d8bf37407 | |||
| 159115b7c7 | |||
| 930dba73c3 | |||
| 22217ac42f | |||
| d46ee17722 | |||
| 5f1d9df828 | |||
| 95cc0d562b | |||
| 3584cd786a | |||
| fa92e6a809 | |||
| 1257e39d92 | |||
| 65c7339199 | |||
| 2cb720a3d2 | |||
| 138ed9c1fa | |||
| 3c7a4833e5 | |||
| 0400b5ef3f | |||
| 122ed3beaf | |||
| b58a45df37 | |||
| 2d450e9a3b | |||
| 3513964883 | |||
| fde9d44286 | |||
| ba8185cb2a | |||
| 362c598d1b | |||
| 185fc93ed5 | |||
| 8b254440d6 | |||
| 5989a94787 | |||
| e290345cd6 | |||
| 4c48bccbad | |||
| ef1bb2b193 | |||
| 9e103451e2 | |||
| 832f5f7019 | |||
| 40f92ac55d | |||
| 887efbd939 | |||
| 6305c7b83c | |||
| 6bbb4e4df2 | |||
| 79e98f6ac4 | |||
| 1c1a96981d | |||
| 6e9d203e52 | |||
| c02fc98d06 | |||
| 895e5748e1 | |||
| 96805ec18e | |||
| 010f1eff60 | |||
| a713a68af8 | |||
| 1547225e52 | |||
| cc52ff7703 | |||
| 3f51798192 | |||
| 8578e19aff | |||
| e4ffa5f3f6 | |||
| 8cc9ebea1e | |||
| 2cb5248ac3 | |||
| 43a9717a33 | |||
| 4fd5a7bfcb | |||
| 3c2c15d4dc | |||
| 7969cfb39f | |||
| f2fe8b1664 | |||
| 23dc056578 | |||
| 3e9dadc85e | |||
| 6e37e120fc | |||
| 091a6ca62e | |||
| a8cdc38272 | |||
| 2296b4b16e | |||
| 4e873c2ab6 | |||
| 130d29bb5f | |||
| 3ae4d6e824 | |||
| be1847d075 | |||
| 68810e04c6 | |||
| b8b894dd36 | |||
| a12b0aff07 | |||
| 3523edfd90 | |||
| fbaab99733 | |||
| 6408db6427 | |||
| 2cd36e8ea0 | |||
| 6a930e2c88 | |||
| 78079c3f2b | |||
| a88c706d98 | |||
| b9d20f8481 | |||
| 545b24fa52 | |||
| 2f6437ec5c | |||
| 806042d58a | |||
| 58e66823a2 | |||
| 119010b16d | |||
| c6895d7dd4 | |||
| 1f7f5e368d | |||
| b80006b600 | |||
| 9e42721660 | |||
| 0f13aee6fb | |||
| 8cc4708c2a | |||
| 507d51eebf | |||
| 89d8f73703 | |||
| f0f37cb2e7 | |||
| 62cd827dc5 | |||
| 1b682b3b6a | |||
| 5e372ecd61 | |||
| 4401c891e8 | |||
| 61a17c94be | |||
| 75911e67bd | |||
| 3a2eb35800 | |||
| 5ae88aba9d | |||
| dbd0a1dbf7 | |||
| d1e4c0fecc | |||
| 522dd18e62 | |||
| 563bfb4582 | |||
| f03d9e1aab | |||
| 454a93cbbf | |||
| a64f376595 | |||
| f620bbf2f5 | |||
| 4ddbc1ee38 | |||
| f9bd169b6e | |||
| 332fdda507 | |||
| 77f46da53a | |||
| ebacd8353f | |||
| a97c45a15d | |||
| f307dc23d7 | |||
| b21f182106 | |||
| 0991b0a091 | |||
| 54eb1f8f23 | |||
| 97df1db020 | |||
| 8c1eb6cfd3 | |||
| 4eeb1bbd8f | |||
| 5778aa1fa1 | |||
| a0c582342c | |||
| cf13f285e4 | |||
| 08d7dd1db4 | |||
| a6908c3ee8 | |||
| cc91fe0988 | |||
| f66e6749ae | |||
| f3fd372584 | |||
| e29a887814 | |||
| f1743d9179 | |||
| 73827e8eda | |||
| abb81c79d7 | |||
| 8b55712485 | |||
| f967acc533 | |||
| 61d4bf3f88 | |||
| 94dc00614c | |||
| 976ec609bc | |||
| 7cc4f8883a | |||
| 9b48e7420e | |||
| eae4f24877 | |||
| 72e24ec057 | |||
| da2cb39c15 | |||
| 695b470305 | |||
| 076bbff5a7 | |||
| 023064558f | |||
| a934784741 | |||
| 13a31a6b83 | |||
| f29c1bee74 | |||
| 3c5ba23f7f | |||
| 777c810671 | |||
| 9a642c49e1 | |||
| a5708767a0 | |||
| 1117eb6579 | |||
| f131e22bc4 | |||
| 76fd40f2f9 | |||
| 52925cb9df | |||
| 3d68237956 | |||
| b79b33c664 | |||
| 8a6b5024a1 | |||
| f51dcd3c96 | |||
| 7a4f10ddda | |||
| 2d7f517b5b | |||
| 3161583d89 | |||
| 9e3b1f2d7e | |||
| ff2d425711 | |||
| 95c4f624c8 | |||
| 7882fff01a | |||
| d68848383e | |||
| f395c5b238 | |||
| a9782addfc | |||
| d093887447 | |||
| f0be299db3 | |||
| 6a3edc34bd | |||
| 135dfe2144 | |||
| 13de4b94dc | |||
| c6ec3c048e | |||
| 6d1680998d | |||
| bbfcb91b1f | |||
| 7d1f5e81ea | |||
| 5f9d183b46 | |||
| 646ebff5dd | |||
| 8f6f312d65 | |||
| 5762e5ec3e | |||
| 52dbe51339 | |||
| dfaad3e8ca | |||
| 7da6f2675d | |||
| 9ae2623d89 | |||
| e64f37c3c5 | |||
| b39ed13500 | |||
| 532a81f846 | |||
| 2b96f7b343 | |||
| 6a07b3c08c | |||
| 744726275d | |||
| 07afdeedac | |||
| b8c3fefd02 | |||
| ac7cb0921b | |||
| 6b6a083916 | |||
| 6acd719f0f | |||
| 455e7f50d8 | |||
| f49fe84488 | |||
| 5ce4bd05df | |||
| b9f2e3d99b | |||
| 42bcf62000 | |||
| 86f5acdc88 | |||
| 45aa8db99d | |||
| d35fc78761 | |||
| d8b0be3eb3 | |||
| 12e884c5b3 | |||
| 115d6033fc | |||
| 9ffeab1ad1 | |||
| 7bad9a9f15 | |||
| 5a003a1da9 | |||
| 9e96129104 | |||
| 5068d59b13 | |||
| bf9c4ab68a | |||
| 44022305cc | |||
| 0595cfb07d | |||
| c8098c7a80 | |||
| 2e71c132fe | |||
| 7c3522f902 | |||
| 4dcb3165e7 | |||
| 4fbe8bec4a | |||
| 4a723a329e | |||
| 592b8980aa | |||
| 1e63a97698 | |||
| 9d41810bed | |||
| 8cdebcf4e0 | |||
| 9744e6e8cb | |||
| f4d6bd1188 | |||
| d8c8c75ec4 | |||
| 9eaaa8997b | |||
| ef2a7d7302 | |||
| b660b92b3f | |||
| 87ae4833c4 | |||
| 4f9d34da81 | |||
| 13ad9d1f5b | |||
| 8cf328dc54 | |||
| af1f371aa7 | |||
| 3e78b603a5 | |||
| 50da793d5b | |||
| 4affbe94be | |||
| d18eacbd35 | |||
| 3de3755281 | |||
| 04a1611139 | |||
| 0b5889d299 | |||
| aa6bf0f367 | |||
| 7164e1626e | |||
| a869415180 | |||
| b39f2de8ad | |||
| b02b1f3ea9 | |||
| 72ad5d94ea | |||
| 1c2358de43 | |||
| ba56dfb574 | |||
| da48e72353 | |||
| 3c5757b0e2 | |||
| e1a310bde7 | |||
| a040f29f03 | |||
| 3f3262c76e | |||
| 5018c4e4db | |||
| 6e5ae126af | |||
| a0b8d8c0ff | |||
| 1636ee5980 | |||
| a092131b73 | |||
| b4a73ff47f | |||
| 73c4f6c2a5 | |||
| d8a886d75a | |||
| 480f26720d | |||
| 333d17b8e1 | |||
| f78caa59d2 | |||
| 1f09dea479 | |||
| 8e619076cb | |||
| d80e9d463d | |||
| 6a17f29147 | |||
| cafc042bf6 | |||
| d2e303436b | |||
| fb0d5acf4c | |||
| 376d34142f | |||
| 8eb7f7e366 | |||
| 762e8afa6f | |||
| c3018e9ee7 | |||
| 996c94fd08 | |||
| fd7c3c4834 | |||
| c3b7f2f974 | |||
| 8589fbda8c | |||
| f1a681c983 | |||
| a17188f51c | |||
| 8a66849a57 | |||
| 20318b8b7d | |||
| d84d6f57a3 | |||
| 619e11c07a | |||
| 01ec0ee85b | |||
| 91b23a2caa | |||
| 053a433d74 | |||
| 3725a41b39 | |||
| fe5ca8e768 | |||
| b1a2e67326 | |||
| 40553ed459 | |||
| ae9e1f1888 | |||
| 9127c17778 | |||
| 8f28fbee11 | |||
| be7bda671e | |||
| c58101cde3 | |||
| 4a16804df7 | |||
| ff92024ec2 | |||
| 6e5b0b5c20 | |||
| c201456f20 | |||
| 02b3d5aacf | |||
| dde1ead9fe | |||
| 3915147b9b | |||
| 55c7fe15a0 | |||
| 82dba4d510 | |||
| 9ecff3766a | |||
| 4fb85c9c9f | |||
| 6ea5922916 | |||
| 287e8f16e6 | |||
| 846422a90f | |||
| ea6621e00e | |||
| 44ffa8a801 | |||
| a1d5911159 | |||
| c38e38d6b4 | |||
| f5b5f97f56 | |||
| 5528302282 | |||
| 995f0a3a58 | |||
| 894ebe38a2 | |||
| 0609febf16 | |||
| 1d6c1cc0ae | |||
| 50b076c4af | |||
| d783f12861 | |||
| f324c2d16c | |||
| 5486975097 | |||
| d4b6b26f4f | |||
| 996dd0b0b9 | |||
| b44588aaba | |||
| 95fbf4d8e5 | |||
| 6f78024717 | |||
| 7b2e257157 | |||
| bb344d07e7 | |||
| 959c2cb84e | |||
| ee7b438f61 | |||
| dc0241306b | |||
| 89ce4db476 | |||
| 55a1405a84 | |||
| fb21fc9274 | |||
| 57b920b8b7 | |||
| bae07c1bfb | |||
| 4f7016f2da | |||
| 7af8441403 | |||
| 7ba95339a6 | |||
| b6c37f2926 | |||
| b8408c3582 | |||
| fb625069cf | |||
| d4297993a4 | |||
| 2104324ded | |||
| 153b2cb484 | |||
| c72adaa749 | |||
| 3c2ed1533c | |||
| b9518bf811 | |||
| 4f0f1bd84f | |||
| e2ef786003 | |||
| 5b134b5de5 | |||
| 62c4da281a | |||
| 4c27f858b9 | |||
| 6ced5c26d0 | |||
| ccd504115d | |||
| 647e5d8021 | |||
| 6a7042d980 | |||
| 7532b032bb | |||
| b5c1d17da5 | |||
| 56a7d91066 | |||
| 93d636a95b | |||
| 7ca771e4ac | |||
| 6e7e7e1241 | |||
| 8b43f32f8c | |||
| a30eb7d16c |
@@ -0,0 +1,92 @@
|
||||
# Generated by "grunt ignorefiles"
|
||||
*/**/yui/src/*/meta/
|
||||
*/**/build/
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
auth/cas/CAS/
|
||||
cache/stores/mongodb/MongoDB/
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
filter/tex/mimetex.*
|
||||
h5p/h5plib/v124/joubel/core/
|
||||
h5p/h5plib/v124/joubel/editor/
|
||||
lib/editor/atto/plugins/html/yui/src/codemirror/
|
||||
lib/editor/atto/plugins/html/yui/src/beautify/
|
||||
lib/editor/atto/yui/src/rangy/js/*.*
|
||||
lib/editor/tinymce/plugins/pdw/tinymce/
|
||||
lib/editor/tinymce/plugins/spellchecker/rpc.php
|
||||
lib/editor/tinymce/tiny_mce/
|
||||
lib/mlbackend/php/phpml/
|
||||
lib/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
lib/phpspreadsheet/
|
||||
lib/google/
|
||||
lib/htmlpurifier/
|
||||
lib/jabber/
|
||||
lib/minify/matthiasmullie-minify/
|
||||
lib/minify/matthiasmullie-pathconverter/
|
||||
lib/pear/HTML/Common.php
|
||||
lib/pear/HTML/QuickForm.php
|
||||
lib/pear/HTML/QuickForm/
|
||||
lib/pear/PEAR.php
|
||||
lib/phpmailer/
|
||||
lib/simplepie/
|
||||
lib/tcpdf/
|
||||
lib/typo3/
|
||||
lib/yuilib/
|
||||
lib/yuilib/gallery/
|
||||
lib/jquery/
|
||||
lib/html2text/
|
||||
lib/markdown/
|
||||
lib/xhprof/
|
||||
lib/horde/
|
||||
lib/requirejs/
|
||||
lib/amd/src/loglevel.js
|
||||
lib/mustache/
|
||||
lib/amd/src/mustache.js
|
||||
lib/graphlib.php
|
||||
lib/php-css-parser/
|
||||
lib/rtlcss/
|
||||
lib/scssphp/
|
||||
lib/spout/
|
||||
lib/amd/src/chartjs-lazy.js
|
||||
lib/maxmind/GeoIp2/
|
||||
lib/maxmind/MaxMind/
|
||||
lib/ltiprovider/
|
||||
lib/amd/src/truncate.js
|
||||
lib/fonts/
|
||||
lib/amd/src/adapter.js
|
||||
lib/validateurlsyntax.php
|
||||
lib/amd/src/popper.js
|
||||
lib/geopattern-php/
|
||||
lib/php-jwt/
|
||||
lib/babel-polyfill/
|
||||
lib/polyfills/
|
||||
lib/emoji-data/
|
||||
lib/plist/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
media/player/videojs/amd/src/videojs-flash-lazy.js
|
||||
media/player/videojs/videojs/video-js.swf
|
||||
mod/assign/feedback/editpdf/fpdi/
|
||||
repository/s3/S3.php
|
||||
theme/boost/scss/bootstrap/
|
||||
theme/boost/amd/src/bootstrap/alert.js
|
||||
theme/boost/amd/src/bootstrap/button.js
|
||||
theme/boost/amd/src/bootstrap/carousel.js
|
||||
theme/boost/amd/src/bootstrap/collapse.js
|
||||
theme/boost/amd/src/bootstrap/dropdown.js
|
||||
theme/boost/amd/src/bootstrap/index.js
|
||||
theme/boost/amd/src/bootstrap/modal.js
|
||||
theme/boost/amd/src/bootstrap/popover.js
|
||||
theme/boost/amd/src/bootstrap/tools/sanitizer.js
|
||||
theme/boost/amd/src/bootstrap/scrollspy.js
|
||||
theme/boost/amd/src/bootstrap/tab.js
|
||||
theme/boost/amd/src/bootstrap/toast.js
|
||||
theme/boost/amd/src/bootstrap/tooltip.js
|
||||
theme/boost/amd/src/bootstrap/util.js
|
||||
theme/boost/amd/src/tether.js
|
||||
theme/boost/scss/fontawesome/
|
||||
@@ -2,7 +2,6 @@
|
||||
'plugins': [
|
||||
'babel',
|
||||
'promise',
|
||||
'jsdoc',
|
||||
],
|
||||
'env': {
|
||||
'browser': true,
|
||||
@@ -192,6 +191,7 @@
|
||||
'property': 'str',
|
||||
'message': 'Use AMD module "core/str" or M.util.get_string()'
|
||||
}],
|
||||
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
@@ -200,34 +200,18 @@
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'no-unused-expressions': 'off',
|
||||
|
||||
// === JSDocs ===
|
||||
"jsdoc/check-access": 'off',
|
||||
"jsdoc/check-alignment": 'off',
|
||||
"jsdoc/check-param-names": 'off',
|
||||
"jsdoc/check-property-names": 'off',
|
||||
"jsdoc/empty-tags": 'off',
|
||||
"jsdoc/implements-on-classes": 'off',
|
||||
"jsdoc/multiline-blocks": 'off',
|
||||
"jsdoc/require-jsdoc": 'off',
|
||||
"jsdoc/require-param": 'off',
|
||||
"jsdoc/require-param-name": 'off',
|
||||
"jsdoc/require-param-type": 'off',
|
||||
"jsdoc/require-property": 'off',
|
||||
"jsdoc/require-property-name": 'off',
|
||||
"jsdoc/require-property-type": 'off',
|
||||
'no-unused-expressions': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile.js", ".grunt/*.js", ".grunt/tasks/*.js", "jsdoc.conf.js"],
|
||||
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile*.js", "babel-plugin-add-module-to-define.js"],
|
||||
// We support es6 now. Woot!
|
||||
env: {
|
||||
es6: true
|
||||
},
|
||||
// We're using babel transpiling so use their parser
|
||||
// for linting.
|
||||
parser: '@babel/eslint-parser',
|
||||
parser: 'babel-eslint',
|
||||
// Check AMD with some slightly stricter rules.
|
||||
rules: {
|
||||
'no-unused-vars': 'error',
|
||||
@@ -254,54 +238,11 @@
|
||||
// === 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',
|
||||
],
|
||||
'promise/avoid-new': 'off'
|
||||
},
|
||||
parserOptions: {
|
||||
'ecmaVersion': 9,
|
||||
'sourceType': 'module',
|
||||
'requireConfigFile': false,
|
||||
'sourceType': 'module'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
name: Core
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- master
|
||||
- MOODLE_[0-9]+_STABLE
|
||||
tags-ignore:
|
||||
- v[0-9]+.[0-9]+.[0-9]+*
|
||||
on: [push]
|
||||
|
||||
env:
|
||||
php: 8.0
|
||||
php: 7.4
|
||||
|
||||
jobs:
|
||||
Grunt:
|
||||
@@ -20,9 +14,8 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Configuring node & npm
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
shell: bash -l {0}
|
||||
run: nvm install
|
||||
|
||||
- name: Installing node stuff
|
||||
run: npm install
|
||||
@@ -55,13 +48,11 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
php: 7.3
|
||||
extensions:
|
||||
php: 7.2
|
||||
db: mysqli
|
||||
- os: ubuntu-18.04
|
||||
php: 8.0
|
||||
php: 7.4
|
||||
db: pgsql
|
||||
extensions: xmlrpc-beta
|
||||
|
||||
steps:
|
||||
- name: Setting up DB mysql
|
||||
@@ -91,8 +82,6 @@ jobs:
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: ${{ matrix.extensions }}
|
||||
ini-values: max_input_vars=5000
|
||||
coverage: none
|
||||
|
||||
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
/cscope.*
|
||||
/.patches/
|
||||
/.idea/
|
||||
.phpstorm.*
|
||||
/nbproject/
|
||||
CVS
|
||||
.DS_Store
|
||||
@@ -34,7 +33,6 @@ CVS
|
||||
/.project
|
||||
/.buildpath
|
||||
/.cache
|
||||
.phpunit.result.cache
|
||||
phpunit.xml
|
||||
# Composer support. Do not ignore composer.json, or composer.lock. These should be shipped by us.
|
||||
composer.phar
|
||||
@@ -46,8 +44,3 @@ composer.phar
|
||||
/lib/yuilib/*/*/*-coverage.js
|
||||
atlassian-ide-plugin.xml
|
||||
/node_modules/
|
||||
/.vscode/
|
||||
moodle-plugin-ci.phar
|
||||
.eslintignore
|
||||
.stylelintignore
|
||||
/jsdoc
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Moodle JavaScript Documentation
|
||||
|
||||
```
|
||||
.-..-.
|
||||
_____ | || |
|
||||
/____/-.---_ .---. .---. .-.| || | .---.
|
||||
| | _ _ |/ _ \/ _ \/ _ || |/ __ \
|
||||
* | | | | | || |_| || |_| || |_| || || |___/
|
||||
|_| |_| |_|\_____/\_____/\_____||_|\_____)
|
||||
|
||||
Moodle - the world's open source learning platform
|
||||
|
||||
```
|
||||
|
||||
## About
|
||||
This generated documentation includes API documentation for JavaScript written in the AMD and ES2015 module formats within Moodle.
|
||||
|
||||
## Related information
|
||||
See [https://docs.moodle.org/dev](https://docs.moodle.org/dev) for other related Developer Documentation.
|
||||
@@ -1,131 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Helper functions for working with Moodle component names, directories, and sources.
|
||||
*
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
/* eslint-env node */
|
||||
|
||||
// Do not include any plugins as stanard.
|
||||
const plugins = [];
|
||||
|
||||
plugins.push('plugins/markdown');
|
||||
|
||||
/**
|
||||
* Get the source configuration.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
const getSource = () => {
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
const ComponentList = require(path.resolve('.grunt/components.js'));
|
||||
const thirdPartyPaths = ComponentList.getThirdPartyPaths();
|
||||
|
||||
const source = {
|
||||
include: [],
|
||||
includePattern: ".+\\.js$",
|
||||
};
|
||||
|
||||
let includeList = [];
|
||||
|
||||
ComponentList.getAmdSrcGlobList().forEach(async pattern => {
|
||||
includeList.push(...glob.sync(pattern));
|
||||
});
|
||||
|
||||
const cwdLength = process.cwd().length + 1;
|
||||
includeList.forEach(path => {
|
||||
if (source.include.indexOf(path) !== -1) {
|
||||
// Ensure no duplicates.
|
||||
return;
|
||||
}
|
||||
|
||||
const relPath = path.substring(cwdLength);
|
||||
if (thirdPartyPaths.indexOf(relPath) !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
source.include.push(path);
|
||||
});
|
||||
|
||||
source.include.push('.grunt/jsdoc/README.md');
|
||||
return source;
|
||||
};
|
||||
|
||||
const tags = {
|
||||
// Allow the use of unknown tags.
|
||||
// We have a lot of legacy uses of these.
|
||||
allowUnknownTags: true,
|
||||
|
||||
// We make use of jsdoc and closure dictionaries as standard.
|
||||
dictionaries: [
|
||||
'jsdoc',
|
||||
'closure',
|
||||
],
|
||||
};
|
||||
|
||||
// Template configuraiton.
|
||||
const templates = {
|
||||
cleverLinks: false,
|
||||
monospaceLinks: false,
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
opts: {
|
||||
destination: "./jsdoc/",
|
||||
template: "node_modules/docdash",
|
||||
},
|
||||
plugins,
|
||||
recurseDepth: 10,
|
||||
source: getSource(),
|
||||
sourceType: 'module',
|
||||
tags,
|
||||
templates,
|
||||
docdash: {
|
||||
collapse: true,
|
||||
search: true,
|
||||
sort: true,
|
||||
sectionOrder: [
|
||||
"Namespaces",
|
||||
"Modules",
|
||||
"Events",
|
||||
"Classes",
|
||||
"Externals",
|
||||
"Mixins",
|
||||
"Tutorials",
|
||||
"Interfaces"
|
||||
],
|
||||
"menu": {
|
||||
"Developer Docs": {
|
||||
href: "https://docs.moodle.org/dev",
|
||||
target: "_blank",
|
||||
"class": "menu-item",
|
||||
id: "devdocs"
|
||||
},
|
||||
"MDN Docs": {
|
||||
href: "https://developer.mozilla.org/en-US/docs/Web/JavaScript",
|
||||
target: "_blank",
|
||||
"class": "menu-item",
|
||||
id: "mdndocs",
|
||||
},
|
||||
},
|
||||
typedefs: true,
|
||||
},
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
const files = grunt.moodleEnv.files;
|
||||
|
||||
// Project configuration.
|
||||
grunt.config.merge({
|
||||
eslint: {
|
||||
// Even though warnings dont stop the build we don't display warnings by default because
|
||||
// at this moment we've got too many core warnings.
|
||||
// To display warnings call: grunt eslint --show-lint-warnings
|
||||
// To fail on warnings call: grunt eslint --max-lint-warnings=0
|
||||
// Also --max-lint-warnings=-1 can be used to display warnings but not fail.
|
||||
options: {
|
||||
quiet: (!grunt.option('show-lint-warnings')) && (typeof grunt.option('max-lint-warnings') === 'undefined'),
|
||||
maxWarnings: ((typeof grunt.option('max-lint-warnings') !== 'undefined') ? grunt.option('max-lint-warnings') : -1)
|
||||
},
|
||||
|
||||
// Check AMD src files.
|
||||
amd: {src: files ? files : grunt.moodleEnv.amdSrc},
|
||||
|
||||
// Check YUI module source files.
|
||||
yui: {src: files ? files : grunt.moodleEnv.yuiSrc},
|
||||
},
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
|
||||
// On watch, we dynamically modify config to build only affected files. This
|
||||
// method is slightly complicated to deal with multiple changed files at once (copied
|
||||
// from the grunt-contrib-watch readme).
|
||||
let changedFiles = Object.create(null);
|
||||
const onChange = grunt.util._.debounce(function() {
|
||||
const files = Object.keys(changedFiles);
|
||||
grunt.config('eslint.amd.src', files);
|
||||
grunt.config('eslint.yui.src', files);
|
||||
changedFiles = Object.create(null);
|
||||
}, 200);
|
||||
|
||||
grunt.event.on('watch', (action, filepath) => {
|
||||
changedFiles[filepath] = action;
|
||||
onChange();
|
||||
});
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
/**
|
||||
* Get the list of feature files to pass to the gherkin linter.
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getGherkinLintTargets = () => {
|
||||
if (grunt.moodleEnv.files) {
|
||||
// Specific files were requested. Only check these.
|
||||
return grunt.moodleEnv.files;
|
||||
}
|
||||
|
||||
if (grunt.moodleEnv.inComponent) {
|
||||
return [`${grunt.moodleEnv.runDir}/tests/behat/*.feature`];
|
||||
}
|
||||
|
||||
return ['**/tests/behat/*.feature'];
|
||||
};
|
||||
|
||||
const handler = function() {
|
||||
const done = this.async();
|
||||
const options = grunt.config('gherkinlint.options');
|
||||
|
||||
// Grab the gherkin-lint linter and required scaffolding.
|
||||
const linter = require('gherkin-lint/dist/linter.js');
|
||||
const featureFinder = require('gherkin-lint/dist/feature-finder.js');
|
||||
const configParser = require('gherkin-lint/dist/config-parser.js');
|
||||
const formatter = require('gherkin-lint/dist/formatters/stylish.js');
|
||||
|
||||
// Run the linter.
|
||||
return linter.lint(
|
||||
featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
|
||||
configParser.getConfiguration(configParser.defaultConfigFileName)
|
||||
)
|
||||
.then(results => {
|
||||
// Print the results out uncondtionally.
|
||||
formatter.printResults(results);
|
||||
|
||||
return results;
|
||||
})
|
||||
.then(results => {
|
||||
// Report on the results.
|
||||
// The done function takes a bool whereby a falsey statement causes the task to fail.
|
||||
return results.every(result => result.errors.length === 0);
|
||||
})
|
||||
.then(done); // eslint-disable-line promise/no-callback-in-promise
|
||||
};
|
||||
|
||||
grunt.registerTask('gherkinlint', 'Run gherkinlint against the current directory', handler);
|
||||
|
||||
grunt.config.set('gherkinlint', {
|
||||
options: {
|
||||
files: getGherkinLintTargets(),
|
||||
}
|
||||
});
|
||||
|
||||
grunt.config.merge({
|
||||
watch: {
|
||||
gherkinlint: {
|
||||
files: [grunt.moodleEnv.inComponent ? 'tests/behat/*.feature' : '**/tests/behat/*.feature'],
|
||||
tasks: ['gherkinlint'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return handler;
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
/**
|
||||
* Generate ignore files (utilising thirdpartylibs.xml data)
|
||||
*/
|
||||
const handler = function() {
|
||||
const path = require('path');
|
||||
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
|
||||
|
||||
// An array of paths to third party directories.
|
||||
const thirdPartyPaths = ComponentList.getThirdPartyPaths();
|
||||
|
||||
// Generate .eslintignore.
|
||||
const eslintIgnores = [
|
||||
'# Generated by "grunt ignorefiles"',
|
||||
// Do not ignore the .grunt directory.
|
||||
'!/.grunt',
|
||||
|
||||
// Ignore all yui/src meta directories and build directories.
|
||||
'*/**/yui/src/*/meta/',
|
||||
'*/**/build/',
|
||||
].concat(thirdPartyPaths);
|
||||
grunt.file.write('.eslintignore', eslintIgnores.join('\n') + '\n');
|
||||
|
||||
// Generate .stylelintignore.
|
||||
const stylelintIgnores = [
|
||||
'# Generated by "grunt ignorefiles"',
|
||||
'**/yui/build/*',
|
||||
'theme/boost/style/moodle.css',
|
||||
'theme/classic/style/moodle.css',
|
||||
'jsdoc/styles/*.css',
|
||||
].concat(thirdPartyPaths);
|
||||
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n') + '\n');
|
||||
};
|
||||
|
||||
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', handler);
|
||||
|
||||
return handler;
|
||||
};
|
||||
@@ -1,222 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function to generate the destination for the uglify 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
|
||||
*
|
||||
* @param {String} destPath the current destination
|
||||
* @param {String} srcPath the matched src path
|
||||
* @return {String} The rewritten destination path.
|
||||
*/
|
||||
|
||||
const babelRename = function(destPath, srcPath) {
|
||||
destPath = srcPath.replace('src', 'build');
|
||||
destPath = destPath.replace('.js', '.min.js');
|
||||
return destPath;
|
||||
};
|
||||
|
||||
module.exports = grunt => {
|
||||
// Load the Ignorefiles tasks.
|
||||
require('./ignorefiles')(grunt);
|
||||
|
||||
// Load the Shifter tasks.
|
||||
require('./shifter')(grunt);
|
||||
|
||||
// Load ESLint.
|
||||
require('./eslint')(grunt);
|
||||
|
||||
// Load JSDoc.
|
||||
require('./jsdoc')(grunt);
|
||||
|
||||
const path = require('path');
|
||||
|
||||
// Register JS tasks.
|
||||
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
|
||||
grunt.registerTask('amd', ['ignorefiles', 'eslint:amd', 'rollup']);
|
||||
grunt.registerTask('js', ['amd', 'yui']);
|
||||
|
||||
// Register NPM tasks.
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-rollup');
|
||||
|
||||
const babelTransform = require('@babel/core').transform;
|
||||
const babel = (options = {}) => {
|
||||
return {
|
||||
name: 'babel',
|
||||
|
||||
transform: (code, id) => {
|
||||
grunt.log.debug(`Transforming ${id}`);
|
||||
options.filename = id;
|
||||
const transformed = babelTransform(code, options);
|
||||
|
||||
return {
|
||||
code: transformed.code,
|
||||
map: transformed.map
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Note: We have to use a rate limit plugin here because rollup runs all tasks asynchronously and in parallel.
|
||||
// When we kick off a full run, if we kick off a rollup of every file this will fork-bomb the machine.
|
||||
// To work around this we use a concurrent Promise queue based on the number of available processors.
|
||||
const rateLimit = () => {
|
||||
const queue = [];
|
||||
let queueRunner;
|
||||
|
||||
const startQueue = () => {
|
||||
if (queueRunner) {
|
||||
return;
|
||||
}
|
||||
|
||||
queueRunner = setTimeout(() => {
|
||||
const limit = Math.max(1, require('os').cpus().length / 2);
|
||||
grunt.log.debug(`Starting rollup with queue size of ${limit}`);
|
||||
runQueue(limit);
|
||||
}, 100);
|
||||
};
|
||||
|
||||
// The queue runner will run the next `size` items in the queue.
|
||||
const runQueue = (size = 1) => {
|
||||
queue.splice(0, size).forEach(resolve => {
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
name: 'ratelimit',
|
||||
|
||||
// The options hook is run in parallel.
|
||||
// We can return an unresolved Promise which is queued for later resolution.
|
||||
options: async() => {
|
||||
return new Promise(resolve => {
|
||||
queue.push(resolve);
|
||||
startQueue();
|
||||
});
|
||||
},
|
||||
|
||||
// When an item in the queue completes, start the next item in the queue.
|
||||
buildEnd: () => {
|
||||
runQueue();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const terser = require('rollup-plugin-terser').terser;
|
||||
grunt.config.merge({
|
||||
rollup: {
|
||||
options: {
|
||||
format: 'esm',
|
||||
dir: 'output',
|
||||
sourcemap: true,
|
||||
treeshake: false,
|
||||
context: 'window',
|
||||
plugins: [
|
||||
rateLimit(),
|
||||
babel({
|
||||
sourceMaps: true,
|
||||
comments: false,
|
||||
compact: false,
|
||||
plugins: [
|
||||
'transform-es2015-modules-amd-lazy',
|
||||
'system-import-transformer',
|
||||
// This plugin modifies the Babel transpiling for "export default"
|
||||
// so that if it's used then only the exported value is returned
|
||||
// by the generated AMD module.
|
||||
//
|
||||
// It also adds the Moodle plugin name to the AMD module definition
|
||||
// so that it can be imported as expected in other modules.
|
||||
path.resolve('.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'
|
||||
],
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: [
|
||||
">0.25%",
|
||||
"last 2 versions",
|
||||
"not ie <= 10",
|
||||
"not op_mini all",
|
||||
"not Opera > 0",
|
||||
"not dead"
|
||||
]
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: false
|
||||
}]
|
||||
]
|
||||
}),
|
||||
|
||||
terser({
|
||||
// Do not mangle variables.
|
||||
// Makes debugging easier.
|
||||
mangle: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
dist: {
|
||||
files: [{
|
||||
expand: true,
|
||||
src: grunt.moodleEnv.files ? grunt.moodleEnv.files : grunt.moodleEnv.amdSrc,
|
||||
rename: babelRename
|
||||
}],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
grunt.config.merge({
|
||||
watch: {
|
||||
amd: {
|
||||
files: grunt.moodleEnv.inComponent
|
||||
? ['amd/src/*.js', 'amd/src/**/*.js']
|
||||
: ['**/amd/src/**/*.js'],
|
||||
tasks: ['amd']
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// On watch, we dynamically modify config to build only affected files. This
|
||||
// method is slightly complicated to deal with multiple changed files at once (copied
|
||||
// from the grunt-contrib-watch readme).
|
||||
let changedFiles = Object.create(null);
|
||||
const onChange = grunt.util._.debounce(function() {
|
||||
const files = Object.keys(changedFiles);
|
||||
grunt.config('rollup.dist.files', [{expand: true, src: files, rename: babelRename}]);
|
||||
changedFiles = Object.create(null);
|
||||
}, 200);
|
||||
|
||||
grunt.event.on('watch', function(action, filepath) {
|
||||
changedFiles[filepath] = action;
|
||||
onChange();
|
||||
});
|
||||
|
||||
return {
|
||||
babelRename,
|
||||
};
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @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",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-jsdoc');
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
grunt.loadNpmTasks('grunt-sass');
|
||||
|
||||
grunt.config.merge({
|
||||
sass: {
|
||||
dist: {
|
||||
files: {
|
||||
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss",
|
||||
"theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss"
|
||||
}
|
||||
},
|
||||
options: {
|
||||
implementation: require('node-sass'),
|
||||
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,155 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
module.exports = grunt => {
|
||||
/**
|
||||
* Shifter task. Is configured with a path to a specific file or a directory,
|
||||
* in the case of a specific file it will work out the right module to be built.
|
||||
*
|
||||
* Note that this task runs the invidiaul shifter jobs async (becase it spawns
|
||||
* so be careful to to call done().
|
||||
*/
|
||||
const handler = function() {
|
||||
const done = this.async();
|
||||
const options = grunt.config('shifter.options');
|
||||
const async = require('async');
|
||||
const path = require('path');
|
||||
|
||||
// Run the shifter processes one at a time to avoid confusing output.
|
||||
async.eachSeries(options.paths, function(src, filedone) {
|
||||
var args = [];
|
||||
args.push(path.normalize(process.cwd() + '/node_modules/shifter/bin/shifter'));
|
||||
|
||||
// Always ignore the node_modules directory.
|
||||
args.push('--excludes', 'node_modules');
|
||||
|
||||
// Determine the most appropriate options to run with based upon the current location.
|
||||
if (grunt.file.isMatch('**/yui/**/*.js', src)) {
|
||||
// When passed a JS file, build our containing module (this happen with
|
||||
// watch).
|
||||
grunt.log.debug('Shifter passed a specific JS file');
|
||||
src = path.dirname(path.dirname(src));
|
||||
options.recursive = false;
|
||||
} else if (grunt.file.isMatch('**/yui/src', src)) {
|
||||
// When in a src directory --walk all modules.
|
||||
grunt.log.debug('In a src directory');
|
||||
args.push('--walk');
|
||||
options.recursive = false;
|
||||
} else if (grunt.file.isMatch('**/yui/src/*', src)) {
|
||||
// When in module, only build our module.
|
||||
grunt.log.debug('In a module directory');
|
||||
options.recursive = false;
|
||||
} else if (grunt.file.isMatch('**/yui/src/*/js', src)) {
|
||||
// When in module src, only build our module.
|
||||
grunt.log.debug('In a source directory');
|
||||
src = path.dirname(src);
|
||||
options.recursive = false;
|
||||
}
|
||||
|
||||
if (grunt.option('watch')) {
|
||||
grunt.fail.fatal('The --watch option has been removed, please use `grunt watch` instead');
|
||||
}
|
||||
|
||||
// Add the stderr option if appropriate
|
||||
if (grunt.option('verbose')) {
|
||||
args.push('--lint-stderr');
|
||||
}
|
||||
|
||||
if (grunt.option('no-color')) {
|
||||
args.push('--color=false');
|
||||
}
|
||||
|
||||
var execShifter = function() {
|
||||
|
||||
grunt.log.ok("Running shifter on " + src);
|
||||
grunt.util.spawn({
|
||||
cmd: "node",
|
||||
args: args,
|
||||
opts: {cwd: src, stdio: 'inherit', env: process.env}
|
||||
}, function(error, result, code) {
|
||||
if (code) {
|
||||
grunt.fail.fatal('Shifter failed with code: ' + code);
|
||||
} else {
|
||||
grunt.log.ok('Shifter build complete.');
|
||||
filedone();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Actually run shifter.
|
||||
if (!options.recursive) {
|
||||
execShifter();
|
||||
} else {
|
||||
// Check that there are yui modules otherwise shifter ends with exit code 1.
|
||||
if (grunt.file.expand({cwd: src}, '**/yui/src/**/*.js').length > 0) {
|
||||
args.push('--recursive');
|
||||
execShifter();
|
||||
} else {
|
||||
grunt.log.ok('No YUI modules to build.');
|
||||
filedone();
|
||||
}
|
||||
}
|
||||
}, done);
|
||||
};
|
||||
|
||||
// Register the shifter task.
|
||||
grunt.registerTask('shifter', 'Run Shifter against the current directory', handler);
|
||||
|
||||
// Configure it.
|
||||
grunt.config.set('shifter', {
|
||||
options: {
|
||||
recursive: true,
|
||||
// Shifter takes a relative path.
|
||||
paths: grunt.moodleEnv.files ? grunt.moodleEnv.files : [grunt.moodleEnv.runDir]
|
||||
}
|
||||
});
|
||||
|
||||
grunt.config.merge({
|
||||
watch: {
|
||||
yui: {
|
||||
files: grunt.moodleEnv.inComponent
|
||||
? ['yui/src/*.json', 'yui/src/**/*.js']
|
||||
: ['**/yui/src/**/*.js'],
|
||||
tasks: ['yui']
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// On watch, we dynamically modify config to build only affected files. This
|
||||
// method is slightly complicated to deal with multiple changed files at once (copied
|
||||
// from the grunt-contrib-watch readme).
|
||||
let changedFiles = Object.create(null);
|
||||
const onChange = grunt.util._.debounce(function() {
|
||||
const files = Object.keys(changedFiles);
|
||||
grunt.config('shifter.options.paths', files);
|
||||
changedFiles = Object.create(null);
|
||||
}, 200);
|
||||
|
||||
grunt.event.on('watch', (action, filepath) => {
|
||||
changedFiles[filepath] = action;
|
||||
onChange();
|
||||
});
|
||||
|
||||
return handler;
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
/**
|
||||
* Generate ignore files (utilising thirdpartylibs.xml data)
|
||||
*/
|
||||
const handler = function() {
|
||||
const path = require('path');
|
||||
|
||||
// Are we in a YUI directory?
|
||||
if (path.basename(path.resolve(grunt.moodleEnv.cwd, '../../')) == 'yui') {
|
||||
grunt.task.run('yui');
|
||||
// Are we in an AMD directory?
|
||||
} else if (grunt.moodleEnv.inAMD) {
|
||||
grunt.task.run('amd');
|
||||
} else {
|
||||
// Run them all!.
|
||||
grunt.task.run('css');
|
||||
grunt.task.run('js');
|
||||
grunt.task.run('gherkinlint');
|
||||
}
|
||||
};
|
||||
|
||||
// Register the startup task.
|
||||
grunt.registerTask('startup', 'Run the correct tasks for the current directory', handler);
|
||||
|
||||
return handler;
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
// Load the ignorefiles tasks.
|
||||
require('./ignorefiles')(grunt);
|
||||
|
||||
// Load the Style Lint tasks.
|
||||
require('./stylelint')(grunt);
|
||||
|
||||
// Load the SASS tasks.
|
||||
require('./sass')(grunt);
|
||||
};
|
||||
@@ -1,183 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
|
||||
const getCssConfigForFiles = files => {
|
||||
return {
|
||||
stylelint: {
|
||||
css: {
|
||||
// Use a fully-qualified path.
|
||||
src: files,
|
||||
options: {
|
||||
configOverrides: {
|
||||
rules: {
|
||||
// These rules have to be disabled in .stylelintrc for scss compat.
|
||||
"at-rule-no-unknown": true,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const getScssConfigForFiles = files => {
|
||||
return {
|
||||
stylelint: {
|
||||
scss: {
|
||||
options: {syntax: 'scss'},
|
||||
src: files,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Register any stylelint tasks.
|
||||
*
|
||||
* @param {Object} grunt
|
||||
* @param {Array} files
|
||||
* @param {String} fullRunDir
|
||||
*/
|
||||
const registerStyleLintTasks = () => {
|
||||
const glob = require('glob');
|
||||
|
||||
// The stylelinters do not handle the case where a configuration was provided but no files were included.
|
||||
// Keep track of whether any files were found.
|
||||
let hasCss = false;
|
||||
let hasScss = false;
|
||||
|
||||
// The stylelint processors do not take a path argument. They always check all provided values.
|
||||
// As a result we must check through each glob and determine if any files match the current directory.
|
||||
const scssFiles = [];
|
||||
const cssFiles = [];
|
||||
|
||||
const requestedFiles = grunt.moodleEnv.files;
|
||||
if (requestedFiles) {
|
||||
// Grunt was called with a files argument.
|
||||
// Check whether each of the requested files matches either the CSS or SCSS source file list.
|
||||
|
||||
requestedFiles.forEach(changedFilePath => {
|
||||
let matchesGlob;
|
||||
|
||||
// Check whether this watched path matches any watched SCSS file.
|
||||
matchesGlob = grunt.moodleEnv.scssSrc.some(watchedPathGlob => {
|
||||
return glob.sync(watchedPathGlob).indexOf(changedFilePath) !== -1;
|
||||
});
|
||||
if (matchesGlob) {
|
||||
scssFiles.push(changedFilePath);
|
||||
hasScss = true;
|
||||
}
|
||||
|
||||
// Check whether this watched path matches any watched CSS file.
|
||||
matchesGlob = grunt.moodleEnv.cssSrc.some(watchedPathGlob => {
|
||||
return glob.sync(watchedPathGlob).indexOf(changedFilePath) !== -1;
|
||||
});
|
||||
if (matchesGlob) {
|
||||
cssFiles.push(changedFilePath);
|
||||
hasCss = true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Grunt was called without a list of files.
|
||||
// The start directory (runDir) may be a child dir of the project.
|
||||
// Check each scssSrc file to see if it's in the start directory.
|
||||
// This means that we can lint just mod/*/styles.css if started in the mod directory.
|
||||
|
||||
grunt.moodleEnv.scssSrc.forEach(path => {
|
||||
if (path.startsWith(grunt.moodleEnv.runDir)) {
|
||||
scssFiles.push(path);
|
||||
hasScss = true;
|
||||
}
|
||||
});
|
||||
|
||||
grunt.moodleEnv.cssSrc.forEach(path => {
|
||||
if (path.startsWith(grunt.moodleEnv.runDir)) {
|
||||
cssFiles.push(path);
|
||||
hasCss = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Register the tasks.
|
||||
const scssTasks = ['sass'];
|
||||
if (hasScss) {
|
||||
grunt.config.merge(getScssConfigForFiles(scssFiles));
|
||||
scssTasks.unshift('stylelint:scss');
|
||||
}
|
||||
scssTasks.unshift('ignorefiles');
|
||||
|
||||
const cssTasks = ['ignorefiles'];
|
||||
if (hasCss) {
|
||||
grunt.config.merge(getCssConfigForFiles(cssFiles));
|
||||
cssTasks.push('stylelint:css');
|
||||
}
|
||||
|
||||
// The tasks must be registered, even if empty to ensure a consistent command list.
|
||||
// They jsut won't run anything.
|
||||
grunt.registerTask('scss', scssTasks);
|
||||
grunt.registerTask('rawcss', cssTasks);
|
||||
};
|
||||
|
||||
// Register CSS tasks.
|
||||
grunt.loadNpmTasks('grunt-stylelint');
|
||||
|
||||
// Register the style lint tasks.
|
||||
registerStyleLintTasks();
|
||||
grunt.registerTask('css', ['scss', 'rawcss']);
|
||||
|
||||
const getCoreThemeMatches = () => {
|
||||
const scssMatch = 'scss/**/*.scss';
|
||||
|
||||
if (grunt.moodleEnv.inTheme) {
|
||||
return [scssMatch];
|
||||
}
|
||||
|
||||
if (grunt.moodleEnv.runDir.startsWith('theme')) {
|
||||
return [`*/${scssMatch}`];
|
||||
}
|
||||
|
||||
return [`theme/*/${scssMatch}`];
|
||||
};
|
||||
|
||||
// Add the watch configuration for rawcss, and scss.
|
||||
grunt.config.merge({
|
||||
watch: {
|
||||
rawcss: {
|
||||
files: [
|
||||
'**/*.css',
|
||||
],
|
||||
excludes: [
|
||||
'**/moodle.css',
|
||||
'**/editor.css',
|
||||
'jsdoc/styles/*.css',
|
||||
],
|
||||
tasks: ['rawcss']
|
||||
},
|
||||
scss: {
|
||||
files: getCoreThemeMatches(),
|
||||
tasks: ['scss']
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,272 +0,0 @@
|
||||
/**
|
||||
* This is a wrapper task to handle the grunt watch command. It attempts to use
|
||||
* Watchman to monitor for file changes, if it's installed, because it's much faster.
|
||||
*
|
||||
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
|
||||
* watcher for backwards compatibility.
|
||||
*/
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
module.exports = grunt => {
|
||||
/**
|
||||
* This is a wrapper task to handle the grunt watch command. It attempts to use
|
||||
* Watchman to monitor for file changes, if it's installed, because it's much faster.
|
||||
*
|
||||
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
|
||||
* watcher for backwards compatibility.
|
||||
*/
|
||||
const watchHandler = function() {
|
||||
const async = require('async');
|
||||
const watchTaskDone = this.async();
|
||||
let watchInitialised = false;
|
||||
let watchTaskQueue = {};
|
||||
let processingQueue = false;
|
||||
|
||||
const watchman = require('fb-watchman');
|
||||
const watchmanClient = new watchman.Client();
|
||||
|
||||
// Grab the tasks and files that have been queued up and execute them.
|
||||
var processWatchTaskQueue = function() {
|
||||
if (!Object.keys(watchTaskQueue).length || processingQueue) {
|
||||
// If there is nothing in the queue or we're already processing then wait.
|
||||
return;
|
||||
}
|
||||
|
||||
processingQueue = true;
|
||||
|
||||
// Grab all tasks currently in the queue.
|
||||
var queueToProcess = watchTaskQueue;
|
||||
// Reset the queue.
|
||||
watchTaskQueue = {};
|
||||
|
||||
async.forEachSeries(
|
||||
Object.keys(queueToProcess),
|
||||
function(task, next) {
|
||||
var files = queueToProcess[task];
|
||||
var filesOption = '--files=' + files.join(',');
|
||||
grunt.log.ok('Running task ' + task + ' for files ' + filesOption);
|
||||
|
||||
// Spawn the task in a child process so that it doesn't kill this one
|
||||
// if it failed.
|
||||
grunt.util.spawn(
|
||||
{
|
||||
// Spawn with the grunt bin.
|
||||
grunt: true,
|
||||
// Run from current working dir and inherit stdio from process.
|
||||
opts: {
|
||||
cwd: grunt.moodleEnv.fullRunDir,
|
||||
stdio: 'inherit'
|
||||
},
|
||||
args: [task, filesOption]
|
||||
},
|
||||
function(err, res, code) {
|
||||
if (code !== 0) {
|
||||
// The grunt task failed.
|
||||
grunt.log.error(err);
|
||||
}
|
||||
|
||||
// Move on to the next task.
|
||||
next();
|
||||
}
|
||||
);
|
||||
},
|
||||
function() {
|
||||
// No longer processing.
|
||||
processingQueue = false;
|
||||
// Once all of the tasks are done then recurse just in case more tasks
|
||||
// were queued while we were processing.
|
||||
processWatchTaskQueue();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const originalWatchConfig = grunt.config.get(['watch']);
|
||||
const watchConfig = Object.keys(originalWatchConfig).reduce(function(carry, key) {
|
||||
if (key == 'options') {
|
||||
return carry;
|
||||
}
|
||||
|
||||
const value = originalWatchConfig[key];
|
||||
|
||||
const taskNames = value.tasks;
|
||||
const files = value.files;
|
||||
let excludes = [];
|
||||
if (value.excludes) {
|
||||
excludes = value.excludes;
|
||||
}
|
||||
|
||||
taskNames.forEach(function(taskName) {
|
||||
carry[taskName] = {
|
||||
files,
|
||||
excludes,
|
||||
};
|
||||
});
|
||||
|
||||
return carry;
|
||||
}, {});
|
||||
|
||||
watchmanClient.on('error', function(error) {
|
||||
// We have to add an error handler here and parse the error string because the
|
||||
// example way from the docs to check if Watchman is installed doesn't actually work!!
|
||||
// See: https://github.com/facebook/watchman/issues/509
|
||||
if (error.message.match('Watchman was not found')) {
|
||||
// If watchman isn't installed then we should fallback to the other watch task.
|
||||
grunt.log.ok('It is recommended that you install Watchman for better performance using the "watch" command.');
|
||||
|
||||
// Fallback to the old grunt-contrib-watch task.
|
||||
grunt.renameTask('watch-grunt', 'watch');
|
||||
grunt.task.run(['watch']);
|
||||
// This task is finished.
|
||||
watchTaskDone(0);
|
||||
} else {
|
||||
grunt.log.error(error);
|
||||
// Fatal error.
|
||||
watchTaskDone(1);
|
||||
}
|
||||
});
|
||||
|
||||
watchmanClient.on('subscription', function(resp) {
|
||||
if (resp.subscription !== 'grunt-watch') {
|
||||
return;
|
||||
}
|
||||
|
||||
resp.files.forEach(function(file) {
|
||||
grunt.log.ok('File changed: ' + file.name);
|
||||
|
||||
var fullPath = grunt.moodleEnv.fullRunDir + '/' + file.name;
|
||||
Object.keys(watchConfig).forEach(function(task) {
|
||||
|
||||
const fileGlobs = watchConfig[task].files;
|
||||
var match = fileGlobs.some(function(fileGlob) {
|
||||
return grunt.file.isMatch(`**/${fileGlob}`, fullPath);
|
||||
});
|
||||
|
||||
if (match) {
|
||||
// If we are watching a subdirectory then the file.name will be relative
|
||||
// to that directory. However the grunt tasks expect the file paths to be
|
||||
// relative to the Gruntfile.js location so let's normalise them before
|
||||
// adding them to the queue.
|
||||
var relativePath = fullPath.replace(grunt.moodleEnv.gruntFilePath + '/', '');
|
||||
if (task in watchTaskQueue) {
|
||||
if (!watchTaskQueue[task].includes(relativePath)) {
|
||||
watchTaskQueue[task] = watchTaskQueue[task].concat(relativePath);
|
||||
}
|
||||
} else {
|
||||
watchTaskQueue[task] = [relativePath];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
processWatchTaskQueue();
|
||||
});
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
// Let the user know that they may need to manually stop the Watchman daemon if they
|
||||
// no longer want it running.
|
||||
if (watchInitialised) {
|
||||
grunt.log.ok('The Watchman daemon may still be running and may need to be stopped manually.');
|
||||
}
|
||||
|
||||
process.exit();
|
||||
});
|
||||
|
||||
// Initiate the watch on the current directory.
|
||||
watchmanClient.command(['watch-project', grunt.moodleEnv.fullRunDir], function(watchError, watchResponse) {
|
||||
if (watchError) {
|
||||
grunt.log.error('Error initiating watch:', watchError);
|
||||
watchTaskDone(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if ('warning' in watchResponse) {
|
||||
grunt.log.error('warning: ', watchResponse.warning);
|
||||
}
|
||||
|
||||
var watch = watchResponse.watch;
|
||||
var relativePath = watchResponse.relative_path;
|
||||
watchInitialised = true;
|
||||
|
||||
watchmanClient.command(['clock', watch], function(clockError, clockResponse) {
|
||||
if (clockError) {
|
||||
grunt.log.error('Failed to query clock:', clockError);
|
||||
watchTaskDone(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate the expression query used by watchman.
|
||||
// Documentation is limited, but see https://facebook.github.io/watchman/docs/expr/allof.html for examples.
|
||||
// We generate an expression to match any value in the files list of all of our tasks, but excluding
|
||||
// all value in the excludes list of that task.
|
||||
//
|
||||
// [anyof, [
|
||||
// [allof, [
|
||||
// [anyof, [
|
||||
// ['match', validPath, 'wholename'],
|
||||
// ['match', validPath, 'wholename'],
|
||||
// ],
|
||||
// [not,
|
||||
// [anyof, [
|
||||
// ['match', invalidPath, 'wholename'],
|
||||
// ['match', invalidPath, 'wholename'],
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
var matchWholeName = fileGlob => ['match', fileGlob, 'wholename'];
|
||||
var matches = Object.keys(watchConfig).map(function(task) {
|
||||
const matchAll = [];
|
||||
matchAll.push(['anyof'].concat(watchConfig[task].files.map(matchWholeName)));
|
||||
|
||||
if (watchConfig[task].excludes.length) {
|
||||
matchAll.push(['not', ['anyof'].concat(watchConfig[task].excludes.map(matchWholeName))]);
|
||||
}
|
||||
|
||||
return ['allof'].concat(matchAll);
|
||||
});
|
||||
|
||||
matches = ['anyof'].concat(matches);
|
||||
|
||||
var sub = {
|
||||
expression: matches,
|
||||
// Which fields we're interested in.
|
||||
fields: ["name", "size", "type"],
|
||||
// Add our time constraint.
|
||||
since: clockResponse.clock
|
||||
};
|
||||
|
||||
if (relativePath) {
|
||||
/* eslint-disable camelcase */
|
||||
sub.relative_root = relativePath;
|
||||
}
|
||||
|
||||
watchmanClient.command(['subscribe', watch, 'grunt-watch', sub], function(subscribeError) {
|
||||
if (subscribeError) {
|
||||
// Probably an error in the subscription criteria.
|
||||
grunt.log.error('failed to subscribe: ', subscribeError);
|
||||
watchTaskDone(1);
|
||||
return;
|
||||
}
|
||||
|
||||
grunt.log.ok('Listening for changes to files in ' + grunt.moodleEnv.fullRunDir);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
|
||||
grunt.renameTask('watch', 'watch-grunt');
|
||||
|
||||
// Register the new watch handler.
|
||||
grunt.registerTask('watch', 'Run tasks on file changes', watchHandler);
|
||||
|
||||
grunt.config.merge({
|
||||
watch: {
|
||||
options: {
|
||||
nospawn: true // We need not to spawn so config can be changed dynamically.
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return watchHandler;
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
# Generated by "grunt ignorefiles"
|
||||
**/yui/build/*
|
||||
theme/boost/style/moodle.css
|
||||
theme/classic/style/moodle.css
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
auth/cas/CAS/
|
||||
cache/stores/mongodb/MongoDB/
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
filter/tex/mimetex.*
|
||||
h5p/h5plib/v124/joubel/core/
|
||||
h5p/h5plib/v124/joubel/editor/
|
||||
lib/editor/atto/plugins/html/yui/src/codemirror/
|
||||
lib/editor/atto/plugins/html/yui/src/beautify/
|
||||
lib/editor/atto/yui/src/rangy/js/*.*
|
||||
lib/editor/tinymce/plugins/pdw/tinymce/
|
||||
lib/editor/tinymce/plugins/spellchecker/rpc.php
|
||||
lib/editor/tinymce/tiny_mce/
|
||||
lib/mlbackend/php/phpml/
|
||||
lib/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
lib/phpspreadsheet/
|
||||
lib/google/
|
||||
lib/htmlpurifier/
|
||||
lib/jabber/
|
||||
lib/minify/matthiasmullie-minify/
|
||||
lib/minify/matthiasmullie-pathconverter/
|
||||
lib/pear/HTML/Common.php
|
||||
lib/pear/HTML/QuickForm.php
|
||||
lib/pear/HTML/QuickForm/
|
||||
lib/pear/PEAR.php
|
||||
lib/phpmailer/
|
||||
lib/simplepie/
|
||||
lib/tcpdf/
|
||||
lib/typo3/
|
||||
lib/yuilib/
|
||||
lib/yuilib/gallery/
|
||||
lib/jquery/
|
||||
lib/html2text/
|
||||
lib/markdown/
|
||||
lib/xhprof/
|
||||
lib/horde/
|
||||
lib/requirejs/
|
||||
lib/amd/src/loglevel.js
|
||||
lib/mustache/
|
||||
lib/amd/src/mustache.js
|
||||
lib/graphlib.php
|
||||
lib/php-css-parser/
|
||||
lib/rtlcss/
|
||||
lib/scssphp/
|
||||
lib/spout/
|
||||
lib/amd/src/chartjs-lazy.js
|
||||
lib/maxmind/GeoIp2/
|
||||
lib/maxmind/MaxMind/
|
||||
lib/ltiprovider/
|
||||
lib/amd/src/truncate.js
|
||||
lib/fonts/
|
||||
lib/amd/src/adapter.js
|
||||
lib/validateurlsyntax.php
|
||||
lib/amd/src/popper.js
|
||||
lib/geopattern-php/
|
||||
lib/php-jwt/
|
||||
lib/babel-polyfill/
|
||||
lib/polyfills/
|
||||
lib/emoji-data/
|
||||
lib/plist/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
media/player/videojs/amd/src/videojs-flash-lazy.js
|
||||
media/player/videojs/videojs/video-js.swf
|
||||
mod/assign/feedback/editpdf/fpdi/
|
||||
repository/s3/S3.php
|
||||
theme/boost/scss/bootstrap/
|
||||
theme/boost/amd/src/bootstrap/alert.js
|
||||
theme/boost/amd/src/bootstrap/button.js
|
||||
theme/boost/amd/src/bootstrap/carousel.js
|
||||
theme/boost/amd/src/bootstrap/collapse.js
|
||||
theme/boost/amd/src/bootstrap/dropdown.js
|
||||
theme/boost/amd/src/bootstrap/index.js
|
||||
theme/boost/amd/src/bootstrap/modal.js
|
||||
theme/boost/amd/src/bootstrap/popover.js
|
||||
theme/boost/amd/src/bootstrap/tools/sanitizer.js
|
||||
theme/boost/amd/src/bootstrap/scrollspy.js
|
||||
theme/boost/amd/src/bootstrap/tab.js
|
||||
theme/boost/amd/src/bootstrap/toast.js
|
||||
theme/boost/amd/src/bootstrap/tooltip.js
|
||||
theme/boost/amd/src/bootstrap/util.js
|
||||
theme/boost/amd/src/tether.js
|
||||
theme/boost/scss/fontawesome/
|
||||
+15
-22
@@ -10,7 +10,7 @@ language: php
|
||||
|
||||
os: linux
|
||||
|
||||
dist: bionic
|
||||
dist: xenial
|
||||
|
||||
services:
|
||||
- mysql
|
||||
@@ -19,12 +19,6 @@ services:
|
||||
addons:
|
||||
postgresql: "9.6"
|
||||
|
||||
branches:
|
||||
except:
|
||||
- master
|
||||
- /MOODLE_[0-9]+_STABLE/
|
||||
- /^v[0-9]+\.[0-9]+\.[0-9]+.*/
|
||||
|
||||
jobs:
|
||||
# Enable fast finish.
|
||||
# This will fail the build if a single job fails (except those in allow_failures).
|
||||
@@ -32,34 +26,34 @@ jobs:
|
||||
fast_finish: true
|
||||
|
||||
include:
|
||||
# First all the lowest php ones (7.3)
|
||||
- php: 7.3
|
||||
# First all the lowest php ones (7.2)
|
||||
- php: 7.2
|
||||
env: DB=none TASK=CITEST
|
||||
- php: 7.3
|
||||
- php: 7.2
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present
|
||||
php: 7.3
|
||||
php: 7.2
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
|
||||
php: 7.3
|
||||
php: 7.2
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
|
||||
# Then, conditionally, all the highest php ones (8.0)
|
||||
# Then, conditionally, all the highest php ones (7.4)
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 8.0
|
||||
php: 7.4
|
||||
env: DB=none TASK=CITEST
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 8.0
|
||||
php: 7.4
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
|
||||
|
||||
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present)
|
||||
php: 8.0
|
||||
php: 7.4
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
|
||||
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
|
||||
php: 8.0
|
||||
php: 7.4
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
|
||||
cache:
|
||||
@@ -118,8 +112,6 @@ install:
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- if [[ ${TRAVIS_PHP_VERSION:0:1} -gt 7 ]]; then pecl install xmlrpc-beta; fi
|
||||
- echo 'max_input_vars=5000' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
|
||||
- phpenv config-rm xdebug.ini
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
@@ -189,9 +181,10 @@ before_script:
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
|
||||
config.php ;
|
||||
# Redis session tests
|
||||
# Redis session tests, but not for PHP 7.2 and up. See MDL-60978 for more info.
|
||||
redissession="define('TEST_SESSION_REDIS_HOST', '127.0.0.1');"
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
|
||||
-e "/require_once/i \\${redissession}" \
|
||||
config.php ;
|
||||
|
||||
# Initialise PHPUnit for Moodle.
|
||||
@@ -221,7 +214,7 @@ before_script:
|
||||
# We need the official upstream for comparison
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
git fetch upstream MOODLE_311_STABLE;
|
||||
git fetch upstream MOODLE_39_STABLE;
|
||||
export GIT_PREVIOUS_COMMIT="`git merge-base FETCH_HEAD $TRAVIS_COMMIT`";
|
||||
export GIT_COMMIT="$TRAVIS_COMMIT";
|
||||
export UPSTREAM_FETCH_HEAD=`git rev-parse FETCH_HEAD`
|
||||
|
||||
+762
-165
@@ -16,129 +16,147 @@
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* Grunt configuration for Moodle.
|
||||
*
|
||||
* @copyright 2014 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* Setup the Grunt Moodle environment.
|
||||
* Calculate the cwd, taking into consideration the `root` option (for Windows).
|
||||
*
|
||||
* @param {Grunt} grunt
|
||||
* @returns {Object}
|
||||
* @param {Object} grunt
|
||||
* @returns {String} The current directory as best we can determine
|
||||
*/
|
||||
const setupMoodleEnvironment = grunt => {
|
||||
const getCwd = grunt => {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
|
||||
|
||||
const getAmdConfiguration = () => {
|
||||
// If the cwd is the amd directory in the current component then it will be empty.
|
||||
// If the cwd is a child of the component's AMD directory, the relative directory will not start with ..
|
||||
let inAMD = !path.relative(`${componentDirectory}/amd`, cwd).startsWith('..');
|
||||
let cwd = fs.realpathSync(process.env.PWD || process.cwd());
|
||||
|
||||
// Globbing pattern for matching all AMD JS source files.
|
||||
let amdSrc = [];
|
||||
if (inComponent) {
|
||||
amdSrc.push(
|
||||
componentDirectory + "/amd/src/*.js",
|
||||
componentDirectory + "/amd/src/**/*.js"
|
||||
);
|
||||
// Windows users can't run grunt in a subdirectory, so allow them to set
|
||||
// the root by passing --root=path/to/dir.
|
||||
if (grunt.option('root')) {
|
||||
const root = grunt.option('root');
|
||||
if (grunt.file.exists(__dirname, root)) {
|
||||
cwd = fs.realpathSync(path.join(__dirname, root));
|
||||
grunt.log.ok('Setting root to ' + cwd);
|
||||
} else {
|
||||
amdSrc = ComponentList.getAmdSrcGlobList();
|
||||
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
|
||||
}
|
||||
}
|
||||
|
||||
return cwd;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register any stylelint tasks.
|
||||
*
|
||||
* @param {Object} grunt
|
||||
* @param {Array} files
|
||||
* @param {String} fullRunDir
|
||||
*/
|
||||
const registerStyleLintTasks = (grunt, files, fullRunDir) => {
|
||||
const getCssConfigForFiles = files => {
|
||||
return {
|
||||
inAMD,
|
||||
amdSrc,
|
||||
stylelint: {
|
||||
css: {
|
||||
// Use a fully-qualified path.
|
||||
src: files,
|
||||
options: {
|
||||
configOverrides: {
|
||||
rules: {
|
||||
// These rules have to be disabled in .stylelintrc for scss compat.
|
||||
"at-rule-no-unknown": true,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const getYuiConfiguration = () => {
|
||||
let yuiSrc = [];
|
||||
if (inComponent) {
|
||||
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
|
||||
const getScssConfigForFiles = files => {
|
||||
return {
|
||||
stylelint: {
|
||||
scss: {
|
||||
options: {syntax: 'scss'},
|
||||
src: files,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
let hasCss = true;
|
||||
let hasScss = true;
|
||||
|
||||
if (files) {
|
||||
// Specific files were passed. Just set them up.
|
||||
grunt.config.merge(getCssConfigForFiles(files));
|
||||
grunt.config.merge(getScssConfigForFiles(files));
|
||||
} else {
|
||||
// The stylelint system does not handle the case where there was no file to lint.
|
||||
// Check whether there are any files to lint in the current directory.
|
||||
const glob = require('glob');
|
||||
|
||||
const scssSrc = [];
|
||||
glob.sync(`${fullRunDir}/**/*.scss`).forEach(path => scssSrc.push(path));
|
||||
|
||||
if (scssSrc.length) {
|
||||
grunt.config.merge(getScssConfigForFiles(scssSrc));
|
||||
} else {
|
||||
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
|
||||
hasScss = false;
|
||||
}
|
||||
|
||||
return {
|
||||
yuiSrc,
|
||||
};
|
||||
};
|
||||
const cssSrc = [];
|
||||
glob.sync(`${fullRunDir}/**/*.css`).forEach(path => cssSrc.push(path));
|
||||
|
||||
const getStyleConfiguration = () => {
|
||||
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
|
||||
// Build the cssSrc and scssSrc.
|
||||
// Valid paths are:
|
||||
// [component]/styles.css; and either
|
||||
// [theme/[themename]]/scss/**/*.scss; or
|
||||
// [theme/[themename]]/style/*.css.
|
||||
//
|
||||
// If a theme has scss, then it is assumed that the style directory contains generated content.
|
||||
let cssSrc = [];
|
||||
let scssSrc = [];
|
||||
|
||||
const checkComponentDirectory = componentDirectory => {
|
||||
const isTheme = componentDirectory.startsWith('theme/');
|
||||
if (isTheme) {
|
||||
const scssDirectory = `${componentDirectory}/scss`;
|
||||
|
||||
if (fs.existsSync(scssDirectory)) {
|
||||
// This theme has an SCSS directory.
|
||||
// Include all scss files within it recursively, but do not check for css files.
|
||||
scssSrc.push(`${scssDirectory}/*.scss`);
|
||||
scssSrc.push(`${scssDirectory}/**/*.scss`);
|
||||
} else {
|
||||
// This theme has no SCSS directory.
|
||||
// Only hte CSS files in the top-level directory are checked.
|
||||
cssSrc.push(`${componentDirectory}/style/*.css`);
|
||||
}
|
||||
} else {
|
||||
// This is not a theme.
|
||||
// All other plugin types are restricted to a single styles.css in their top level.
|
||||
cssSrc.push(`${componentDirectory}/styles.css`);
|
||||
}
|
||||
};
|
||||
|
||||
if (inComponent) {
|
||||
checkComponentDirectory(componentDirectory);
|
||||
if (cssSrc.length) {
|
||||
grunt.config.merge(getCssConfigForFiles(cssSrc));
|
||||
} else {
|
||||
ComponentList.getComponentPaths(`${gruntFilePath}/`).forEach(componentPath => {
|
||||
checkComponentDirectory(componentPath);
|
||||
});
|
||||
hasCss = false;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
cssSrc,
|
||||
scssSrc,
|
||||
};
|
||||
};
|
||||
const scssTasks = ['sass'];
|
||||
if (hasScss) {
|
||||
scssTasks.unshift('stylelint:scss');
|
||||
}
|
||||
grunt.registerTask('scss', scssTasks);
|
||||
|
||||
/**
|
||||
* Calculate the cwd, taking into consideration the `root` option (for Windows).
|
||||
*
|
||||
* @param {Object} grunt
|
||||
* @returns {String} The current directory as best we can determine
|
||||
*/
|
||||
const getCwd = grunt => {
|
||||
let cwd = fs.realpathSync(process.env.PWD || process.cwd());
|
||||
const cssTasks = [];
|
||||
if (hasCss) {
|
||||
cssTasks.push('stylelint:css');
|
||||
}
|
||||
grunt.registerTask('rawcss', cssTasks);
|
||||
|
||||
// Windows users can't run grunt in a subdirectory, so allow them to set
|
||||
// the root by passing --root=path/to/dir.
|
||||
if (grunt.option('root')) {
|
||||
const root = grunt.option('root');
|
||||
if (grunt.file.exists(__dirname, root)) {
|
||||
cwd = fs.realpathSync(path.join(__dirname, root));
|
||||
grunt.log.ok('Setting root to ' + cwd);
|
||||
} else {
|
||||
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
|
||||
}
|
||||
}
|
||||
grunt.registerTask('css', ['scss', 'rawcss']);
|
||||
};
|
||||
|
||||
return cwd;
|
||||
};
|
||||
/**
|
||||
* Grunt configuration.
|
||||
*
|
||||
* @param {Object} grunt
|
||||
*/
|
||||
module.exports = function(grunt) {
|
||||
const path = require('path');
|
||||
const tasks = {};
|
||||
const async = require('async');
|
||||
const DOMParser = require('xmldom').DOMParser;
|
||||
const xpath = require('xpath');
|
||||
const semver = require('semver');
|
||||
const watchman = require('fb-watchman');
|
||||
const watchmanClient = new watchman.Client();
|
||||
const fs = require('fs');
|
||||
const ComponentList = require(path.resolve('GruntfileComponents.js'));
|
||||
const sass = require('node-sass');
|
||||
|
||||
// Verify the node version is new enough.
|
||||
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
|
||||
var actual = semver.valid(process.version);
|
||||
if (!semver.satisfies(actual, expected)) {
|
||||
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
|
||||
}
|
||||
|
||||
// Detect directories:
|
||||
// * gruntFilePath The real path on disk to this Gruntfile.js
|
||||
@@ -153,19 +171,8 @@ const setupMoodleEnvironment = grunt => {
|
||||
const relativeCwd = path.relative(gruntFilePath, cwd);
|
||||
const componentDirectory = ComponentList.getOwningComponentDirectory(relativeCwd);
|
||||
const inComponent = !!componentDirectory;
|
||||
const inTheme = !!componentDirectory && componentDirectory.startsWith('theme/');
|
||||
const runDir = inComponent ? componentDirectory : relativeCwd;
|
||||
const fullRunDir = fs.realpathSync(gruntFilePath + path.sep + runDir);
|
||||
const {inAMD, amdSrc} = getAmdConfiguration();
|
||||
const {yuiSrc} = getYuiConfiguration();
|
||||
const {cssSrc, scssSrc} = getStyleConfiguration();
|
||||
|
||||
let files = null;
|
||||
if (grunt.option('files')) {
|
||||
// Accept a comma separated list of files to process.
|
||||
files = grunt.option('files').split(',');
|
||||
}
|
||||
|
||||
grunt.log.debug('============================================================================');
|
||||
grunt.log.debug(`= Node version: ${process.versions.node}`);
|
||||
grunt.log.debug(`= grunt version: ${grunt.package.version}`);
|
||||
@@ -185,77 +192,667 @@ const setupMoodleEnvironment = grunt => {
|
||||
grunt.log.ok(`Running tasks for component directory ${componentDirectory}`);
|
||||
}
|
||||
|
||||
return {
|
||||
amdSrc,
|
||||
componentDirectory,
|
||||
cwd,
|
||||
cssSrc,
|
||||
files,
|
||||
fullRunDir,
|
||||
gruntFilePath,
|
||||
inAMD,
|
||||
inComponent,
|
||||
inTheme,
|
||||
relativeCwd,
|
||||
runDir,
|
||||
scssSrc,
|
||||
yuiSrc,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify tha tthe current NodeJS version matches the required version in package.json.
|
||||
*
|
||||
* @param {Grunt} grunt
|
||||
*/
|
||||
const verifyNodeVersion = grunt => {
|
||||
const semver = require('semver');
|
||||
|
||||
// Verify the node version is new enough.
|
||||
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
|
||||
var actual = semver.valid(process.version);
|
||||
if (!semver.satisfies(actual, expected)) {
|
||||
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
|
||||
let files = null;
|
||||
if (grunt.option('files')) {
|
||||
// Accept a comma separated list of files to process.
|
||||
files = grunt.option('files').split(',');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Grunt configuration.
|
||||
*
|
||||
* @param {Grunt} grunt
|
||||
*/
|
||||
module.exports = function(grunt) {
|
||||
// Verify that the Node version meets our requirements.
|
||||
verifyNodeVersion(grunt);
|
||||
// If the cwd is the amd directory in the current component then it will be empty.
|
||||
// If the cwd is a child of the component's AMD directory, the relative directory will not start with ..
|
||||
const inAMD = !path.relative(`${componentDirectory}/amd`, cwd).startsWith('..');
|
||||
|
||||
// Setup the Moodle environemnt within the Grunt object.
|
||||
grunt.moodleEnv = setupMoodleEnvironment(grunt);
|
||||
// Globbing pattern for matching all AMD JS source files.
|
||||
let amdSrc = [];
|
||||
if (inComponent) {
|
||||
amdSrc.push(componentDirectory + "/amd/src/*.js");
|
||||
amdSrc.push(componentDirectory + "/amd/src/**/*.js");
|
||||
} else {
|
||||
amdSrc = ComponentList.getAmdSrcGlobList();
|
||||
}
|
||||
|
||||
let yuiSrc = [];
|
||||
if (inComponent) {
|
||||
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
|
||||
} else {
|
||||
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the named task.
|
||||
* Function to generate the destination for the uglify 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
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {Grunt} grunt
|
||||
* @param {String} destPath the current destination
|
||||
* @param {String} srcPath the matched src path
|
||||
* @return {String} The rewritten destination path.
|
||||
*/
|
||||
const addTask = (name, grunt) => {
|
||||
const path = require('path');
|
||||
const taskPath = path.resolve(`./.grunt/tasks/${name}.js`);
|
||||
|
||||
grunt.log.debug(`Including tasks for ${name} from ${taskPath}`);
|
||||
|
||||
require(path.resolve(`./.grunt/tasks/${name}.js`))(grunt);
|
||||
var babelRename = function(destPath, srcPath) {
|
||||
destPath = srcPath.replace('src', 'build');
|
||||
destPath = destPath.replace('.js', '.min.js');
|
||||
return destPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find thirdpartylibs.xml and generate an array of paths contained within
|
||||
* them (used to generate ignore files and so on).
|
||||
*
|
||||
* @return {array} The list of thirdparty paths.
|
||||
*/
|
||||
var getThirdPartyPathsFromXML = function() {
|
||||
const thirdpartyfiles = ComponentList.getThirdPartyLibsList(gruntFilePath + '/');
|
||||
const libs = ['node_modules/', 'vendor/'];
|
||||
|
||||
// Add Moodle task configuration.
|
||||
addTask('gherkinlint', grunt);
|
||||
addTask('ignorefiles', grunt);
|
||||
thirdpartyfiles.forEach(function(file) {
|
||||
const dirname = path.dirname(file);
|
||||
|
||||
addTask('javascript', grunt);
|
||||
addTask('style', grunt);
|
||||
const doc = new DOMParser().parseFromString(grunt.file.read(file));
|
||||
const nodes = xpath.select("/libraries/library/location/text()", doc);
|
||||
|
||||
addTask('watch', grunt);
|
||||
addTask('startup', grunt);
|
||||
nodes.forEach(function(node) {
|
||||
let lib = path.posix.join(dirname, node.toString());
|
||||
if (grunt.file.isDir(lib)) {
|
||||
// Ensure trailing slash on dirs.
|
||||
lib = lib.replace(/\/?$/, '/');
|
||||
}
|
||||
|
||||
// Look for duplicate paths before adding to array.
|
||||
if (libs.indexOf(lib) === -1) {
|
||||
libs.push(lib);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return libs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of feature files to pass to the gherkin linter.
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getGherkinLintTargets = () => {
|
||||
if (files) {
|
||||
// Specific files were requested. Only check these.
|
||||
return files;
|
||||
}
|
||||
|
||||
if (inComponent) {
|
||||
return [`${runDir}/tests/behat/*.feature`];
|
||||
}
|
||||
|
||||
return ['**/tests/behat/*.feature'];
|
||||
};
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
eslint: {
|
||||
// Even though warnings dont stop the build we don't display warnings by default because
|
||||
// at this moment we've got too many core warnings.
|
||||
// To display warnings call: grunt eslint --show-lint-warnings
|
||||
// To fail on warnings call: grunt eslint --max-lint-warnings=0
|
||||
// Also --max-lint-warnings=-1 can be used to display warnings but not fail.
|
||||
options: {
|
||||
quiet: (!grunt.option('show-lint-warnings')) && (typeof grunt.option('max-lint-warnings') === 'undefined'),
|
||||
maxWarnings: ((typeof grunt.option('max-lint-warnings') !== 'undefined') ? grunt.option('max-lint-warnings') : -1)
|
||||
},
|
||||
amd: {src: files ? files : amdSrc},
|
||||
// Check YUI module source files.
|
||||
yui: {src: files ? files : yuiSrc},
|
||||
},
|
||||
babel: {
|
||||
options: {
|
||||
sourceMaps: true,
|
||||
comments: false,
|
||||
plugins: [
|
||||
'transform-es2015-modules-amd-lazy',
|
||||
'system-import-transformer',
|
||||
// This plugin modifies the Babel transpiling for "export default"
|
||||
// so that if it's used then only the exported value is returned
|
||||
// by the generated AMD module.
|
||||
//
|
||||
// It also adds the Moodle plugin name to the AMD module definition
|
||||
// so that it can be imported as expected in other modules.
|
||||
path.resolve('babel-plugin-add-module-to-define.js'),
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-syntax-import-meta',
|
||||
['@babel/plugin-proposal-class-properties', {'loose': false}],
|
||||
'@babel/plugin-proposal-json-strings'
|
||||
],
|
||||
presets: [
|
||||
['minify', {
|
||||
// This minification plugin needs to be disabled because it breaks the
|
||||
// source map generation and causes invalid source maps to be output.
|
||||
simplify: false,
|
||||
builtIns: false
|
||||
}],
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: [
|
||||
">0.25%",
|
||||
"last 2 versions",
|
||||
"not ie <= 10",
|
||||
"not op_mini all",
|
||||
"not Opera > 0",
|
||||
"not dead"
|
||||
]
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: false
|
||||
}]
|
||||
]
|
||||
},
|
||||
dist: {
|
||||
files: [{
|
||||
expand: true,
|
||||
src: files ? files : amdSrc,
|
||||
rename: babelRename
|
||||
}]
|
||||
}
|
||||
},
|
||||
sass: {
|
||||
dist: {
|
||||
files: {
|
||||
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss",
|
||||
"theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss"
|
||||
}
|
||||
},
|
||||
options: {
|
||||
implementation: sass,
|
||||
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
options: {
|
||||
nospawn: true // We need not to spawn so config can be changed dynamically.
|
||||
},
|
||||
amd: {
|
||||
files: inComponent
|
||||
? ['amd/src/*.js', 'amd/src/**/*.js']
|
||||
: ['**/amd/src/**/*.js'],
|
||||
tasks: ['amd']
|
||||
},
|
||||
boost: {
|
||||
files: [inComponent ? 'scss/**/*.scss' : 'theme/boost/scss/**/*.scss'],
|
||||
tasks: ['scss']
|
||||
},
|
||||
rawcss: {
|
||||
files: [
|
||||
'**/*.css',
|
||||
],
|
||||
excludes: [
|
||||
'**/moodle.css',
|
||||
'**/editor.css',
|
||||
],
|
||||
tasks: ['rawcss']
|
||||
},
|
||||
yui: {
|
||||
files: inComponent
|
||||
? ['yui/src/*.json', 'yui/src/**/*.js']
|
||||
: ['**/yui/src/**/*.js'],
|
||||
tasks: ['yui']
|
||||
},
|
||||
gherkinlint: {
|
||||
files: [inComponent ? 'tests/behat/*.feature' : '**/tests/behat/*.feature'],
|
||||
tasks: ['gherkinlint']
|
||||
}
|
||||
},
|
||||
shifter: {
|
||||
options: {
|
||||
recursive: true,
|
||||
// Shifter takes a relative path.
|
||||
paths: files ? files : [runDir]
|
||||
}
|
||||
},
|
||||
gherkinlint: {
|
||||
options: {
|
||||
files: getGherkinLintTargets(),
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Generate ignore files (utilising thirdpartylibs.xml data)
|
||||
*/
|
||||
tasks.ignorefiles = function() {
|
||||
// An array of paths to third party directories.
|
||||
const thirdPartyPaths = getThirdPartyPathsFromXML();
|
||||
// Generate .eslintignore.
|
||||
const eslintIgnores = [
|
||||
'# Generated by "grunt ignorefiles"',
|
||||
'*/**/yui/src/*/meta/',
|
||||
'*/**/build/',
|
||||
].concat(thirdPartyPaths);
|
||||
grunt.file.write('.eslintignore', eslintIgnores.join('\n'));
|
||||
|
||||
// Generate .stylelintignore.
|
||||
const stylelintIgnores = [
|
||||
'# Generated by "grunt ignorefiles"',
|
||||
'**/yui/build/*',
|
||||
'theme/boost/style/moodle.css',
|
||||
'theme/classic/style/moodle.css',
|
||||
].concat(thirdPartyPaths);
|
||||
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Shifter task. Is configured with a path to a specific file or a directory,
|
||||
* in the case of a specific file it will work out the right module to be built.
|
||||
*
|
||||
* Note that this task runs the invidiaul shifter jobs async (becase it spawns
|
||||
* so be careful to to call done().
|
||||
*/
|
||||
tasks.shifter = function() {
|
||||
var done = this.async(),
|
||||
options = grunt.config('shifter.options');
|
||||
|
||||
// Run the shifter processes one at a time to avoid confusing output.
|
||||
async.eachSeries(options.paths, function(src, filedone) {
|
||||
var args = [];
|
||||
args.push(path.normalize(__dirname + '/node_modules/shifter/bin/shifter'));
|
||||
|
||||
// Always ignore the node_modules directory.
|
||||
args.push('--excludes', 'node_modules');
|
||||
|
||||
// Determine the most appropriate options to run with based upon the current location.
|
||||
if (grunt.file.isMatch('**/yui/**/*.js', src)) {
|
||||
// When passed a JS file, build our containing module (this happen with
|
||||
// watch).
|
||||
grunt.log.debug('Shifter passed a specific JS file');
|
||||
src = path.dirname(path.dirname(src));
|
||||
options.recursive = false;
|
||||
} else if (grunt.file.isMatch('**/yui/src', src)) {
|
||||
// When in a src directory --walk all modules.
|
||||
grunt.log.debug('In a src directory');
|
||||
args.push('--walk');
|
||||
options.recursive = false;
|
||||
} else if (grunt.file.isMatch('**/yui/src/*', src)) {
|
||||
// When in module, only build our module.
|
||||
grunt.log.debug('In a module directory');
|
||||
options.recursive = false;
|
||||
} else if (grunt.file.isMatch('**/yui/src/*/js', src)) {
|
||||
// When in module src, only build our module.
|
||||
grunt.log.debug('In a source directory');
|
||||
src = path.dirname(src);
|
||||
options.recursive = false;
|
||||
}
|
||||
|
||||
if (grunt.option('watch')) {
|
||||
grunt.fail.fatal('The --watch option has been removed, please use `grunt watch` instead');
|
||||
}
|
||||
|
||||
// Add the stderr option if appropriate
|
||||
if (grunt.option('verbose')) {
|
||||
args.push('--lint-stderr');
|
||||
}
|
||||
|
||||
if (grunt.option('no-color')) {
|
||||
args.push('--color=false');
|
||||
}
|
||||
|
||||
var execShifter = function() {
|
||||
|
||||
grunt.log.ok("Running shifter on " + src);
|
||||
grunt.util.spawn({
|
||||
cmd: "node",
|
||||
args: args,
|
||||
opts: {cwd: src, stdio: 'inherit', env: process.env}
|
||||
}, function(error, result, code) {
|
||||
if (code) {
|
||||
grunt.fail.fatal('Shifter failed with code: ' + code);
|
||||
} else {
|
||||
grunt.log.ok('Shifter build complete.');
|
||||
filedone();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Actually run shifter.
|
||||
if (!options.recursive) {
|
||||
execShifter();
|
||||
} else {
|
||||
// Check that there are yui modules otherwise shifter ends with exit code 1.
|
||||
if (grunt.file.expand({cwd: src}, '**/yui/src/**/*.js').length > 0) {
|
||||
args.push('--recursive');
|
||||
execShifter();
|
||||
} else {
|
||||
grunt.log.ok('No YUI modules to build.');
|
||||
filedone();
|
||||
}
|
||||
}
|
||||
}, done);
|
||||
};
|
||||
|
||||
tasks.gherkinlint = function() {
|
||||
const done = this.async();
|
||||
const options = grunt.config('gherkinlint.options');
|
||||
|
||||
// Grab the gherkin-lint linter and required scaffolding.
|
||||
const linter = require('gherkin-lint/dist/linter.js');
|
||||
const featureFinder = require('gherkin-lint/dist/feature-finder.js');
|
||||
const configParser = require('gherkin-lint/dist/config-parser.js');
|
||||
const formatter = require('gherkin-lint/dist/formatters/stylish.js');
|
||||
|
||||
// Run the linter.
|
||||
return linter.lint(
|
||||
featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
|
||||
configParser.getConfiguration(configParser.defaultConfigFileName)
|
||||
)
|
||||
.then(results => {
|
||||
// Print the results out uncondtionally.
|
||||
formatter.printResults(results);
|
||||
|
||||
return results;
|
||||
})
|
||||
.then(results => {
|
||||
// Report on the results.
|
||||
// The done function takes a bool whereby a falsey statement causes the task to fail.
|
||||
return results.every(result => result.errors.length === 0);
|
||||
})
|
||||
.then(done); // eslint-disable-line promise/no-callback-in-promise
|
||||
};
|
||||
|
||||
tasks.startup = function() {
|
||||
// Are we in a YUI directory?
|
||||
if (path.basename(path.resolve(cwd, '../../')) == 'yui') {
|
||||
grunt.task.run('yui');
|
||||
// Are we in an AMD directory?
|
||||
} else if (inAMD) {
|
||||
grunt.task.run('amd');
|
||||
} else {
|
||||
// Run them all!.
|
||||
grunt.task.run('css');
|
||||
grunt.task.run('js');
|
||||
grunt.task.run('gherkinlint');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a wrapper task to handle the grunt watch command. It attempts to use
|
||||
* Watchman to monitor for file changes, if it's installed, because it's much faster.
|
||||
*
|
||||
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
|
||||
* watcher for backwards compatibility.
|
||||
*/
|
||||
tasks.watch = function() {
|
||||
var watchTaskDone = this.async();
|
||||
var watchInitialised = false;
|
||||
var watchTaskQueue = {};
|
||||
var processingQueue = false;
|
||||
|
||||
// Grab the tasks and files that have been queued up and execute them.
|
||||
var processWatchTaskQueue = function() {
|
||||
if (!Object.keys(watchTaskQueue).length || processingQueue) {
|
||||
// If there is nothing in the queue or we're already processing then wait.
|
||||
return;
|
||||
}
|
||||
|
||||
processingQueue = true;
|
||||
|
||||
// Grab all tasks currently in the queue.
|
||||
var queueToProcess = watchTaskQueue;
|
||||
// Reset the queue.
|
||||
watchTaskQueue = {};
|
||||
|
||||
async.forEachSeries(
|
||||
Object.keys(queueToProcess),
|
||||
function(task, next) {
|
||||
var files = queueToProcess[task];
|
||||
var filesOption = '--files=' + files.join(',');
|
||||
grunt.log.ok('Running task ' + task + ' for files ' + filesOption);
|
||||
|
||||
// Spawn the task in a child process so that it doesn't kill this one
|
||||
// if it failed.
|
||||
grunt.util.spawn(
|
||||
{
|
||||
// Spawn with the grunt bin.
|
||||
grunt: true,
|
||||
// Run from current working dir and inherit stdio from process.
|
||||
opts: {
|
||||
cwd: fullRunDir,
|
||||
stdio: 'inherit'
|
||||
},
|
||||
args: [task, filesOption]
|
||||
},
|
||||
function(err, res, code) {
|
||||
if (code !== 0) {
|
||||
// The grunt task failed.
|
||||
grunt.log.error(err);
|
||||
}
|
||||
|
||||
// Move on to the next task.
|
||||
next();
|
||||
}
|
||||
);
|
||||
},
|
||||
function() {
|
||||
// No longer processing.
|
||||
processingQueue = false;
|
||||
// Once all of the tasks are done then recurse just in case more tasks
|
||||
// were queued while we were processing.
|
||||
processWatchTaskQueue();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const originalWatchConfig = grunt.config.get(['watch']);
|
||||
const watchConfig = Object.keys(originalWatchConfig).reduce(function(carry, key) {
|
||||
if (key == 'options') {
|
||||
return carry;
|
||||
}
|
||||
|
||||
const value = originalWatchConfig[key];
|
||||
|
||||
const taskNames = value.tasks;
|
||||
const files = value.files;
|
||||
let excludes = [];
|
||||
if (value.excludes) {
|
||||
excludes = value.excludes;
|
||||
}
|
||||
|
||||
taskNames.forEach(function(taskName) {
|
||||
carry[taskName] = {
|
||||
files,
|
||||
excludes,
|
||||
};
|
||||
});
|
||||
|
||||
return carry;
|
||||
}, {});
|
||||
|
||||
watchmanClient.on('error', function(error) {
|
||||
// We have to add an error handler here and parse the error string because the
|
||||
// example way from the docs to check if Watchman is installed doesn't actually work!!
|
||||
// See: https://github.com/facebook/watchman/issues/509
|
||||
if (error.message.match('Watchman was not found')) {
|
||||
// If watchman isn't installed then we should fallback to the other watch task.
|
||||
grunt.log.ok('It is recommended that you install Watchman for better performance using the "watch" command.');
|
||||
|
||||
// Fallback to the old grunt-contrib-watch task.
|
||||
grunt.renameTask('watch-grunt', 'watch');
|
||||
grunt.task.run(['watch']);
|
||||
// This task is finished.
|
||||
watchTaskDone(0);
|
||||
} else {
|
||||
grunt.log.error(error);
|
||||
// Fatal error.
|
||||
watchTaskDone(1);
|
||||
}
|
||||
});
|
||||
|
||||
watchmanClient.on('subscription', function(resp) {
|
||||
if (resp.subscription !== 'grunt-watch') {
|
||||
return;
|
||||
}
|
||||
|
||||
resp.files.forEach(function(file) {
|
||||
grunt.log.ok('File changed: ' + file.name);
|
||||
|
||||
var fullPath = fullRunDir + '/' + file.name;
|
||||
Object.keys(watchConfig).forEach(function(task) {
|
||||
|
||||
const fileGlobs = watchConfig[task].files;
|
||||
var match = fileGlobs.some(function(fileGlob) {
|
||||
return grunt.file.isMatch(`**/${fileGlob}`, fullPath);
|
||||
});
|
||||
|
||||
if (match) {
|
||||
// If we are watching a subdirectory then the file.name will be relative
|
||||
// to that directory. However the grunt tasks expect the file paths to be
|
||||
// relative to the Gruntfile.js location so let's normalise them before
|
||||
// adding them to the queue.
|
||||
var relativePath = fullPath.replace(gruntFilePath + '/', '');
|
||||
if (task in watchTaskQueue) {
|
||||
if (!watchTaskQueue[task].includes(relativePath)) {
|
||||
watchTaskQueue[task] = watchTaskQueue[task].concat(relativePath);
|
||||
}
|
||||
} else {
|
||||
watchTaskQueue[task] = [relativePath];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
processWatchTaskQueue();
|
||||
});
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
// Let the user know that they may need to manually stop the Watchman daemon if they
|
||||
// no longer want it running.
|
||||
if (watchInitialised) {
|
||||
grunt.log.ok('The Watchman daemon may still be running and may need to be stopped manually.');
|
||||
}
|
||||
|
||||
process.exit();
|
||||
});
|
||||
|
||||
// Initiate the watch on the current directory.
|
||||
watchmanClient.command(['watch-project', fullRunDir], function(watchError, watchResponse) {
|
||||
if (watchError) {
|
||||
grunt.log.error('Error initiating watch:', watchError);
|
||||
watchTaskDone(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if ('warning' in watchResponse) {
|
||||
grunt.log.error('warning: ', watchResponse.warning);
|
||||
}
|
||||
|
||||
var watch = watchResponse.watch;
|
||||
var relativePath = watchResponse.relative_path;
|
||||
watchInitialised = true;
|
||||
|
||||
watchmanClient.command(['clock', watch], function(clockError, clockResponse) {
|
||||
if (clockError) {
|
||||
grunt.log.error('Failed to query clock:', clockError);
|
||||
watchTaskDone(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate the expression query used by watchman.
|
||||
// Documentation is limited, but see https://facebook.github.io/watchman/docs/expr/allof.html for examples.
|
||||
// We generate an expression to match any value in the files list of all of our tasks, but excluding
|
||||
// all value in the excludes list of that task.
|
||||
//
|
||||
// [anyof, [
|
||||
// [allof, [
|
||||
// [anyof, [
|
||||
// ['match', validPath, 'wholename'],
|
||||
// ['match', validPath, 'wholename'],
|
||||
// ],
|
||||
// [not,
|
||||
// [anyof, [
|
||||
// ['match', invalidPath, 'wholename'],
|
||||
// ['match', invalidPath, 'wholename'],
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
var matchWholeName = fileGlob => ['match', fileGlob, 'wholename'];
|
||||
var matches = Object.keys(watchConfig).map(function(task) {
|
||||
const matchAll = [];
|
||||
matchAll.push(['anyof'].concat(watchConfig[task].files.map(matchWholeName)));
|
||||
|
||||
if (watchConfig[task].excludes.length) {
|
||||
matchAll.push(['not', ['anyof'].concat(watchConfig[task].excludes.map(matchWholeName))]);
|
||||
}
|
||||
|
||||
return ['allof'].concat(matchAll);
|
||||
});
|
||||
|
||||
matches = ['anyof'].concat(matches);
|
||||
|
||||
var sub = {
|
||||
expression: matches,
|
||||
// Which fields we're interested in.
|
||||
fields: ["name", "size", "type"],
|
||||
// Add our time constraint.
|
||||
since: clockResponse.clock
|
||||
};
|
||||
|
||||
if (relativePath) {
|
||||
/* eslint-disable camelcase */
|
||||
sub.relative_root = relativePath;
|
||||
}
|
||||
|
||||
watchmanClient.command(['subscribe', watch, 'grunt-watch', sub], function(subscribeError) {
|
||||
if (subscribeError) {
|
||||
// Probably an error in the subscription criteria.
|
||||
grunt.log.error('failed to subscribe: ', subscribeError);
|
||||
watchTaskDone(1);
|
||||
return;
|
||||
}
|
||||
|
||||
grunt.log.ok('Listening for changes to files in ' + fullRunDir);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// On watch, we dynamically modify config to build only affected files. This
|
||||
// method is slightly complicated to deal with multiple changed files at once (copied
|
||||
// from the grunt-contrib-watch readme).
|
||||
var changedFiles = Object.create(null);
|
||||
var onChange = grunt.util._.debounce(function() {
|
||||
var files = Object.keys(changedFiles);
|
||||
grunt.config('eslint.amd.src', files);
|
||||
grunt.config('eslint.yui.src', files);
|
||||
grunt.config('shifter.options.paths', files);
|
||||
grunt.config('gherkinlint.options.files', files);
|
||||
grunt.config('babel.dist.files', [{expand: true, src: files, rename: babelRename}]);
|
||||
changedFiles = Object.create(null);
|
||||
}, 200);
|
||||
|
||||
grunt.event.on('watch', function(action, filepath) {
|
||||
changedFiles[filepath] = action;
|
||||
onChange();
|
||||
});
|
||||
|
||||
// Register NPM tasks.
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-sass');
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
grunt.loadNpmTasks('grunt-stylelint');
|
||||
grunt.loadNpmTasks('grunt-babel');
|
||||
|
||||
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
|
||||
grunt.renameTask('watch', 'watch-grunt');
|
||||
|
||||
// Register JS tasks.
|
||||
grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter);
|
||||
grunt.registerTask('gherkinlint', 'Run gherkinlint against the current directory', tasks.gherkinlint);
|
||||
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles);
|
||||
grunt.registerTask('watch', 'Run tasks on file changes', tasks.watch);
|
||||
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
|
||||
grunt.registerTask('amd', ['eslint:amd', 'babel']);
|
||||
grunt.registerTask('js', ['amd', 'yui']);
|
||||
|
||||
// Register CSS tasks.
|
||||
registerStyleLintTasks(grunt, files, fullRunDir);
|
||||
|
||||
// Register the startup task.
|
||||
grunt.registerTask('startup', 'Run the correct tasks for the current directory', tasks.startup);
|
||||
|
||||
// Register the default task.
|
||||
grunt.registerTask('default', ['startup']);
|
||||
|
||||
@@ -92,16 +92,6 @@ const fetchComponentData = () => {
|
||||
return componentData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of component paths.
|
||||
*
|
||||
* @param {string} relativeTo
|
||||
* @returns {array}
|
||||
*/
|
||||
const getComponentPaths = (relativeTo = '') => fetchComponentData().pathList.map(componentPath => {
|
||||
return componentPath.replace(relativeTo, '');
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the list of paths to build AMD sources.
|
||||
*
|
||||
@@ -150,49 +140,6 @@ const getThirdPartyLibsList = relativeTo => {
|
||||
.sort();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of thirdparty library paths.
|
||||
*
|
||||
* @returns {array}
|
||||
*/
|
||||
const getThirdPartyPaths = () => {
|
||||
const DOMParser = require('xmldom').DOMParser;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const xpath = require('xpath');
|
||||
|
||||
const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./'));
|
||||
const libs = ['node_modules/', 'vendor/'];
|
||||
|
||||
const addLibToList = lib => {
|
||||
if (!lib.match('\\*') && fs.statSync(lib).isDirectory()) {
|
||||
// Ensure trailing slash on dirs.
|
||||
lib = lib.replace(/\/?$/, '/');
|
||||
}
|
||||
|
||||
// Look for duplicate paths before adding to array.
|
||||
if (libs.indexOf(lib) === -1) {
|
||||
libs.push(lib);
|
||||
}
|
||||
};
|
||||
|
||||
thirdpartyfiles.forEach(function(file) {
|
||||
const dirname = path.dirname(file);
|
||||
|
||||
const xmlContent = fs.readFileSync(file, 'utf8');
|
||||
const doc = new DOMParser().parseFromString(xmlContent);
|
||||
const nodes = xpath.select("/libraries/library/location/text()", doc);
|
||||
|
||||
nodes.forEach(function(node) {
|
||||
let lib = path.posix.join(dirname, node.toString());
|
||||
addLibToList(lib);
|
||||
});
|
||||
});
|
||||
|
||||
return libs;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the name of the component matching the specified path.
|
||||
*
|
||||
@@ -235,9 +182,7 @@ const getOwningComponentDirectory = checkPath => {
|
||||
module.exports = {
|
||||
getAmdSrcGlobList,
|
||||
getComponentFromPath,
|
||||
getComponentPaths,
|
||||
getOwningComponentDirectory,
|
||||
getYuiSrcGlobList,
|
||||
getThirdPartyLibsList,
|
||||
getThirdPartyPaths,
|
||||
};
|
||||
@@ -15,31 +15,34 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tests for PDFlib
|
||||
* Admin settings search form
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2021 Brendan Heywood (brendan@catalyst-au.net)
|
||||
* @package admin
|
||||
* @copyright 2016 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once $CFG->libdir.'/formslib.php';
|
||||
|
||||
/**
|
||||
* Tests for PDFlib
|
||||
* Admin settings search form
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2021 Brendan Heywood (brendan@catalyst-au.net)
|
||||
* @package admin
|
||||
* @copyright 2016 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_pdflib_testcase extends advanced_testcase {
|
||||
class admin_settings_search_form extends moodleform {
|
||||
function definition () {
|
||||
$mform = $this->_form;
|
||||
|
||||
public function test_gettcpdf_producer() {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir.'/pdflib.php');
|
||||
|
||||
// This is to reduce the information disclosure in PDF metadata.
|
||||
// If we upgrade TCPDF keep it just the major version.
|
||||
$producer = TCPDF_STATIC::getTCPDFProducer();
|
||||
$this->assertEquals('TCPDF (http://www.tcpdf.org)', $producer);
|
||||
//$mform->addElement('header', 'settingsheader', get_string('search', 'admin'));
|
||||
$elements = [];
|
||||
$elements[] = $mform->createElement('text', 'query', get_string('query', 'admin'));
|
||||
$elements[] = $mform->createElement('submit', 'search', get_string('search'));
|
||||
$mform->addGroup($elements);
|
||||
$mform->setType('query', PARAM_RAW);
|
||||
$mform->setDefault('query', optional_param('query', '', PARAM_RAW));
|
||||
}
|
||||
}
|
||||
+4
-13
@@ -44,9 +44,7 @@ switch ($action) {
|
||||
$key = array_search($auth, $authsenabled);
|
||||
if ($key !== false) {
|
||||
unset($authsenabled[$key]);
|
||||
$value = implode(',', $authsenabled);
|
||||
add_to_config_log('auth', $CFG->auth, $value, 'core');
|
||||
set_config('auth', $value);
|
||||
set_config('auth', implode(',', $authsenabled));
|
||||
}
|
||||
|
||||
if ($auth == $CFG->registerauth) {
|
||||
@@ -61,11 +59,8 @@ switch ($action) {
|
||||
if (!in_array($auth, $authsenabled)) {
|
||||
$authsenabled[] = $auth;
|
||||
$authsenabled = array_unique($authsenabled);
|
||||
$value = implode(',', $authsenabled);
|
||||
add_to_config_log('auth', $CFG->auth, $value, 'core');
|
||||
set_config('auth', $value);
|
||||
set_config('auth', implode(',', $authsenabled));
|
||||
}
|
||||
|
||||
\core\session\manager::gc(); // Remove stale sessions.
|
||||
core_plugin_manager::reset_caches();
|
||||
break;
|
||||
@@ -81,9 +76,7 @@ switch ($action) {
|
||||
$fsave = $authsenabled[$key];
|
||||
$authsenabled[$key] = $authsenabled[$key + 1];
|
||||
$authsenabled[$key + 1] = $fsave;
|
||||
$value = implode(',', $authsenabled);
|
||||
add_to_config_log('auth', $CFG->auth, $value, 'core');
|
||||
set_config('auth', $value);
|
||||
set_config('auth', implode(',', $authsenabled));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -98,9 +91,7 @@ switch ($action) {
|
||||
$fsave = $authsenabled[$key];
|
||||
$authsenabled[$key] = $authsenabled[$key - 1];
|
||||
$authsenabled[$key - 1] = $fsave;
|
||||
$value = implode(',', $authsenabled);
|
||||
add_to_config_log('auth', $CFG->auth, $value, 'core');
|
||||
set_config('auth', $value);
|
||||
set_config('auth', implode(',', $authsenabled));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -171,6 +171,8 @@ function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts,
|
||||
// limit for the setting name is 100.
|
||||
continue;
|
||||
}
|
||||
} elseif ($fieldname == 'url') {
|
||||
$fieldname = get_string('webpage');
|
||||
} else {
|
||||
$fieldname = get_string($fieldname);
|
||||
}
|
||||
|
||||
@@ -158,9 +158,4 @@ echo $outputhtml;
|
||||
echo html_writer::end_tag('fieldset');
|
||||
echo html_writer::end_tag('form');
|
||||
|
||||
$PAGE->requires->yui_module('moodle-core-formchangechecker', 'M.core_formchangechecker.init', [[
|
||||
'formid' => 'adminsettings'
|
||||
]]);
|
||||
$PAGE->requires->string_for_js('changesmadereallygoaway', 'moodle');
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -43,7 +43,7 @@ class testoutgoingmailconf_form extends \moodleform {
|
||||
$mform = $this->_form;
|
||||
|
||||
// Recipient.
|
||||
$options = ['maxlength' => '100', 'size' => '25', 'autocomplete' => 'email'];
|
||||
$options = ['maxlength' => '100', 'size' => '25'];
|
||||
$mform->addElement('text', 'recipient', get_string('testoutgoingmailconf_toemail', 'admin'), $options);
|
||||
$mform->setType('recipient', PARAM_EMAIL);
|
||||
$mform->addRule('recipient', get_string('required'), 'required');
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* External admin page class that allows a callback to be provided to determine whether page can be accessed
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2019 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\externalpage;
|
||||
|
||||
use admin_externalpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
|
||||
/**
|
||||
* Admin externalpage class
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2019 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class accesscallback extends admin_externalpage {
|
||||
|
||||
/** @var callable $accesscheckcallback */
|
||||
protected $accesscheckcallback;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $visiblename
|
||||
* @param string $url
|
||||
* @param callable $accesscheckcallback The callback method that will be executed to check whether user has access to
|
||||
* this page. The setting instance ($this) is passed as an argument to the callback. Should return boolean value
|
||||
* @param bool $hidden
|
||||
*/
|
||||
public function __construct(string $name, string $visiblename, string $url, callable $accesscheckcallback,
|
||||
bool $hidden = false) {
|
||||
|
||||
$this->accesscheckcallback = $accesscheckcallback;
|
||||
|
||||
parent::__construct($name, $visiblename, $url, [], $hidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the current user has access to this external page based on access callback
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function check_access() {
|
||||
return ($this->accesscheckcallback)($this);
|
||||
}
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Auto complete admin setting.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2020 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
/**
|
||||
* Auto complete setting class.
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @copyright 2020 The Open University
|
||||
*/
|
||||
class autocomplete extends \admin_setting_configmultiselect {
|
||||
/** @var boolean Should we allow typing new entries to the field? */
|
||||
protected $tags = false;
|
||||
/** @var string Name of an AMD module to send/process ajax requests. */
|
||||
protected $ajax = '';
|
||||
/** @var string Placeholder text for an empty list. */
|
||||
protected $placeholder = '';
|
||||
/** @var bool Whether the search has to be case-sensitive. */
|
||||
protected $casesensitive = false;
|
||||
/** @var bool Show suggestions by default - but this can be turned off. */
|
||||
protected $showsuggestions = true;
|
||||
/** @var string String that is shown when there are no selections. */
|
||||
protected $noselectionstring = '';
|
||||
/** @var string Delimiter to store values in database. */
|
||||
protected $delimiter = ',';
|
||||
/** @var string Should be multiple choices? */
|
||||
protected $multiple = true;
|
||||
/** @var string The link to manage choices. */
|
||||
protected $manageurl = true;
|
||||
/** @var string The text to display in manage link. */
|
||||
protected $managetext = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting'
|
||||
* for ones in config_plugins.
|
||||
* @param string $visiblename localised
|
||||
* @param string $description long localised info
|
||||
* @param array $defaultsetting array of selected items
|
||||
* @param array $choices options for autocomplete field
|
||||
* @param array $attributes settings for autocomplete field
|
||||
*/
|
||||
public function __construct($name, $visiblename, $description, $defaultsetting, $choices, $attributes = null) {
|
||||
|
||||
if ($attributes === null) {
|
||||
$attributes = [];
|
||||
}
|
||||
|
||||
$this->placeholder = get_string('search');
|
||||
$this->noselectionstring = get_string('noselection', 'form');
|
||||
$defaultattributes = [
|
||||
'tags',
|
||||
'showsuggestions',
|
||||
'placeholder',
|
||||
'noselectionstring',
|
||||
'ajax',
|
||||
'casesensitive',
|
||||
'delimiter',
|
||||
'multiple',
|
||||
'manageurl',
|
||||
'managetext'
|
||||
];
|
||||
|
||||
foreach ($defaultattributes as $attributename) {
|
||||
if (isset($attributes[$attributename])) {
|
||||
$this->$attributename = $attributes[$attributename];
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting, $choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the select setting(s)
|
||||
*
|
||||
* @return mixed null or array. Null if no settings else array of setting(s)
|
||||
*/
|
||||
public function get_setting() {
|
||||
$result = $this->config_read($this->name);
|
||||
if (is_null($result)) {
|
||||
return null;
|
||||
}
|
||||
if ($result === '') {
|
||||
return [];
|
||||
}
|
||||
return explode($this->delimiter, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves setting(s) provided through $data
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function write_setting($data) {
|
||||
if (!is_array($data)) {
|
||||
return ''; // Ignore it.
|
||||
}
|
||||
if (!$this->load_choices() || empty($this->choices)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
unset($data['xxxxx']);
|
||||
|
||||
$save = [];
|
||||
foreach ($data as $value) {
|
||||
if (!array_key_exists($value, $this->choices)) {
|
||||
continue; // Ignore it.
|
||||
}
|
||||
$save[] = $value;
|
||||
}
|
||||
|
||||
return ($this->config_write($this->name, implode($this->delimiter, $save)) ? '' : get_string('errorsetting', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns XHTML autocomplete field
|
||||
*
|
||||
* @param array $data Array of values to select by default
|
||||
* @param string $query
|
||||
* @return string XHTML autocomplete field
|
||||
*/
|
||||
public function output_html($data, $query = '') {
|
||||
global $OUTPUT;
|
||||
|
||||
if (!$this->load_choices() or empty($this->choices)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$default = $this->get_defaultsetting();
|
||||
if (empty($default)) {
|
||||
$default = [];
|
||||
}
|
||||
|
||||
if (is_null($data)) {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
$context = [
|
||||
'id' => $this->get_id(),
|
||||
'name' => $this->get_full_name()
|
||||
];
|
||||
|
||||
$defaults = [];
|
||||
$options = [];
|
||||
$template = 'core_admin/local/settings/autocomplete';
|
||||
|
||||
foreach ($this->choices as $value => $name) {
|
||||
if (in_array($value, $default)) {
|
||||
$defaults[] = $name;
|
||||
}
|
||||
$options[] = [
|
||||
'value' => $value,
|
||||
'text' => $name,
|
||||
'selected' => in_array($value, $data),
|
||||
'disabled' => false
|
||||
];
|
||||
}
|
||||
|
||||
$context['options'] = $options;
|
||||
$context['tags'] = $this->tags;
|
||||
$context['placeholder'] = $this->placeholder;
|
||||
$context['casesensitive'] = $this->casesensitive;
|
||||
$context['multiple'] = $this->multiple;
|
||||
$context['showsuggestions'] = $this->showsuggestions;
|
||||
$context['manageurl'] = $this->manageurl;
|
||||
$context['managetext'] = $this->managetext;
|
||||
|
||||
if (is_null($default)) {
|
||||
$defaultinfo = null;
|
||||
} if (!empty($defaults)) {
|
||||
$defaultinfo = implode(', ', $defaults);
|
||||
} else {
|
||||
$defaultinfo = get_string('none');
|
||||
}
|
||||
|
||||
$element = $OUTPUT->render_from_template($template, $context);
|
||||
|
||||
return format_admin_setting($this, $this->visiblename, $element, $this->description, true, '', $defaultinfo, $query);
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,6 @@ class filesize extends \admin_setting {
|
||||
if (is_null($bytes)) {
|
||||
return null;
|
||||
}
|
||||
$bytes = intval($bytes);
|
||||
|
||||
return self::parse_bytes($bytes);
|
||||
}
|
||||
@@ -146,10 +145,9 @@ class filesize extends \admin_setting {
|
||||
return get_string('errorsetting', 'admin');
|
||||
}
|
||||
|
||||
// Calculate size in bytes, ensuring we don't overflow PHP_INT_MAX.
|
||||
$bytes = $data['v'] * $data['u'];
|
||||
$result = (is_int($bytes) && $this->config_write($this->name, $bytes));
|
||||
|
||||
$result = $this->config_write($this->name, $bytes);
|
||||
return ($result ? '' : get_string('errorsetting', 'admin'));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Payment gateway admin setting.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2020 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
/**
|
||||
* Generic class for managing plugins in a table that allows re-ordering and enable/disable of each plugin.
|
||||
*/
|
||||
class manage_payment_gateway_plugins extends \admin_setting_manage_plugins {
|
||||
/**
|
||||
* Get the admin settings section title (use get_string).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_section_title() {
|
||||
return get_string('type_paygw_plural', 'plugin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of plugin to manage.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_type() {
|
||||
return 'paygw';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the second column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_info_column_name() {
|
||||
return get_string('supportedcurrencies', 'core_payment');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of plugin to manage.
|
||||
*
|
||||
* @param plugininfo The plugin info class.
|
||||
* @return string
|
||||
*/
|
||||
public function get_info_column($plugininfo) {
|
||||
$codes = $plugininfo->get_supported_currencies();
|
||||
|
||||
$currencies = [];
|
||||
foreach ($codes as $c) {
|
||||
$currencies[$c] = new \lang_string($c, 'core_currencies');
|
||||
}
|
||||
|
||||
return implode(get_string('listsep', 'langconfig') . ' ', $currencies);
|
||||
}
|
||||
}
|
||||
@@ -57,8 +57,6 @@ class task_log_table extends \table_sql {
|
||||
'userid' => get_string('user', 'admin'),
|
||||
'timestart' => get_string('task_starttime', 'admin'),
|
||||
'duration' => get_string('task_duration', 'admin'),
|
||||
'hostname' => get_string('hostname', 'tool_task'),
|
||||
'pid' => get_string('pid', 'tool_task'),
|
||||
'db' => get_string('task_dbstats', 'admin'),
|
||||
'result' => get_string('task_result', 'admin'),
|
||||
'actions' => '',
|
||||
@@ -124,9 +122,8 @@ class task_log_table extends \table_sql {
|
||||
$sort = "ORDER BY $sort";
|
||||
}
|
||||
|
||||
// TODO Does not support custom user profile fields (MDL-70456).
|
||||
$userfieldsapi = \core_user\fields::for_identity(\context_system::instance(), false)->with_userpic();
|
||||
$userfields = $userfieldsapi->get_sql('u', false, 'user', 'userid2', false)->selects;
|
||||
$extrafields = get_extra_user_fields(\context_system::instance());
|
||||
$userfields = \user_picture::fields('u', $extrafields, 'userid2', 'user');
|
||||
|
||||
$where = '';
|
||||
if (!empty($this->sql->where)) {
|
||||
@@ -135,7 +132,6 @@ class task_log_table extends \table_sql {
|
||||
|
||||
$sql = "SELECT
|
||||
tl.id, tl.type, tl.component, tl.classname, tl.userid, tl.timestart, tl.timeend,
|
||||
tl.hostname, tl.pid,
|
||||
tl.dbreads, tl.dbwrites, tl.result,
|
||||
tl.dbreads + tl.dbwrites AS db,
|
||||
tl.timeend - tl.timestart AS duration,
|
||||
|
||||
@@ -37,13 +37,11 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'ignorelimits' => false,
|
||||
'force' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'e' => 'execute',
|
||||
'k' => 'keep-alive',
|
||||
'i' => 'ignorelimits',
|
||||
'f' => 'force',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -63,7 +61,6 @@ Options:
|
||||
-e, --execute Run all queued adhoc tasks
|
||||
-k, --keep-alive=N Keep this script alive for N seconds and poll for new adhoc tasks
|
||||
-i --ignorelimits Ignore task_adhoc_concurrency_limit and task_adhoc_max_runtime limits
|
||||
-f, --force Run even if cron is disabled
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
|
||||
@@ -95,12 +92,6 @@ if (moodle_needs_upgrading()) {
|
||||
if (empty($options['execute'])) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (empty($options['keep-alive'])) {
|
||||
$options['keep-alive'] = 0;
|
||||
}
|
||||
|
||||
+1
-8
@@ -120,14 +120,7 @@ if ($options['unset'] || $options['set'] !== null) {
|
||||
}
|
||||
|
||||
// Check that the variable is not hard-set in the main config.php already.
|
||||
$component = $options['component'];
|
||||
if (!empty($component)) {
|
||||
$componentsettings = $CFG->forced_plugin_settings[$component] ?? [];
|
||||
$settinginconfig = array_key_exists($options['name'], $componentsettings);
|
||||
} else {
|
||||
$settinginconfig = array_key_exists($options['name'], $CFG->config_php_settings);
|
||||
}
|
||||
if ($settinginconfig) {
|
||||
if (array_key_exists($options['name'], $CFG->config_php_settings)) {
|
||||
cli_error('The configuration variable is hard-set in the config.php, unable to change.', 4);
|
||||
}
|
||||
|
||||
|
||||
+6
-105
@@ -36,23 +36,14 @@ require_once($CFG->libdir.'/cronlib.php');
|
||||
|
||||
// now get cli options
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
array(
|
||||
'help' => false,
|
||||
'stop' => false,
|
||||
'list' => false,
|
||||
'force' => false,
|
||||
'enable' => false,
|
||||
'disable' => false,
|
||||
'disable-wait' => false,
|
||||
], [
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
's' => 'stop',
|
||||
'l' => 'list',
|
||||
'f' => 'force',
|
||||
'e' => 'enable',
|
||||
'd' => 'disable',
|
||||
'w' => 'disable-wait',
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
@@ -65,13 +56,8 @@ if ($options['help']) {
|
||||
"Execute periodic cron actions.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
-s, --stop Notify all other running cron processes to stop after the current task
|
||||
-l, --list Show the list of currently running tasks and how long they have been running
|
||||
-f, --force Execute task even if cron is disabled
|
||||
-e, --enable Enable cron
|
||||
-d, --disable Disable cron
|
||||
-w, --disable-wait=600 Disable cron and wait until all tasks finished or fail after N seconds (optional param)
|
||||
-h, --help Print out this help
|
||||
-s, --stop Notify all other running cron processes to stop after the current task
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/cron.php
|
||||
@@ -88,91 +74,6 @@ if ($options['stop']) {
|
||||
die;
|
||||
}
|
||||
|
||||
if ($options['enable']) {
|
||||
set_config('cron_enabled', 1);
|
||||
mtrace('Cron has been enabled for the site.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['disable']) {
|
||||
set_config('cron_enabled', 0);
|
||||
\core\task\manager::clear_static_caches();
|
||||
mtrace('Cron has been disabled for the site.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['list']) {
|
||||
$tasks = \core\task\manager::get_running_tasks();
|
||||
mtrace('The list of currently running tasks:');
|
||||
$format = "%7s %-12s %-9s %-20s %-52s\n";
|
||||
printf ($format,
|
||||
'PID',
|
||||
'HOST',
|
||||
'TYPE',
|
||||
'TIME',
|
||||
'CLASSNAME'
|
||||
);
|
||||
foreach ($tasks as $task) {
|
||||
printf ($format,
|
||||
$task->pid,
|
||||
substr($task->hostname, 0, 12),
|
||||
$task->type,
|
||||
format_time(time() - $task->timestarted),
|
||||
substr($task->classname, 0, 52)
|
||||
);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($wait = $options['disable-wait']) {
|
||||
$started = time();
|
||||
if (true === $wait) {
|
||||
// Default waiting time.
|
||||
$waitsec = 600;
|
||||
} else {
|
||||
$waitsec = $wait;
|
||||
$wait = true;
|
||||
}
|
||||
|
||||
set_config('cron_enabled', 0);
|
||||
\core\task\manager::clear_static_caches();
|
||||
mtrace('Cron has been disabled for the site.');
|
||||
mtrace('Allocating '. format_time($waitsec) . ' for the tasks to finish.');
|
||||
|
||||
$lastcount = 0;
|
||||
while ($wait) {
|
||||
$tasks = \core\task\manager::get_running_tasks();
|
||||
|
||||
if (count($tasks) == 0) {
|
||||
mtrace('');
|
||||
mtrace('All scheduled and adhoc tasks finished.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (time() - $started >= $waitsec) {
|
||||
mtrace('');
|
||||
mtrace('Wait time ('. format_time($waitsec) . ') elapsed, but ' . count($tasks) . ' task(s) still running.');
|
||||
mtrace('Exiting with code 1.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (count($tasks) !== $lastcount) {
|
||||
mtrace('');
|
||||
mtrace(count($tasks) . " tasks currently running.", '');
|
||||
$lastcount = count($tasks);
|
||||
} else {
|
||||
mtrace('.', '');
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
\core\local\cli\shutdown::script_supports_graceful_exit();
|
||||
|
||||
cron_run();
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* CLI script to reset dashboards.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2021 Brendan Heywood (brendan@catalyst-au.net)
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
require_once($CFG->dirroot.'/my/lib.php');
|
||||
|
||||
list($options, $unrecognized) = cli_get_params([
|
||||
'help' => false,
|
||||
'execute' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'e' => 'execute',
|
||||
]);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2);
|
||||
}
|
||||
|
||||
if (!$options['execute']) {
|
||||
$help = <<<EOF
|
||||
Resets Moodle dashboards for all users
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
-e, --execute Actually run the reset
|
||||
|
||||
Example:
|
||||
\$ sudo -u www-data /usr/bin/php admin/cli/dashboard_reset.php -e
|
||||
|
||||
EOF;
|
||||
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$progressbar = new progress_bar();
|
||||
$progressbar->create();
|
||||
my_reset_page_for_all_users(MY_PAGE_PRIVATE, 'my-index', $progressbar);
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Fix orphaned calendar events that were broken by MDL-67494.
|
||||
*
|
||||
* This script will look for all the calendar events which userids
|
||||
* where broken by a wrong upgrade step, affecting to Moodle 3.9.5
|
||||
* and up.
|
||||
*
|
||||
* It performs checks to both:
|
||||
* a) Detect if the site was affected (ran the wrong upgrade step).
|
||||
* b) Look for orphaned calendar events, categorising them as:
|
||||
* - standard: site / category / course / group / user events
|
||||
* - subscription: events created via subscriptions.
|
||||
* - action: normal action events, created to show common important dates.
|
||||
* - override: user and group override events, particular, that some activities support.
|
||||
* - custom: other events, not being any of the above, common or particular.
|
||||
* By specifying it (--fix) try to recover as many broken events (missing userid) as
|
||||
* possible. Standard, subscription, action, override events in core are fully supported but
|
||||
* override or custom events should be fixed by each plugin as far as there isn't any standard
|
||||
* API (plugin-wise) to launch a rebuild of the calendar events.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2021 onwards Simey Lameze <simey@moodle.com>
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require_once(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir . "/clilib.php");
|
||||
require_once($CFG->libdir . '/db/upgradelib.php');
|
||||
|
||||
// Supported options.
|
||||
$long = ['fix' => false, 'help' => false];
|
||||
$short = ['f' => 'fix', 'h' => 'help'];
|
||||
|
||||
// CLI options.
|
||||
[$options, $unrecognized] = cli_get_params($long, $short);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
$help = <<<EOT
|
||||
Fix orphaned calendar events.
|
||||
|
||||
This script detects calendar events that have had their
|
||||
userid lost. By default it will perform various checks
|
||||
and report them, showing the site status in an easy way.
|
||||
|
||||
Also, optionally (--fix), it wil try to recover as many
|
||||
lost userids as possible from different sources. Note that
|
||||
this script aims to process well-know events in core,
|
||||
leaving custom events in 3rd part plugins mostly unmodified
|
||||
because there isn't any consistent way to regenerate them.
|
||||
|
||||
For more details: https://tracker.moodle.org/browse/MDL-71156
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help.
|
||||
-f, --fix Fix the orphaned calendar events in the DB.
|
||||
If not specified only check and report problems to STDERR.
|
||||
|
||||
Usage:
|
||||
- Only report: \$ sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_calendar_events.php
|
||||
- Report and fix: \$ sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_calendar_events.php -f
|
||||
EOT;
|
||||
|
||||
cli_writeln($help);
|
||||
die;
|
||||
}
|
||||
|
||||
// Check various usual pre-requisites.
|
||||
if (empty($CFG->version)) {
|
||||
cli_error('Database is not yet installed.');
|
||||
}
|
||||
|
||||
$admin = get_admin();
|
||||
if (!$admin) {
|
||||
cli_error('Error: No admin account was found.');
|
||||
}
|
||||
|
||||
if (moodle_needs_upgrading()) {
|
||||
cli_error('Moodle upgrade pending, script execution suspended.');
|
||||
}
|
||||
|
||||
// Do everything as admin by default.
|
||||
\core\session\manager::set_user($admin);
|
||||
|
||||
// Report current site status.
|
||||
cli_heading('Checking the site status');
|
||||
$needsfix = upgrade_calendar_site_status();
|
||||
|
||||
// Report current calendar events status.
|
||||
cli_heading('Checking the calendar events status');
|
||||
$info = upgrade_calendar_events_status();
|
||||
$hasbadevents = $info['total']->bad > 0 || $info['total']->bad != $info['other']->bad;
|
||||
$needsfix = $needsfix || $hasbadevents;
|
||||
|
||||
// If, selected, fix as many calendar events as possible.
|
||||
if ($options['fix']) {
|
||||
|
||||
// If the report has told us that the fix was not needed... ask for confirmation!
|
||||
if (!$needsfix) {
|
||||
cli_writeln("This site DOES NOT NEED to run the calendar events fix.");
|
||||
$input = cli_input('Are you completely sure that you want to run the fix? (y/N)', 'N', ['y', 'Y', 'n', 'N']);
|
||||
if (strtolower($input) != 'y') {
|
||||
exit(0);
|
||||
}
|
||||
cli_writeln("");
|
||||
}
|
||||
cli_heading('Fixing as many as possible calendar events');
|
||||
upgrade_calendar_events_fix_remaining($info);
|
||||
// Report current (after fix) calendar events status.
|
||||
cli_heading('Checking the calendar events status (after fix)');
|
||||
upgrade_calendar_events_status();
|
||||
} else if ($needsfix) {
|
||||
// Fix option was not provided but problem events have been found. Notify the user and provide info how to fix these events.
|
||||
cli_writeln("This site NEEDS to run the calendar events fix!");
|
||||
cli_writeln("To fix the calendar events, re-run this script with the --fix option.");
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Generates a secure key for the current server (presuming it does not already exist).
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2020 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use \core\encryption;
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir . '/clilib.php');
|
||||
|
||||
// Get cli options.
|
||||
[$options, $unrecognized] = cli_get_params(
|
||||
['help' => false, 'method' => null],
|
||||
['h' => 'help']);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
// TODO: MDL-71421 - Remove the openssl alternative once sodium becomes a requirement in Moodle 4.2.
|
||||
|
||||
if ($options['help']) {
|
||||
echo "Generate secure key
|
||||
|
||||
This script manually creates a secure key within the secret data root folder (configured in
|
||||
config.php as \$CFG->secretdataroot). You must run it using an account with access to write
|
||||
to that folder.
|
||||
|
||||
In normal use Moodle automatically creates the key; this script is intended when setting up
|
||||
a new Moodle system, for cases where the secure folder is not on shared storage and the key
|
||||
may be manually installed on multiple servers.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
--method <method> Generate key for specified encryption method instead of default.
|
||||
* sodium
|
||||
* openssl-aes-256-ctr
|
||||
|
||||
Example:
|
||||
php admin/cli/generate_key.php
|
||||
";
|
||||
exit;
|
||||
}
|
||||
|
||||
$method = $options['method'];
|
||||
|
||||
if (encryption::key_exists($method)) {
|
||||
echo 'Key already exists: ' . encryption::get_key_file($method) . "\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Creates key with default permissions (no chmod).
|
||||
echo "Generating key...\n";
|
||||
encryption::create_key($method, false);
|
||||
|
||||
echo "\nKey created: " . encryption::get_key_file($method) . "\n\n";
|
||||
echo "If the key folder is not shared storage, then key files should be copied to all servers.\n";
|
||||
@@ -56,7 +56,6 @@ Options:
|
||||
--agree-license Indicates agreement with software license.
|
||||
--fullname=STRING Name of the site
|
||||
--shortname=STRING Name of the site
|
||||
--summary=STRING The summary to be displayed on the front page
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
@@ -97,7 +96,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'adminemail' => '',
|
||||
'fullname' => '',
|
||||
'shortname' => '',
|
||||
'summary' => '',
|
||||
'agree-license' => false,
|
||||
'help' => false
|
||||
),
|
||||
@@ -106,11 +104,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
)
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
// We show help text even if tables are installed.
|
||||
if ($options['help']) {
|
||||
echo $help;
|
||||
|
||||
@@ -119,7 +119,7 @@ if (!empty($options['collation'])) {
|
||||
if ($dbcollation->value !== $collation || $dbcharset->value !== $charset) {
|
||||
// Try to convert the DB.
|
||||
echo "Converting database to '$collation' for $CFG->wwwroot:\n";
|
||||
$sql = "ALTER DATABASE `$CFG->dbname` DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
|
||||
$sql = "ALTER DATABASE $CFG->dbname DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
|
||||
try {
|
||||
$DB->change_database_structure($sql);
|
||||
} catch (exception $e) {
|
||||
@@ -146,7 +146,7 @@ if (!empty($options['collation'])) {
|
||||
|
||||
} else {
|
||||
try {
|
||||
$DB->change_database_structure("ALTER TABLE `$table->name` CONVERT TO CHARACTER SET $charset COLLATE $collation");
|
||||
$DB->change_database_structure("ALTER TABLE $table->name CONVERT TO CHARACTER SET $charset COLLATE $collation");
|
||||
echo "CONVERTED\n";
|
||||
$converted++;
|
||||
} catch (ddl_exception $e) {
|
||||
@@ -163,7 +163,7 @@ if (!empty($options['collation'])) {
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "SHOW FULL COLUMNS FROM `$table->name` WHERE collation IS NOT NULL";
|
||||
$sql = "SHOW FULL COLUMNS FROM $table->name WHERE collation IS NOT NULL";
|
||||
$rs2 = $DB->get_recordset_sql($sql);
|
||||
foreach ($rs2 as $column) {
|
||||
$column = (object)array_change_key_case((array)$column, CASE_LOWER);
|
||||
@@ -181,7 +181,7 @@ if (!empty($options['collation'])) {
|
||||
$notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
|
||||
$default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
|
||||
// primary, unique and inc are not supported for texts
|
||||
$sql = "ALTER TABLE `$table->name`
|
||||
$sql = "ALTER TABLE $table->name
|
||||
MODIFY COLUMN $column->field $column->type
|
||||
CHARACTER SET $charset
|
||||
COLLATE $collation $notnull $default";
|
||||
@@ -192,11 +192,11 @@ if (!empty($options['collation'])) {
|
||||
$default = !is_null($column->default) ? "DEFAULT '$column->default'" : '';
|
||||
|
||||
if ($rowformat != '') {
|
||||
$sql = "ALTER TABLE `$table->name` $rowformat";
|
||||
$sql = "ALTER TABLE $table->name $rowformat";
|
||||
$DB->change_database_structure($sql);
|
||||
}
|
||||
|
||||
$sql = "ALTER TABLE `$table->name`
|
||||
$sql = "ALTER TABLE $table->name
|
||||
MODIFY COLUMN $column->field $column->type
|
||||
CHARACTER SET $charset
|
||||
COLLATE $collation $notnull $default";
|
||||
@@ -315,8 +315,8 @@ function mysql_set_row_format($tablename, $charset, $collation, $engine) {
|
||||
if ($rs->row_format == 'Compact' || $rs->row_format == 'Redundant') {
|
||||
$rowformat = $DB->get_row_format_sql($engine, $collation);
|
||||
// Try to convert to compressed format and then try updating the collation again.
|
||||
$DB->change_database_structure("ALTER TABLE `$tablename` $rowformat");
|
||||
$DB->change_database_structure("ALTER TABLE `$tablename` CONVERT TO CHARACTER SET $charset COLLATE $collation");
|
||||
$DB->change_database_structure("ALTER TABLE $tablename $rowformat");
|
||||
$DB->change_database_structure("ALTER TABLE $tablename CONVERT TO CHARACTER SET $charset COLLATE $collation");
|
||||
} else {
|
||||
// Row format may not be the problem. Can not diagnose problem. Send fail reply.
|
||||
return false;
|
||||
|
||||
@@ -158,7 +158,7 @@ if (!empty($options['info'])) {
|
||||
}
|
||||
|
||||
foreach ($fixtables as $table) {
|
||||
$DB->change_database_structure("ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed");
|
||||
$DB->change_database_structure("ALTER TABLE {$prefix}$table ROW_FORMAT=Compressed");
|
||||
echo str_pad($prefix . $table, 32, ' ', STR_PAD_RIGHT) . " ... Compressed\n";
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ if (!empty($options['info'])) {
|
||||
echo "SET GLOBAL innodb_file_per_table=1;\n";
|
||||
echo "SET GLOBAL innodb_file_format=Barracuda;\n";
|
||||
foreach ($fixtables as $table) {
|
||||
echo "ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed;\n";
|
||||
echo "ALTER TABLE {$prefix}$table ROW_FORMAT=Compressed;\n";
|
||||
}
|
||||
echo "\n";
|
||||
exit(0);
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This script allows to restore a course from CLI.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2020 Catalyst IT
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', 1);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir . '/clilib.php');
|
||||
require_once($CFG->dirroot . "/backup/util/includes/restore_includes.php");
|
||||
|
||||
list($options, $unrecognized) = cli_get_params([
|
||||
'file' => '',
|
||||
'categoryid' => '',
|
||||
'showdebugging' => false,
|
||||
'help' => false,
|
||||
], [
|
||||
'f' => 'file',
|
||||
'c' => 'categoryid',
|
||||
's' => 'showdebugging',
|
||||
'h' => 'help',
|
||||
]);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help'] || !($options['file']) || !($options['categoryid'])) {
|
||||
$help = <<<EOL
|
||||
Restore backup into provided category.
|
||||
|
||||
Options:
|
||||
-f, --file=STRING Path to the backup file.
|
||||
-c, --categoryid=INT ID of the category to restore too.
|
||||
-s, --showdebugging Show developer level debugging information
|
||||
-h, --help Print out this help.
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/restore_backup.php --file=/path/to/backup/file.mbz --categoryid=1\n
|
||||
EOL;
|
||||
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['showdebugging']) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if (!$admin = get_admin()) {
|
||||
print_error('noadmins');
|
||||
}
|
||||
|
||||
if (!file_exists($options['file'])) {
|
||||
print_error('filenotfound');
|
||||
}
|
||||
|
||||
if (!$category = $DB->get_record('course_categories', ['id' => $options['categoryid']], 'id')) {
|
||||
print_error('invalidcategoryid');
|
||||
}
|
||||
|
||||
$backupdir = "restore_" . uniqid();
|
||||
$path = $CFG->tempdir . DIRECTORY_SEPARATOR . "backup" . DIRECTORY_SEPARATOR . $backupdir;
|
||||
|
||||
cli_heading(get_string('extractingbackupfileto', 'backup', $path));
|
||||
$fp = get_file_packer('application/vnd.moodle.backup');
|
||||
$fp->extract_to_pathname($options['file'], $path);
|
||||
|
||||
cli_heading(get_string('preprocessingbackupfile'));
|
||||
try {
|
||||
list($fullname, $shortname) = restore_dbops::calculate_course_names(0, get_string('restoringcourse', 'backup'),
|
||||
get_string('restoringcourseshortname', 'backup'));
|
||||
|
||||
$courseid = restore_dbops::create_new_course($fullname, $shortname, $category->id);
|
||||
|
||||
$rc = new restore_controller($backupdir, $courseid, backup::INTERACTIVE_NO,
|
||||
backup::MODE_GENERAL, $admin->id, backup::TARGET_NEW_COURSE);
|
||||
$rc->execute_precheck();
|
||||
$rc->execute_plan();
|
||||
$rc->destroy();
|
||||
} catch (Exception $e) {
|
||||
cli_heading(get_string('cleaningtempdata'));
|
||||
fulldelete($path);
|
||||
print_error('generalexceptionmessage', 'error', '', $e->getMessage());
|
||||
}
|
||||
|
||||
cli_heading(get_string('restoredcourseid', 'backup', $courseid));
|
||||
exit(0);
|
||||
@@ -30,17 +30,8 @@ require_once("$CFG->libdir/clilib.php");
|
||||
require_once("$CFG->libdir/cronlib.php");
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'help' => false,
|
||||
'list' => false,
|
||||
'execute' => false,
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'force' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'f' => 'force',
|
||||
]
|
||||
array('help' => false, 'list' => false, 'execute' => false, 'showsql' => false, 'showdebugging' => false),
|
||||
array('h' => 'help')
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
@@ -58,7 +49,6 @@ if ($options['help'] or (!$options['list'] and !$options['execute'])) {
|
||||
--showsql Show sql queries before they are executed
|
||||
--showdebugging Show developer level debugging information
|
||||
-h, --help Print out this help
|
||||
-f, --force Execute task even if cron is disabled
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
|
||||
@@ -131,13 +121,6 @@ if ($execute = $options['execute']) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
\core\task\manager::scheduled_task_starting($task);
|
||||
|
||||
// Increase memory limit.
|
||||
raise_memory_limit(MEMORY_EXTRA);
|
||||
|
||||
|
||||
@@ -38,17 +38,17 @@ if ($unrecognized) {
|
||||
}
|
||||
|
||||
// If necessary add files that should be ignored - such as in 3rd party plugins.
|
||||
$ignorelist = array();
|
||||
$blacklist = array();
|
||||
$path = $options['path'];
|
||||
if (!file_exists($path)) {
|
||||
cli_error("Invalid path $path");
|
||||
}
|
||||
|
||||
if ($options['ie9fix']) {
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $ignorelist);
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $blacklist);
|
||||
|
||||
} else if ($options['noaspectratio']) {
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $ignorelist);
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $blacklist);
|
||||
|
||||
} else {
|
||||
$help =
|
||||
@@ -153,9 +153,9 @@ function core_admin_svgtool_noaspectratio($file) {
|
||||
* @param string $base
|
||||
* @param string $sub
|
||||
* @param string $filecallback
|
||||
* @param array $ignorelist List of files to be ignored and skipped.
|
||||
* @param array $blacklist
|
||||
*/
|
||||
function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
|
||||
function core_admin_recurse_svgs($base, $sub, $filecallback, $blacklist) {
|
||||
if (is_dir("$base/$sub")) {
|
||||
$items = new DirectoryIterator("$base/$sub");
|
||||
foreach ($items as $item) {
|
||||
@@ -163,7 +163,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
|
||||
continue;
|
||||
}
|
||||
$file = $item->getFilename();
|
||||
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $ignorelist);
|
||||
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $blacklist);
|
||||
}
|
||||
unset($item);
|
||||
unset($items);
|
||||
@@ -174,7 +174,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
|
||||
return;
|
||||
}
|
||||
$file = realpath("$base/$sub");
|
||||
if (in_array($file, $ignorelist)) {
|
||||
if (in_array($file, $blacklist)) {
|
||||
return;
|
||||
}
|
||||
$filecallback($file);
|
||||
|
||||
@@ -39,8 +39,6 @@ Options:
|
||||
--purge-missing Uninstall all missing from disk plugins.
|
||||
--plugins=<plugin name> A comma separated list of plugins to be uninstalled. E.g. mod_assign,mod_forum
|
||||
--run Execute uninstall. If this option is not set, then the script will be run in a dry mode.
|
||||
--showsql Show sql queries before they are executed.
|
||||
--showdebugging Show developer level debugging information.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -74,8 +72,6 @@ list($options, $unrecognised) = cli_get_params([
|
||||
'purge-missing' => false,
|
||||
'plugins' => false,
|
||||
'run' => false,
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
], [
|
||||
'h' => 'help'
|
||||
]);
|
||||
@@ -90,14 +86,6 @@ if ($options['help']) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['showdebugging']) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if ($options['showsql']) {
|
||||
$DB->set_debug(true);
|
||||
}
|
||||
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
$plugininfo = $pluginman->get_plugins();
|
||||
|
||||
|
||||
@@ -135,15 +135,6 @@ if (!$envstatus) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Make sure there are no files left over from previous versions.
|
||||
if (upgrade_stale_php_files_present()) {
|
||||
cli_problem(get_string('upgradestalefiles', 'admin'));
|
||||
|
||||
// Stale file info contains HTML elements which aren't suitable for CLI.
|
||||
$upgradestalefilesinfo = get_string('upgradestalefilesinfo', 'admin', get_docs_url('Upgrading'));
|
||||
cli_error(strip_tags($upgradestalefilesinfo));
|
||||
}
|
||||
|
||||
// Test plugin dependencies.
|
||||
$failed = array();
|
||||
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
|
||||
|
||||
+1
-203
@@ -3163,11 +3163,6 @@
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_igbinary322_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="igbinary322buggyversion" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.10" requires="3.5">
|
||||
@@ -3350,11 +3345,6 @@
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_igbinary322_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="igbinary322buggyversion" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.11" requires="3.6">
|
||||
@@ -3457,7 +3447,7 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="optional"/>
|
||||
<PHP_EXTENSION name="sodium" level="required"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
@@ -3537,198 +3527,6 @@
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.0" requires="3.6">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.2.29" />
|
||||
<VENDOR name="mysql" version="5.7" />
|
||||
<VENDOR name="postgres" version="10" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.3.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlrpc" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="xmlrpcrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="optional"/>
|
||||
<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="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</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_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
@@ -119,19 +119,10 @@ if (($form = data_submitted()) && confirm_sesskey()) {
|
||||
// Save processors enabled/disabled status.
|
||||
foreach ($allprocessors as $processor) {
|
||||
$enabled = isset($form->{$processor->name});
|
||||
if ($enabled != $processor->enabled) {
|
||||
add_to_config_log($processor->name, $processor->enabled, $enabled, 'core');
|
||||
}
|
||||
\core_message\api::update_processor_status($processor, $enabled);
|
||||
}
|
||||
|
||||
foreach ($newpreferences as $name => $value) {
|
||||
$old = isset($preferences->$name) ? $preferences->$name : '';
|
||||
|
||||
if ($old != $value) {
|
||||
add_to_config_log($name, $old, $value, 'core');
|
||||
}
|
||||
|
||||
set_config($name, $value, 'message');
|
||||
}
|
||||
$transaction->allow_commit();
|
||||
|
||||
@@ -34,12 +34,11 @@ $error = optional_param('error', '', PARAM_RAW);
|
||||
if ($error) {
|
||||
$message = optional_param('error_description', '', PARAM_RAW);
|
||||
if ($message) {
|
||||
$SESSION->loginerrormsg = $message;
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
print_error($message);
|
||||
} else {
|
||||
$SESSION->loginerrormsg = $error;
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
print_error($error);
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
// The authorization code generated by the authorization server.
|
||||
@@ -54,6 +53,5 @@ if (isset($params['sesskey']) and confirm_sesskey($params['sesskey'])) {
|
||||
$redirecturl->param('oauth2code', $code);
|
||||
redirect($redirecturl);
|
||||
} else {
|
||||
$SESSION->loginerrormsg = get_string('invalidsesskey', 'error');
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
print_error('invalidsesskey');
|
||||
}
|
||||
|
||||
@@ -38,11 +38,12 @@ $form = new core_admin\form\purge_caches(null, ['returnurl' => $returnurl]);
|
||||
if ($data = $form->get_data()) {
|
||||
|
||||
// Valid request. Purge, and redirect the user back to where they came from.
|
||||
$selected = $data->purgeselectedoptions;
|
||||
purge_caches($selected);
|
||||
|
||||
if (isset($data->all)) {
|
||||
purge_caches();
|
||||
$message = get_string('purgecachesfinished', 'admin');
|
||||
} else {
|
||||
purge_caches($data->purgeselectedoptions);
|
||||
$message = get_string('purgeselectedcachesfinished', 'admin');
|
||||
}
|
||||
|
||||
@@ -51,14 +52,8 @@ if ($data = $form->get_data()) {
|
||||
$message = get_string('purgecachesfinished', 'admin');
|
||||
}
|
||||
|
||||
// Redirect and/or show notification message confirming cache(s) were purged.
|
||||
if (isset($message)) {
|
||||
if (!$PAGE->url->compare($returnurl, URL_MATCH_BASE)) {
|
||||
redirect($returnurl, $message);
|
||||
}
|
||||
|
||||
// We are already on the purge caches page, add the notification.
|
||||
\core\notification::add($message, \core\output\notification::NOTIFY_INFO);
|
||||
redirect($returnurl, $message);
|
||||
}
|
||||
|
||||
// Otherwise, show a form to actually purge the caches.
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Endpoint to get the Moodle version
|
||||
*
|
||||
* Moodle linkchecker will check this endpoint when it cannot get the Moodle version otherwise.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2022 Victor Deniz <victor@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
|
||||
// Get public key.
|
||||
$key = download_file_content(HUB_STATSPUBLICKEY);
|
||||
// Check $key is a valid public key.
|
||||
$publickey = openssl_pkey_get_public($key);
|
||||
if ($publickey !== false) {
|
||||
$publickeystr = openssl_pkey_get_details($publickey)['key'];
|
||||
} else {
|
||||
die('Error getting a valid public key');
|
||||
}
|
||||
|
||||
// Encrypt data.
|
||||
$message = $CFG->release;
|
||||
$success = openssl_public_encrypt(utf8_encode($message), $encrypteddata, $publickeystr);
|
||||
|
||||
if ($success) {
|
||||
echo base64_encode($encrypteddata);
|
||||
} else {
|
||||
die ('Error encrypting the data');
|
||||
}
|
||||
+16
-27
@@ -220,7 +220,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$output .= $this->container_end();
|
||||
}
|
||||
|
||||
$button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get', true);
|
||||
$button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get');
|
||||
$button->class = 'continuebutton';
|
||||
$output .= $this->render($button);
|
||||
$output .= $this->footer();
|
||||
@@ -1616,18 +1616,12 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
|
||||
$plugininfo = $pluginman->get_plugins();
|
||||
|
||||
$numtotal = $numextension = $numupdatable = $numinstallable = 0;
|
||||
$numtotal = $numextension = $numupdatable = 0;
|
||||
|
||||
foreach ($plugininfo as $type => $plugins) {
|
||||
foreach ($plugins as $name => $plugin) {
|
||||
if ($res = $plugin->available_updates()) {
|
||||
if ($plugin->available_updates()) {
|
||||
$numupdatable++;
|
||||
foreach ($res as $updateinfo) {
|
||||
if ($pluginman->is_remote_plugin_installable($updateinfo->component, $updateinfo->version, $reason, false)) {
|
||||
$numinstallable++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($plugin->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
continue;
|
||||
@@ -1670,13 +1664,16 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$out .= $this->output->heading(get_string('overviewext', 'core_plugin'), 3);
|
||||
}
|
||||
|
||||
if ($numinstallable) {
|
||||
$out .= $this->output->single_button(
|
||||
new moodle_url($this->page->url, array('installupdatex' => 1)),
|
||||
get_string('updateavailableinstallall', 'core_admin', $numinstallable),
|
||||
'post',
|
||||
array('class' => 'singlebutton updateavailableinstallall')
|
||||
);
|
||||
if ($numupdatable) {
|
||||
$installableupdates = $pluginman->filter_installable($pluginman->available_updates());
|
||||
if ($installableupdates) {
|
||||
$out .= $this->output->single_button(
|
||||
new moodle_url($this->page->url, array('installupdatex' => 1)),
|
||||
get_string('updateavailableinstallall', 'core_admin', count($installableupdates)),
|
||||
'post',
|
||||
array('class' => 'singlebutton updateavailableinstallall')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$out .= html_writer::div($infoall, 'info info-all').
|
||||
@@ -1910,7 +1907,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
'infos'
|
||||
);
|
||||
|
||||
if ($pluginman->is_remote_plugin_installable($updateinfo->component, $updateinfo->version, $reason, false)) {
|
||||
if ($pluginman->is_remote_plugin_installable($updateinfo->component, $updateinfo->version, $reason)) {
|
||||
$box .= $this->output->single_button(
|
||||
new moodle_url($this->page->url, array('installupdate' => $updateinfo->component,
|
||||
'installupdateversion' => $updateinfo->version)),
|
||||
@@ -2130,16 +2127,8 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$output .= $this->container_start('upgradekeyreq');
|
||||
$output .= $this->heading(get_string('upgradekeyreq', 'core_admin'));
|
||||
$output .= html_writer::start_tag('form', array('method' => 'POST', 'action' => $url));
|
||||
$output .= html_writer::empty_tag('input', [
|
||||
'name' => 'upgradekey',
|
||||
'type' => 'password',
|
||||
'class' => 'form-control w-auto',
|
||||
]);
|
||||
$output .= html_writer::empty_tag('input', [
|
||||
'type' => 'submit',
|
||||
'value' => get_string('submit'),
|
||||
'class' => 'btn btn-primary mt-3',
|
||||
]);
|
||||
$output .= html_writer::empty_tag('input', array('name' => 'upgradekey', 'type' => 'password'));
|
||||
$output .= html_writer::empty_tag('input', array('value' => get_string('submit'), 'type' => 'submit'));
|
||||
$output .= html_writer::end_tag('form');
|
||||
$output .= $this->container_end();
|
||||
$output .= $this->footer();
|
||||
|
||||
@@ -271,8 +271,7 @@ if ($roleid) {
|
||||
foreach ($assignableroles as $roleid => $notused) {
|
||||
$roleusers = '';
|
||||
if (0 < $assigncounts[$roleid] && $assigncounts[$roleid] <= MAX_USERS_TO_LIST_PER_ROLE) {
|
||||
$userfieldsapi = \core_user\fields::for_name();
|
||||
$userfields = 'u.id, u.username' . $userfieldsapi->get_sql('u')->selects;
|
||||
$userfields = 'u.id, u.username, ' . get_all_user_name_fields(true, 'u');
|
||||
$roleusers = get_role_users($roleid, $context, false, $userfields);
|
||||
if (!empty($roleusers)) {
|
||||
$strroleusers = array();
|
||||
|
||||
@@ -163,8 +163,7 @@ if (!empty($capabilities)) {
|
||||
echo html_writer::start_tag('div', array('class'=>'submit_buttons'));
|
||||
$attrs = array('type'=>'submit', 'name'=>'savechanges', 'value'=>get_string('savechanges'), 'class'=>'btn btn-primary');
|
||||
echo html_writer::empty_tag('input', $attrs);
|
||||
$attrs = array('type' => 'submit', 'name' => 'cancel', 'value' => get_string('cancel'),
|
||||
'class' => 'btn btn-secondary ml-1');
|
||||
$attrs = array('type'=>'submit', 'name'=>'cancel', 'value'=>get_string('cancel'), 'class' => 'btn btn-secondary');
|
||||
echo html_writer::empty_tag('input', $attrs);
|
||||
echo html_writer::end_tag('div');
|
||||
echo html_writer::end_tag('div');
|
||||
|
||||
@@ -22,17 +22,16 @@
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_role\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_role\privacy\provider;
|
||||
use core_privacy\local\request\approved_contextlist;
|
||||
use core_privacy\local\request\writer;
|
||||
use core_privacy\tests\provider_testcase;
|
||||
use core_privacy\local\request\transform;
|
||||
use tool_cohortroles\api;
|
||||
use core_privacy\local\request\approved_userlist;
|
||||
use \core_role\privacy\provider;
|
||||
use \core_privacy\local\request\approved_contextlist;
|
||||
use \core_privacy\local\request\writer;
|
||||
use \core_privacy\tests\provider_testcase;
|
||||
use \core_privacy\local\request\transform;
|
||||
use \tool_cohortroles\api;
|
||||
use \core_privacy\local\request\approved_userlist;
|
||||
|
||||
/**
|
||||
* Privacy test for core_role
|
||||
@@ -40,7 +39,7 @@ use core_privacy\local\request\approved_userlist;
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider_test extends provider_testcase {
|
||||
class core_role_privacy_testcase extends provider_testcase {
|
||||
/**
|
||||
* Test to check export_user_preferences.
|
||||
* returns user preferences data.
|
||||
@@ -537,7 +536,7 @@ class provider_test extends provider_testcase {
|
||||
$user1->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist2->get_userids());
|
||||
$this->assertEquals($expected, $userlist2->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for coursecontext1 should user1, user2 and admin (role creator).
|
||||
$userlist3 = new \core_privacy\local\request\userlist($coursecontext1, $component);
|
||||
@@ -548,7 +547,7 @@ class provider_test extends provider_testcase {
|
||||
$user2->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist3->get_userids());
|
||||
$this->assertEquals($expected, $userlist3->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for coursecatcontext should user2 and admin (role creator).
|
||||
$userlist4 = new \core_privacy\local\request\userlist($coursecatcontext, $component);
|
||||
@@ -558,7 +557,7 @@ class provider_test extends provider_testcase {
|
||||
$user2->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist4->get_userids());
|
||||
$this->assertEquals($expected, $userlist4->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for systemcontext should user1 and admin (role creator).
|
||||
$userlist6 = new \core_privacy\local\request\userlist($systemcontext, $component);
|
||||
@@ -568,7 +567,7 @@ class provider_test extends provider_testcase {
|
||||
$user1->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist6->get_userids());
|
||||
$this->assertEquals($expected, $userlist6->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for cmcontext should user1, user2 and admin (role creator).
|
||||
$userlist7 = new \core_privacy\local\request\userlist($cmcontext, $component);
|
||||
@@ -579,7 +578,7 @@ class provider_test extends provider_testcase {
|
||||
$user2->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist7->get_userids());
|
||||
$this->assertEquals($expected, $userlist7->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for blockcontext should user1 and admin (role creator).
|
||||
$userlist8 = new \core_privacy\local\request\userlist($blockcontext, $component);
|
||||
@@ -589,7 +588,7 @@ class provider_test extends provider_testcase {
|
||||
$user1->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist8->get_userids());
|
||||
$this->assertEquals($expected, $userlist8->get_userids(), '', 0.0, 10, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -745,4 +744,4 @@ class provider_test extends provider_testcase {
|
||||
}
|
||||
return $rolesnames;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-10
@@ -68,16 +68,9 @@ if ($errormsg !== '') {
|
||||
$showsettingslinks = true;
|
||||
|
||||
if ($hassiteconfig) {
|
||||
$data = [
|
||||
'action' => new moodle_url('/admin/search.php'),
|
||||
'btnclass' => 'btn-primary',
|
||||
'inputname' => 'query',
|
||||
'searchstring' => get_string('search'),
|
||||
'query' => $query,
|
||||
'extraclasses' => 'd-flex justify-content-center'
|
||||
];
|
||||
echo $OUTPUT->render_from_template('core/search_input', $data);
|
||||
|
||||
require_once("admin_settings_search_form.php");
|
||||
$form = new admin_settings_search_form();
|
||||
$form->display();
|
||||
echo '<hr>';
|
||||
if ($query) {
|
||||
echo admin_search_settings_html($query);
|
||||
|
||||
@@ -144,20 +144,5 @@ if ($hassiteconfig && \core_analytics\manager::is_analytics_enabled()) {
|
||||
$settings->add(new admin_setting_configduration('analytics/modeltimelimit', new lang_string('modeltimelimit', 'analytics'),
|
||||
new lang_string('modeltimelimitinfo', 'analytics'), 20 * MINSECS));
|
||||
|
||||
$options = array(
|
||||
0 => new lang_string('neverdelete', 'analytics'),
|
||||
1000 => new lang_string('numdays', '', 1000),
|
||||
365 => new lang_string('numdays', '', 365),
|
||||
180 => new lang_string('numdays', '', 180),
|
||||
150 => new lang_string('numdays', '', 150),
|
||||
120 => new lang_string('numdays', '', 120),
|
||||
90 => new lang_string('numdays', '', 90),
|
||||
60 => new lang_string('numdays', '', 60),
|
||||
35 => new lang_string('numdays', '', 35));
|
||||
$settings->add(new admin_setting_configselect('analytics/calclifetime',
|
||||
new lang_string('calclifetime', 'analytics'),
|
||||
new lang_string('configlcalclifetime', 'analytics'), 35, $options));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,6 +269,7 @@ preferences,moodle|/user/preferences.php|t/preferences',
|
||||
$setting = new admin_setting_configcheckbox('cachejs', new lang_string('cachejs', 'admin'), new lang_string('cachejs_help', 'admin'), 1);
|
||||
$setting->set_updatedcallback('js_reset_all_caches');
|
||||
$temp->add($setting);
|
||||
$temp->add(new admin_setting_configcheckbox('modchooserdefault', new lang_string('modchooserdefault', 'admin'), new lang_string('configmodchooserdefault', 'admin'), 1));
|
||||
$ADMIN->add('appearance', $temp);
|
||||
|
||||
// Link to tag management interface.
|
||||
|
||||
@@ -57,14 +57,20 @@ if (($hassiteconfig || has_any_capability(array(
|
||||
new lang_string('badgesalt_desc', 'badges'),
|
||||
'badges' . $SITE->timecreated, PARAM_ALPHANUM));
|
||||
|
||||
$backpacks = badges_get_site_backpacks();
|
||||
$choices = array();
|
||||
$defaultchoice = 0;
|
||||
foreach ($backpacks as $backpack) {
|
||||
$choices[$backpack->id] = $backpack->backpackweburl;
|
||||
if ($backpack->backpackweburl == BADGRIO_BACKPACKWEBURL) {
|
||||
$defaultchoice = $backpack->id;
|
||||
}
|
||||
}
|
||||
|
||||
$globalsettings->add(new admin_setting_configcheckbox('badges_allowcoursebadges',
|
||||
new lang_string('allowcoursebadges', 'badges'),
|
||||
new lang_string('allowcoursebadges_desc', 'badges'), 1));
|
||||
|
||||
$globalsettings->add(new admin_setting_configcheckbox('badges_allowexternalbackpack',
|
||||
new lang_string('allowexternalbackpack', 'badges'),
|
||||
new lang_string('allowexternalbackpack_desc', 'badges'), 1));
|
||||
|
||||
$ADMIN->add('badges', $globalsettings);
|
||||
|
||||
$ADMIN->add('badges',
|
||||
@@ -91,6 +97,19 @@ if (($hassiteconfig || has_any_capability(array(
|
||||
array('moodle/badges:createbadge'), empty($CFG->enablebadges)
|
||||
)
|
||||
);
|
||||
$backpacksettings = new admin_settingpage('backpacksettings', new lang_string('backpacksettings', 'badges'),
|
||||
array('moodle/badges:manageglobalsettings'), empty($CFG->enablebadges));
|
||||
|
||||
$backpacksettings->add(new admin_setting_configcheckbox('badges_allowexternalbackpack',
|
||||
new lang_string('allowexternalbackpack', 'badges'),
|
||||
new lang_string('allowexternalbackpack_desc', 'badges'), 1));
|
||||
|
||||
$backpacksettings->add(new admin_setting_configselect('badges_site_backpack',
|
||||
new lang_string('sitebackpack', 'badges'),
|
||||
new lang_string('sitebackpack_help', 'badges'),
|
||||
$defaultchoice, $choices));
|
||||
|
||||
$ADMIN->add('badges', $backpacksettings);
|
||||
|
||||
$ADMIN->add('badges',
|
||||
new admin_externalpage('managebackpacks',
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core_admin\local\settings\filesize;
|
||||
|
||||
$capabilities = array(
|
||||
'moodle/backup:backupcourse',
|
||||
'moodle/category:manage',
|
||||
@@ -77,17 +75,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configselect('moodlecourse/visible', new lang_string('visible'), new lang_string('visible_help'),
|
||||
1, $choices));
|
||||
|
||||
// Enable/disable download course content.
|
||||
$choices = [
|
||||
DOWNLOAD_COURSE_CONTENT_DISABLED => new lang_string('no'),
|
||||
DOWNLOAD_COURSE_CONTENT_ENABLED => new lang_string('yes'),
|
||||
];
|
||||
$downloadcontentsitedefault = new admin_setting_configselect('moodlecourse/downloadcontentsitedefault',
|
||||
new lang_string('enabledownloadcoursecontent', 'course'),
|
||||
new lang_string('downloadcoursecontent_help', 'course'), 0, $choices);
|
||||
$downloadcontentsitedefault->add_dependent_on('downloadcoursecontentallowed');
|
||||
$temp->add($downloadcontentsitedefault);
|
||||
|
||||
// Course format.
|
||||
$temp->add(new admin_setting_heading('courseformathdr', new lang_string('type_format', 'plugin'), ''));
|
||||
|
||||
@@ -139,13 +126,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
new lang_string('coursehelpshowgrades'), 1, array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
|
||||
$temp->add(new admin_setting_configselect('moodlecourse/showreports', new lang_string('showreports'), '', 0,
|
||||
array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
|
||||
$temp->add(new admin_setting_configselect('moodlecourse/showactivitydates',
|
||||
new lang_string('showactivitydates'),
|
||||
new lang_string('showactivitydates_help'), 1, [
|
||||
0 => new lang_string('no'),
|
||||
1 => new lang_string('yes')
|
||||
]
|
||||
));
|
||||
|
||||
// Files and uploads.
|
||||
$temp->add(new admin_setting_heading('filesanduploadshdr', new lang_string('filesanduploads'), ''));
|
||||
@@ -170,15 +150,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configselect('moodlecourse/enablecompletion', new lang_string('completion', 'completion'),
|
||||
new lang_string('enablecompletion_help', 'completion'), 1, array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
|
||||
|
||||
// Display completion conditions.
|
||||
$temp->add(new admin_setting_configselect('moodlecourse/showcompletionconditions',
|
||||
new lang_string('showcompletionconditions', 'completion'),
|
||||
new lang_string('showcompletionconditions_help', 'completion'), 1, [
|
||||
0 => new lang_string('no'),
|
||||
1 => new lang_string('yes')
|
||||
]
|
||||
));
|
||||
|
||||
// Groups.
|
||||
$temp->add(new admin_setting_heading('groups', new lang_string('groups', 'group'), ''));
|
||||
$choices = array();
|
||||
@@ -190,21 +161,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
|
||||
$ADMIN->add('courses', $temp);
|
||||
|
||||
// Download course content.
|
||||
$downloadcoursedefaulturl = new moodle_url('/admin/settings.php', ['section' => 'coursesettings']);
|
||||
$temp = new admin_settingpage('downloadcoursecontent', new lang_string('downloadcoursecontent', 'course'));
|
||||
$temp->add(new admin_setting_configcheckbox('downloadcoursecontentallowed',
|
||||
new lang_string('downloadcoursecontentallowed', 'admin'),
|
||||
new lang_string('downloadcoursecontentallowed_desc', 'admin', $downloadcoursedefaulturl->out()), 0));
|
||||
|
||||
// 50MB default maximum size per file when downloading course content.
|
||||
$defaultmaxdownloadsize = 50 * filesize::UNIT_MB;
|
||||
$temp->add(new filesize('maxsizeperdownloadcoursefile', new lang_string('maxsizeperdownloadcoursefile', 'admin'),
|
||||
new lang_string('maxsizeperdownloadcoursefile_desc', 'admin'), $defaultmaxdownloadsize, filesize::UNIT_MB));
|
||||
$temp->hide_if('maxsizeperdownloadcoursefile', 'downloadcoursecontentallowed');
|
||||
|
||||
$ADMIN->add('courses', $temp);
|
||||
|
||||
// "courserequests" settingpage.
|
||||
$temp = new admin_settingpage('courserequest', new lang_string('courserequest'));
|
||||
$temp->add(new admin_setting_configcheckbox('enablecourserequests',
|
||||
@@ -228,7 +184,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
// Add a category for the Activity Chooser.
|
||||
$ADMIN->add('courses', new admin_category('activitychooser', new lang_string('activitychoosercategory', 'course')));
|
||||
$temp = new admin_settingpage('activitychoosersettings', new lang_string('activitychoosersettings', 'course'));
|
||||
// Tab mode for the activity chooser.
|
||||
$temp->add(
|
||||
new admin_setting_configselect(
|
||||
'activitychoosertabmode',
|
||||
@@ -242,31 +197,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
// Build a list of plugins that use the footer callback.
|
||||
$pluginswithfunction = get_plugins_with_function('custom_chooser_footer', 'lib.php');
|
||||
$pluginsoptions = [];
|
||||
$pluginsoptions[COURSE_CHOOSER_FOOTER_NONE] = get_string('activitychooserhidefooter', 'course');
|
||||
if ($pluginswithfunction) {
|
||||
foreach ($pluginswithfunction as $plugintype => $plugins) {
|
||||
foreach ($plugins as $pluginname => $pluginfunction) {
|
||||
$plugin = $plugintype.'_'.$pluginname;
|
||||
$pluginsoptions[$plugin] = get_string('pluginname', $plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Select what plugin to show in the footer.
|
||||
$temp->add(
|
||||
new admin_setting_configselect(
|
||||
'activitychooseractivefooter',
|
||||
new lang_string('activitychooseractivefooter', 'course'),
|
||||
new lang_string('activitychooseractivefooter_desc', 'course'),
|
||||
COURSE_CHOOSER_FOOTER_NONE,
|
||||
$pluginsoptions
|
||||
)
|
||||
);
|
||||
|
||||
$ADMIN->add('activitychooser', $temp);
|
||||
$ADMIN->add('activitychooser',
|
||||
new admin_externalpage('activitychooserrecommended', new lang_string('activitychooserrecommendations', 'course'),
|
||||
@@ -329,9 +259,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
['value' => 1, 'locked' => 0])
|
||||
);
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_legacyfiles',
|
||||
new lang_string('generallegacyfiles', 'backup'),
|
||||
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
$ADMIN->add('backups', $temp);
|
||||
|
||||
// Create a page for general import configuration and defaults.
|
||||
@@ -343,11 +270,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
|
||||
// Import defaults section.
|
||||
$temp->add(new admin_setting_heading('importsettings', new lang_string('importsettings', 'backup'), ''));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock(
|
||||
'backup/backup_import_permissions',
|
||||
new lang_string('generalpermissions', 'backup'),
|
||||
new lang_string('configgeneralpermissions', 'backup'),
|
||||
array('value' => 0, 'locked' => 0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_activities', new lang_string('generalactivities','backup'), new lang_string('configgeneralactivities','backup'), array('value'=>1, 'locked'=>0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_blocks', new lang_string('generalblocks','backup'), new lang_string('configgeneralblocks','backup'), array('value'=>1, 'locked'=>0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_filters', new lang_string('generalfilters','backup'), new lang_string('configgeneralfilters','backup'), array('value'=>1, 'locked'=>0)));
|
||||
@@ -363,9 +285,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
new lang_string('configgeneralcontentbankcontent', 'backup'),
|
||||
['value' => 1, 'locked' => 0])
|
||||
);
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_legacyfiles',
|
||||
new lang_string('generallegacyfiles', 'backup'),
|
||||
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
|
||||
$ADMIN->add('backups', $temp);
|
||||
|
||||
@@ -492,10 +411,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
1)
|
||||
);
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_legacyfiles',
|
||||
new lang_string('generallegacyfiles', 'backup'),
|
||||
new lang_string('configlegacyfiles', 'backup'), 1));
|
||||
|
||||
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_messages', new lang_string('messages', 'message'), new lang_string('backupmessageshelp','message'), 0));
|
||||
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_blogs', new lang_string('blogs', 'blog'), new lang_string('backupblogshelp','blog'), 0));
|
||||
|
||||
@@ -522,9 +437,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_role_assignments',
|
||||
new lang_string('generalroleassignments', 'backup'),
|
||||
new lang_string('configrestoreroleassignments', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_permissions',
|
||||
new lang_string('generalpermissions', 'backup'),
|
||||
new lang_string('configrestorepermissions', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_activities',
|
||||
new lang_string('generalactivities', 'backup'),
|
||||
new lang_string('configrestoreactivities', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
@@ -561,9 +473,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_contentbankcontent',
|
||||
new lang_string('generalcontentbankcontent', 'backup'),
|
||||
new lang_string('configrestorecontentbankcontent', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_legacyfiles',
|
||||
new lang_string('generallegacyfiles', 'backup'),
|
||||
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
|
||||
// Restore defaults when merging into another course.
|
||||
$temp->add(new admin_setting_heading('mergerestoredefaults', new lang_string('mergerestoredefaults', 'backup'), ''));
|
||||
|
||||
@@ -38,17 +38,9 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
// "debugging" settingpage
|
||||
$temp = new admin_settingpage('debugging', new lang_string('debugging', 'admin'));
|
||||
$temp->add(new admin_setting_special_debug());
|
||||
$temp->add(new admin_setting_configcheckbox('debugdisplay', new lang_string('debugdisplay', 'admin'),
|
||||
new lang_string('configdebugdisplay', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('debugdisplay', new lang_string('debugdisplay', 'admin'), new lang_string('configdebugdisplay', 'admin'), ini_get_bool('display_errors')));
|
||||
$temp->add(new admin_setting_configcheckbox('perfdebug', new lang_string('perfdebug', 'admin'), new lang_string('configperfdebug', 'admin'), '7', '15', '7'));
|
||||
$temp->add(new admin_setting_configcheckbox('debugstringids', new lang_string('debugstringids', 'admin'), new lang_string('debugstringids_desc', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configselect('debugsqltrace',
|
||||
new lang_string('debugsqltrace', 'admin'),
|
||||
new lang_string('debugsqltrace_desc', 'admin'), 0, array(
|
||||
0 => new lang_string('disabled', 'admin'),
|
||||
1 => new lang_string('debugsqltrace1', 'admin'),
|
||||
2 => new lang_string('debugsqltrace2', 'admin'),
|
||||
100 => new lang_string('debugsqltrace100', 'admin'))));
|
||||
$temp->add(new admin_setting_configcheckbox('debugvalidators', new lang_string('debugvalidators', 'admin'), new lang_string('configdebugvalidators', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('debugpageinfo', new lang_string('debugpageinfo', 'admin'), new lang_string('configdebugpageinfo', 'admin'), 0));
|
||||
$ADMIN->add('development', $temp);
|
||||
|
||||
@@ -8,8 +8,6 @@ if ($hassiteconfig) {
|
||||
$temp = new admin_settingpage('langsettings', new lang_string('languagesettings', 'admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('autolang', new lang_string('autolang', 'admin'), new lang_string('configautolang', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configselect('lang', new lang_string('lang', 'admin'), new lang_string('configlang', 'admin'), current_language(), get_string_manager()->get_list_of_translations())); // $CFG->lang might be set in installer already, default en is in setup.php
|
||||
$temp->add(new admin_setting_configcheckbox('autolangusercreation', new lang_string('autolangusercreation', 'admin'),
|
||||
new lang_string('configautolangusercreation', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('langmenu', new lang_string('langmenu', 'admin'), new lang_string('configlangmenu', 'admin'), 1));
|
||||
$temp->add(new admin_setting_langlist());
|
||||
$temp->add(new admin_setting_configcheckbox('langcache', new lang_string('langcache', 'admin'), new lang_string('langcache_desc', 'admin'), 1));
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Adds payments links to the admin tree
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2020 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$ADMIN->add('payment', new admin_externalpage(
|
||||
'paymentaccounts',
|
||||
new lang_string('paymentaccounts', 'payment'),
|
||||
new moodle_url("/payment/accounts.php"),
|
||||
['moodle/payment:manageaccounts', 'moodle/payment:viewpayments']));
|
||||
+51
-108
@@ -167,42 +167,6 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('modules', new admin_category('antivirussettings', new lang_string('antiviruses', 'antivirus')));
|
||||
$temp = new admin_settingpage('manageantiviruses', new lang_string('antivirussettings', 'antivirus'));
|
||||
$temp->add(new admin_setting_manageantiviruses());
|
||||
|
||||
// Common settings.
|
||||
$temp->add(new admin_setting_heading('antiviruscommonsettings', new lang_string('antiviruscommonsettings', 'antivirus'), ''));
|
||||
|
||||
// Alert email.
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'antivirus/notifyemail',
|
||||
new lang_string('notifyemail', 'antivirus'),
|
||||
new lang_string('notifyemail_help', 'antivirus'),
|
||||
'',
|
||||
PARAM_EMAIL
|
||||
)
|
||||
);
|
||||
|
||||
// Enable quarantine.
|
||||
$temp->add(
|
||||
new admin_setting_configcheckbox(
|
||||
'antivirus/enablequarantine',
|
||||
new lang_string('enablequarantine', 'antivirus'),
|
||||
new lang_string('enablequarantine_help', 'antivirus',
|
||||
\core\antivirus\quarantine::DEFAULT_QUARANTINE_FOLDER),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
// Quarantine time.
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'antivirus/quarantinetime',
|
||||
new lang_string('quarantinetime', 'antivirus'),
|
||||
new lang_string('quarantinetime_desc', 'antivirus'),
|
||||
\core\antivirus\quarantine::DEFAULT_QUARANTINE_TIME
|
||||
)
|
||||
);
|
||||
|
||||
$ADMIN->add('antivirussettings', $temp);
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('antivirus');
|
||||
core_collator::asort_objects_by_property($plugins, 'displayname');
|
||||
@@ -231,9 +195,6 @@ if ($hassiteconfig) {
|
||||
array('0' => new lang_string('none'), '1' => new lang_string('allfiles'), '2' => new lang_string('htmlfilesonly')));
|
||||
$items[] = new admin_setting_configcheckbox('filtermatchoneperpage', new lang_string('filtermatchoneperpage', 'admin'), new lang_string('configfiltermatchoneperpage', 'admin'), 0);
|
||||
$items[] = new admin_setting_configcheckbox('filtermatchonepertext', new lang_string('filtermatchonepertext', 'admin'), new lang_string('configfiltermatchonepertext', 'admin'), 0);
|
||||
$items[] = new admin_setting_configcheckbox('filternavigationwithsystemcontext',
|
||||
new lang_string('filternavigationwithsystemcontext', 'admin'),
|
||||
new lang_string('configfilternavigationwithsystemcontext', 'admin'), 0);
|
||||
foreach ($items as $item) {
|
||||
$item->set_updatedcallback('reset_text_filters_cache');
|
||||
$temp->add($item);
|
||||
@@ -283,25 +244,6 @@ if ($hassiteconfig) {
|
||||
$plugin->load_settings($ADMIN, 'mediaplayers', $hassiteconfig);
|
||||
}
|
||||
|
||||
// Payment gateway plugins.
|
||||
$ADMIN->add('modules', new admin_category('paymentgateways', new lang_string('type_paygw_plural', 'plugin')));
|
||||
$temp = new admin_settingpage('managepaymentgateways', new lang_string('type_paygwmanage', 'plugin'));
|
||||
$temp->add(new \core_admin\local\settings\manage_payment_gateway_plugins());
|
||||
$temp->add(new admin_setting_description(
|
||||
'managepaymentgatewayspostfix',
|
||||
'',
|
||||
new lang_string('gotopaymentaccounts', 'payment',
|
||||
html_writer::link(new moodle_url('/payment/accounts.php'), get_string('paymentaccounts', 'payment')))
|
||||
));
|
||||
$ADMIN->add('paymentgateways', $temp);
|
||||
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('paygw');
|
||||
core_collator::asort_objects_by_property($plugins, 'displayname');
|
||||
foreach ($plugins as $plugin) {
|
||||
/** @var \core\plugininfo\paygw $plugin */
|
||||
$plugin->load_settings($ADMIN, 'paymentgateways', $hassiteconfig);
|
||||
}
|
||||
|
||||
// Data format settings.
|
||||
$ADMIN->add('modules', new admin_category('dataformatsettings', new lang_string('dataformats')));
|
||||
$temp = new admin_settingpage('managedataformats', new lang_string('managedataformats'));
|
||||
@@ -404,6 +346,55 @@ if ($hassiteconfig) {
|
||||
/** @var \core\plugininfo\repository $plugin */
|
||||
$plugin->load_settings($ADMIN, 'repositorysettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
/// Web services
|
||||
$ADMIN->add('modules', new admin_category('webservicesettings', new lang_string('webservices', 'webservice')));
|
||||
|
||||
/// overview page
|
||||
$temp = new admin_settingpage('webservicesoverview', new lang_string('webservicesoverview', 'webservice'));
|
||||
$temp->add(new admin_setting_webservicesoverview());
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
//API documentation
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('webservicedocumentation', new lang_string('wsdocapi', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/documentation.php", 'moodle/site:config', false));
|
||||
/// manage service
|
||||
$temp = new admin_settingpage('externalservices', new lang_string('externalservices', 'webservice'));
|
||||
$temp->add(new admin_setting_heading('manageserviceshelpexplaination', new lang_string('information', 'webservice'), new lang_string('servicehelpexplanation', 'webservice')));
|
||||
$temp->add(new admin_setting_manageexternalservices());
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('externalservice', new lang_string('editaservice', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/service.php", 'moodle/site:config', true));
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('externalservicefunctions', new lang_string('externalservicefunctions', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/service_functions.php", 'moodle/site:config', true));
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusers', new lang_string('externalserviceusers', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/service_users.php", 'moodle/site:config', true));
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusersettings', new lang_string('serviceusersettings', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/service_user_settings.php", 'moodle/site:config', true));
|
||||
/// manage protocol page link
|
||||
$temp = new admin_settingpage('webserviceprotocols', new lang_string('manageprotocols', 'webservice'));
|
||||
$temp->add(new admin_setting_managewebserviceprotocols());
|
||||
if (empty($CFG->enablewebservices)) {
|
||||
$temp->add(new admin_setting_heading('webservicesaredisabled', '', new lang_string('disabledwarning', 'webservice')));
|
||||
}
|
||||
|
||||
// We cannot use $OUTPUT this early, doing so means that we lose the ability
|
||||
// to set the page layout on all admin pages.
|
||||
// $wsdoclink = $OUTPUT->doc_link('How_to_get_a_security_key');
|
||||
$url = new moodle_url(get_docs_url('How_to_get_a_security_key'));
|
||||
$wsdoclink = html_writer::tag('a', new lang_string('supplyinfo', 'webservice'), array('href'=>$url));
|
||||
$temp->add(new admin_setting_configcheckbox('enablewsdocumentation', new lang_string('enablewsdocumentation',
|
||||
'admin'), new lang_string('configenablewsdocumentation', 'admin', $wsdoclink), false));
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
/// links to protocol pages
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('webservice');
|
||||
core_collator::asort_objects_by_property($plugins, 'displayname');
|
||||
foreach ($plugins as $plugin) {
|
||||
/** @var \core\plugininfo\webservice $plugin */
|
||||
$plugin->load_settings($ADMIN, 'webservicesettings', $hassiteconfig);
|
||||
}
|
||||
/// manage token page link
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('addwebservicetoken', new lang_string('managetokens', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/tokens.php", 'moodle/site:config', true));
|
||||
$temp = new admin_settingpage('webservicetokens', new lang_string('managetokens', 'webservice'));
|
||||
$temp->add(new admin_setting_managewebservicetokens());
|
||||
if (empty($CFG->enablewebservices)) {
|
||||
$temp->add(new admin_setting_heading('webservicesaredisabled', '', new lang_string('disabledwarning', 'webservice')));
|
||||
}
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
}
|
||||
|
||||
// Question type settings
|
||||
@@ -558,19 +549,8 @@ if ($hassiteconfig) {
|
||||
|
||||
// Search engine selection.
|
||||
$temp->add(new admin_setting_heading('searchengineheading', new lang_string('searchengine', 'admin'), ''));
|
||||
$searchengineselect = new admin_setting_configselect('searchengine',
|
||||
new lang_string('selectsearchengine', 'admin'), '', 'simpledb', $engines);
|
||||
$searchengineselect->set_validate_function(function(string $value): string {
|
||||
global $CFG;
|
||||
|
||||
// Check nobody's setting the indexing and query-only server to the same one.
|
||||
if (isset($CFG->searchenginequeryonly) && $CFG->searchenginequeryonly === $value) {
|
||||
return get_string('searchenginequeryonlysame', 'admin');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
$temp->add($searchengineselect);
|
||||
$temp->add(new admin_setting_configselect('searchengine',
|
||||
new lang_string('selectsearchengine', 'admin'), '', 'simpledb', $engines));
|
||||
$temp->add(new admin_setting_heading('searchoptionsheading', new lang_string('searchoptions', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configcheckbox('searchindexwhendisabled',
|
||||
new lang_string('searchindexwhendisabled', 'admin'), new lang_string('searchindexwhendisabled_desc', 'admin'),
|
||||
@@ -610,43 +590,6 @@ if ($hassiteconfig) {
|
||||
new lang_string('searchhideallcategory_desc', 'admin'),
|
||||
0));
|
||||
|
||||
$temp->add(new admin_setting_heading('searchmanagement', new lang_string('searchmanagement', 'admin'),
|
||||
new lang_string('searchmanagement_desc', 'admin')));
|
||||
|
||||
// Get list of search engines including those with alternate settings.
|
||||
$searchenginequeryonlyselect = new admin_setting_configselect('searchenginequeryonly',
|
||||
new lang_string('searchenginequeryonly', 'admin'),
|
||||
new lang_string('searchenginequeryonly_desc', 'admin'), '', function() use($engines) {
|
||||
$options = ['' => new lang_string('searchenginequeryonly_none', 'admin')];
|
||||
foreach ($engines as $name => $display) {
|
||||
$options[$name] = $display;
|
||||
|
||||
$classname = '\search_' . $name . '\engine';
|
||||
$engine = new $classname;
|
||||
if ($engine->has_alternate_configuration()) {
|
||||
$options[$name . '-alternate'] =
|
||||
new lang_string('searchenginealternatesettings', 'admin', $display);
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
});
|
||||
$searchenginequeryonlyselect->set_validate_function(function(string $value): string {
|
||||
global $CFG;
|
||||
|
||||
// Check nobody's setting the indexing and query-only server to the same one.
|
||||
if (isset($CFG->searchengine) && $CFG->searchengine === $value) {
|
||||
return get_string('searchenginequeryonlysame', 'admin');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
$temp->add($searchenginequeryonlyselect);
|
||||
$temp->add(new admin_setting_configcheckbox('searchbannerenable',
|
||||
new lang_string('searchbannerenable', 'admin'), new lang_string('searchbannerenable_desc', 'admin'),
|
||||
0));
|
||||
$temp->add(new admin_setting_confightmleditor('searchbanner',
|
||||
new lang_string('searchbanner', 'admin'), '', ''));
|
||||
|
||||
$ADMIN->add('searchplugins', $temp);
|
||||
$ADMIN->add('searchplugins', new admin_externalpage('searchareas', new lang_string('searchareas', 'admin'),
|
||||
new moodle_url('/admin/searchareas.php')));
|
||||
|
||||
@@ -160,23 +160,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$temp->add(new admin_setting_configportlist('curlsecurityallowedport',
|
||||
new lang_string('curlsecurityallowedport', 'admin'),
|
||||
new lang_string('curlsecurityallowedportsyntax', 'admin'), ""));
|
||||
|
||||
// HTTP Header referrer policy settings.
|
||||
$referreroptions = [
|
||||
'default' => get_string('referrernone', 'admin'),
|
||||
'no-referrer' => 'no-referrer',
|
||||
'no-referrer-when-downgrade' => 'no-referrer-when-downgrade',
|
||||
'origin' => 'origin',
|
||||
'origin-when-cross-origin' => 'origin-when-cross-origin',
|
||||
'same-origin' => 'same-origin',
|
||||
'strict-origin' => 'strict-origin',
|
||||
'strict-origin-when-cross-origin' => 'strict-origin-when-cross-origin',
|
||||
'unsafe-url' => 'unsafe-url',
|
||||
];
|
||||
$temp->add(new admin_setting_configselect('referrerpolicy',
|
||||
new lang_string('referrerpolicy', 'admin'),
|
||||
new lang_string('referrerpolicydesc', 'admin'), 'default', $referreroptions));
|
||||
|
||||
$ADMIN->add('security', $temp);
|
||||
|
||||
// "notifications" settingpage
|
||||
|
||||
+313
-536
@@ -1,243 +1,162 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://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/>.
|
||||
|
||||
/**
|
||||
* Defines settingpages and externalpages under the "server" category.
|
||||
*
|
||||
* @package core
|
||||
* @category admin
|
||||
* @copyright 2006 Martin Dougiamas
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
// This file defines settingpages and externalpages under the "server" category
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
|
||||
if ($hassiteconfig) {
|
||||
// System paths.
|
||||
$temp = new admin_settingpage('systempaths', new lang_string('systempaths', 'admin'));
|
||||
$temp->add(new admin_setting_configexecutable('pathtophp', new lang_string('pathtophp', 'admin'),
|
||||
new lang_string('configpathtophp', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'),
|
||||
new lang_string('configpathtodu', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'),
|
||||
new lang_string('edhelpaspellpath'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'),
|
||||
new lang_string('pathtodot_help', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtogs', new lang_string('pathtogs', 'admin'),
|
||||
new lang_string('pathtogs_help', 'admin'), '/usr/bin/gs'));
|
||||
$temp->add(new admin_setting_configexecutable('pathtopdftoppm', new lang_string('pathtopdftoppm', 'admin'),
|
||||
new lang_string('pathtopdftoppm_help', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtopython', new lang_string('pathtopython', 'admin'),
|
||||
new lang_string('pathtopythondesc', 'admin'), ''));
|
||||
$ADMIN->add('server', $temp);
|
||||
// "systempaths" settingpage
|
||||
$temp = new admin_settingpage('systempaths', new lang_string('systempaths','admin'));
|
||||
$temp->add(new admin_setting_configexecutable('pathtophp', new lang_string('pathtophp', 'admin'),
|
||||
new lang_string('configpathtophp', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'), new lang_string('configpathtodu', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'), new lang_string('edhelpaspellpath'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'), new lang_string('pathtodot_help', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtogs', new lang_string('pathtogs', 'admin'), new lang_string('pathtogs_help', 'admin'), '/usr/bin/gs'));
|
||||
$temp->add(new admin_setting_configexecutable('pathtopython', new lang_string('pathtopython', 'admin'),
|
||||
new lang_string('pathtopythondesc', 'admin'), ''));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// Support contact.
|
||||
$temp = new admin_settingpage('supportcontact', new lang_string('supportcontact', 'admin'));
|
||||
$primaryadmin = get_admin();
|
||||
if ($primaryadmin) {
|
||||
$primaryadminemail = $primaryadmin->email;
|
||||
$primaryadminname = fullname($primaryadmin, true);
|
||||
} else {
|
||||
// No defaults during installation - admin user must be created first.
|
||||
$primaryadminemail = null;
|
||||
$primaryadminname = null;
|
||||
}
|
||||
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'),
|
||||
new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
|
||||
$setting = new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'),
|
||||
new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_EMAIL);
|
||||
$setting->set_force_ltr(true);
|
||||
$temp->add($setting);
|
||||
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'),
|
||||
new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// Session handling.
|
||||
$temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandling', 'admin'));
|
||||
if (empty($CFG->session_handler_class) and $DB->session_lock_supported()) {
|
||||
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'),
|
||||
new lang_string('configdbsessions', 'admin'), 0));
|
||||
}
|
||||
|
||||
$temp->add(new admin_setting_configduration('sessiontimeout', new lang_string('sessiontimeout', 'admin'),
|
||||
new lang_string('configsessiontimeout', 'admin'), 8 * 60 * 60));
|
||||
// "supportcontact" settingpage
|
||||
$temp = new admin_settingpage('supportcontact', new lang_string('supportcontact','admin'));
|
||||
$primaryadmin = get_admin();
|
||||
if ($primaryadmin) {
|
||||
$primaryadminemail = $primaryadmin->email;
|
||||
$primaryadminname = fullname($primaryadmin, true);
|
||||
} else {
|
||||
// no defaults during installation - admin user must be created first
|
||||
$primaryadminemail = NULL;
|
||||
$primaryadminname = NULL;
|
||||
}
|
||||
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'),
|
||||
new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
|
||||
$setting = new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'),
|
||||
new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_EMAIL);
|
||||
$setting->set_force_ltr(true);
|
||||
$temp->add($setting);
|
||||
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'), new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$sessiontimeoutwarning = new admin_setting_configduration('sessiontimeoutwarning',
|
||||
new lang_string('sessiontimeoutwarning', 'admin'),
|
||||
new lang_string('configsessiontimeoutwarning', 'admin'), 20 * 60);
|
||||
|
||||
$sessiontimeoutwarning->set_validate_function(function(int $value): string {
|
||||
global $CFG;
|
||||
// Check sessiontimeoutwarning is less than sessiontimeout.
|
||||
if ($CFG->sessiontimeout <= $value) {
|
||||
return get_string('configsessiontimeoutwarningcheck', 'admin');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
// "sessionhandling" settingpage
|
||||
$temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandling', 'admin'));
|
||||
if (empty($CFG->session_handler_class) and $DB->session_lock_supported()) {
|
||||
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'), new lang_string('configdbsessions', 'admin'), 0));
|
||||
}
|
||||
|
||||
$temp->add($sessiontimeoutwarning);
|
||||
$temp->add(new admin_setting_configduration('sessiontimeout', new lang_string('sessiontimeout', 'admin'),
|
||||
new lang_string('configsessiontimeout', 'admin'), 8 * 60 * 60));
|
||||
|
||||
$temp->add(new admin_setting_configtext('sessioncookie', new lang_string('sessioncookie', 'admin'),
|
||||
new lang_string('configsessioncookie', 'admin'), '', PARAM_ALPHANUM));
|
||||
$temp->add(new admin_setting_configtext('sessioncookiepath', new lang_string('sessioncookiepath', 'admin'),
|
||||
new lang_string('configsessioncookiepath', 'admin'), '', PARAM_RAW));
|
||||
$temp->add(new admin_setting_configtext('sessioncookiedomain', new lang_string('sessioncookiedomain', 'admin'),
|
||||
new lang_string('configsessioncookiedomain', 'admin'), '', PARAM_RAW, 50));
|
||||
$ADMIN->add('server', $temp);
|
||||
$temp->add(new admin_setting_configtext('sessioncookie', new lang_string('sessioncookie', 'admin'), new lang_string('configsessioncookie', 'admin'), '', PARAM_ALPHANUM));
|
||||
$temp->add(new admin_setting_configtext('sessioncookiepath', new lang_string('sessioncookiepath', 'admin'), new lang_string('configsessioncookiepath', 'admin'), '', PARAM_RAW));
|
||||
$temp->add(new admin_setting_configtext('sessioncookiedomain', new lang_string('sessioncookiedomain', 'admin'), new lang_string('configsessioncookiedomain', 'admin'), '', PARAM_RAW, 50));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// Statistics.
|
||||
$temp = new admin_settingpage('stats', new lang_string('stats'), 'moodle/site:config', empty($CFG->enablestats));
|
||||
$temp->add(new admin_setting_configselect('statsfirstrun', new lang_string('statsfirstrun', 'admin'),
|
||||
new lang_string('configstatsfirstrun', 'admin'), 'none',
|
||||
[
|
||||
'none' => new lang_string('none'),
|
||||
60 * 60 * 24 * 7 => new lang_string('numweeks', 'moodle', 1),
|
||||
60 * 60 * 24 * 14 => new lang_string('numweeks', 'moodle', 2),
|
||||
60 * 60 * 24 * 21 => new lang_string('numweeks', 'moodle', 3),
|
||||
60 * 60 * 24 * 28 => new lang_string('nummonths', 'moodle', 1),
|
||||
60 * 60 * 24 * 56 => new lang_string('nummonths', 'moodle', 2),
|
||||
60 * 60 * 24 * 84 => new lang_string('nummonths', 'moodle', 3),
|
||||
60 * 60 * 24 * 112 => new lang_string('nummonths', 'moodle', 4),
|
||||
60 * 60 * 24 * 140 => new lang_string('nummonths', 'moodle', 5),
|
||||
60 * 60 * 24 * 168 => new lang_string('nummonths', 'moodle', 6),
|
||||
'all' => new lang_string('all')
|
||||
]
|
||||
));
|
||||
$temp->add(new admin_setting_configselect('statsmaxruntime', new lang_string('statsmaxruntime', 'admin'),
|
||||
new lang_string('configstatsmaxruntime3', 'admin'), 0,
|
||||
[
|
||||
0 => new lang_string('untilcomplete'),
|
||||
60 * 30 => '10 ' . new lang_string('minutes'),
|
||||
60 * 30 => '30 ' . new lang_string('minutes'),
|
||||
60 * 60 => '1 ' . new lang_string('hour'),
|
||||
60 * 60 * 2 => '2 ' . new lang_string('hours'),
|
||||
60 * 60 * 3 => '3 ' . new lang_string('hours'),
|
||||
60 * 60 * 4 => '4 ' . new lang_string('hours'),
|
||||
60 * 60 * 5 => '5 ' . new lang_string('hours'),
|
||||
60 * 60 * 6 => '6 ' . new lang_string('hours'),
|
||||
60 * 60 * 7 => '7 ' . new lang_string('hours'),
|
||||
60 * 60 * 8 => '8 ' . new lang_string('hours'),
|
||||
]
|
||||
));
|
||||
$temp->add(new admin_setting_configtext('statsruntimedays', new lang_string('statsruntimedays', 'admin'),
|
||||
new lang_string('configstatsruntimedays', 'admin'), 31, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('statsuserthreshold', new lang_string('statsuserthreshold', 'admin'),
|
||||
new lang_string('configstatsuserthreshold', 'admin'), 0, PARAM_INT));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// HTTP.
|
||||
$temp = new admin_settingpage('http', new lang_string('http', 'admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('slasharguments', new lang_string('slasharguments', 'admin'),
|
||||
new lang_string('configslasharguments', 'admin'), 1));
|
||||
$temp->add(new admin_setting_heading('reverseproxy', new lang_string('reverseproxy', 'admin'), '', ''));
|
||||
$options = [
|
||||
0 => 'HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR => 'HTTP_CLIENT, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR | GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'REMOTE_ADDR'
|
||||
];
|
||||
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'),
|
||||
new lang_string('configgetremoteaddrconf', 'admin'),
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR | GETREMOTEADDR_SKIP_HTTP_CLIENT_IP, $options));
|
||||
$temp->add(new admin_setting_configtext('reverseproxyignore', new lang_string('reverseproxyignore', 'admin'),
|
||||
new lang_string('configreverseproxyignore', 'admin'), ''));
|
||||
// "stats" settingpage
|
||||
$temp = new admin_settingpage('stats', new lang_string('stats'), 'moodle/site:config', empty($CFG->enablestats));
|
||||
$temp->add(new admin_setting_configselect('statsfirstrun', new lang_string('statsfirstrun', 'admin'), new lang_string('configstatsfirstrun', 'admin'), 'none', array('none' => new lang_string('none'),
|
||||
60*60*24*7 => new lang_string('numweeks','moodle',1),
|
||||
60*60*24*14 => new lang_string('numweeks','moodle',2),
|
||||
60*60*24*21 => new lang_string('numweeks','moodle',3),
|
||||
60*60*24*28 => new lang_string('nummonths','moodle',1),
|
||||
60*60*24*56 => new lang_string('nummonths','moodle',2),
|
||||
60*60*24*84 => new lang_string('nummonths','moodle',3),
|
||||
60*60*24*112 => new lang_string('nummonths','moodle',4),
|
||||
60*60*24*140 => new lang_string('nummonths','moodle',5),
|
||||
60*60*24*168 => new lang_string('nummonths','moodle',6),
|
||||
'all' => new lang_string('all') )));
|
||||
$temp->add(new admin_setting_configselect('statsmaxruntime', new lang_string('statsmaxruntime', 'admin'), new lang_string('configstatsmaxruntime3', 'admin'), 0, array(0 => new lang_string('untilcomplete'),
|
||||
60*30 => '10 '.new lang_string('minutes'),
|
||||
60*30 => '30 '.new lang_string('minutes'),
|
||||
60*60 => '1 '.new lang_string('hour'),
|
||||
60*60*2 => '2 '.new lang_string('hours'),
|
||||
60*60*3 => '3 '.new lang_string('hours'),
|
||||
60*60*4 => '4 '.new lang_string('hours'),
|
||||
60*60*5 => '5 '.new lang_string('hours'),
|
||||
60*60*6 => '6 '.new lang_string('hours'),
|
||||
60*60*7 => '7 '.new lang_string('hours'),
|
||||
60*60*8 => '8 '.new lang_string('hours') )));
|
||||
$temp->add(new admin_setting_configtext('statsruntimedays', new lang_string('statsruntimedays', 'admin'), new lang_string('configstatsruntimedays', 'admin'), 31, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('statsuserthreshold', new lang_string('statsuserthreshold', 'admin'), new lang_string('configstatsuserthreshold', 'admin'), 0, PARAM_INT));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp->add(new admin_setting_heading('webproxy', new lang_string('webproxy', 'admin'),
|
||||
new lang_string('webproxyinfo', 'admin')));
|
||||
$temp->add(new admin_setting_configtext('proxyhost', new lang_string('proxyhost', 'admin'),
|
||||
new lang_string('configproxyhost', 'admin'), '', PARAM_HOST));
|
||||
$temp->add(new admin_setting_configtext('proxyport', new lang_string('proxyport', 'admin'),
|
||||
new lang_string('configproxyport', 'admin'), 0, PARAM_INT));
|
||||
$options = ['HTTP' => 'HTTP'];
|
||||
if (defined('CURLPROXY_SOCKS5')) {
|
||||
$options['SOCKS5'] = 'SOCKS5';
|
||||
}
|
||||
$temp->add(new admin_setting_configselect('proxytype', new lang_string('proxytype', 'admin'),
|
||||
new lang_string('configproxytype', 'admin'), 'HTTP', $options));
|
||||
$temp->add(new admin_setting_configtext('proxyuser', new lang_string('proxyuser', 'admin'),
|
||||
new lang_string('configproxyuser', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configpasswordunmask('proxypassword', new lang_string('proxypassword', 'admin'),
|
||||
new lang_string('configproxypassword', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'),
|
||||
new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp = new admin_settingpage('maintenancemode', new lang_string('sitemaintenancemode', 'admin'));
|
||||
$options = [0 => new lang_string('disable'), 1 => new lang_string('enable')];
|
||||
$temp->add(new admin_setting_configselect('maintenance_enabled', new lang_string('sitemaintenancemode', 'admin'),
|
||||
new lang_string('helpsitemaintenance', 'admin'), 0, $options));
|
||||
$temp->add(new admin_setting_confightmleditor('maintenance_message', new lang_string('optionalmaintenancemessage', 'admin'),
|
||||
'', ''));
|
||||
$ADMIN->add('server', $temp);
|
||||
// "http" settingpage
|
||||
$temp = new admin_settingpage('http', new lang_string('http', 'admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('slasharguments', new lang_string('slasharguments', 'admin'), new lang_string('configslasharguments', 'admin'), 1));
|
||||
$temp->add(new admin_setting_heading('reverseproxy', new lang_string('reverseproxy', 'admin'), '', ''));
|
||||
$options = array(
|
||||
0 => 'HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR => 'HTTP_CLIENT, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR|GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'REMOTE_ADDR');
|
||||
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'),
|
||||
new lang_string('configgetremoteaddrconf', 'admin'),
|
||||
GETREMOTEADDR_SKIP_DEFAULT, $options));
|
||||
$temp->add(new admin_setting_configtext('reverseproxyignore', new lang_string('reverseproxyignore', 'admin'), new lang_string('configreverseproxyignore', 'admin'), ''));
|
||||
|
||||
// Cleanup.
|
||||
$temp = new admin_settingpage('cleanup', new lang_string('cleanup', 'admin'));
|
||||
$temp->add(new admin_setting_configselect('deleteunconfirmed', new lang_string('deleteunconfirmed', 'admin'),
|
||||
new lang_string('configdeleteunconfirmed', 'admin'), 168,
|
||||
[
|
||||
0 => new lang_string('never'),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
144 => new lang_string('numdays', '', 6),
|
||||
120 => new lang_string('numdays', '', 5),
|
||||
96 => new lang_string('numdays', '', 4),
|
||||
72 => new lang_string('numdays', '', 3),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
24 => new lang_string('numdays', '', 1),
|
||||
12 => new lang_string('numhours', '', 12),
|
||||
6 => new lang_string('numhours', '', 6),
|
||||
1 => new lang_string('numhours', '', 1),
|
||||
]
|
||||
));
|
||||
$temp->add(new admin_setting_heading('webproxy', new lang_string('webproxy', 'admin'), new lang_string('webproxyinfo', 'admin')));
|
||||
$temp->add(new admin_setting_configtext('proxyhost', new lang_string('proxyhost', 'admin'), new lang_string('configproxyhost', 'admin'), '', PARAM_HOST));
|
||||
$temp->add(new admin_setting_configtext('proxyport', new lang_string('proxyport', 'admin'), new lang_string('configproxyport', 'admin'), 0, PARAM_INT));
|
||||
$options = array('HTTP'=>'HTTP');
|
||||
if (defined('CURLPROXY_SOCKS5')) {
|
||||
$options['SOCKS5'] = 'SOCKS5';
|
||||
}
|
||||
$temp->add(new admin_setting_configselect('proxytype', new lang_string('proxytype', 'admin'), new lang_string('configproxytype','admin'), 'HTTP', $options));
|
||||
$temp->add(new admin_setting_configtext('proxyuser', new lang_string('proxyuser', 'admin'), new lang_string('configproxyuser', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configpasswordunmask('proxypassword', new lang_string('proxypassword', 'admin'), new lang_string('configproxypassword', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'), new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp->add(new admin_setting_configselect('deleteincompleteusers', new lang_string('deleteincompleteusers', 'admin'),
|
||||
new lang_string('configdeleteincompleteusers', 'admin'), 0,
|
||||
[
|
||||
0 => new lang_string('never'),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
144 => new lang_string('numdays', '', 6),
|
||||
120 => new lang_string('numdays', '', 5),
|
||||
96 => new lang_string('numdays', '', 4),
|
||||
72 => new lang_string('numdays', '', 3),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
24 => new lang_string('numdays', '', 1),
|
||||
]
|
||||
));
|
||||
$temp = new admin_settingpage('maintenancemode', new lang_string('sitemaintenancemode', 'admin'));
|
||||
$options = array(0=>new lang_string('disable'), 1=>new lang_string('enable'));
|
||||
$temp->add(new admin_setting_configselect('maintenance_enabled', new lang_string('sitemaintenancemode', 'admin'),
|
||||
new lang_string('helpsitemaintenance', 'admin'), 0, $options));
|
||||
$temp->add(new admin_setting_confightmleditor('maintenance_message', new lang_string('optionalmaintenancemessage', 'admin'),
|
||||
'', ''));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('disablegradehistory', new lang_string('disablegradehistory', 'grades'),
|
||||
new lang_string('disablegradehistory_help', 'grades'), 0));
|
||||
$temp = new admin_settingpage('cleanup', new lang_string('cleanup', 'admin'));
|
||||
$temp->add(new admin_setting_configselect('deleteunconfirmed', new lang_string('deleteunconfirmed', 'admin'), new lang_string('configdeleteunconfirmed', 'admin'), 168, array(0 => new lang_string('never'),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
144 => new lang_string('numdays', '', 6),
|
||||
120 => new lang_string('numdays', '', 5),
|
||||
96 => new lang_string('numdays', '', 4),
|
||||
72 => new lang_string('numdays', '', 3),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
24 => new lang_string('numdays', '', 1),
|
||||
12 => new lang_string('numhours', '', 12),
|
||||
6 => new lang_string('numhours', '', 6),
|
||||
1 => new lang_string('numhours', '', 1))));
|
||||
|
||||
$temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_string('gradehistorylifetime', 'grades'),
|
||||
new lang_string('gradehistorylifetime_help', 'grades'), 0,
|
||||
[
|
||||
0 => new lang_string('neverdeletehistory', 'grades'),
|
||||
1000 => new lang_string('numdays', '', 1000),
|
||||
365 => new lang_string('numdays', '', 365),
|
||||
180 => new lang_string('numdays', '', 180),
|
||||
150 => new lang_string('numdays', '', 150),
|
||||
120 => new lang_string('numdays', '', 120),
|
||||
90 => new lang_string('numdays', '', 90),
|
||||
60 => new lang_string('numdays', '', 60),
|
||||
30 => new lang_string('numdays', '', 30),
|
||||
]
|
||||
));
|
||||
$temp->add(new admin_setting_configselect('deleteincompleteusers', new lang_string('deleteincompleteusers', 'admin'), new lang_string('configdeleteincompleteusers', 'admin'), 0, array(0 => new lang_string('never'),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
144 => new lang_string('numdays', '', 6),
|
||||
120 => new lang_string('numdays', '', 5),
|
||||
96 => new lang_string('numdays', '', 4),
|
||||
72 => new lang_string('numdays', '', 3),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
24 => new lang_string('numdays', '', 1))));
|
||||
|
||||
$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'),
|
||||
new lang_string('configtempdatafoldercleanup', 'admin'), 168,
|
||||
[
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('disablegradehistory', new lang_string('disablegradehistory', 'grades'),
|
||||
new lang_string('disablegradehistory_help', 'grades'), 0));
|
||||
|
||||
$temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_string('gradehistorylifetime', 'grades'),
|
||||
new lang_string('gradehistorylifetime_help', 'grades'), 0, array(0 => new lang_string('neverdeletehistory', 'grades'),
|
||||
1000 => new lang_string('numdays', '', 1000),
|
||||
365 => new lang_string('numdays', '', 365),
|
||||
180 => new lang_string('numdays', '', 180),
|
||||
150 => new lang_string('numdays', '', 150),
|
||||
120 => new lang_string('numdays', '', 120),
|
||||
90 => new lang_string('numdays', '', 90),
|
||||
60 => new lang_string('numdays', '', 60),
|
||||
30 => new lang_string('numdays', '', 30))));
|
||||
|
||||
$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'),
|
||||
new lang_string('configtempdatafoldercleanup', 'admin'), 168, array(
|
||||
1 => new lang_string('numhours', '', 1),
|
||||
3 => new lang_string('numhours', '', 3),
|
||||
6 => new lang_string('numhours', '', 6),
|
||||
@@ -247,366 +166,224 @@ if ($hassiteconfig) {
|
||||
24 => new lang_string('numhours', '', 24),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
]
|
||||
));
|
||||
)));
|
||||
|
||||
$ADMIN->add('server', $temp);
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp->add(new admin_setting_configduration('filescleanupperiod',
|
||||
new lang_string('filescleanupperiod', 'admin'),
|
||||
new lang_string('filescleanupperiod_help', 'admin'),
|
||||
86400));
|
||||
|
||||
// Environment.
|
||||
$ADMIN->add('server', new admin_externalpage('environment', new lang_string('environment', 'admin'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/environment.php"));
|
||||
$ADMIN->add('server', new admin_externalpage('environment', new lang_string('environment','admin'), "$CFG->wwwroot/$CFG->admin/environment.php"));
|
||||
$ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo'), "$CFG->wwwroot/$CFG->admin/phpinfo.php"));
|
||||
$ADMIN->add('server', new admin_externalpage('testoutgoingmailconf', new lang_string('testoutgoingmailconf', 'admin'),
|
||||
new moodle_url("$CFG->wwwroot/$CFG->admin/testoutgoingmailconf.php"), 'moodle/site:config', true));
|
||||
|
||||
// PHP info.
|
||||
$ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/phpinfo.php"));
|
||||
|
||||
// Test outgoing mail configuration (hidden, accessed via direct link from the settings page).
|
||||
$ADMIN->add('server', new admin_externalpage('testoutgoingmailconf', new lang_string('testoutgoingmailconf', 'admin'),
|
||||
new moodle_url('/admin/testoutgoingmailconf.php'), 'moodle/site:config', true));
|
||||
// "performance" settingpage
|
||||
$temp = new admin_settingpage('performance', new lang_string('performance', 'admin'));
|
||||
|
||||
// Performance.
|
||||
$temp = new admin_settingpage('performance', new lang_string('performance', 'admin'));
|
||||
// Memory limit options for large administration tasks.
|
||||
$memoryoptions = array(
|
||||
'64M' => '64M',
|
||||
'128M' => '128M',
|
||||
'256M' => '256M',
|
||||
'512M' => '512M',
|
||||
'1024M' => '1024M',
|
||||
'2048M' => '2048M');
|
||||
|
||||
// Memory limit options for large administration tasks.
|
||||
$memoryoptions = [
|
||||
'64M' => '64M',
|
||||
'128M' => '128M',
|
||||
'256M' => '256M',
|
||||
'512M' => '512M',
|
||||
'1024M' => '1024M',
|
||||
'2048M' => '2048M',
|
||||
];
|
||||
// Allow larger memory usage for 64-bit sites only.
|
||||
if (PHP_INT_SIZE === 8) {
|
||||
$memoryoptions['3072M'] = '3072M';
|
||||
$memoryoptions['4096M'] = '4096M';
|
||||
}
|
||||
|
||||
// Allow larger memory usage for 64-bit sites only.
|
||||
if (PHP_INT_SIZE === 8) {
|
||||
$memoryoptions['3072M'] = '3072M';
|
||||
$memoryoptions['4096M'] = '4096M';
|
||||
}
|
||||
|
||||
$temp->add(new admin_setting_configselect('extramemorylimit', new lang_string('extramemorylimit', 'admin'),
|
||||
new lang_string('configextramemorylimit', 'admin'), '512M', $memoryoptions));
|
||||
|
||||
$temp->add(new admin_setting_configtext('maxtimelimit', new lang_string('maxtimelimit', 'admin'),
|
||||
$temp->add(new admin_setting_configselect('extramemorylimit', new lang_string('extramemorylimit', 'admin'),
|
||||
new lang_string('configextramemorylimit', 'admin'), '512M',
|
||||
$memoryoptions));
|
||||
$temp->add(new admin_setting_configtext('maxtimelimit', new lang_string('maxtimelimit', 'admin'),
|
||||
new lang_string('maxtimelimit_desc', 'admin'), 0, PARAM_INT));
|
||||
|
||||
$temp->add(new admin_setting_configtext('curlcache', new lang_string('curlcache', 'admin'),
|
||||
new lang_string('configcurlcache', 'admin'), 120, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('curlcache', new lang_string('curlcache', 'admin'),
|
||||
new lang_string('configcurlcache', 'admin'), 120, PARAM_INT));
|
||||
|
||||
$temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('curltimeoutkbitrate', 'admin'),
|
||||
new lang_string('curltimeoutkbitrate_help', 'admin'), 56, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('curltimeoutkbitrate', 'admin'),
|
||||
new lang_string('curltimeoutkbitrate_help', 'admin'), 56, PARAM_INT));
|
||||
|
||||
$ADMIN->add('server', $temp);
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// Tasks.
|
||||
$ADMIN->add('server', new admin_category('taskconfig', new lang_string('taskadmintitle', 'admin')));
|
||||
|
||||
// Task processing.
|
||||
$temp = new admin_settingpage('taskprocessing', new lang_string('taskprocessing', 'admin'));
|
||||
$ADMIN->add('server', new admin_category('taskconfig', new lang_string('taskadmintitle', 'admin')));
|
||||
$temp = new admin_settingpage('taskprocessing', new lang_string('taskprocessing','admin'));
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_scheduled_concurrency_limit',
|
||||
new lang_string('task_scheduled_concurrency_limit', 'admin'),
|
||||
new lang_string('task_scheduled_concurrency_limit_desc', 'admin'),
|
||||
3,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
|
||||
$setting = new admin_setting_configcheckbox(
|
||||
'cron_enabled',
|
||||
new lang_string('cron_enabled', 'admin'),
|
||||
new lang_string('cron_enabled_desc', 'admin'),
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_scheduled_max_runtime',
|
||||
new lang_string('task_scheduled_max_runtime', 'admin'),
|
||||
new lang_string('task_scheduled_max_runtime_desc', 'admin'),
|
||||
30 * MINSECS
|
||||
)
|
||||
);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_adhoc_concurrency_limit',
|
||||
new lang_string('task_adhoc_concurrency_limit', 'admin'),
|
||||
new lang_string('task_adhoc_concurrency_limit_desc', 'admin'),
|
||||
3,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_adhoc_max_runtime',
|
||||
new lang_string('task_adhoc_max_runtime', 'admin'),
|
||||
new lang_string('task_adhoc_max_runtime_desc', 'admin'),
|
||||
30 * MINSECS
|
||||
)
|
||||
);
|
||||
$ADMIN->add('taskconfig', $temp);
|
||||
|
||||
$temp = new admin_settingpage('tasklogging', new lang_string('tasklogging','admin'));
|
||||
$temp->add(
|
||||
new admin_setting_configselect(
|
||||
'task_logmode',
|
||||
new lang_string('task_logmode', 'admin'),
|
||||
new lang_string('task_logmode_desc', 'admin'),
|
||||
\core\task\logmanager::MODE_ALL,
|
||||
[
|
||||
\core\task\logmanager::MODE_ALL => new lang_string('task_logmode_all', 'admin'),
|
||||
\core\task\logmanager::MODE_FAILONLY => new lang_string('task_logmode_failonly', 'admin'),
|
||||
\core\task\logmanager::MODE_NONE => new lang_string('task_logmode_none', 'admin'),
|
||||
]
|
||||
)
|
||||
);
|
||||
$temp->add(
|
||||
new admin_setting_configcheckbox(
|
||||
'task_logtostdout',
|
||||
new lang_string('task_logtostdout', 'admin'),
|
||||
new lang_string('task_logtostdout_desc', 'admin'),
|
||||
1
|
||||
);
|
||||
$setting->set_updatedcallback('theme_reset_static_caches');
|
||||
$temp->add($setting);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_scheduled_concurrency_limit',
|
||||
new lang_string('task_scheduled_concurrency_limit', 'admin'),
|
||||
new lang_string('task_scheduled_concurrency_limit_desc', 'admin'),
|
||||
3,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
if (\core\task\logmanager::uses_standard_settings()) {
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_scheduled_max_runtime',
|
||||
new lang_string('task_scheduled_max_runtime', 'admin'),
|
||||
new lang_string('task_scheduled_max_runtime_desc', 'admin'),
|
||||
30 * MINSECS
|
||||
'task_logretention',
|
||||
new \lang_string('task_logretention', 'admin'),
|
||||
new \lang_string('task_logretention_desc', 'admin'),
|
||||
28 * DAYSECS
|
||||
)
|
||||
);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_adhoc_concurrency_limit',
|
||||
new lang_string('task_adhoc_concurrency_limit', 'admin'),
|
||||
new lang_string('task_adhoc_concurrency_limit_desc', 'admin'),
|
||||
3,
|
||||
'task_logretainruns',
|
||||
new \lang_string('task_logretainruns', 'admin'),
|
||||
new \lang_string('task_logretainruns_desc', 'admin'),
|
||||
20,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
}
|
||||
$ADMIN->add('taskconfig', $temp);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_adhoc_max_runtime',
|
||||
new lang_string('task_adhoc_max_runtime', 'admin'),
|
||||
new lang_string('task_adhoc_max_runtime_desc', 'admin'),
|
||||
30 * MINSECS
|
||||
)
|
||||
);
|
||||
$ADMIN->add('taskconfig', $temp);
|
||||
if (\core\task\logmanager::uses_standard_settings()) {
|
||||
$ADMIN->add('taskconfig', new admin_externalpage(
|
||||
'tasklogs',
|
||||
new lang_string('tasklogs','admin'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/tasklogs.php"
|
||||
));
|
||||
}
|
||||
|
||||
// Task log configuration.
|
||||
$temp = new admin_settingpage('tasklogging', new lang_string('tasklogging', 'admin'));
|
||||
$temp->add(
|
||||
new admin_setting_configselect(
|
||||
'task_logmode',
|
||||
new lang_string('task_logmode', 'admin'),
|
||||
new lang_string('task_logmode_desc', 'admin'),
|
||||
\core\task\logmanager::MODE_ALL,
|
||||
[
|
||||
\core\task\logmanager::MODE_ALL => new lang_string('task_logmode_all', 'admin'),
|
||||
\core\task\logmanager::MODE_FAILONLY => new lang_string('task_logmode_failonly', 'admin'),
|
||||
\core\task\logmanager::MODE_NONE => new lang_string('task_logmode_none', 'admin'),
|
||||
]
|
||||
)
|
||||
);
|
||||
$temp->add(
|
||||
new admin_setting_configcheckbox(
|
||||
'task_logtostdout',
|
||||
new lang_string('task_logtostdout', 'admin'),
|
||||
new lang_string('task_logtostdout_desc', 'admin'),
|
||||
1
|
||||
)
|
||||
);
|
||||
// E-mail settings.
|
||||
$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
|
||||
|
||||
if (\core\task\logmanager::uses_standard_settings()) {
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_logretention',
|
||||
new \lang_string('task_logretention', 'admin'),
|
||||
new \lang_string('task_logretention_desc', 'admin'),
|
||||
28 * DAYSECS
|
||||
)
|
||||
);
|
||||
$temp = new admin_settingpage('outgoingmailconfig', new lang_string('outgoingmailconfig', 'admin'));
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_logretainruns',
|
||||
new \lang_string('task_logretainruns', 'admin'),
|
||||
new \lang_string('task_logretainruns_desc', 'admin'),
|
||||
20,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
}
|
||||
$ADMIN->add('taskconfig', $temp);
|
||||
|
||||
// Task logs.
|
||||
if (\core\task\logmanager::uses_standard_settings()) {
|
||||
$ADMIN->add('taskconfig', new admin_externalpage(
|
||||
'tasklogs',
|
||||
new lang_string('tasklogs', 'admin'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/tasklogs.php"
|
||||
));
|
||||
}
|
||||
|
||||
// Email.
|
||||
$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
|
||||
|
||||
// Outgoing mail configuration.
|
||||
$temp = new admin_settingpage('outgoingmailconfig', new lang_string('outgoingmailconfig', 'admin'));
|
||||
|
||||
$temp->add(new admin_setting_heading('smtpheading', new lang_string('smtp', 'admin'),
|
||||
new lang_string('smtpdetail', 'admin')));
|
||||
|
||||
$temp->add(new admin_setting_configtext('smtphosts', new lang_string('smtphosts', 'admin'),
|
||||
new lang_string('configsmtphosts', 'admin'), '', PARAM_RAW));
|
||||
|
||||
$options = [
|
||||
'' => new lang_string('none', 'admin'),
|
||||
'ssl' => 'SSL',
|
||||
'tls' => 'TLS',
|
||||
];
|
||||
|
||||
$temp->add(new admin_setting_configselect('smtpsecure', new lang_string('smtpsecure', 'admin'),
|
||||
new lang_string('configsmtpsecure', 'admin'), '', $options));
|
||||
|
||||
$authtypeoptions = [
|
||||
'LOGIN' => 'LOGIN',
|
||||
'PLAIN' => 'PLAIN',
|
||||
'NTLM' => 'NTLM',
|
||||
'CRAM-MD5' => 'CRAM-MD5',
|
||||
];
|
||||
|
||||
$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
|
||||
new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));
|
||||
|
||||
$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
|
||||
new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));
|
||||
|
||||
$temp->add(new admin_setting_configpasswordunmask('smtppass', new lang_string('smtppass', 'admin'),
|
||||
new lang_string('configsmtpuser', 'admin'), ''));
|
||||
|
||||
$temp->add(new admin_setting_configtext('smtpmaxbulk', new lang_string('smtpmaxbulk', 'admin'),
|
||||
new lang_string('configsmtpmaxbulk', 'admin'), 1, PARAM_INT));
|
||||
|
||||
$temp->add(new admin_setting_heading('noreplydomainheading', new lang_string('noreplydomain', 'admin'),
|
||||
$temp->add(new admin_setting_heading('smtpheading', new lang_string('smtp', 'admin'),
|
||||
new lang_string('smtpdetail', 'admin')));
|
||||
$temp->add(new admin_setting_configtext('smtphosts', new lang_string('smtphosts', 'admin'),
|
||||
new lang_string('configsmtphosts', 'admin'), '', PARAM_RAW));
|
||||
$options = array('' => new lang_string('none', 'admin'), 'ssl' => 'SSL', 'tls' => 'TLS');
|
||||
$temp->add(new admin_setting_configselect('smtpsecure', new lang_string('smtpsecure', 'admin'),
|
||||
new lang_string('configsmtpsecure', 'admin'), '', $options));
|
||||
$authtypeoptions = array('LOGIN' => 'LOGIN', 'PLAIN' => 'PLAIN', 'NTLM' => 'NTLM', 'CRAM-MD5' => 'CRAM-MD5');
|
||||
$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
|
||||
new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));
|
||||
$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
|
||||
new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));
|
||||
$temp->add(new admin_setting_configpasswordunmask('smtppass', new lang_string('smtppass', 'admin'),
|
||||
new lang_string('configsmtpuser', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configtext('smtpmaxbulk', new lang_string('smtpmaxbulk', 'admin'),
|
||||
new lang_string('configsmtpmaxbulk', 'admin'), 1, PARAM_INT));
|
||||
$temp->add(new admin_setting_heading('noreplydomainheading', new lang_string('noreplydomain', 'admin'),
|
||||
new lang_string('noreplydomaindetail', 'admin')));
|
||||
|
||||
$temp->add(new admin_setting_configtext('noreplyaddress', new lang_string('noreplyaddress', 'admin'),
|
||||
new lang_string('confignoreplyaddress', 'admin'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_EMAIL));
|
||||
|
||||
$temp->add(new admin_setting_configtextarea('allowedemaildomains',
|
||||
$temp->add(new admin_setting_configtext('noreplyaddress', new lang_string('noreplyaddress', 'admin'),
|
||||
new lang_string('confignoreplyaddress', 'admin'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_EMAIL));
|
||||
$temp->add(new admin_setting_configtextarea('allowedemaildomains',
|
||||
new lang_string('allowedemaildomains', 'admin'),
|
||||
new lang_string('configallowedemaildomains', 'admin'),
|
||||
''));
|
||||
|
||||
$temp->add(new admin_setting_heading('divertallemailsheading', new lang_string('divertallemails', 'admin'),
|
||||
new lang_string('divertallemailsdetail', 'admin')));
|
||||
$temp->add(new admin_setting_configtext('divertallemailsto',
|
||||
new lang_string('divertallemailsto', 'admin'),
|
||||
new lang_string('divertallemailsto_desc', 'admin'),
|
||||
''));
|
||||
$temp->add(new admin_setting_configtextarea('divertallemailsexcept',
|
||||
new lang_string('divertallemailsexcept', 'admin'),
|
||||
new lang_string('divertallemailsexcept_desc', 'admin'),
|
||||
'', PARAM_RAW, '50', '4'));
|
||||
|
||||
$noreplyaddress = isset($CFG->noreplyaddress) ? $CFG->noreplyaddress : 'noreply@example.com';
|
||||
$dkimdomain = substr(strrchr($noreplyaddress, "@"), 1);
|
||||
$dkimselector = empty($CFG->emaildkimselector) ? '[selector]' : $CFG->emaildkimselector;
|
||||
$pempath = "\$CFG->dataroot/dkim/{$dkimdomain}/{$dkimselector}.private";
|
||||
$temp->add(new admin_setting_heading('emaildkim', new lang_string('emaildkim', 'admin'),
|
||||
new lang_string('emaildkiminfo', 'admin', ['path' => $pempath, 'docs' => \get_docs_url('Mail_configuration#DKIM')])));
|
||||
$temp->add(new admin_setting_configtext('emaildkimselector', new lang_string('emaildkimselector', 'admin'),
|
||||
new lang_string('configemaildkimselector', 'admin'), '', PARAM_FILE));
|
||||
|
||||
$url = new moodle_url('/admin/testoutgoingmailconf.php');
|
||||
$link = html_writer::link($url, get_string('testoutgoingmailconf', 'admin'));
|
||||
$temp->add(new admin_setting_heading('testoutgoinmailc', new lang_string('testoutgoingmailconf', 'admin'),
|
||||
$url = new moodle_url('/admin/testoutgoingmailconf.php');
|
||||
$link = html_writer::link($url, get_string('testoutgoingmailconf', 'admin'));
|
||||
$temp->add(new admin_setting_heading('testoutgoinmailc', new lang_string('testoutgoingmailconf', 'admin'),
|
||||
new lang_string('testoutgoingmaildetail', 'admin', $link)));
|
||||
|
||||
$temp->add(new admin_setting_heading('emaildoesnotfit', new lang_string('doesnotfit', 'admin'),
|
||||
$temp->add(new admin_setting_heading('emaildoesnotfit', new lang_string('doesnotfit', 'admin'),
|
||||
new lang_string('doesnotfitdetail', 'admin')));
|
||||
$charsets = get_list_of_charsets();
|
||||
unset($charsets['UTF-8']); // Not needed here.
|
||||
$options = array();
|
||||
$options['0'] = 'UTF-8';
|
||||
$options = array_merge($options, $charsets);
|
||||
$temp->add(new admin_setting_configselect('sitemailcharset', new lang_string('sitemailcharset', 'admin'),
|
||||
new lang_string('configsitemailcharset','admin'), '0', $options));
|
||||
$temp->add(new admin_setting_configcheckbox('allowusermailcharset', new lang_string('allowusermailcharset', 'admin'),
|
||||
new lang_string('configallowusermailcharset', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowattachments', new lang_string('allowattachments', 'admin'),
|
||||
new lang_string('configallowattachments', 'admin'), 1));
|
||||
$options = array('LF' => 'LF', 'CRLF' => 'CRLF');
|
||||
$temp->add(new admin_setting_configselect('mailnewline', new lang_string('mailnewline', 'admin'),
|
||||
new lang_string('configmailnewline', 'admin'), 'LF', $options));
|
||||
|
||||
$charsets = get_list_of_charsets();
|
||||
unset($charsets['UTF-8']);
|
||||
$options = [
|
||||
'0' => 'UTF-8',
|
||||
];
|
||||
$options = array_merge($options, $charsets);
|
||||
$temp->add(new admin_setting_configselect('sitemailcharset', new lang_string('sitemailcharset', 'admin'),
|
||||
new lang_string('configsitemailcharset', 'admin'), '0', $options));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('allowusermailcharset', new lang_string('allowusermailcharset', 'admin'),
|
||||
new lang_string('configallowusermailcharset', 'admin'), 0));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('allowattachments', new lang_string('allowattachments', 'admin'),
|
||||
new lang_string('configallowattachments', 'admin'), 1));
|
||||
|
||||
$options = [
|
||||
'LF' => 'LF',
|
||||
'CRLF' => 'CRLF',
|
||||
];
|
||||
$temp->add(new admin_setting_configselect('mailnewline', new lang_string('mailnewline', 'admin'),
|
||||
new lang_string('configmailnewline', 'admin'), 'LF', $options));
|
||||
|
||||
$choices = [
|
||||
new lang_string('never', 'admin'),
|
||||
new lang_string('always', 'admin'),
|
||||
new lang_string('onlynoreply', 'admin'),
|
||||
];
|
||||
$temp->add(new admin_setting_configselect('emailfromvia', new lang_string('emailfromvia', 'admin'),
|
||||
new lang_string('configemailfromvia', 'admin'), 1, $choices));
|
||||
|
||||
$choices = array(new lang_string('never', 'admin'),
|
||||
new lang_string('always', 'admin'),
|
||||
new lang_string('onlynoreply', 'admin'));
|
||||
$temp->add(new admin_setting_configselect('emailfromvia', new lang_string('emailfromvia', 'admin'),
|
||||
new lang_string('configemailfromvia', 'admin'), 1, $choices));
|
||||
$temp->add(new admin_setting_configtext('emailsubjectprefix', new lang_string('emailsubjectprefix', 'admin'),
|
||||
new lang_string('configemailsubjectprefix', 'admin'), '', PARAM_RAW));
|
||||
|
||||
$temp->add(new admin_setting_configtextarea('emailheaders', new lang_string('emailheaders', 'admin'),
|
||||
new lang_string('configemailheaders', 'admin'), '', PARAM_RAW, '50', '3'));
|
||||
$ADMIN->add('email', $temp);
|
||||
|
||||
$ADMIN->add('email', $temp);
|
||||
|
||||
// Update notifications.
|
||||
if (empty($CFG->disableupdatenotifications)) {
|
||||
$temp = new admin_settingpage('updatenotifications', new lang_string('updatenotifications', 'core_admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('updateautocheck', new lang_string('updateautocheck', 'core_admin'),
|
||||
new lang_string('updateautocheck_desc', 'core_admin'), 1));
|
||||
$temp->add(new admin_setting_configselect('updateminmaturity', new lang_string('updateminmaturity', 'core_admin'),
|
||||
new lang_string('updateminmaturity_desc', 'core_admin'), MATURITY_STABLE,
|
||||
[
|
||||
MATURITY_ALPHA => new lang_string('maturity'.MATURITY_ALPHA, 'core_admin'),
|
||||
MATURITY_BETA => new lang_string('maturity'.MATURITY_BETA, 'core_admin'),
|
||||
MATURITY_RC => new lang_string('maturity'.MATURITY_RC, 'core_admin'),
|
||||
MATURITY_STABLE => new lang_string('maturity'.MATURITY_STABLE, 'core_admin'),
|
||||
]
|
||||
));
|
||||
$temp->add(new admin_setting_configcheckbox('updatenotifybuilds', new lang_string('updatenotifybuilds', 'core_admin'),
|
||||
new lang_string('updatenotifybuilds_desc', 'core_admin'), 0));
|
||||
$ADMIN->add('server', $temp);
|
||||
}
|
||||
|
||||
// Web services.
|
||||
$ADMIN->add('server', new admin_category('webservicesettings', new lang_string('webservices', 'webservice')));
|
||||
|
||||
// Web services > Overview.
|
||||
$temp = new admin_settingpage('webservicesoverview', new lang_string('webservicesoverview', 'webservice'));
|
||||
$temp->add(new admin_setting_webservicesoverview());
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
|
||||
// Web services > API documentation.
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('webservicedocumentation', new lang_string('wsdocapi', 'webservice'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/webservice/documentation.php", 'moodle/site:config', false));
|
||||
|
||||
// Web services > External services.
|
||||
$temp = new admin_settingpage('externalservices', new lang_string('externalservices', 'webservice'));
|
||||
|
||||
$temp->add(new admin_setting_heading('manageserviceshelpexplaination', new lang_string('information', 'webservice'),
|
||||
new lang_string('servicehelpexplanation', 'webservice')));
|
||||
|
||||
$temp->add(new admin_setting_manageexternalservices());
|
||||
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('externalservice', new lang_string('editaservice', 'webservice'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/webservice/service.php", 'moodle/site:config', true));
|
||||
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('externalservicefunctions',
|
||||
new lang_string('externalservicefunctions', 'webservice'), "{$CFG->wwwroot}/{$CFG->admin}/webservice/service_functions.php",
|
||||
'moodle/site:config', true));
|
||||
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusers',
|
||||
new lang_string('externalserviceusers', 'webservice'), "{$CFG->wwwroot}/{$CFG->admin}/webservice/service_users.php",
|
||||
'moodle/site:config', true));
|
||||
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusersettings',
|
||||
new lang_string('serviceusersettings', 'webservice'), "{$CFG->wwwroot}/{$CFG->admin}/webservice/service_user_settings.php",
|
||||
'moodle/site:config', true));
|
||||
|
||||
// Web services > Manage protocols.
|
||||
$temp = new admin_settingpage('webserviceprotocols', new lang_string('manageprotocols', 'webservice'));
|
||||
$temp->add(new admin_setting_managewebserviceprotocols());
|
||||
if (empty($CFG->enablewebservices)) {
|
||||
$temp->add(new admin_setting_heading('webservicesaredisabled', '', new lang_string('disabledwarning', 'webservice')));
|
||||
}
|
||||
|
||||
// We cannot use $OUTPUT->doc_link() this early, we would lose the ability to set the page layout on all admin pages.
|
||||
$url = new moodle_url(get_docs_url('How_to_get_a_security_key'));
|
||||
$wsdoclink = html_writer::link($url, new lang_string('supplyinfo', 'webservice'), ['target' => '_blank']);
|
||||
$temp->add(new admin_setting_configcheckbox('enablewsdocumentation', new lang_string('enablewsdocumentation', 'admin'),
|
||||
new lang_string('configenablewsdocumentation', 'admin', $wsdoclink), false));
|
||||
|
||||
$ADMIN->add('webservicesettings', $temp);
|
||||
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('webservice');
|
||||
core_collator::asort_objects_by_property($plugins, 'displayname');
|
||||
foreach ($plugins as $plugin) {
|
||||
/** @var \core\plugininfo\webservice $plugin */
|
||||
$plugin->load_settings($ADMIN, 'webservicesettings', $hassiteconfig);
|
||||
}
|
||||
|
||||
// Web services > Manage tokens.
|
||||
$ADMIN->add('webservicesettings', new admin_externalpage('webservicetokens', new lang_string('managetokens', 'webservice'),
|
||||
new moodle_url('/admin/webservice/tokens.php')));
|
||||
// "update notifications" settingpage
|
||||
if (empty($CFG->disableupdatenotifications)) {
|
||||
$temp = new admin_settingpage('updatenotifications', new lang_string('updatenotifications', 'core_admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('updateautocheck', new lang_string('updateautocheck', 'core_admin'),
|
||||
new lang_string('updateautocheck_desc', 'core_admin'), 1));
|
||||
$temp->add(new admin_setting_configselect('updateminmaturity', new lang_string('updateminmaturity', 'core_admin'),
|
||||
new lang_string('updateminmaturity_desc', 'core_admin'), MATURITY_STABLE,
|
||||
array(
|
||||
MATURITY_ALPHA => new lang_string('maturity'.MATURITY_ALPHA, 'core_admin'),
|
||||
MATURITY_BETA => new lang_string('maturity'.MATURITY_BETA, 'core_admin'),
|
||||
MATURITY_RC => new lang_string('maturity'.MATURITY_RC, 'core_admin'),
|
||||
MATURITY_STABLE => new lang_string('maturity'.MATURITY_STABLE, 'core_admin'),
|
||||
)));
|
||||
$temp->add(new admin_setting_configcheckbox('updatenotifybuilds', new lang_string('updatenotifybuilds', 'core_admin'),
|
||||
new lang_string('updatenotifybuilds_desc', 'core_admin'), 0));
|
||||
$ADMIN->add('server', $temp);
|
||||
}
|
||||
|
||||
} // end of speedup
|
||||
|
||||
@@ -39,7 +39,6 @@ $ADMIN->add('root', new admin_category('license', new lang_string('license')));
|
||||
$ADMIN->add('root', new admin_category('location', new lang_string('location','admin')));
|
||||
$ADMIN->add('root', new admin_category('language', new lang_string('language')));
|
||||
$ADMIN->add('root', new admin_category('messaging', new lang_string('messagingcategory', 'admin')));
|
||||
$ADMIN->add('root', new admin_category('payment', new lang_string('payments', 'payment')));
|
||||
$ADMIN->add('root', new admin_category('modules', new lang_string('plugins', 'admin')));
|
||||
$ADMIN->add('root', new admin_category('security', new lang_string('security','admin')));
|
||||
$ADMIN->add('root', new admin_category('appearance', new lang_string('appearance','admin')));
|
||||
|
||||
+19
-39
@@ -87,14 +87,6 @@ if ($hassiteconfig
|
||||
$choices['1'] = new lang_string('trackforumsyes');
|
||||
$temp->add(new admin_setting_configselect('defaultpreference_trackforums', new lang_string('trackforums'),
|
||||
'', 0, $choices));
|
||||
|
||||
$choices = [];
|
||||
$choices[\core_contentbank\content::VISIBILITY_PUBLIC] = new lang_string('visibilitychoicepublic', 'core_contentbank');
|
||||
$choices[\core_contentbank\content::VISIBILITY_UNLISTED] = new lang_string('visibilitychoiceunlisted', 'core_contentbank');
|
||||
$temp->add(new admin_setting_configselect('defaultpreference_core_contentbank_visibility',
|
||||
new lang_string('visibilitypref', 'core_contentbank'),
|
||||
new lang_string('visibilitypref_help', 'core_contentbank'),
|
||||
\core_contentbank\content::VISIBILITY_PUBLIC, $choices));
|
||||
}
|
||||
$ADMIN->add('accounts', $temp);
|
||||
|
||||
@@ -196,6 +188,12 @@ if ($hassiteconfig
|
||||
'country' => new lang_string('country'),
|
||||
'moodlenetprofile' => new lang_string('moodlenetprofile', 'user'),
|
||||
'timezone' => new lang_string('timezone'),
|
||||
'webpage' => new lang_string('webpage'),
|
||||
'icqnumber' => new lang_string('icqnumber'),
|
||||
'skypeid' => new lang_string('skypeid'),
|
||||
'yahooid' => new lang_string('yahooid'),
|
||||
'aimid' => new lang_string('aimid'),
|
||||
'msnid' => new lang_string('msnid'),
|
||||
'firstaccess' => new lang_string('firstaccess'),
|
||||
'lastaccess' => new lang_string('lastaccess'),
|
||||
'lastip' => new lang_string('lastip'),
|
||||
@@ -208,39 +206,21 @@ if ($hassiteconfig
|
||||
// with moodle/site:viewuseridentity).
|
||||
// Options include fields from the user table that might be helpful to
|
||||
// distinguish when adding or listing users ('I want to add the John
|
||||
// Smith from Science faculty') and any custom profile fields.
|
||||
// Smith from Science faculty').
|
||||
// Custom user profile fields are not currently supported.
|
||||
$temp->add(new admin_setting_configmulticheckbox('showuseridentity',
|
||||
new lang_string('showuseridentity', 'admin'),
|
||||
new lang_string('showuseridentity_desc', 'admin'), ['email' => 1],
|
||||
function() {
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot.'/user/profile/lib.php');
|
||||
|
||||
// Basic fields available in user table.
|
||||
$fields = [
|
||||
'username' => new lang_string('username'),
|
||||
'idnumber' => new lang_string('idnumber'),
|
||||
'email' => new lang_string('email'),
|
||||
'phone1' => new lang_string('phone1'),
|
||||
'phone2' => new lang_string('phone2'),
|
||||
'department' => new lang_string('department'),
|
||||
'institution' => new lang_string('institution'),
|
||||
'city' => new lang_string('city'),
|
||||
'country' => new lang_string('country'),
|
||||
];
|
||||
|
||||
// Custom profile fields.
|
||||
$profilefields = profile_get_custom_fields();
|
||||
foreach ($profilefields as $field) {
|
||||
// Only reasonable-length text fields can be used as identity fields.
|
||||
if ($field->param2 > 255 || $field->datatype != 'text') {
|
||||
continue;
|
||||
}
|
||||
$fields['profile_field_' . $field->shortname] = $field->name . ' *';
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}));
|
||||
new lang_string('showuseridentity_desc', 'admin'), array('email' => 1), array(
|
||||
'username' => new lang_string('username'),
|
||||
'idnumber' => new lang_string('idnumber'),
|
||||
'email' => new lang_string('email'),
|
||||
'phone1' => new lang_string('phone1'),
|
||||
'phone2' => new lang_string('phone2'),
|
||||
'department' => new lang_string('department'),
|
||||
'institution' => new lang_string('institution'),
|
||||
'city' => new lang_string('city'),
|
||||
'country' => new lang_string('country'),
|
||||
)));
|
||||
$setting = new admin_setting_configtext('fullnamedisplay', new lang_string('fullnamedisplay', 'admin'),
|
||||
new lang_string('configfullnamedisplay', 'admin'), 'language', PARAM_TEXT, 50);
|
||||
$setting->set_force_ltr(true);
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_admin\local\settings\autocomplete
|
||||
|
||||
Admin setting auto complete.
|
||||
|
||||
Context variables required for this template:
|
||||
* name - element name
|
||||
* id - element id
|
||||
* options - choices
|
||||
* multiple - is multiple choices?
|
||||
* manageurl - url to manage choices
|
||||
* managetext - string to display manage url
|
||||
* tags - Should we allow typing new entries to the field?
|
||||
* ajax - Name of an AMD module to send/process ajax requests
|
||||
* placeholder - Placeholder text for an empty list
|
||||
* casesensitive - Whether the search has to be case-sensitive
|
||||
* showsuggestions - Show suggestions by default - but this can be turned off
|
||||
* noselectionstring - String that is shown when there are no selections
|
||||
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"name": "name0",
|
||||
"id": "id0",
|
||||
"options": [{
|
||||
"value": "1",
|
||||
"text": "option 1",
|
||||
"selected": true,
|
||||
"disabled": false
|
||||
}],
|
||||
"multiple": true,
|
||||
"manageurl": "",
|
||||
"managetext": "",
|
||||
"tags": false,
|
||||
"ajax": "",
|
||||
"placeholder": "",
|
||||
"casesensitive": false,
|
||||
"showsuggestions": true,
|
||||
"noselectionstring": ""
|
||||
}
|
||||
}}
|
||||
{{!
|
||||
Setting autocomplete.
|
||||
}}
|
||||
|
||||
<div class="form-select defaultsnext">
|
||||
<input type="hidden" name="{{name}}[xxxxx]" value="_qf__force_multiselect_submission">
|
||||
<select class="custom-select" name="{{name}}[]"
|
||||
id="{{id}}"
|
||||
{{#multiple}}multiple{{/multiple}}>
|
||||
{{#options}}
|
||||
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{{text}}}</option>
|
||||
{{/options}}
|
||||
</select>
|
||||
{{#manageurl}}
|
||||
<a href="{{manageurl}}">{{managetext}}</a>
|
||||
{{/manageurl}}
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
{{#js}}
|
||||
require(['core/form-autocomplete'], function(module) {
|
||||
module.enhance({{#quote}}#{{id}}{{/quote}},
|
||||
{{tags}},
|
||||
{{#quote}}{{ajax}}{{/quote}},
|
||||
{{#quote}}{{placeholder}}{{/quote}},
|
||||
{{casesensitive}},
|
||||
{{showsuggestions}},
|
||||
{{#quote}}{{noselectionstring}}{{/quote}});
|
||||
});
|
||||
{{/js}}
|
||||
@@ -48,6 +48,6 @@
|
||||
</div>
|
||||
<input type="text" name="{{name}}" id="{{id}}" value="{{value}}" size="12" class="form-control text-ltr" {{#readonly}}disabled{{/readonly}}>
|
||||
{{#haspreviewconfig}}
|
||||
<input type="button" id="{{id}}_preview" value="{{#cleanstr}}preview{{/cleanstr}}" class="admin_colourpicker_preview">
|
||||
<input type="button" id="{{id}}_preview" value={{#quote}}{{#str}}preview{{/str}}{{/quote}} class="admin_colourpicker_preview">
|
||||
{{/haspreviewconfig}}
|
||||
</div>
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_admin/admin_setting_encryptedpassword
|
||||
|
||||
Admin encrypted password template.
|
||||
|
||||
Context variables required for this template:
|
||||
* name - form element name
|
||||
* set - whether it is set or empty
|
||||
* id - element id
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"name": "test",
|
||||
"id": "test0",
|
||||
"set": true
|
||||
}
|
||||
}}
|
||||
<div class="core_admin_encryptedpassword" data-encryptedpasswordid="{{ id }}"
|
||||
{{#novalue}}data-novalue="y"{{/novalue}}>
|
||||
{{#set}}
|
||||
<span>{{# str }} encryptedpassword_set, admin {{/ str }}</span>
|
||||
{{/set}}
|
||||
{{^set}}
|
||||
<a href="#" title="{{# str }} encryptedpassword_edit, admin {{/ str }}">
|
||||
<span>{{# str }} novalueclicktoset, form {{/ str }}</span>
|
||||
{{# pix }} t/passwordunmask-edit, core, {{# str }} passwordunmaskedithint, form {{/ str }}{{/ pix }}
|
||||
</a>
|
||||
{{/set}}
|
||||
<input style="display: none" type="password" name="{{name}}" disabled>
|
||||
{{!
|
||||
Using buttons instead of links here allows them to be connected to the label, so the button
|
||||
works if you click the label.
|
||||
}}
|
||||
{{#set}}
|
||||
<button type="button" id="{{id}}" title="{{# str }} encryptedpassword_edit, admin {{/ str }}" class="btn btn-link" data-editbutton>
|
||||
{{# pix }} t/passwordunmask-edit, core, {{/ pix }}
|
||||
</button>
|
||||
{{/set}}
|
||||
<button type="button" style="display: none" title="{{# str }} cancel {{/ str }}" class="btn btn-link" data-cancelbutton>
|
||||
<i class="icon fa fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{#js}}
|
||||
require(['core_form/encryptedpassword'], function(encryptedpassword) {
|
||||
new encryptedpassword.EncryptedPassword("{{ id }}");
|
||||
});
|
||||
{{/js}}
|
||||
@@ -53,8 +53,11 @@ class behat_admin extends behat_base {
|
||||
}
|
||||
|
||||
foreach ($data as $label => $value) {
|
||||
// Navigate straight to the search results fo rthis label.
|
||||
$this->execute('behat_general::i_visit', ["/admin/search.php?query=" . urlencode($label)]);
|
||||
$this->execute('behat_navigation::i_select_from_flat_navigation_drawer', [get_string('administrationsite')]);
|
||||
|
||||
// Search by label.
|
||||
$this->execute('behat_forms::i_set_the_field_to', [get_string('query', 'admin'), $label]);
|
||||
$this->execute("behat_forms::press_button", get_string('search', 'admin'));
|
||||
|
||||
// Admin settings does not use the same DOM structure than other moodle forms
|
||||
// but we also need to use lib/behat/form_field/* to deal with the different moodle form elements.
|
||||
@@ -86,7 +89,7 @@ class behat_admin extends behat_base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified site settings. A table with | config | value | (optional)plugin | (optional)encrypted | is expected.
|
||||
* Sets the specified site settings. A table with | config | value | (optional)plugin | is expected.
|
||||
*
|
||||
* @Given /^the following config values are set as admin:$/
|
||||
* @param TableNode $table
|
||||
@@ -100,20 +103,11 @@ class behat_admin extends behat_base {
|
||||
foreach ($data as $config => $value) {
|
||||
// Default plugin value is null.
|
||||
$plugin = null;
|
||||
$encrypted = false;
|
||||
|
||||
if (is_array($value)) {
|
||||
$plugin = $value[1];
|
||||
if (array_key_exists(2, $value)) {
|
||||
$encrypted = $value[2] === 'encrypted';
|
||||
}
|
||||
$value = $value[0];
|
||||
}
|
||||
|
||||
if ($encrypted) {
|
||||
$value = \core\encryption::encrypt($value);
|
||||
}
|
||||
|
||||
set_config($config, $value, $plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
@core @core_admin
|
||||
Feature: An administrator can browse user accounts
|
||||
In order to find the user accounts I am looking for
|
||||
As an admin
|
||||
I can browse users and see their basic information
|
||||
|
||||
Background:
|
||||
Given the following "custom profile fields" exist:
|
||||
| datatype | shortname | name |
|
||||
| text | frog | Favourite frog |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email | department | profile_field_frog | firstnamephonetic |
|
||||
| user1 | User | One | one@example.com | Attack | Kermit | Yewzer |
|
||||
| user2 | User | Two | two@example.com | Defence | Tree | Yoozare |
|
||||
And I log in as "admin"
|
||||
|
||||
Scenario: User accounts display default fields
|
||||
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 / Surname | Email address |
|
||||
| User One | one@example.com |
|
||||
| User Two | two@example.com |
|
||||
# Should not see other identity fields or non-default name fields.
|
||||
And I should not see "Department" in the "table" "css_element"
|
||||
And I should not see "Attack"
|
||||
And I should not see "Favourite frog" in the "table" "css_element"
|
||||
And I should not see "Kermit"
|
||||
And I should not see "First name - phonetic" in the "table" "css_element"
|
||||
And I should not see "Yoozare"
|
||||
|
||||
Scenario: User accounts with extra name fields
|
||||
Given the following config values are set as admin:
|
||||
| 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 / Surname | Email address |
|
||||
| Yewzer One | one@example.com |
|
||||
| Yoozare Two | two@example.com |
|
||||
|
||||
Scenario: User accounts with specified identity fields
|
||||
Given the following config values are set as admin:
|
||||
| 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 / Surname | Favourite frog | Department |
|
||||
| User One | Kermit | Attack |
|
||||
| User Two | Tree | Defence |
|
||||
And I should not see "Email address" in the "table" "css_element"
|
||||
And I should not see "one@example.com"
|
||||
|
||||
Scenario: Sort user accounts by custom profile field
|
||||
Given the following config values are set as admin:
|
||||
| showuseridentity | profile_field_frog |
|
||||
When I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I follow "Favourite frog"
|
||||
Then "Kermit" "text" should appear before "Tree" "text"
|
||||
And I follow "Favourite frog"
|
||||
Then "Tree" "text" should appear before "Kermi" "text"
|
||||
@@ -5,16 +5,12 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
|
||||
I need to filter the users account list using different filter
|
||||
|
||||
Background:
|
||||
Given the following "custom profile fields" exist:
|
||||
| datatype | shortname | name |
|
||||
| text | frog | Favourite frog |
|
||||
| text | undead | Type of undead |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email | auth | confirmed | lastip | institution | department | profile_field_frog | profile_field_undead |
|
||||
| user1 | User | One | one@example.com | manual | 0 | 127.0.1.1 | moodle | red | Kermit | |
|
||||
| user2 | User | Two | two@example.com | ldap | 1 | 0.0.0.0 | moodle | blue | Mr Toad | Zombie |
|
||||
| user3 | User | Three | three@example.com | manual | 1 | 0.0.0.0 | | | | |
|
||||
| user4 | User | Four | four@example.com | ldap | 0 | 127.0.1.2 | | | | |
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email | auth | confirmed | lastip | institution | department |
|
||||
| user1 | User | One | one@example.com | manual | 0 | 127.0.1.1 | moodle | red |
|
||||
| user2 | User | Two | two@example.com | ldap | 1 | 0.0.0.0 | moodle | blue |
|
||||
| user3 | User | Three | three@example.com | manual | 1 | 0.0.0.0 | | |
|
||||
| user4 | User | Four | four@example.com | ldap | 0 | 127.0.1.2 | | |
|
||||
And the following "cohorts" exist:
|
||||
| name | idnumber |
|
||||
| Cohort 1 | CH1 |
|
||||
@@ -120,20 +116,3 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
|
||||
And I press "Add filter"
|
||||
And I should see "User One"
|
||||
And I should not see "User Two"
|
||||
|
||||
Scenario: Filter users by custom profile field (specific or any)
|
||||
When I set the field "id_profile_fld" to "Favourite frog"
|
||||
And I set the field "id_profile" to "Kermit"
|
||||
And I press "Add filter"
|
||||
Then I should see "User One"
|
||||
And I should not see "User Two"
|
||||
And I should not see "User Three"
|
||||
And I should not see "User Four"
|
||||
And I press "Remove all filters"
|
||||
And I set the field "id_profile_fld" to "any field"
|
||||
And I set the field "id_profile" to "Zombie"
|
||||
And I press "Add filter"
|
||||
And I should see "User Two"
|
||||
And I should not see "User One"
|
||||
And I should not see "User Three"
|
||||
And I should not see "User Four"
|
||||
|
||||
@@ -1,76 +1,27 @@
|
||||
@core @core_admin
|
||||
Feature: Manage external services tokens
|
||||
In order to manage external service usage
|
||||
Feature: Manage tokens
|
||||
In order to manage webservice usage
|
||||
As an admin
|
||||
I need to be able to create, filter and delete tokens
|
||||
I need to be able to create and delete tokens
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | password | firstname | lastname |
|
||||
| user1 | user1 | Firstname1 | Lastname1 |
|
||||
| user2 | user2 | Firstname2 | Lastname2 |
|
||||
| user3 | user3 | Firstname3 | Lastname3 |
|
||||
| user4 | user4 | Firstname4 | Lastname4 |
|
||||
| username | password | firstname | lastname |
|
||||
| testuser | testuser | Joe | Bloggs |
|
||||
| testuser2 | testuser2 | TestFirstname | TestLastname |
|
||||
And I change window size to "small"
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
|
||||
@javascript
|
||||
Scenario: Add a token to user identified by name and then delete that token
|
||||
Given I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I navigate to "Server > Web services > Manage tokens" in site administration
|
||||
And I press "Create token"
|
||||
And I set the field "User" to "Firstname1 Lastname1"
|
||||
And I set the field "Service" to "Moodle mobile web service"
|
||||
Scenario: Add & delete a token
|
||||
Given I navigate to "Plugins > Web services > Manage tokens" in site administration
|
||||
And I follow "Add"
|
||||
And I set the field "User" to "Joe Bloggs"
|
||||
And I set the field "IP restriction" to "127.0.0.1"
|
||||
When I press "Save changes"
|
||||
Then I should see "Moodle mobile web service" in the "Firstname1 Lastname1" "table_row"
|
||||
And I should see "127.0.0.1" in the "Firstname1 Lastname1" "table_row"
|
||||
And I click on "Delete" "link" in the "Firstname1 Lastname1" "table_row"
|
||||
And I should see "Do you really want to delete this web service token for Firstname1 Lastname1 on the service Moodle mobile web service?"
|
||||
Then I should see "Joe Bloggs"
|
||||
And I should see "127.0.0.1"
|
||||
And I follow "Delete"
|
||||
And I press "Delete"
|
||||
And "Firstname1 Lastname1" "table_row" should not exist
|
||||
|
||||
@javascript @skip_chrome_zerosize
|
||||
Scenario: Tokens can be filtered by user and by service
|
||||
Given the following "core_webservice > Service" exists:
|
||||
| name | Site information |
|
||||
| shortname | siteinfo |
|
||||
| enabled | 1 |
|
||||
And the following "core_webservice > Service function" exists:
|
||||
| service | siteinfo |
|
||||
| functions | core_webservice_get_site_info |
|
||||
And the following "core_webservice > Tokens" exist:
|
||||
| user | service |
|
||||
| user2 | siteinfo |
|
||||
| user3 | moodle_mobile_app |
|
||||
| user4 | siteinfo |
|
||||
When I log in as "admin"
|
||||
And I navigate to "Server > Web services > Manage tokens" in site administration
|
||||
|
||||
# All created tokens are shown by default.
|
||||
And "Firstname1 Lastname1" "table_row" should not exist
|
||||
And I should see "Site information" in the "Firstname2 Lastname2" "table_row"
|
||||
And I should see "Moodle mobile web service" in the "Firstname3 Lastname3" "table_row"
|
||||
And I should see "Site information" in the "Firstname4 Lastname4" "table_row"
|
||||
|
||||
# Filter tokens by user (note we can select the user by the identity field here).
|
||||
When I click on "Tokens filter" "link"
|
||||
And I set the field "User" to "user2@example.com"
|
||||
And I press "Show only matching tokens"
|
||||
Then "Firstname3 Lastname3" "table_row" should not exist
|
||||
And "Firstname4 Lastname4" "table_row" should not exist
|
||||
And I should see "Site information" in the "Firstname2 Lastname2" "table_row"
|
||||
|
||||
# Reset the filter.
|
||||
And I press "Show all tokens"
|
||||
And I should see "Site information" in the "Firstname2 Lastname2" "table_row"
|
||||
And I should see "Moodle mobile web service" in the "Firstname3 Lastname3" "table_row"
|
||||
And I should see "Site information" in the "Firstname4 Lastname4" "table_row"
|
||||
|
||||
# Filter tokens by service.
|
||||
And I click on "Tokens filter" "link"
|
||||
And I set the field "Service" to "Site information"
|
||||
And I press "Show only matching tokens"
|
||||
And I should see "Site information" in the "Firstname2 Lastname2" "table_row"
|
||||
And I should see "Site information" in the "Firstname4 Lastname4" "table_row"
|
||||
And "Firstname3 Lastname3" "table_row" should not exist
|
||||
And I should not see "Joe Bloggs"
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
@core @core_admin
|
||||
Feature: Web service user settings
|
||||
In order to configure authorised users for a web service
|
||||
As an admin
|
||||
I need to use the page that lets you do that
|
||||
|
||||
Background:
|
||||
# Include a custom profile field so we can check it gets displayed
|
||||
Given the following "custom profile fields" exist:
|
||||
| datatype | shortname | name | param2 |
|
||||
| text | frog | Favourite frog | 100 |
|
||||
And the following config values are set as admin:
|
||||
| showuseridentity | email,profile_field_frog |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email | profile_field_frog |
|
||||
| user1 | User | One | 1@example.org | Kermit |
|
||||
And the following "core_webservice > Service" exists:
|
||||
| name | Silly service |
|
||||
| shortname | silly |
|
||||
| restrictedusers | 1 |
|
||||
| enabled | 1 |
|
||||
|
||||
Scenario: Add a user to a web service
|
||||
When I log in as "admin"
|
||||
And I navigate to "Server > Web services > External services" in site administration
|
||||
And I click on "Authorised users" "link" in the "Silly service" "table_row"
|
||||
And I set the field "Not authorised users" to "User One"
|
||||
And I press "Add"
|
||||
Then I should see "User One" in the ".alloweduserlist" "css_element"
|
||||
And I should see "1@example.org" in the ".alloweduserlist" "css_element"
|
||||
And I should see "Kermit" in the ".alloweduserlist" "css_element"
|
||||
+2
-10
@@ -1,10 +1,2 @@
|
||||
/**
|
||||
* Shows a dialogue with info about this logs.
|
||||
*
|
||||
* @module tool_analytics/log_info
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define("tool_analytics/log_info",["jquery","core/str","core/modal_factory","core/notification"],(function($,str,ModalFactory,Notification){return{loadInfo:function(id,info){var link=$('[data-model-log-id="'+id+'"]');str.get_string("loginfo","tool_analytics").then((function(langString){var bodyInfo=$("<ul>");return info.forEach((function(item){bodyInfo.append("<li>"+item+"</li>")})),bodyInfo.append("</ul>"),ModalFactory.create({title:langString,body:bodyInfo.html(),large:!0},link)})).catch(Notification.exception)}}}));
|
||||
|
||||
//# sourceMappingURL=log_info.min.js.map
|
||||
define ("tool_analytics/log_info",["jquery","core/str","core/modal_factory","core/notification"],function(a,b,c,d){return{loadInfo:function loadInfo(e,f){var g=a("[data-model-log-id=\""+e+"\"]");b.get_string("loginfo","tool_analytics").then(function(b){var d=a("<ul>");f.forEach(function(a){d.append("<li>"+a+"</li>")});d.append("</ul>");return c.create({title:b,body:d.html(),large:!0},g)}).catch(d.exception)}}});
|
||||
//# sourceMappingURL=log_info.min.js.map
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"log_info.min.js","sources":["../src/log_info.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Shows a dialogue with info about this logs.\n *\n * @module tool_analytics/log_info\n * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/modal_factory', 'core/notification'], function($, str, ModalFactory, Notification) {\n\n return /** @alias module:tool_analytics/log_info */ {\n\n /**\n * Prepares a modal info for a log's results.\n *\n * @method loadInfo\n * @param {int} id\n * @param {string[]} info\n */\n loadInfo: function(id, info) {\n\n var link = $('[data-model-log-id=\"' + id + '\"]');\n str.get_string('loginfo', 'tool_analytics').then(function(langString) {\n\n var bodyInfo = $(\"<ul>\");\n info.forEach(function(item) {\n bodyInfo.append('<li>' + item + '</li>');\n });\n bodyInfo.append(\"</ul>\");\n\n return ModalFactory.create({\n title: langString,\n body: bodyInfo.html(),\n large: true,\n }, link);\n\n }).catch(Notification.exception);\n }\n };\n});\n"],"names":["define","$","str","ModalFactory","Notification","loadInfo","id","info","link","get_string","then","langString","bodyInfo","forEach","item","append","create","title","body","html","large","catch","exception"],"mappings":";;;;;;;AAsBAA,iCAAO,CAAC,SAAU,WAAY,qBAAsB,sBAAsB,SAASC,EAAGC,IAAKC,aAAcC,oBAEjD,CAShDC,SAAU,SAASC,GAAIC,UAEfC,KAAOP,EAAE,uBAAyBK,GAAK,MAC3CJ,IAAIO,WAAW,UAAW,kBAAkBC,MAAK,SAASC,gBAElDC,SAAWX,EAAE,eACjBM,KAAKM,SAAQ,SAASC,MAClBF,SAASG,OAAO,OAASD,KAAO,YAEpCF,SAASG,OAAO,SAETZ,aAAaa,OAAO,CACvBC,MAAON,WACPO,KAAMN,SAASO,OACfC,OAAO,GACRZ,SAEJa,MAAMjB,aAAakB"}
|
||||
{"version":3,"sources":["../src/log_info.js"],"names":["define","$","str","ModalFactory","Notification","loadInfo","id","info","link","get_string","then","langString","bodyInfo","forEach","item","append","create","title","body","html","large","catch","exception"],"mappings":"AAwBAA,OAAM,2BAAC,CAAC,QAAD,CAAW,UAAX,CAAuB,oBAAvB,CAA6C,mBAA7C,CAAD,CAAoE,SAASC,CAAT,CAAYC,CAAZ,CAAiBC,CAAjB,CAA+BC,CAA/B,CAA6C,CAEnH,MAAoD,CAShDC,QAAQ,CAAE,kBAASC,CAAT,CAAaC,CAAb,CAAmB,CAEzB,GAAIC,CAAAA,CAAI,CAAGP,CAAC,CAAC,wBAAyBK,CAAzB,CAA8B,KAA/B,CAAZ,CACAJ,CAAG,CAACO,UAAJ,CAAe,SAAf,CAA0B,gBAA1B,EAA4CC,IAA5C,CAAiD,SAASC,CAAT,CAAqB,CAElE,GAAIC,CAAAA,CAAQ,CAAGX,CAAC,CAAC,MAAD,CAAhB,CACAM,CAAI,CAACM,OAAL,CAAa,SAASC,CAAT,CAAe,CACxBF,CAAQ,CAACG,MAAT,CAAgB,OAASD,CAAT,CAAgB,OAAhC,CACH,CAFD,EAGAF,CAAQ,CAACG,MAAT,CAAgB,OAAhB,EAEA,MAAOZ,CAAAA,CAAY,CAACa,MAAb,CAAoB,CACvBC,KAAK,CAAEN,CADgB,CAEvBO,IAAI,CAAEN,CAAQ,CAACO,IAAT,EAFiB,CAGvBC,KAAK,GAHkB,CAApB,CAIJZ,CAJI,CAMV,CAdD,EAcGa,KAdH,CAcSjB,CAAY,CAACkB,SAdtB,CAeH,CA3B+C,CA6BvD,CA/BK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Shows a dialogue with info about this logs.\n *\n * @module tool_analytics/log_info\n * @class log_info\n * @package tool_analytics\n * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/modal_factory', 'core/notification'], function($, str, ModalFactory, Notification) {\n\n return /** @alias module:tool_analytics/log_info */ {\n\n /**\n * Prepares a modal info for a log's results.\n *\n * @method loadInfo\n * @param {int} id\n * @param {string[]} info\n */\n loadInfo: function(id, info) {\n\n var link = $('[data-model-log-id=\"' + id + '\"]');\n str.get_string('loginfo', 'tool_analytics').then(function(langString) {\n\n var bodyInfo = $(\"<ul>\");\n info.forEach(function(item) {\n bodyInfo.append('<li>' + item + '</li>');\n });\n bodyInfo.append(\"</ul>\");\n\n return ModalFactory.create({\n title: langString,\n body: bodyInfo.html(),\n large: true,\n }, link);\n\n }).catch(Notification.exception);\n }\n };\n});\n"],"file":"log_info.min.js"}
|
||||
+2
-10
@@ -1,10 +1,2 @@
|
||||
/**
|
||||
* AMD module for model actions confirmation.
|
||||
*
|
||||
* @module tool_analytics/model
|
||||
* @copyright 2017 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define("tool_analytics/model",["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],(function($,Str,log,Notification,ModalFactory,ModalEvents,Templates){var actionsList={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},delete:{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}};return{confirmAction:function(actionId,actionType){$('[data-action-id="'+actionId+'"]').on("click",(function(ev){ev.preventDefault();var a=$(ev.currentTarget);if(void 0!==actionsList[actionType]){var wrap,reqStrings=[actionsList[actionType].title,actionsList[actionType].body];reqStrings[1].param=(wrap=$(a).closest("[data-model-name]")).length?wrap.attr("data-model-name"):(log.error("Unexpected DOM error - unable to obtain the model name"),"");var stringsPromise=Str.get_strings(reqStrings),modalPromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL});$.when(stringsPromise,modalPromise).then((function(strings,modal){return modal.setTitle(strings[0]),modal.setBody(strings[1]),modal.setSaveButtonText(strings[0]),modal.getRoot().on(ModalEvents.save,(function(){window.location.href=a.attr("href")})),modal.show(),modal})).fail(Notification.exception)}else log.error('Action "'+actionType+'" is not allowed.')}))},selectEvaluationOptions:function(actionId,trainedOnlyExternally){$('[data-action-id="'+actionId+'"]').on("click",(function(ev){ev.preventDefault();var a=$(ev.currentTarget),timeSplittingMethods=$(this).attr("data-timesplitting-methods"),stringsPromise=Str.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluate",component:"tool_analytics"}]),modalPromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL}),bodyPromise=Templates.render("tool_analytics/evaluation_options",{trainedexternally:trainedOnlyExternally,timesplittingmethods:JSON.parse(timeSplittingMethods)});$.when(stringsPromise,modalPromise).then((function(strings,modal){return modal.getRoot().on(ModalEvents.hidden,modal.destroy.bind(modal)),modal.setTitle(strings[0]),modal.setSaveButtonText(strings[1]),modal.setBody(bodyPromise),modal.getRoot().on(ModalEvents.save,(function(){"trainedmodel"==$("input[name='evaluationmode']:checked").val()&&a.attr("href",a.attr("href")+"&mode=trainedmodel");var timeSplittingMethod=$("#id-evaluation-timesplitting").val();a.attr("href",a.attr("href")+"×plitting="+timeSplittingMethod),window.location.href=a.attr("href")})),modal.show(),modal})).fail(Notification.exception)}))},selectExportOptions:function(actionId,isTrained){$('[data-action-id="'+actionId+'"]').on("click",(function(ev){ev.preventDefault();var a=$(ev.currentTarget);if(!isTrained)return a.attr("href",a.attr("href")+"&action=exportmodel&includeweights=0"),void(window.location.href=a.attr("href"));var stringsPromise=Str.get_strings([{key:"export",component:"tool_analytics"}]),modalPromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL}),bodyPromise=Templates.render("tool_analytics/export_options",{});$.when(stringsPromise,modalPromise).then((function(strings,modal){return modal.getRoot().on(ModalEvents.hidden,modal.destroy.bind(modal)),modal.setTitle(strings[0]),modal.setSaveButtonText(strings[0]),modal.setBody(bodyPromise),modal.getRoot().on(ModalEvents.save,(function(){"exportdata"==$("input[name='exportoption']:checked").val()?a.attr("href",a.attr("href")+"&action=exportdata"):(a.attr("href",a.attr("href")+"&action=exportmodel"),$("#id-includeweights").is(":checked")?a.attr("href",a.attr("href")+"&includeweights=1"):a.attr("href",a.attr("href")+"&includeweights=0")),window.location.href=a.attr("href")})),modal.show(),modal})).fail(Notification.exception)}))}}}));
|
||||
|
||||
//# sourceMappingURL=model.min.js.map
|
||||
define ("tool_analytics/model",["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],function(b,c,d,e,f,g,h){var i={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},delete:{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}},j=function(a){var c=b(a).closest("[data-model-name]");if(c.length){return c.attr("data-model-name")}else{d.error("Unexpected DOM error - unable to obtain the model name");return""}};return{confirmAction:function confirmAction(a,h){b("[data-action-id=\""+a+"\"]").on("click",function(k){k.preventDefault();var l=b(k.currentTarget);if("undefined"==typeof i[h]){d.error("Action \""+h+"\" is not allowed.");return}var a=[i[h].title,i[h].body];a[1].param=j(l);var m=c.get_strings(a),n=f.create({type:f.types.SAVE_CANCEL});b.when(m,n).then(function(a,b){b.setTitle(a[0]);b.setBody(a[1]);b.setSaveButtonText(a[0]);b.getRoot().on(g.save,function(){window.location.href=l.attr("href")});b.show();return b}).fail(e.exception)})},selectEvaluationOptions:function selectEvaluationOptions(a,d){b("[data-action-id=\""+a+"\"]").on("click",function(i){i.preventDefault();var j=b(i.currentTarget),a=b(this).attr("data-timesplitting-methods"),k=c.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluate",component:"tool_analytics"}]),l=f.create({type:f.types.SAVE_CANCEL}),m=h.render("tool_analytics/evaluation_options",{trainedexternally:d,timesplittingmethods:JSON.parse(a)});b.when(k,l).then(function(a,c){c.getRoot().on(g.hidden,c.destroy.bind(c));c.setTitle(a[0]);c.setSaveButtonText(a[1]);c.setBody(m);c.getRoot().on(g.save,function(){var a=b("input[name='evaluationmode']:checked").val();if("trainedmodel"==a){j.attr("href",j.attr("href")+"&mode=trainedmodel")}var c=b("#id-evaluation-timesplitting").val();j.attr("href",j.attr("href")+"×plitting="+c);window.location.href=j.attr("href")});c.show();return c}).fail(e.exception)})},selectExportOptions:function selectExportOptions(a,d){b("[data-action-id=\""+a+"\"]").on("click",function(i){i.preventDefault();var j=b(i.currentTarget);if(!d){j.attr("href",j.attr("href")+"&action=exportmodel&includeweights=0");window.location.href=j.attr("href");return}var a=c.get_strings([{key:"export",component:"tool_analytics"}]),k=f.create({type:f.types.SAVE_CANCEL}),l=h.render("tool_analytics/export_options",{});b.when(a,k).then(function(a,c){c.getRoot().on(g.hidden,c.destroy.bind(c));c.setTitle(a[0]);c.setSaveButtonText(a[0]);c.setBody(l);c.getRoot().on(g.save,function(){var a=b("input[name='exportoption']:checked").val();if("exportdata"==a){j.attr("href",j.attr("href")+"&action=exportdata")}else{j.attr("href",j.attr("href")+"&action=exportmodel");if(b("#id-includeweights").is(":checked")){j.attr("href",j.attr("href")+"&includeweights=1")}else{j.attr("href",j.attr("href")+"&includeweights=0")}}window.location.href=j.attr("href")});c.show();return c}).fail(e.exception)})}}});
|
||||
//# sourceMappingURL=model.min.js.map
|
||||
|
||||
File diff suppressed because one or more lines are too long
+2
-10
@@ -1,10 +1,2 @@
|
||||
/**
|
||||
* Potential contexts selector module.
|
||||
*
|
||||
* @module tool_analytics/potential-contexts
|
||||
* @copyright 2019 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define("tool_analytics/potential-contexts",["jquery","core/ajax"],(function($,Ajax){return{processResults:function(selector,results){var contexts=[];return $.isArray(results)?($.each(results,(function(index,context){contexts.push({value:context.id,label:context.name})})),contexts):results},transport:function(selector,query,success,failure){var modelid=$(selector).attr("modelid")||null;Ajax.call([{methodname:"tool_analytics_potential_contexts",args:{query:query,modelid:modelid}}])[0].then(success).fail(failure)}}}));
|
||||
|
||||
//# sourceMappingURL=potential-contexts.min.js.map
|
||||
define ("tool_analytics/potential-contexts",["jquery","core/ajax"],function(a,b){return{processResults:function processResults(b,c){var d=[];if(a.isArray(c)){a.each(c,function(a,b){d.push({value:b.id,label:b.name})});return d}else{return c}},transport:function transport(c,d,e,f){var g,h=a(c).attr("modelid")||null;g=b.call([{methodname:"tool_analytics_potential_contexts",args:{query:d,modelid:h}}]);g[0].then(e).fail(f)}}});
|
||||
//# sourceMappingURL=potential-contexts.min.js.map
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"potential-contexts.min.js","sources":["../src/potential-contexts.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Potential contexts selector module.\n *\n * @module tool_analytics/potential-contexts\n * @copyright 2019 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n return /** @alias module:tool_analytics/potential-contexts */ {\n\n processResults: function(selector, results) {\n var contexts = [];\n if ($.isArray(results)) {\n $.each(results, function(index, context) {\n contexts.push({\n value: context.id,\n label: context.name\n });\n });\n return contexts;\n\n } else {\n return results;\n }\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n let modelid = $(selector).attr('modelid') || null;\n promise = Ajax.call([{\n methodname: 'tool_analytics_potential_contexts',\n args: {\n query: query,\n modelid: modelid\n }\n }]);\n\n promise[0].then(success).fail(failure);\n }\n\n };\n\n});\n"],"names":["define","$","Ajax","processResults","selector","results","contexts","isArray","each","index","context","push","value","id","label","name","transport","query","success","failure","modelid","attr","call","methodname","args","then","fail"],"mappings":";;;;;;;AAuBAA,2CAAO,CAAC,SAAU,cAAc,SAASC,EAAGC,YAEsB,CAE1DC,eAAgB,SAASC,SAAUC,aAC3BC,SAAW,UACXL,EAAEM,QAAQF,UACVJ,EAAEO,KAAKH,SAAS,SAASI,MAAOC,SAC5BJ,SAASK,KAAK,CACVC,MAAOF,QAAQG,GACfC,MAAOJ,QAAQK,UAGhBT,UAGAD,SAIfW,UAAW,SAASZ,SAAUa,MAAOC,QAASC,aAGtCC,QAAUnB,EAAEG,UAAUiB,KAAK,YAAc,KACnCnB,KAAKoB,KAAK,CAAC,CACjBC,WAAY,oCACZC,KAAM,CACFP,MAAOA,MACPG,QAASA,YAIT,GAAGK,KAAKP,SAASQ,KAAKP"}
|
||||
{"version":3,"sources":["../src/potential-contexts.js"],"names":["define","$","Ajax","processResults","selector","results","contexts","isArray","each","index","context","push","value","id","label","name","transport","query","success","failure","promise","modelid","attr","call","methodname","args","then","fail"],"mappings":"AAyBAA,OAAM,qCAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAE9C,MAA8D,CAE1DC,cAAc,CAAE,wBAASC,CAAT,CAAmBC,CAAnB,CAA4B,CACxC,GAAIC,CAAAA,CAAQ,CAAG,EAAf,CACA,GAAIL,CAAC,CAACM,OAAF,CAAUF,CAAV,CAAJ,CAAwB,CACpBJ,CAAC,CAACO,IAAF,CAAOH,CAAP,CAAgB,SAASI,CAAT,CAAgBC,CAAhB,CAAyB,CACrCJ,CAAQ,CAACK,IAAT,CAAc,CACVC,KAAK,CAAEF,CAAO,CAACG,EADL,CAEVC,KAAK,CAAEJ,CAAO,CAACK,IAFL,CAAd,CAIH,CALD,EAMA,MAAOT,CAAAA,CAEV,CATD,IASO,CACH,MAAOD,CAAAA,CACV,CACJ,CAhByD,CAkB1DW,SAAS,CAAE,mBAASZ,CAAT,CAAmBa,CAAnB,CAA0BC,CAA1B,CAAmCC,CAAnC,CAA4C,IAC/CC,CAAAA,CAD+C,CAG/CC,CAAO,CAAGpB,CAAC,CAACG,CAAD,CAAD,CAAYkB,IAAZ,CAAiB,SAAjB,GAA+B,IAHM,CAInDF,CAAO,CAAGlB,CAAI,CAACqB,IAAL,CAAU,CAAC,CACjBC,UAAU,CAAE,mCADK,CAEjBC,IAAI,CAAE,CACFR,KAAK,CAAEA,CADL,CAEFI,OAAO,CAAEA,CAFP,CAFW,CAAD,CAAV,CAAV,CAQAD,CAAO,CAAC,CAAD,CAAP,CAAWM,IAAX,CAAgBR,CAAhB,EAAyBS,IAAzB,CAA8BR,CAA9B,CACH,CA/ByD,CAmCjE,CArCK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Potential contexts selector module.\n *\n * @module tool_analytics/potential-contexts\n * @class potential-contexts\n * @package tool_analytics\n * @copyright 2019 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n return /** @alias module:tool_analytics/potential-contexts */ {\n\n processResults: function(selector, results) {\n var contexts = [];\n if ($.isArray(results)) {\n $.each(results, function(index, context) {\n contexts.push({\n value: context.id,\n label: context.name\n });\n });\n return contexts;\n\n } else {\n return results;\n }\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n let modelid = $(selector).attr('modelid') || null;\n promise = Ajax.call([{\n methodname: 'tool_analytics_potential_contexts',\n args: {\n query: query,\n modelid: modelid\n }\n }]);\n\n promise[0].then(success).fail(failure);\n }\n\n };\n\n});\n"],"file":"potential-contexts.min.js"}
|
||||
@@ -17,6 +17,8 @@
|
||||
* Shows a dialogue with info about this logs.
|
||||
*
|
||||
* @module tool_analytics/log_info
|
||||
* @class log_info
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
* Potential contexts selector module.
|
||||
*
|
||||
* @module tool_analytics/potential-contexts
|
||||
* @class potential-contexts
|
||||
* @package tool_analytics
|
||||
* @copyright 2019 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
@@ -64,7 +64,7 @@ class models_list implements \renderable, \templatable {
|
||||
$data = new \stdClass();
|
||||
|
||||
$newmodelmenu = new \action_menu();
|
||||
$newmodelmenu->set_menu_trigger(get_string('newmodel', 'tool_analytics'), 'btn btn-secondary');
|
||||
$newmodelmenu->set_menu_trigger(get_string('newmodel', 'tool_analytics'), 'btn btn-default');
|
||||
$newmodelmenu->set_alignment(\action_menu::TL, \action_menu::BL);
|
||||
|
||||
$newmodelmenu->add(new \action_menu_link(
|
||||
|
||||
@@ -137,7 +137,7 @@ if (!empty($validdatasets) && !$model->is_enabled() && $options['non-interactive
|
||||
}
|
||||
|
||||
// Refresh the instance to prevent unexpected issues.
|
||||
$model = new \core_analytics\model($options['modelid']);
|
||||
$model = new \core_analytics\model($modelobj);
|
||||
|
||||
// Set the time splitting method file and enable it.
|
||||
$model->enable($input);
|
||||
|
||||
@@ -57,10 +57,10 @@
|
||||
{{/trainedexternally}}
|
||||
|
||||
{{! Hidden by default if #trainedexternally as the default option is trainedmodel in this case.}}
|
||||
<div id="id-evaluation-timesplitting-container" class="mt-3 {{#trainedexternally}}hidden{{/trainedexternally}}">
|
||||
<div id="id-evaluation-timesplitting-container" class="m-t-1 {{#trainedexternally}}hidden{{/trainedexternally}}">
|
||||
{{#str}} selecttimesplittingforevaluation, tool_analytics {{/str}}
|
||||
<div>
|
||||
<select id="id-evaluation-timesplitting" name="timesplitting" class="custom-select mt-3">
|
||||
<select id="id-evaluation-timesplitting" name="timesplitting" class="custom-select m-t-1">
|
||||
{{#timesplittingmethods}}
|
||||
<option value="{{id}}">{{text}}</option>
|
||||
{{/timesplittingmethods}}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<input class="custom-control-input" type="radio" name="exportoption" id="id-mode-exportmodel" value="exportmodel" checked>
|
||||
<label class="custom-control-label" for="id-mode-exportmodel">{{#str}} exportmodel, tool_analytics {{/str}}</label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox ml-5" id="id-includeweights-container">
|
||||
<div class="custom-control custom-checkbox m-l-2" id="id-includeweights-container">
|
||||
<input class="custom-control-input" type="checkbox" id="id-includeweights" value="1" checked>
|
||||
<label class="custom-control-label" for="id-includeweights">{{#str}} exportincludeweights, tool_analytics {{/str}}</label>
|
||||
</div>
|
||||
|
||||
+5
-8
@@ -24,17 +24,13 @@
|
||||
* @since Moodle 3.8
|
||||
*/
|
||||
|
||||
namespace tool_analytics\external;
|
||||
|
||||
use externallib_advanced_testcase;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
|
||||
require_once($CFG->dirroot . '/analytics/tests/fixtures/test_indicator_max.php');
|
||||
require_once($CFG->dirroot . '/analytics/tests/fixtures/test_target_course_level_shortname.php');
|
||||
require_once(__DIR__ . '/../../../../analytics/tests/fixtures/test_indicator_max.php');
|
||||
require_once(__DIR__ . '/../../../../analytics/tests/fixtures/test_target_course_level_shortname.php');
|
||||
|
||||
/**
|
||||
* Tool analytics external functions tests
|
||||
@@ -45,7 +41,7 @@ require_once($CFG->dirroot . '/analytics/tests/fixtures/test_target_course_level
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @since Moodle 3.8
|
||||
*/
|
||||
class external_test extends externallib_advanced_testcase {
|
||||
class tool_analytics_external_testcase extends externallib_advanced_testcase {
|
||||
|
||||
/**
|
||||
* test_potential_contexts description
|
||||
@@ -70,6 +66,8 @@ class external_test extends externallib_advanced_testcase {
|
||||
|
||||
/**
|
||||
* test_potential_contexts description
|
||||
*
|
||||
* @expectedException required_capability_exception
|
||||
*/
|
||||
public function test_potential_contexts_no_manager() {
|
||||
$this->resetAfterTest();
|
||||
@@ -77,7 +75,6 @@ class external_test extends externallib_advanced_testcase {
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
$this->expectException(\required_capability_exception::class);
|
||||
$this->assertCount(2, \tool_analytics\external::potential_contexts());
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2021051700; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2021051100; // Requires this Moodle version.
|
||||
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2020060900; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_analytics'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2021051700;
|
||||
$plugin->requires = 2021051100;
|
||||
$plugin->version = 2020061500;
|
||||
$plugin->requires = 2020060900;
|
||||
$plugin->component = 'tool_availabilityconditions';
|
||||
|
||||
@@ -49,10 +49,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'torun' => 0,
|
||||
'optimize-runs' => '',
|
||||
'add-core-features-to-theme' => false,
|
||||
'axe' => false,
|
||||
'disable-composer' => false,
|
||||
'composer-upgrade' => true,
|
||||
'composer-self-update' => true,
|
||||
),
|
||||
array(
|
||||
'j' => 'parallel',
|
||||
@@ -68,36 +64,18 @@ $help = "
|
||||
Behat utilities to initialise behat tests
|
||||
|
||||
Usage:
|
||||
php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]]
|
||||
[--axe] [-o | --optimize-runs] [-a | --add-core-features-to-theme]
|
||||
[--no-composer-self-update] [--no-composer-upgrade]
|
||||
[--disable-composer]
|
||||
[--help]
|
||||
php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]] [--help]
|
||||
|
||||
Options:
|
||||
-j, --parallel Number of parallel behat run to initialise
|
||||
-m, --maxruns Max parallel processes to be executed at one time
|
||||
--fromrun Execute run starting from (Used for parallel runs on different vms)
|
||||
--torun Execute run till (Used for parallel runs on different vms)
|
||||
--axe Include axe accessibility tests
|
||||
-j, --parallel Number of parallel behat run to initialise
|
||||
-m, --maxruns Max parallel processes to be executed at one time.
|
||||
--fromrun Execute run starting from (Used for parallel runs on different vms)
|
||||
--torun Execute run till (Used for parallel runs on different vms)
|
||||
|
||||
-o, --optimize-runs
|
||||
Split features with specified tags in all parallel runs.
|
||||
-o, --optimize-runs Split features with specified tags in all parallel runs.
|
||||
-a, --add-core-features-to-theme Add all core features to specified theme's
|
||||
|
||||
-a, --add-core-features-to-theme
|
||||
Add all core features to specified theme's
|
||||
|
||||
--no-composer-self-update
|
||||
Prevent upgrade of the composer utility using its self-update command
|
||||
|
||||
--no-composer-upgrade
|
||||
Prevent update development dependencies using composer
|
||||
|
||||
--disable-composer
|
||||
A shortcut to disable composer self-update and dependency update
|
||||
Note: Installation of composer and/or dependencies will still happen as required
|
||||
|
||||
-h, --help Print out this help
|
||||
-h, --help Print out this help
|
||||
|
||||
Example from Moodle root directory:
|
||||
\$ php admin/tool/behat/cli/init.php --parallel=2
|
||||
@@ -124,10 +102,7 @@ if ($options['parallel'] && $options['parallel'] > 1) {
|
||||
}
|
||||
} else {
|
||||
// Only sanitize options for single run.
|
||||
$cmdoptionsforsinglerun = [
|
||||
'add-core-features-to-theme',
|
||||
'axe',
|
||||
];
|
||||
$cmdoptionsforsinglerun = array('add-core-features-to-theme');
|
||||
|
||||
foreach ($cmdoptionsforsinglerun as $option) {
|
||||
if (!empty($options[$option])) {
|
||||
@@ -140,15 +115,8 @@ if ($options['parallel'] && $options['parallel'] > 1) {
|
||||
$cwd = getcwd();
|
||||
$output = null;
|
||||
|
||||
if ($options['disable-composer']) {
|
||||
// Disable self-update and upgrade easily.
|
||||
// Note: Installation will still occur regardless of this setting.
|
||||
$options['composer-self-update'] = false;
|
||||
$options['composer-upgrade'] = false;
|
||||
}
|
||||
|
||||
// Install and update composer and dependencies as required.
|
||||
testing_update_composer_dependencies($options['composer-self-update'], $options['composer-upgrade']);
|
||||
// If behat dependencies not downloaded then do it first, else symfony/process can't be used.
|
||||
testing_update_composer_dependencies();
|
||||
|
||||
// Check whether the behat test environment needs to be updated.
|
||||
chdir(__DIR__);
|
||||
|
||||
@@ -45,7 +45,7 @@ list($options, $unrecognised) = cli_get_params(
|
||||
array(
|
||||
'stop-on-failure' => 0,
|
||||
'verbose' => false,
|
||||
'replace' => '',
|
||||
'replace' => false,
|
||||
'help' => false,
|
||||
'tags' => '',
|
||||
'profile' => '',
|
||||
@@ -70,7 +70,7 @@ $help = "
|
||||
Behat utilities to run behat tests in parallel
|
||||
|
||||
Usage:
|
||||
php run.php [--BEHAT_OPTION=\"value\"] [--feature=\"value\"] [--replace=\"{run}\"] [--fromrun=value --torun=value] [--help]
|
||||
php run.php [--BEHAT_OPTION=\"value\"] [--feature=\"value\"] [--replace] [--fromrun=value --torun=value] [--help]
|
||||
|
||||
Options:
|
||||
--BEHAT_OPTION Any combination of behat option specified in http://behat.readthedocs.org/en/v2.5/guides/6.cli.html
|
||||
@@ -144,10 +144,9 @@ $extraopts = $unrecognised;
|
||||
if ($options['profile']) {
|
||||
$profile = $options['profile'];
|
||||
|
||||
// If profile passed is not set, then exit (note we skip if the 'replace' option is found within the 'profile' value).
|
||||
// If profile passed is not set, then exit.
|
||||
if (!isset($CFG->behat_config[$profile]) && !isset($CFG->behat_profiles[$profile]) &&
|
||||
!($options['replace'] && (strpos($profile, (string) $options['replace']) !== false))) {
|
||||
|
||||
!(isset($options['replace']) && (strpos($options['profile'], $options['replace']) >= 0 ))) {
|
||||
echo "Invalid profile passed: " . $profile . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'torun' => 0,
|
||||
'optimize-runs' => '',
|
||||
'add-core-features-to-theme' => false,
|
||||
'axe' => false,
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
@@ -70,7 +69,7 @@ $help = "
|
||||
Behat utilities to manage the test environment
|
||||
|
||||
Usage:
|
||||
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--axe|--help] [--parallel=value [--maxruns=value]]
|
||||
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--help] [--parallel=value [--maxruns=value]]
|
||||
|
||||
Options:
|
||||
--install Installs the test environment for acceptance tests
|
||||
@@ -79,7 +78,6 @@ Options:
|
||||
--disable Disables test environment
|
||||
--diag Get behat test environment status code
|
||||
--updatesteps Update feature step file.
|
||||
--axe Include axe accessibility tests
|
||||
|
||||
-j, --parallel Number of parallel behat run operation
|
||||
-m, --maxruns Max parallel processes to be executed at one time.
|
||||
|
||||
@@ -49,7 +49,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'updatesteps' => false,
|
||||
'optimize-runs' => '',
|
||||
'add-core-features-to-theme' => false,
|
||||
'axe' => false,
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
@@ -76,7 +75,6 @@ Options:
|
||||
--disable Disables test environment
|
||||
--diag Get behat test environment status code
|
||||
--updatesteps Update feature step file.
|
||||
--axe Include axe accessibility tests
|
||||
|
||||
-o, --optimize-runs Split features with specified tags in all parallel runs.
|
||||
-a, --add-core-features-to-theme Add all core features to specified theme's
|
||||
@@ -183,17 +181,11 @@ if ($options['install']) {
|
||||
behat_config_manager::set_behat_run_config_value('behatsiteenabled', 1);
|
||||
}
|
||||
|
||||
// Define whether to run Behat with axe tests.
|
||||
behat_config_manager::set_behat_run_config_value('axe', $options['axe']);
|
||||
|
||||
// Enable test mode.
|
||||
$timestart = microtime(true);
|
||||
mtrace('Creating Behat configuration ...', '');
|
||||
behat_util::start_test_mode($options['add-core-features-to-theme'], $options['optimize-runs'], $parallel, $run);
|
||||
mtrace(' done in ' . round(microtime(true) - $timestart, 2) . ' seconds.');
|
||||
|
||||
// Themes are only built in the 'enable' command.
|
||||
behat_util::build_themes(true);
|
||||
behat_util::build_themes();
|
||||
mtrace("Testing environment themes built");
|
||||
|
||||
// This is only displayed once for parallel install.
|
||||
|
||||
@@ -21,5 +21,5 @@ Feature: Transform date time string arguments
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test assignment name"
|
||||
And I should see "##yesterday##%d %B %Y##"
|
||||
And I should see "##yesterday##%A, %d %B %Y##"
|
||||
And I log out
|
||||
|
||||
@@ -49,14 +49,10 @@ Feature: Edit capabilities
|
||||
|
||||
Scenario: Module capabilities overrides
|
||||
Given I log in as "teacher1"
|
||||
And the following "activity" exists:
|
||||
| activity | forum |
|
||||
| course | C1 |
|
||||
| idnumber | 00001 |
|
||||
| name | I'm the name |
|
||||
| intro | I'm the introduction |
|
||||
| section | 1 |
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I add a "Forum" to section "1" and I fill the form with:
|
||||
| Forum name | I'm the name |
|
||||
| Description | I'm the introduction |
|
||||
And I follow "I'm the name"
|
||||
And I navigate to "Permissions" in current page administration
|
||||
And I override the system permissions of "Student" role with:
|
||||
@@ -79,9 +75,9 @@ Feature: Edit capabilities
|
||||
| Your word for 'Student' | Studier & 'learner' |
|
||||
And I press "Save and display"
|
||||
And I navigate to course participants
|
||||
Then I should see "Teacher >= editing (Teacher)" in the "Teacher 1" "table_row"
|
||||
And I should see "Teacher < \"editing\" (Non-editing teacher)" in the "Teaching Assistant" "table_row"
|
||||
And I should see "Studier & 'learner' (Student)" in the "Student One" "table_row"
|
||||
Then I should see "Teacher >= editing" in the "Teacher 1" "table_row"
|
||||
And I should see "Teacher < \"editing\"" in the "Teaching Assistant" "table_row"
|
||||
And I should see "Studier & 'learner'" in the "Student One" "table_row"
|
||||
And I navigate to "Users > Permissions" in current page administration
|
||||
And I should see "Teacher >= editing" in the "mod/forum:replypost" "table_row"
|
||||
And I should see "Teacher < \"editing\"" in the "mod/forum:replypost" "table_row"
|
||||
|
||||
@@ -48,7 +48,7 @@ Feature: Verify that all form fields values can be get and set
|
||||
And the "Unenrol users" select box should not contain "Baker"
|
||||
And the "Unenrol users" select box should not contain "President, Baker"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I follow "Test this one"
|
||||
And I press "Create page"
|
||||
# Text (textarea & editor) & Select (multi-select) - Checking "I set the following fields to these values".
|
||||
When I set the following fields to these values:
|
||||
@@ -61,7 +61,8 @@ Feature: Verify that all form fields values can be get and set
|
||||
# Checkbox - Checking "I set the field" and "The field matches value" ticked.
|
||||
And I set the field "Force format" to "1"
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I expand all fieldsets
|
||||
And the field "Force format" matches value "1"
|
||||
@@ -69,7 +70,8 @@ Feature: Verify that all form fields values can be get and set
|
||||
# Checkbox - Checking "I set the field" and "The field matches value" unticked.
|
||||
And I set the field "Force format" to ""
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I expand all fieldsets
|
||||
And the field "Force format" matches value ""
|
||||
@@ -78,7 +80,8 @@ Feature: Verify that all form fields values can be get and set
|
||||
And I set the following fields to these values:
|
||||
| Force format | 1 |
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I expand all fieldsets
|
||||
And the following fields match these values:
|
||||
@@ -89,7 +92,8 @@ Feature: Verify that all form fields values can be get and set
|
||||
And I set the following fields to these values:
|
||||
| Force format | |
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I expand all fieldsets
|
||||
And the following fields match these values:
|
||||
@@ -111,24 +115,16 @@ Feature: Verify that all form fields values can be get and set
|
||||
| Wiki name | Test this one baby |
|
||||
| Default format | HTML |
|
||||
And I press "Cancel"
|
||||
And I am on "Course 1" course homepage
|
||||
# Radio - Checking "I set the field" and "the field matches value".
|
||||
And the following "activity" exists:
|
||||
| activity | choice |
|
||||
| course | C1 |
|
||||
| idnumber | choice1 |
|
||||
| intro | Test choice description |
|
||||
| name | Test choice name |
|
||||
| choice1 | Option 1, Option 2, Option 3 |
|
||||
| section | 1 |
|
||||
| allowupdate | 1 |
|
||||
And I am on "Course 1" course homepage
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I set the field "Option 1" to "one"
|
||||
And I set the field "Option 2" to "two"
|
||||
And I set the field "Option 3" to "three"
|
||||
And I press "Save and return to course"
|
||||
And I am on "Course 1" course homepage
|
||||
And I am on the "Test choice name" "choice activity" page
|
||||
And I add a "Choice" to section "1" and I fill the form with:
|
||||
| Choice name | Test choice name |
|
||||
| Description | Test choice description |
|
||||
| Allow choice to be updated | Yes |
|
||||
| Option 1 | one |
|
||||
| Option 2 | two |
|
||||
| Option 3 | three |
|
||||
And I follow "Test choice name"
|
||||
And I set the field "one" to "1"
|
||||
And I press "Save my choice"
|
||||
And the field "one" matches value "1"
|
||||
@@ -178,23 +174,31 @@ Feature: Verify that all form fields values can be get and set
|
||||
And I press "Cancel"
|
||||
# Advanced checkbox requires real browser to allow uncheck to work. MDL-58681. MDL-55386.
|
||||
# Advanced checkbox - Checking "I set the field" and "The field matches value" ticked.
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I set the field "Display description on course page" to "1"
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And the field "Display description on course page" matches value "1"
|
||||
And the field "Display description on course page" does not match value ""
|
||||
# Advanced checkbox - Checking "I set the field" and "The field matches value" unticked.
|
||||
And I set the field "Display description on course page" to ""
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And the field "Display description on course page" matches value ""
|
||||
And the field "Display description on course page" does not match value "1"
|
||||
# Advanced checkbox - Checking "I set the following fields to these values:" and "The following fields match these values" ticked.
|
||||
And I set the following fields to these values:
|
||||
| Display description on course page | 1 |
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And the following fields match these values:
|
||||
| Display description on course page | 1 |
|
||||
And the following fields do not match these values:
|
||||
@@ -203,7 +207,9 @@ Feature: Verify that all form fields values can be get and set
|
||||
And I set the following fields to these values:
|
||||
| Display description on course page | |
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And the following fields match these values:
|
||||
| Display description on course page | |
|
||||
And the following fields do not match these values:
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
@tool @tool_behat
|
||||
Feature: Use core page resolvers for the I am on the page steps
|
||||
In order to write tests correctly
|
||||
As a developer
|
||||
I need to have steps which take me straight to a page
|
||||
|
||||
Scenario Outline: When I am on an instance
|
||||
Given the following "categories" exist:
|
||||
| name | category | idnumber |
|
||||
| Cat 1 | 0 | CAT1 |
|
||||
And the following "course" exists:
|
||||
| fullname | Economics 101 |
|
||||
| shortname | ECON101 |
|
||||
| idnumber | 2021-econ101 |
|
||||
And the following "activity" exists:
|
||||
| course | ECON101 |
|
||||
| activity | forum |
|
||||
| name | Fundamentals of Economics |
|
||||
| idnumber | fundamentalsofeconomics |
|
||||
And I log in as "admin"
|
||||
When I am on the <identifier> <type> page
|
||||
Then I should see "<shouldsee>"
|
||||
|
||||
Examples:
|
||||
| description | identifier | type | shouldsee |
|
||||
| Course Category idnumber | CAT1 | category | Add a new course |
|
||||
| Course Category name | "Cat 1" | Category | Add a new course |
|
||||
| Course Full name | "Economics 101" | course | Fundamentals of Economics |
|
||||
| Course Short name | ECON101 | COURSE | Fundamentals of Economics |
|
||||
| Course idnumber | "2021-econ101" | Course | Fundamentals of Economics |
|
||||
| Forum idnumber | fundamentalsofeconomics | Activity | Add a new discussion |
|
||||
| Generic activity editing | fundamentalsofeconomics | "Activity editing" | Updating: Forum |
|
||||
| Forum name | "Fundamentals of Economics" | "Forum activity" | Add a new discussion |
|
||||
| Forum name editing | "Fundamentals of Economics" | "Forum activity editing" | Updating: Forum |
|
||||
| Forum name permissions | "Fundamentals of Economics" | "Forum activity permissions" | Permissions in Forum: Fun |
|
||||
| Forum name roles | "Fundamentals of Economics" | "Forum activity roles" | Assign roles in Forum: Fun |
|
||||
|
||||
Scenario Outline: When I am on an instance logged in as
|
||||
Given the following "categories" exist:
|
||||
| name | category | idnumber |
|
||||
| Cat 1 | 0 | CAT1 |
|
||||
And the following "course" exists:
|
||||
| fullname | Economics 101 |
|
||||
| shortname | ECON101 |
|
||||
| idnumber | 2021-econ101 |
|
||||
And the following "activity" exists:
|
||||
| course | ECON101 |
|
||||
| activity | forum |
|
||||
| name | Fundamentals of Economics |
|
||||
| idnumber | fundamentalsofeconomics |
|
||||
When I am on the <identifier> <type> page logged in as admin
|
||||
Then I should see "<shouldsee>"
|
||||
|
||||
Examples:
|
||||
| description | identifier | type | shouldsee |
|
||||
| Course Category idnumber | CAT1 | category | Add a new course |
|
||||
| Course Category name | "Cat 1" | Category | Add a new course |
|
||||
| Course Full name | "Economics 101" | course | Fundamentals of Economics |
|
||||
| Course Short name | ECON101 | COURSE | Fundamentals of Economics |
|
||||
| Course idnumber | "2021-econ101" | Course | Fundamentals of Economics |
|
||||
| Forum idnumber | fundamentalsofeconomics | Activity | Add a new discussion |
|
||||
| Generic activity editing | fundamentalsofeconomics | "Activity editing" | Updating: Forum |
|
||||
| Forum name | "Fundamentals of Economics" | "Forum activity" | Add a new discussion |
|
||||
| Forum name editing | "Fundamentals of Economics" | "Forum activity editing" | Updating: Forum |
|
||||
| Forum name permissions | "Fundamentals of Economics" | "Forum activity permissions" | Permissions in Forum: Fun |
|
||||
| Forum name roles | "Fundamentals of Economics" | "Forum activity roles" | Assign roles in Forum: Fun |
|
||||
|
||||
Scenario Outline: When I am on a named page
|
||||
Given I log in as "admin"
|
||||
When I am on the <identifier> page
|
||||
Then I should see "<shouldsee>"
|
||||
|
||||
Examples:
|
||||
| description | identifier | shouldsee |
|
||||
| Admin page | "Admin notifications" | Check for available updates |
|
||||
| Home page | Homepage | Recently accessed courses |
|
||||
|
||||
Scenario Outline: When I am on a named page logged in as
|
||||
When I am on the <identifier> page logged in as admin
|
||||
Then I should see "<shouldsee>"
|
||||
|
||||
Examples:
|
||||
| description | identifier | shouldsee |
|
||||
| Admin page | "Admin notifications" | Check for available updates |
|
||||
| Home page | Homepage | Recently accessed courses |
|
||||
@@ -1,110 +0,0 @@
|
||||
@tool_behat
|
||||
Feature: Verify that the behat login and logout steps work as expected
|
||||
In order to use behat login and log out steps
|
||||
As a test writer
|
||||
I need to verify that login and logout happen when the steps are used
|
||||
|
||||
Scenario: Log in as a user using the step
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
When I log in as "traverst1"
|
||||
Then I should see "Thomas Travers"
|
||||
|
||||
@javascript
|
||||
Scenario: Log in as a user using the step (javascript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
When I log in as "traverst1"
|
||||
Then I should see "Thomas Travers"
|
||||
|
||||
Scenario: Log out using the log out step
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
And I am logged in as traverst1
|
||||
When I log out
|
||||
Then I should not see "Thomas Travers"
|
||||
And I should see "You are not logged in"
|
||||
|
||||
@javascript
|
||||
Scenario: Log out using the log out step (javascript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
And I am logged in as traverst1
|
||||
When I log out
|
||||
Then I should not see "Thomas Travers"
|
||||
And I should see "You are not logged in"
|
||||
|
||||
Scenario: Log in step should automatically log user out if already logged in
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
| emeryj | Jane | Emery |
|
||||
And I am logged in as traverst1
|
||||
When I log in as "emeryj"
|
||||
Then I should not see "Thomas Travers"
|
||||
And I should see "Jane Emery"
|
||||
|
||||
@javascript
|
||||
Scenario: Log in step should automatically log user out if already logged in (javascript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
| emeryj | Jane | Emery |
|
||||
And I am logged in as traverst1
|
||||
When I log in as "emeryj"
|
||||
Then I should not see "Thomas Travers"
|
||||
And I should see "Jane Emery"
|
||||
|
||||
Scenario: I am on page logged in as should redirect to correct page
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
And the following "course" exists:
|
||||
| fullname | Life, the Universe, and Everything |
|
||||
| shortname | hhgttg |
|
||||
When I am on the hhgttg Course page logged in as traverst1
|
||||
Then I should see "Thomas Travers"
|
||||
And I should see "Life, the Universe, and Everything"
|
||||
|
||||
@javascript
|
||||
Scenario: I am on page logged in as should redirect to correct page (javascript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
And the following "course" exists:
|
||||
| fullname | Life, the Universe, and Everything |
|
||||
| shortname | hhgttg |
|
||||
When I am on the hhgttg Course page logged in as traverst1
|
||||
Then I should see "Thomas Travers"
|
||||
And I should see "Life, the Universe, and Everything"
|
||||
|
||||
Scenario: I am on page logged in as should redirect to correct page when automatically logging a user out
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
| emeryj | Jane | Emery |
|
||||
And the following "course" exists:
|
||||
| fullname | Life, the Universe, and Everything |
|
||||
| shortname | hhgttg |
|
||||
And I am logged in as emeryj
|
||||
When I am on the hhgttg Course page logged in as traverst1
|
||||
Then I should see "Thomas Travers"
|
||||
And I should see "Life, the Universe, and Everything"
|
||||
|
||||
@javascript
|
||||
Scenario: I am on page logged in as should redirect to correct page when automatically logging a user out (javacript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
| emeryj | Jane | Emery |
|
||||
And the following "course" exists:
|
||||
| fullname | Life, the Universe, and Everything |
|
||||
| shortname | hhgttg |
|
||||
And I am logged in as emeryj
|
||||
When I am on the hhgttg Course page logged in as traverst1
|
||||
Then I should see "Thomas Travers"
|
||||
And I should see "Life, the Universe, and Everything"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user