Compare commits
775 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ec58cefefb | |||
| e4cda88e76 | |||
| 8752df87ed | |||
| 511dab1cd3 | |||
| b26a5e5e08 | |||
| fcb699808c | |||
| f9dc16ca05 | |||
| a350376b65 | |||
| 29f7a9a210 | |||
| 022a019637 | |||
| 50f5563c1f | |||
| 1c0b8f8c50 | |||
| c879cb24df | |||
| 6890ad18e3 | |||
| b88679e3a1 | |||
| 8c1917588d | |||
| c50c904c9e | |||
| 9023021ae0 | |||
| 919ead58fe | |||
| 27de77007b | |||
| 34d1c23668 | |||
| dc7ca062ca | |||
| 8100d46f85 | |||
| f4dfe66ea8 | |||
| e92c6b19b8 | |||
| fa79a1876c | |||
| c9ab02b0cc | |||
| 9c2241dee4 | |||
| 8028bf10dc | |||
| 04704c2108 | |||
| fbe13d55f3 | |||
| 75d6582fef | |||
| 7ca4fd97d9 | |||
| 940ed72017 | |||
| 477cd8b5fe | |||
| a8efb07714 | |||
| 51c9ea5194 | |||
| b0a1b4ce8b | |||
| 3d9175f6f1 | |||
| fd2427746f | |||
| 49afa008f4 | |||
| 551892e2a7 | |||
| 45c339ef09 | |||
| e9fe9f4ae3 | |||
| 1d1b148ca9 | |||
| 15b4174a9f | |||
| 99ab172211 | |||
| 5cc9f3448c | |||
| 4dd870de20 | |||
| c353963ef8 | |||
| 60585523ad | |||
| eeaf19eb5c | |||
| 63da614e4f | |||
| 73372330a9 | |||
| 5f3de24306 | |||
| c15eac212b | |||
| 01c8c8828b | |||
| 2dbe5f54f1 | |||
| bcf59d235b | |||
| 32574e9cae | |||
| 256f8a261c | |||
| 60232d2b9b | |||
| 864ddb77c5 | |||
| 462fe3e925 | |||
| 6bb7478e8d | |||
| 03960b96cb | |||
| 4d00ebae7a | |||
| 352e2f7787 | |||
| 2d2b8d9170 | |||
| 53f2acb263 | |||
| 3ea25c3b77 | |||
| 7931148cbb | |||
| 1031836d89 | |||
| ec1e1fd01a | |||
| b5a04a9fe2 | |||
| be7b73a24b | |||
| 0c438b4d3e | |||
| 3f0373cb7e | |||
| 6a64b9c5b7 | |||
| 04569f819f | |||
| a850fa5de8 | |||
| 8d0d0b1f59 | |||
| 8ea746fa79 | |||
| 5d7bd0208a | |||
| 52ad601de1 | |||
| 2e02b4d678 | |||
| 859578b0d5 | |||
| 761b8a95f9 | |||
| 4ca3d0a0ae | |||
| 75c793f830 | |||
| d546f308d2 | |||
| 74f37f98ad | |||
| aead807ce6 | |||
| f7ad3eaca3 | |||
| da4fc1e256 | |||
| 35364e22fc | |||
| b1ef67ba62 | |||
| 461bf54590 | |||
| 6ba76c0097 | |||
| 323ea697c3 | |||
| 46f6bae002 | |||
| 8aacc3fa2b | |||
| 0715960dd8 | |||
| 65084e7371 | |||
| da4b94e012 | |||
| 05679468c5 | |||
| 0a64b2ed99 | |||
| e243810142 | |||
| a5fa563757 | |||
| f018e92334 | |||
| 46e3cfa354 | |||
| 25cf4fa5ca | |||
| 0fb7847e09 | |||
| b63f17b5f1 | |||
| 52305c9a2e | |||
| 6b3d163a56 | |||
| efc576fc5c | |||
| 90fbc58de6 | |||
| 087845bb30 | |||
| 7d10f35278 | |||
| 9476b48942 | |||
| 7e11261633 | |||
| 15a4e4c87c | |||
| 895f38cc76 | |||
| acd1c82403 | |||
| c9271eba7c | |||
| 0cf4bb2afc | |||
| 58a89a46e4 | |||
| 1882bb4792 | |||
| bb7d679395 | |||
| 048a652106 | |||
| 23e24a504e | |||
| 761898c876 | |||
| dc976fba1e | |||
| e2faf67247 | |||
| b97899634c | |||
| 2427b92114 | |||
| 34770016ee | |||
| d00c00dd4f | |||
| ed1cc02522 | |||
| e1151bf6f5 | |||
| bbb887f6ae | |||
| 4403b8f60d | |||
| 3c3b43a58c | |||
| 04e2dc7c3b | |||
| 05574af1a6 | |||
| 5337ca485c | |||
| 3b0034cc91 | |||
| ab6ca27571 | |||
| 149e530cc1 | |||
| 9a7aed4a25 | |||
| ed04c3824c | |||
| 97e8cb0de4 | |||
| a435c63e16 | |||
| c2321a263b | |||
| f3d7526419 | |||
| d3432a883c | |||
| e1cab8e18e | |||
| bc28c05995 | |||
| 4865d2a0ae | |||
| 8317134779 | |||
| fbac2e9296 | |||
| c978fa26e2 | |||
| 599eed0f95 | |||
| 7d52d5def6 | |||
| 8813318d61 | |||
| 0459910b53 | |||
| adeaafd59d | |||
| 0dd7bb8374 | |||
| bcba1347f8 | |||
| b0e1edd427 | |||
| b0007a154c | |||
| 8c9d3695e3 | |||
| 184944ce6a | |||
| ad9f9e54a3 | |||
| 943b261760 | |||
| 8dbc7c6532 | |||
| 6f7fe5df9c | |||
| 7e5f0e1fe6 | |||
| 11b6df58db | |||
| 36beec930e | |||
| 750fe24949 | |||
| cc718b59d0 | |||
| 4dcc2d37c6 | |||
| d358b91e2b | |||
| c053b93f0c | |||
| cdf91cc236 | |||
| fab34222ca | |||
| a9f5f8094c | |||
| 10e16c69c8 | |||
| e66e3740a7 | |||
| 6594c54b2e | |||
| 6dc336a5d4 | |||
| 39128991d7 | |||
| e1990f2f33 | |||
| 1ce223c7e1 | |||
| 6694715840 | |||
| 0a43a459ba | |||
| 7e0bcbfb19 | |||
| eaf89f7754 | |||
| 5bbfcc25c0 | |||
| 4a495d66b8 | |||
| b13ec3c353 | |||
| 5903054142 | |||
| 2dd9b53fd6 | |||
| 7f20e2071c | |||
| 0ab106f41c | |||
| 9f82c9aece | |||
| 1f13dff1a7 | |||
| be396eddf0 | |||
| 4af4d709a4 | |||
| 46606b3ddd | |||
| 35bc26b516 | |||
| 106c64ac24 | |||
| ddf72dd60d | |||
| 0ae27225f5 | |||
| a6674bf8a4 | |||
| dc87fd4b3f | |||
| d81a94807b | |||
| c611109ed7 | |||
| 74ef7dc5b1 | |||
| 8996ed98c7 | |||
| 3fcba4be5e | |||
| 55d463b9f2 | |||
| bbb58b10ad | |||
| f266c852c3 | |||
| b14daeaa9a | |||
| 8e083da3d5 | |||
| 8312eeacb0 | |||
| 0ce40927cf | |||
| 0cdfaccd4e | |||
| d386d21360 | |||
| 5429ece3f8 | |||
| 32f99bc4d1 | |||
| df0df3110d | |||
| 2ced8c6674 | |||
| 17056bf206 | |||
| 27b09acf75 | |||
| d159c32b84 | |||
| 221f0e16d0 | |||
| 55189def65 | |||
| 086a2adc35 | |||
| 3c315a874a | |||
| b4a8a99898 | |||
| 08e8205d6f | |||
| 0a54a501eb | |||
| 213ea00afe | |||
| 9428e33d55 | |||
| 31a98b3fb2 | |||
| ae6da7d6a0 | |||
| 4d5bc273ce | |||
| 33c7881448 | |||
| b7146b655a | |||
| 178d5a0e23 | |||
| f576390bd2 | |||
| 7ed7afad98 | |||
| a7e12a77b1 | |||
| 09e02634d4 | |||
| be019636d1 | |||
| 7789be4030 | |||
| 91c9ca0f49 | |||
| 7c0923a3e4 | |||
| 83cba7b9b0 | |||
| cb4418bc5b | |||
| 4db3403481 | |||
| 9296086653 | |||
| 38d4a1b75f | |||
| 1b4ef7cd88 | |||
| 3576eb4835 | |||
| 39eb58c754 | |||
| c6731f8045 | |||
| 252f95e1b7 | |||
| c24c9e174b | |||
| 199333208d | |||
| 91557080d7 | |||
| 3370b20e3c | |||
| 2c98bfc4f4 | |||
| 36f0c3d531 | |||
| 1ebbd18b82 | |||
| 04a02b5bd9 | |||
| 506df9bdbd | |||
| 873b4847f5 | |||
| a2aa548af7 | |||
| d0c89df9ee | |||
| 30eccfabaa | |||
| 63e2c543ae | |||
| a69b38d604 | |||
| 0ea391d1eb | |||
| 17d4bc49f6 | |||
| 57a13a5971 | |||
| 12fce2a4bd | |||
| b68dd3a121 | |||
| eb4c7963c0 | |||
| dde0818f6c | |||
| ad28920d0b | |||
| a5cde22a26 | |||
| 44719d2ad9 | |||
| 784c09c834 | |||
| 004be78003 | |||
| 7fae5f61ef | |||
| d7cadcc244 | |||
| 2cb45addb1 | |||
| 5ea92799c4 | |||
| 55c9482171 | |||
| 1a7928173b | |||
| c3299761f7 | |||
| 9aeb59af73 | |||
| 3759daa952 | |||
| 15044cea7f | |||
| 1170a8b694 | |||
| 69959c371f | |||
| ec46b18e13 | |||
| f1acce7bef | |||
| 1c6e578db4 | |||
| a7ea95030c | |||
| 3f04dbee09 | |||
| 6a91117d4a | |||
| cfe9f53e91 | |||
| decd480c42 | |||
| d947f53d4c | |||
| 00877bf283 | |||
| 6f86e933ed | |||
| 6d7b36da59 | |||
| 7924191691 | |||
| 0628d11380 | |||
| 151a63b4cc | |||
| 4ebfbfe88c | |||
| 93a60507fc | |||
| 0a8371c690 | |||
| 604f19afd6 | |||
| bda1473afa | |||
| d70cfda576 | |||
| 3dc820a057 | |||
| 4b64516b0e | |||
| e8496407e9 | |||
| 0ab3fd7958 | |||
| d103bdba3d | |||
| cf1d32e9c5 | |||
| b5fe033b18 | |||
| 05a3e35677 | |||
| 03058394f2 | |||
| 1a80427018 | |||
| a2b727d7bc | |||
| b2a382016f | |||
| 31efbf2e0e | |||
| 3540343ceb | |||
| 78076a621f | |||
| ca80e9a68d | |||
| 9b9b38f44e | |||
| 8e5b007c3e | |||
| d487ee2240 | |||
| 300e4aef4c | |||
| eefa5c928f | |||
| 407dcd4922 | |||
| 8d9a36fb8a | |||
| b2d43a7db1 | |||
| 876a5c143b | |||
| c562848596 | |||
| 74efdb135d | |||
| 46d1546c6e | |||
| c2ba78902c | |||
| 12fb5964f2 | |||
| 52a84caaaa | |||
| 524f6a656b | |||
| 86e69ea7b2 | |||
| 12820e3a56 | |||
| 36905f42b8 | |||
| fd532533dd | |||
| d6806beb3e | |||
| 9ab387d707 | |||
| 2a4d1c64bf | |||
| a0999ab66f | |||
| 7e3f7e3d7c | |||
| 823bc36276 | |||
| 1f3aacf8fc | |||
| 38bcf316ee | |||
| f993881244 | |||
| 3277fc9db6 | |||
| ef3720efbd | |||
| 41bc6b9400 | |||
| b9f8e3e114 | |||
| 355d07e0b4 | |||
| 5af206ad2a | |||
| 5ec265b48d | |||
| 35b29ce7d9 | |||
| bec49592ce | |||
| 57bb99edd4 | |||
| eb6b828b81 | |||
| 8b09853319 | |||
| fe1031244b | |||
| 03de8ed6d9 | |||
| 6fae5e65e9 | |||
| d7157063c3 | |||
| 477fb6c9d6 | |||
| c50b024463 | |||
| fadd2915eb | |||
| c71355941b | |||
| 18871c74e2 | |||
| 5cffc7f78b | |||
| 946159a554 | |||
| 8d371859dc | |||
| aad6afe979 | |||
| d12c1406df | |||
| 5130127a3e | |||
| 651dbb729c | |||
| 2c8db06e7a | |||
| e98d18241f | |||
| 3e460f45ac | |||
| d5e30e0108 | |||
| 7db1a61a72 | |||
| d335530a28 | |||
| 6fe5bb1b96 | |||
| e2a73965ca | |||
| ccd0b96591 | |||
| 851f0d3354 | |||
| 5576a97713 | |||
| b235c3a5a7 | |||
| c00b8b7cab | |||
| b19f178e0d | |||
| 56b28e8e0b | |||
| 6658d9fba1 | |||
| 09dabe003a | |||
| 85f136094b | |||
| 1c55d84794 | |||
| 3ac504fd3d | |||
| 1f25df48b1 | |||
| 64ba1753a8 | |||
| 0e8d14f4e9 | |||
| 9c28e07d31 | |||
| 4ea44f96e5 | |||
| c5c1b8b121 | |||
| 3490f29ad9 | |||
| 3b03a3da47 | |||
| a6aefe15f0 | |||
| b294665c21 | |||
| 2b50abffa2 | |||
| acb848cdce | |||
| 7cd362b873 | |||
| cc16de4ccc | |||
| c0af823086 | |||
| 8b026809c5 | |||
| 2dbc9a5005 | |||
| d224506353 | |||
| 0d1187b052 | |||
| a2e3aa6806 | |||
| adac2a9e55 | |||
| 2fca843e49 | |||
| 157a497a3e | |||
| 4f0fc4f45b | |||
| 27b1425eb2 | |||
| 40e41c1997 | |||
| 89ce0b387e | |||
| 9b64c178dd | |||
| 69cc1d1dd5 | |||
| 39c8e99e67 | |||
| 833ab0ea9f | |||
| 2b87250347 | |||
| 95d1f1f18d | |||
| d23f05828f | |||
| 972340b678 | |||
| 3971892bd3 | |||
| b18b714165 | |||
| 781545d34d | |||
| 19fe7f27a8 | |||
| bd686af064 | |||
| fd18dc14ff | |||
| e840b14f4c | |||
| 730aa1dcb0 | |||
| 9ef6492e5d | |||
| 41ad54e182 | |||
| 2a1fb5b5e7 | |||
| 56adf1f3d8 | |||
| a36870c175 | |||
| a0f377cf2b | |||
| 7905d70497 | |||
| d0a55062f9 | |||
| 7f177d440c | |||
| 8730ffcbe1 | |||
| 486aa319c2 | |||
| 6fa8e1c86f | |||
| dcfb713ca6 | |||
| 9d82cdb62e | |||
| a88f50d1b2 | |||
| 94adb3429b | |||
| bd516bf05c | |||
| 02829c03c1 | |||
| e9435e8f6d | |||
| 6a750d283d | |||
| b5e39191fc | |||
| 42c1cf3b03 | |||
| a5cd815635 | |||
| 1fdb4fda4a | |||
| 61772eb89b | |||
| e49ccc92c4 | |||
| f9f289f69d | |||
| e16b858ff9 | |||
| f4bdb898c7 | |||
| 2d502fd749 | |||
| b552d604ff | |||
| 6d73afb2bf | |||
| 0ad2d843d7 | |||
| 82a1e8fae7 | |||
| a2c1a20055 | |||
| 76c3dc5f6b | |||
| 62ea8b1cae | |||
| c36d5093e3 | |||
| fae57261e7 | |||
| 11a49b08e7 | |||
| a730c334c7 | |||
| fb5e3957be | |||
| 54524f1ff0 | |||
| bbfbe8e260 | |||
| cfe02e4d3e | |||
| 611399214b | |||
| 321de29e93 | |||
| f200ba55f8 | |||
| 8d791e12ba | |||
| 8923308d47 | |||
| 0e97e40e5a | |||
| 7254648363 | |||
| c3176af430 | |||
| cb82c4d901 | |||
| bf127517b3 | |||
| 29e56fef72 | |||
| b249ab9df4 | |||
| 7805d0bb44 | |||
| 6fcc509ed1 | |||
| ebd136ca12 | |||
| c96a155937 | |||
| fdb7f85140 | |||
| fbae45d7c9 | |||
| a398a60092 | |||
| de0e594a10 | |||
| 93097192e6 | |||
| 1427573cde | |||
| 28790a42ad | |||
| e5f0085cdb | |||
| 682593054d | |||
| 8fba6189fe | |||
| 31188e93d6 | |||
| 9bc368f71c | |||
| 1aa7c68c6f | |||
| 23efc7337a | |||
| cf4b6c8c94 | |||
| abb2037b0f | |||
| c94b6b2ab7 | |||
| ab5d361c80 | |||
| 334333b6c7 | |||
| 3d08cd2272 | |||
| 83a5ed90ce | |||
| d945333b47 | |||
| da84b731c7 | |||
| 36f3b1e418 | |||
| a3cc6898e9 | |||
| fcbca18c7b | |||
| c0280f4405 | |||
| c83543095a | |||
| 13e34fb428 | |||
| c705434a62 | |||
| cfe1a9a8d8 | |||
| 94d05a5bfb | |||
| 2562b9f3a3 | |||
| e8b05c6cb4 | |||
| 8f0297915c | |||
| b25763e875 | |||
| 84bcfbb0d5 | |||
| e419e7acba | |||
| 309aad5a82 | |||
| 8452418666 | |||
| 5ba67416e6 | |||
| bd0de2d965 | |||
| db54910ce2 | |||
| 9d356676c3 | |||
| a9d3f4b96c | |||
| ca6cf0bd21 | |||
| 7d990ee185 | |||
| e2a11dc2aa | |||
| a2a6303397 | |||
| 6c4cdd6d96 | |||
| 4bb41b4e5a | |||
| a937d4d807 | |||
| 2301f9bfaa | |||
| 0e9c755896 | |||
| 3452156e6e | |||
| 6ef1780225 | |||
| a8c60a4c31 | |||
| b2995f7a29 | |||
| 51201bc672 | |||
| aa13890df0 | |||
| 644b80410d | |||
| b36a28b37a | |||
| 386223bd86 | |||
| 95359bf9e7 | |||
| 1bc2a3b345 | |||
| 709b46dbfd | |||
| 94c19e0fea | |||
| 4a60349a8a | |||
| 2189db9c86 | |||
| f54cb0c257 | |||
| 95e0ff974c | |||
| db361e09e7 | |||
| f2b1242364 | |||
| d0fd7bc58c | |||
| 916809d995 | |||
| e22ac10067 | |||
| f558127d0e | |||
| fc1d22ea70 | |||
| 5d1979c911 | |||
| fe346f0afb | |||
| 8d5470145d | |||
| 61d32ad081 | |||
| 558ef4f778 | |||
| c8221dedcd | |||
| 5265491a8f | |||
| b96e85feac | |||
| 817d6dcdbb | |||
| de1a942280 | |||
| 3e1c856bd9 | |||
| cce23499e6 | |||
| 74160de2cb | |||
| 4ca7232b1f | |||
| ded581156a | |||
| 4cfc74d176 | |||
| 893cf77d33 | |||
| e66f450c8f | |||
| f9f41f5061 | |||
| 76e2d15794 | |||
| 31d3fd27fc | |||
| 2874c6d5a1 | |||
| d8892dcca3 | |||
| 85a1c2c99e | |||
| 58bf730494 | |||
| d179137f1b | |||
| 8eafd115cc | |||
| 3b111cf8a0 | |||
| a244344e2e | |||
| 23fed91412 | |||
| dee4097c9d | |||
| 7665c701fd | |||
| 3827cbe523 | |||
| f6a2d57b3e | |||
| 35a5c1adda | |||
| e4d86a6ec4 | |||
| 8d2229db48 | |||
| 4d6b3406c5 | |||
| 11a58dd4b0 | |||
| 0713666486 | |||
| 260e9753d4 | |||
| e83fad7382 | |||
| c7e5431086 | |||
| 10ba6d0aa1 | |||
| a4f4cbf095 | |||
| 66c757f689 | |||
| 2f7236aa3c | |||
| a704b87f8b | |||
| 59f48908aa | |||
| e6f0b5a3a3 | |||
| 7a85cc6d2e | |||
| 3d08c7d396 | |||
| f809bca508 | |||
| fbcc91236e | |||
| 2dab18e681 | |||
| 3565a77362 | |||
| cbecc140f7 | |||
| c3a4859c7d | |||
| 330ba8cb10 | |||
| 4e32add0ac | |||
| e48fecc679 | |||
| d7113bee4e | |||
| 61ce84f178 | |||
| e3bfcb1cde | |||
| 4a6a2636a0 | |||
| 09646d7b53 | |||
| 9211552660 | |||
| f51678c56a | |||
| fa3b387185 | |||
| dddff390da | |||
| 6bcc070827 | |||
| e1e362b7ff | |||
| ae12edc741 | |||
| 5934444b27 | |||
| c187594e5b | |||
| f9f0f1cc26 | |||
| f0b7948c96 | |||
| 3114d04721 | |||
| e78b9f9574 | |||
| b0d96c297b | |||
| 54d32ce4a9 | |||
| 71f44b0611 | |||
| b8a0258357 | |||
| db8fea04f5 | |||
| 227281d355 | |||
| fb6460ca98 | |||
| 424c5df1eb | |||
| 64c4074699 | |||
| b4ab127434 | |||
| 4d03cc37b2 | |||
| 195e7c9cf1 | |||
| 1ffb6b09ee | |||
| 06411e3689 | |||
| e419e18f0d | |||
| 3263daba84 | |||
| 59a5923924 | |||
| f2602288eb | |||
| 4413ca209f | |||
| 427f046cff | |||
| e29edbe89e | |||
| e9df0c43bc | |||
| d71659dd6d | |||
| fb6c682850 | |||
| 356a8ee948 | |||
| fe9ecef92b | |||
| 9c1f7874d8 | |||
| 96fac6d9ce | |||
| 4b327e1109 | |||
| f649cd722f | |||
| 03e84b68a1 | |||
| 51dc7d230f | |||
| 1044e94507 | |||
| c4303bba51 | |||
| 9d32114bf6 | |||
| 8ddb17b641 | |||
| 30990ac512 | |||
| 0c6f661def | |||
| 24d0335a0a | |||
| 52836faa5b | |||
| 64f64e44d8 | |||
| a133b89976 | |||
| 93fec2c58c | |||
| 3db6d44feb | |||
| 83aa08c7e1 | |||
| 79082f8b6b | |||
| 544c7d68b6 | |||
| 699a82df1a | |||
| d369c098be | |||
| 191448afc5 | |||
| 606fbca6b4 | |||
| 050eb97c33 | |||
| f6f824597a | |||
| f2b4fba61e | |||
| 3a394dd671 | |||
| 98480b3932 | |||
| e010b2e75c | |||
| aa3a9c7895 | |||
| f075ec01ca | |||
| c4c770f48c | |||
| 24ce9b8a10 | |||
| adebc5f811 | |||
| afc19a201c | |||
| aa7707cd52 | |||
| 676c840c5c | |||
| 1222c2125e | |||
| 776b4a85d1 | |||
| 29fe254b17 | |||
| bf84a08900 | |||
| 97043c76b7 | |||
| c1813ed818 | |||
| 49f1803c9d | |||
| 157f8a87b4 | |||
| c66bf80bd8 | |||
| ad25efc776 | |||
| 1019a2b5ba | |||
| 7404858689 | |||
| 7b313f407a | |||
| 931fc89e13 | |||
| fbbfe9aa00 | |||
| b81952a23d | |||
| 12ffcc5097 | |||
| bd1eaea02b | |||
| 99a8358b85 | |||
| 0a352c4790 | |||
| 67dfb55d49 | |||
| 12bd4bc5ad | |||
| 22ec6995ea | |||
| ae3af1d860 |
@@ -0,0 +1,95 @@
|
||||
# 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/behat/axe/
|
||||
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/
|
||||
lib/zipstream/
|
||||
lib/php-enum/
|
||||
lib/http-message/
|
||||
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/scss/fontawesome/
|
||||
@@ -2,14 +2,9 @@
|
||||
'plugins': [
|
||||
'babel',
|
||||
'promise',
|
||||
'jsdoc',
|
||||
],
|
||||
'env': {
|
||||
'browser': true,
|
||||
// Enable ES6+ features by default.
|
||||
// See http://eslint.org/docs/user-guide/configuring#specifying-environments
|
||||
// Note: The YUI override must exactly match this when disabling the ES6+ version because those features are not supported by Shifter.
|
||||
'es2020': true,
|
||||
'amd': true
|
||||
},
|
||||
'globals': {
|
||||
@@ -87,7 +82,6 @@
|
||||
'no-octal-escape': 'error',
|
||||
'no-proto': 'error',
|
||||
'no-redeclare': 'warn',
|
||||
'no-restricted-globals': ['error', { 'name': 'Notification' }],
|
||||
'no-return-assign': 'error',
|
||||
'no-script-url': 'error',
|
||||
'no-self-assign': 'error',
|
||||
@@ -197,42 +191,27 @@
|
||||
'property': 'str',
|
||||
'message': 'Use AMD module "core/str" or M.util.get_string()'
|
||||
}],
|
||||
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/yui/src/**/*.js"],
|
||||
'env': {
|
||||
// Disable ES6+ for YUI files.
|
||||
'es2020': false,
|
||||
},
|
||||
// Disable some rules which we can't safely define for YUI rollups.
|
||||
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',
|
||||
@@ -259,53 +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: {
|
||||
'sourceType': 'module',
|
||||
'requireConfigFile': false,
|
||||
'ecmaVersion': 9,
|
||||
'sourceType': 'module'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Template configuraton file for github actions CI/CD.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com}
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
// This cannot be used out from a github actions workflow, so just exit.
|
||||
getenv('GITHUB_WORKFLOW') || die; // phpcs:ignore moodle.Files.MoodleInternal.MoodleInternalGlobalState
|
||||
|
||||
unset($CFG);
|
||||
global $CFG;
|
||||
$CFG = new stdClass();
|
||||
|
||||
$CFG->dbtype = getenv('dbtype');
|
||||
$CFG->dblibrary = 'native';
|
||||
$CFG->dbhost = '127.0.0.1';
|
||||
$CFG->dbname = 'test';
|
||||
$CFG->dbuser = 'test';
|
||||
$CFG->dbpass = 'test';
|
||||
$CFG->prefix = 'm_';
|
||||
$CFG->dboptions = ['dbcollation' => 'utf8mb4_bin'];
|
||||
|
||||
$host = 'localhost';
|
||||
$CFG->wwwroot = "http://{$host}";
|
||||
$CFG->dataroot = realpath(dirname(__DIR__)) . '/moodledata';
|
||||
$CFG->admin = 'admin';
|
||||
$CFG->directorypermissions = 0777;
|
||||
|
||||
// Debug options - possible to be controlled by flag in future.
|
||||
$CFG->debug = (E_ALL | E_STRICT); // DEBUG_DEVELOPER.
|
||||
$CFG->debugdisplay = 1;
|
||||
$CFG->debugstringids = 1; // Add strings=1 to url to get string ids.
|
||||
$CFG->perfdebug = 15;
|
||||
$CFG->debugpageinfo = 1;
|
||||
$CFG->allowthemechangeonurl = 1;
|
||||
$CFG->passwordpolicy = 0;
|
||||
$CFG->cronclionly = 0;
|
||||
$CFG->pathtophp = getenv('pathtophp');
|
||||
|
||||
$CFG->phpunit_dataroot = realpath(dirname(__DIR__)) . '/phpunitdata';
|
||||
$CFG->phpunit_prefix = 't_';
|
||||
|
||||
define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://localhost:8080');
|
||||
define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://localhost:8080');
|
||||
|
||||
define('TEST_SESSION_REDIS_HOST', 'localhost');
|
||||
define('TEST_CACHESTORE_REDIS_TESTSERVERS', 'localhost');
|
||||
|
||||
// TODO: add others (solr, mongodb, memcached, ldap...).
|
||||
|
||||
// Too much for now: define('PHPUNIT_LONGTEST', true); // Only leaves a few tests out and they are run later by CI.
|
||||
|
||||
require_once(__DIR__ . '/lib/setup.php');
|
||||
@@ -1,117 +0,0 @@
|
||||
name: Core
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- master
|
||||
- MOODLE_[0-9]+_STABLE
|
||||
tags-ignore:
|
||||
- v[0-9]+.[0-9]+.[0-9]+*
|
||||
|
||||
env:
|
||||
php: 8.0
|
||||
|
||||
jobs:
|
||||
Grunt:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checking out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Configuring node & npm
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Installing node stuff
|
||||
run: npm install
|
||||
|
||||
- name: Running grunt
|
||||
run: npx grunt
|
||||
|
||||
- name: Looking for uncommitted changes
|
||||
# Add all files to the git index and then run diff --cached to see all changes.
|
||||
# This ensures that we get the status of all files, including new files.
|
||||
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
|
||||
run: |
|
||||
git add .
|
||||
git reset -- npm-shrinkwrap.json
|
||||
git diff --cached --exit-code
|
||||
|
||||
PHPUnit:
|
||||
runs-on: ${{ matrix.os }}
|
||||
services:
|
||||
exttests:
|
||||
image: moodlehq/moodle-exttests
|
||||
ports:
|
||||
- 8080:80
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
php: 7.3
|
||||
extensions:
|
||||
db: mysqli
|
||||
- os: ubuntu-22.04
|
||||
php: 8.0
|
||||
db: pgsql
|
||||
extensions: xmlrpc-beta
|
||||
|
||||
steps:
|
||||
- name: Setting up DB mysql
|
||||
if: ${{ matrix.db == 'mysqli' }}
|
||||
uses: moodlehq/mysql-action@v1
|
||||
with:
|
||||
collation server: utf8mb4_bin
|
||||
mysql version: 5.7
|
||||
mysql database: test
|
||||
mysql user: test
|
||||
mysql password: test
|
||||
use tmpfs: true
|
||||
tmpfs size: '1024M'
|
||||
extra conf: --skip-log-bin
|
||||
|
||||
- name: Setting up DB pgsql
|
||||
if: ${{ matrix.db == 'pgsql' }}
|
||||
uses: m4nu56/postgresql-action@v1
|
||||
with:
|
||||
postgresql version: 10
|
||||
postgresql db: test
|
||||
postgresql user: test
|
||||
postgresql password: test
|
||||
|
||||
- name: Configuring git vars
|
||||
uses: rlespinasse/github-slug-action@v4
|
||||
|
||||
- name: Setting up PHP ${{ matrix.php }}
|
||||
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 }}
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setting up PHPUnit
|
||||
env:
|
||||
dbtype: ${{ matrix.db }}
|
||||
run: |
|
||||
echo "pathtophp=$(which php)" >> $GITHUB_ENV # Inject installed pathtophp to env. The template config needs it.
|
||||
cp .github/workflows/config-template.php config.php
|
||||
mkdir ../moodledata
|
||||
sudo locale-gen en_AU.UTF-8
|
||||
php admin/tool/phpunit/cli/init.php --no-composer-self-update
|
||||
|
||||
- name: Running PHPUnit tests
|
||||
env:
|
||||
dbtype: ${{ matrix.db }}
|
||||
phpunit_options: ${{ secrets.phpunit_options }}
|
||||
run: vendor/bin/phpunit $phpunit_options
|
||||
-10
@@ -26,7 +26,6 @@
|
||||
/cscope.*
|
||||
/.patches/
|
||||
/.idea/
|
||||
.phpstorm.*
|
||||
/nbproject/
|
||||
CVS
|
||||
.DS_Store
|
||||
@@ -47,12 +46,3 @@ composer.phar
|
||||
atlassian-ide-plugin.xml
|
||||
/node_modules/
|
||||
/.vscode/
|
||||
moodle-plugin-ci.phar
|
||||
.eslintignore
|
||||
.stylelintignore
|
||||
/jsdoc
|
||||
/admin/tool/componentlibrary/docs
|
||||
/admin/tool/componentlibrary/hugo/site/data/my-index.json
|
||||
.hugo_build.lock
|
||||
phpcs.xml
|
||||
jsconfig.json
|
||||
|
||||
@@ -1,244 +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 */
|
||||
|
||||
/** @var {Object} A list of subsystems in Moodle */
|
||||
const componentData = {};
|
||||
|
||||
/**
|
||||
* Load details of all moodle modules.
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
const fetchComponentData = () => {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const glob = require('glob');
|
||||
const gruntFilePath = process.cwd();
|
||||
|
||||
if (!Object.entries(componentData).length) {
|
||||
componentData.subsystems = {};
|
||||
componentData.pathList = [];
|
||||
|
||||
// Fetch the component definiitions from the distributed JSON file.
|
||||
const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`));
|
||||
|
||||
// Build the list of moodle subsystems.
|
||||
componentData.subsystems.lib = 'core';
|
||||
componentData.pathList.push(process.cwd() + path.sep + 'lib');
|
||||
for (const [component, thisPath] of Object.entries(components.subsystems)) {
|
||||
if (thisPath) {
|
||||
// Prefix "core_" to the front of the subsystems.
|
||||
componentData.subsystems[thisPath] = `core_${component}`;
|
||||
componentData.pathList.push(process.cwd() + path.sep + thisPath);
|
||||
}
|
||||
}
|
||||
|
||||
// The list of components incldues the list of subsystems.
|
||||
componentData.components = componentData.subsystems;
|
||||
|
||||
// Go through each of the plugintypes.
|
||||
Object.entries(components.plugintypes).forEach(([pluginType, pluginTypePath]) => {
|
||||
// We don't allow any code in this place..?
|
||||
glob.sync(`${pluginTypePath}/*/version.php`).forEach(versionPath => {
|
||||
const componentPath = fs.realpathSync(path.dirname(versionPath));
|
||||
const componentName = path.basename(componentPath);
|
||||
const frankenstyleName = `${pluginType}_${componentName}`;
|
||||
componentData.components[`${pluginTypePath}/${componentName}`] = frankenstyleName;
|
||||
componentData.pathList.push(componentPath);
|
||||
|
||||
// Look for any subplugins.
|
||||
const subPluginConfigurationFile = `${componentPath}/db/subplugins.json`;
|
||||
if (fs.existsSync(subPluginConfigurationFile)) {
|
||||
const subpluginList = JSON.parse(fs.readFileSync(fs.realpathSync(subPluginConfigurationFile)));
|
||||
|
||||
Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => {
|
||||
glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => {
|
||||
const componentPath = fs.realpathSync(path.dirname(versionPath));
|
||||
const componentName = path.basename(componentPath);
|
||||
const frankenstyleName = `${subpluginType}_${componentName}`;
|
||||
|
||||
componentData.components[`${subpluginTypePath}/${componentName}`] = frankenstyleName;
|
||||
componentData.pathList.push(componentPath);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getAmdSrcGlobList = () => {
|
||||
const globList = [];
|
||||
fetchComponentData().pathList.forEach(componentPath => {
|
||||
globList.push(`${componentPath}/amd/src/*.js`);
|
||||
globList.push(`${componentPath}/amd/src/**/*.js`);
|
||||
});
|
||||
|
||||
return globList;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of paths to build YUI sources.
|
||||
*
|
||||
* @param {String} relativeTo
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getYuiSrcGlobList = relativeTo => {
|
||||
const globList = [];
|
||||
fetchComponentData().pathList.forEach(componentPath => {
|
||||
const relativeComponentPath = componentPath.replace(relativeTo, '');
|
||||
globList.push(`${relativeComponentPath}/yui/src/**/*.js`);
|
||||
});
|
||||
|
||||
return globList;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of paths to thirdpartylibs.xml.
|
||||
*
|
||||
* @param {String} relativeTo
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getThirdPartyLibsList = relativeTo => {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
return fetchComponentData().pathList
|
||||
.map(componentPath => path.relative(relativeTo, componentPath) + '/thirdpartylibs.xml')
|
||||
.map(componentPath => componentPath.replace(/\\/g, '/'))
|
||||
.filter(path => fs.existsSync(path))
|
||||
.sort();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of thirdparty library paths.
|
||||
*
|
||||
* @returns {array}
|
||||
*/
|
||||
const getThirdPartyPaths = () => {
|
||||
const DOMParser = require('@xmldom/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.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {String|null} Name of matching component.
|
||||
*/
|
||||
const getComponentFromPath = path => {
|
||||
const componentList = fetchComponentData().components;
|
||||
|
||||
if (componentList.hasOwnProperty(path)) {
|
||||
return componentList[path];
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether the supplied path, relative to the Gruntfile.js, is in a known component.
|
||||
*
|
||||
* @param {String} checkPath The path to check. This can be with either Windows, or Linux directory separators.
|
||||
* @returns {String|null}
|
||||
*/
|
||||
const getOwningComponentDirectory = checkPath => {
|
||||
const path = require('path');
|
||||
|
||||
// Fetch all components into a reverse sorted array.
|
||||
// This ensures that components which are within the directory of another component match first.
|
||||
const pathList = Object.keys(fetchComponentData().components).sort().reverse();
|
||||
for (const componentPath of pathList) {
|
||||
// If the componentPath is the directory being checked, it will be empty.
|
||||
// If the componentPath is a parent of the directory being checked, the relative directory will not start with ..
|
||||
if (!path.relative(componentPath, checkPath).startsWith('..')) {
|
||||
return componentPath;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
fetchComponentData,
|
||||
getAmdSrcGlobList,
|
||||
getComponentFromPath,
|
||||
getComponentPaths,
|
||||
getOwningComponentDirectory,
|
||||
getYuiSrcGlobList,
|
||||
getThirdPartyLibsList,
|
||||
getThirdPartyPaths,
|
||||
};
|
||||
@@ -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,140 +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 */
|
||||
|
||||
/**
|
||||
* Component Library build tasks.
|
||||
*
|
||||
* @copyright 2021 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
|
||||
/**
|
||||
* Get a child path of the component library.
|
||||
*
|
||||
* @param {string} path
|
||||
* @returns {string}
|
||||
*/
|
||||
const getCLPath = path => `admin/tool/componentlibrary/${path}`;
|
||||
|
||||
/**
|
||||
* Get a spawn handler.
|
||||
*
|
||||
* This is a generic function to write the spawn output, and then to exit if required and mark the async task as
|
||||
* complete.
|
||||
*
|
||||
* @param {Promise} done
|
||||
* @returns {function}
|
||||
*/
|
||||
const getSpawnHandler = done => (error, result, code) => {
|
||||
grunt.log.write(result);
|
||||
|
||||
if (error) {
|
||||
process.exit(code);
|
||||
}
|
||||
done();
|
||||
};
|
||||
|
||||
/**
|
||||
* Spawn a function against Node with the provided args.
|
||||
*
|
||||
* @param {array} args
|
||||
* @returns {object}
|
||||
*/
|
||||
const spawnNodeCall = args => grunt.util.spawn({
|
||||
cmd: 'node',
|
||||
args,
|
||||
}, getSpawnHandler(grunt.task.current.async()));
|
||||
|
||||
/**
|
||||
* Build the docs using Hugo.
|
||||
*
|
||||
* @returns {Object} Reference to the spawned task
|
||||
*/
|
||||
const docsBuild = () => spawnNodeCall([
|
||||
'node_modules/hugo-bin/cli.js',
|
||||
'--config', getCLPath('config.yml'),
|
||||
'--cleanDestinationDir',
|
||||
]);
|
||||
|
||||
/**
|
||||
* Build the docs index using the hugo-lunr-indexer.
|
||||
*
|
||||
* @returns {Object} Reference to the spawned task
|
||||
*/
|
||||
const indexBuild = () => spawnNodeCall([
|
||||
'node_modules/hugo-lunr-indexer/bin/hli.js',
|
||||
'-i', getCLPath('content/**'),
|
||||
'-o', getCLPath('hugo/site/data/my-index.json'),
|
||||
'-l', 'yaml',
|
||||
'-d', '---',
|
||||
]);
|
||||
|
||||
/**
|
||||
* Build the hugo CSS.
|
||||
*
|
||||
* @returns {Object} Reference to the spawned task
|
||||
*/
|
||||
const cssBuild = () => spawnNodeCall([
|
||||
'node_modules/node-sass/bin/node-sass',
|
||||
'--output-style', 'expanded',
|
||||
'--source-map', true,
|
||||
'--source-map-contents', true,
|
||||
'--precision', 6,
|
||||
getCLPath('hugo/scss/docs.scss'),
|
||||
'-o', getCLPath('hugo/dist/css/'),
|
||||
]);
|
||||
|
||||
// Register the various component library tasks.
|
||||
grunt.registerTask('componentlibrary:docsBuild', 'Build the component library', docsBuild);
|
||||
grunt.registerTask('componentlibrary:cssBuild', 'Build the component library', cssBuild);
|
||||
grunt.registerTask('componentlibrary:indexBuild', 'Build the component library', indexBuild);
|
||||
grunt.registerTask('componentlibrary', 'Build the component library', [
|
||||
'componentlibrary:docsBuild',
|
||||
'componentlibrary:cssBuild',
|
||||
'componentlibrary:indexBuild',
|
||||
]);
|
||||
|
||||
grunt.config.merge({
|
||||
watch: {
|
||||
componentLibraryDocs: {
|
||||
files: [
|
||||
getCLPath('content/**/*.md'),
|
||||
getCLPath('hugo'),
|
||||
],
|
||||
tasks: ['componentlibrary:docsBuild', 'componentlibrary:indexBuild'],
|
||||
},
|
||||
componentLibraryCSS: {
|
||||
files: [
|
||||
getCLPath('hugo/scss/**/*.scss'),
|
||||
'hugo',
|
||||
],
|
||||
tasks: ['componentlibrary:cssBuild'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Add the 'componentlibrary' task as a startup task.
|
||||
grunt.moodleEnv.startupTasks.push('componentlibrary');
|
||||
|
||||
return {
|
||||
docsBuild,
|
||||
cssBuild,
|
||||
indexBuild,
|
||||
};
|
||||
};
|
||||
@@ -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,92 +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'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Add the 'gherkinlint' task as a startup task.
|
||||
grunt.moodleEnv.startupTasks.push('gherkinlint');
|
||||
|
||||
return handler;
|
||||
};
|
||||
@@ -1,100 +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 the PHPCS configuration.
|
||||
*
|
||||
* @param {Object} thirdPartyPaths
|
||||
*/
|
||||
const phpcsIgnore = (thirdPartyPaths) => {
|
||||
const {toXML} = require('jstoxml');
|
||||
|
||||
const config = {
|
||||
_name: 'ruleset',
|
||||
_attrs: {
|
||||
name: "MoodleCore",
|
||||
},
|
||||
_content: [
|
||||
{
|
||||
rule: {
|
||||
_attrs: {
|
||||
ref: './phpcs.xml.dist',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
thirdPartyPaths.forEach(library => {
|
||||
config._content.push({
|
||||
'exclude-pattern': library,
|
||||
});
|
||||
});
|
||||
|
||||
grunt.file.write('phpcs.xml', toXML(config, {
|
||||
header: true,
|
||||
indent: ' ',
|
||||
}) + "\n");
|
||||
};
|
||||
|
||||
/**
|
||||
* 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',
|
||||
'admin/tool/componentlibrary/hugo/dist/css/docs.css',
|
||||
].concat(thirdPartyPaths);
|
||||
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n') + '\n');
|
||||
|
||||
phpcsIgnore(thirdPartyPaths);
|
||||
};
|
||||
|
||||
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', handler);
|
||||
|
||||
return handler;
|
||||
};
|
||||
@@ -1,227 +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(`amd/src`, `amd/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 jsconfig.
|
||||
require('./jsconfig')(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.3%",
|
||||
"last 2 versions",
|
||||
"not ie >= 0",
|
||||
"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']
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Add the 'js' task as a startup task.
|
||||
grunt.moodleEnv.startupTasks.push('js');
|
||||
|
||||
// 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,53 +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 2022 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
const configuration = {
|
||||
compilerOptions: {
|
||||
baseUrl: ".",
|
||||
paths: {
|
||||
},
|
||||
target: "es2015",
|
||||
allowSyntheticDefaultImports: false,
|
||||
},
|
||||
exclude: [
|
||||
"node_modules",
|
||||
],
|
||||
include: [],
|
||||
};
|
||||
|
||||
module.exports = (grunt) => {
|
||||
const handler = () => {
|
||||
const jsconfigData = Object.assign({}, configuration);
|
||||
|
||||
const path = require('path');
|
||||
const {fetchComponentData} = require(path.join(process.cwd(), '.grunt', 'components.js'));
|
||||
|
||||
const componentData = fetchComponentData().components;
|
||||
for (const [thisPath, component] of Object.entries(componentData)) {
|
||||
jsconfigData.compilerOptions.paths[`${component}/*`] = [`${thisPath}/amd/src/*`];
|
||||
jsconfigData.include.push(`${thisPath}/amd/src/**/*`);
|
||||
}
|
||||
|
||||
grunt.file.write('jsconfig.json', JSON.stringify(jsconfigData, null, " ") + "\n");
|
||||
};
|
||||
grunt.registerTask('jsconfig', 'Generate a jsconfig configuration compatible with the LSP', handler);
|
||||
};
|
||||
@@ -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,46 +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 all of the requested startup tasks.
|
||||
grunt.moodleEnv.startupTasks.forEach(taskName => grunt.task.run(taskName));
|
||||
}
|
||||
};
|
||||
|
||||
// Register the startup task.
|
||||
grunt.registerTask('startup', 'Run the correct tasks for the current directory', handler);
|
||||
|
||||
return handler;
|
||||
};
|
||||
@@ -1,35 +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);
|
||||
|
||||
// Add the 'css' task as a startup task.
|
||||
grunt.moodleEnv.startupTasks.push('css');
|
||||
};
|
||||
@@ -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,96 @@
|
||||
# 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/behat/axe/
|
||||
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/
|
||||
lib/zipstream/
|
||||
lib/php-enum/
|
||||
lib/http-message/
|
||||
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/scss/fontawesome/
|
||||
+78
-45
@@ -10,20 +10,36 @@ language: php
|
||||
|
||||
os: linux
|
||||
|
||||
dist: bionic
|
||||
dist: xenial
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- docker
|
||||
|
||||
addons:
|
||||
postgresql: "10"
|
||||
php:
|
||||
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
|
||||
- 7.4
|
||||
- 7.2
|
||||
|
||||
branches:
|
||||
except:
|
||||
- master
|
||||
- /MOODLE_[0-9]+_STABLE/
|
||||
- /^v[0-9]+\.[0-9]+\.[0-9]+.*/
|
||||
addons:
|
||||
postgresql: "9.6"
|
||||
|
||||
env:
|
||||
# Although we want to run these jobs and see failures as quickly as possible, we also want to get the slowest job to
|
||||
# start first so that the total run time is not too high.
|
||||
#
|
||||
# We only run MySQL on PHP 7.2, so run that first.
|
||||
# CI Tests should be second-highest in priority as these only take <= 60 seconds to run under normal circumstances.
|
||||
# Postgres is significantly is pretty reasonable in its run-time.
|
||||
|
||||
# Run CI Tests without running PHPUnit.
|
||||
- DB=none TASK=CITEST
|
||||
|
||||
# Run unit tests on Postgres
|
||||
- DB=pgsql TASK=PHPUNIT
|
||||
|
||||
# Perform an upgrade test too.
|
||||
- DB=pgsql TASK=UPGRADE
|
||||
|
||||
jobs:
|
||||
# Enable fast finish.
|
||||
@@ -32,35 +48,12 @@ jobs:
|
||||
fast_finish: true
|
||||
|
||||
include:
|
||||
# First all the lowest php ones (7.3)
|
||||
- php: 7.3
|
||||
env: DB=none TASK=CITEST
|
||||
- php: 7.3
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/gallium'
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present
|
||||
php: 7.3
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
|
||||
php: 7.3
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
|
||||
# Then, conditionally, all the highest php ones (8.0)
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 8.0
|
||||
env: DB=none TASK=CITEST
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 8.0
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/gallium'
|
||||
|
||||
- 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
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
|
||||
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
|
||||
php: 8.0
|
||||
# Run mysql only on highest - it's just too slow
|
||||
- php: 7.4
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
# Run grunt/npm install on highest version too ('node' is an alias for the latest node.js version.)
|
||||
- php: 7.4
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@@ -81,8 +74,7 @@ install:
|
||||
sudo service mysql stop
|
||||
sudo mv /var/lib/mysql /mnt/ramdisk
|
||||
sudo ln -s /mnt/ramdisk/mysql /var/lib/mysql
|
||||
echo -e "[mysqld]\nskip-log-bin" | sudo tee -a /etc/mysql/my.cnf
|
||||
sudo service mysql start
|
||||
sudo service mysql restart
|
||||
fi
|
||||
- >
|
||||
if [ "$DB" = 'pgsql' ];
|
||||
@@ -93,7 +85,6 @@ install:
|
||||
sudo mv /var/lib/postgresql /mnt/ramdisk
|
||||
sudo ln -s /mnt/ramdisk/postgresql /var/lib/postgresql
|
||||
sudo service postgresql start 9.6
|
||||
sh -c 'until pg_isready -p 5432; do echo "Waiting for the DB to be up..."; sleep 2; done'
|
||||
fi
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
@@ -120,11 +111,9 @@ 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' ];
|
||||
if [ "$TASK" = 'PHPUNIT' -o "$TASK" = 'UPGRADE' ];
|
||||
then
|
||||
# Copy generic configuration in place.
|
||||
cp config-dist.php config.php ;
|
||||
@@ -191,9 +180,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.
|
||||
@@ -223,7 +213,7 @@ before_script:
|
||||
# We need the official upstream for comparison
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
git fetch upstream MOODLE_400_STABLE;
|
||||
git fetch upstream MOODLE_310_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`
|
||||
@@ -234,6 +224,32 @@ before_script:
|
||||
export phpcmd=`which php`;
|
||||
fi
|
||||
|
||||
########################################################################
|
||||
# Upgrade test
|
||||
########################################################################
|
||||
- >
|
||||
if [ "$TASK" = 'UPGRADE' ];
|
||||
then
|
||||
# We need the official upstream.
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
# Checkout 30 STABLE branch (the first version compatible with PHP 7.x)
|
||||
git fetch upstream MOODLE_30_STABLE;
|
||||
git checkout MOODLE_30_STABLE;
|
||||
|
||||
# Perform the upgrade
|
||||
php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
|
||||
|
||||
# Return to the previous commit
|
||||
git checkout -;
|
||||
|
||||
# Perform the upgrade
|
||||
php admin/cli/upgrade.php --non-interactive --allow-unstable ;
|
||||
|
||||
# The local_ci repository can be used to check upgrade savepoints.
|
||||
git clone https://github.com/moodlehq/moodle-local_ci.git local/ci ;
|
||||
fi
|
||||
|
||||
script:
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
@@ -259,6 +275,23 @@ script:
|
||||
git diff --cached --exit-code ;
|
||||
fi
|
||||
|
||||
########################################################################
|
||||
# Upgrade test
|
||||
########################################################################
|
||||
- >
|
||||
if [ "$TASK" = 'UPGRADE' ];
|
||||
then
|
||||
cp local/ci/check_upgrade_savepoints/check_upgrade_savepoints.php ./check_upgrade_savepoints.php
|
||||
result=`php check_upgrade_savepoints.php`;
|
||||
# Check if there are problems
|
||||
count=`echo "$result" | grep -P "ERROR|WARN" | wc -l` ;
|
||||
if (($count > 0));
|
||||
then
|
||||
echo "$result"
|
||||
exit 1 ;
|
||||
fi
|
||||
fi
|
||||
|
||||
after_script:
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
|
||||
+762
-168
@@ -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,80 +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;
|
||||
};
|
||||
|
||||
// Startup tasks.
|
||||
grunt.moodleEnv.startupTasks = [];
|
||||
/**
|
||||
* 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);
|
||||
addTask('componentlibrary', 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']);
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
// 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 */
|
||||
|
||||
/** @var {Object} A list of subsystems in Moodle */
|
||||
const componentData = {};
|
||||
|
||||
/**
|
||||
* Load details of all moodle modules.
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
const fetchComponentData = () => {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const glob = require('glob');
|
||||
const gruntFilePath = process.cwd();
|
||||
|
||||
if (!Object.entries(componentData).length) {
|
||||
componentData.subsystems = {};
|
||||
componentData.pathList = [];
|
||||
|
||||
// Fetch the component definiitions from the distributed JSON file.
|
||||
const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`));
|
||||
|
||||
// Build the list of moodle subsystems.
|
||||
componentData.subsystems.lib = 'core';
|
||||
componentData.pathList.push(process.cwd() + path.sep + 'lib');
|
||||
for (const [component, thisPath] of Object.entries(components.subsystems)) {
|
||||
if (thisPath) {
|
||||
// Prefix "core_" to the front of the subsystems.
|
||||
componentData.subsystems[thisPath] = `core_${component}`;
|
||||
componentData.pathList.push(process.cwd() + path.sep + thisPath);
|
||||
}
|
||||
}
|
||||
|
||||
// The list of components incldues the list of subsystems.
|
||||
componentData.components = componentData.subsystems;
|
||||
|
||||
// Go through each of the plugintypes.
|
||||
Object.entries(components.plugintypes).forEach(([pluginType, pluginTypePath]) => {
|
||||
// We don't allow any code in this place..?
|
||||
glob.sync(`${pluginTypePath}/*/version.php`).forEach(versionPath => {
|
||||
const componentPath = fs.realpathSync(path.dirname(versionPath));
|
||||
const componentName = path.basename(componentPath);
|
||||
const frankenstyleName = `${pluginType}_${componentName}`;
|
||||
componentData.components[`${pluginTypePath}/${componentName}`] = frankenstyleName;
|
||||
componentData.pathList.push(componentPath);
|
||||
|
||||
// Look for any subplugins.
|
||||
const subPluginConfigurationFile = `${componentPath}/db/subplugins.json`;
|
||||
if (fs.existsSync(subPluginConfigurationFile)) {
|
||||
const subpluginList = JSON.parse(fs.readFileSync(fs.realpathSync(subPluginConfigurationFile)));
|
||||
|
||||
Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => {
|
||||
glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => {
|
||||
const componentPath = fs.realpathSync(path.dirname(versionPath));
|
||||
const componentName = path.basename(componentPath);
|
||||
const frankenstyleName = `${subpluginType}_${componentName}`;
|
||||
|
||||
componentData.components[`${subpluginTypePath}/${componentName}`] = frankenstyleName;
|
||||
componentData.pathList.push(componentPath);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return componentData;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of paths to build AMD sources.
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getAmdSrcGlobList = () => {
|
||||
const globList = [];
|
||||
fetchComponentData().pathList.forEach(componentPath => {
|
||||
globList.push(`${componentPath}/amd/src/*.js`);
|
||||
globList.push(`${componentPath}/amd/src/**/*.js`);
|
||||
});
|
||||
|
||||
return globList;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of paths to build YUI sources.
|
||||
*
|
||||
* @param {String} relativeTo
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getYuiSrcGlobList = relativeTo => {
|
||||
const globList = [];
|
||||
fetchComponentData().pathList.forEach(componentPath => {
|
||||
const relativeComponentPath = componentPath.replace(relativeTo, '');
|
||||
globList.push(`${relativeComponentPath}/yui/src/**/*.js`);
|
||||
});
|
||||
|
||||
return globList;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of paths to thirdpartylibs.xml.
|
||||
*
|
||||
* @param {String} relativeTo
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getThirdPartyLibsList = relativeTo => {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
return fetchComponentData().pathList
|
||||
.map(componentPath => path.relative(relativeTo, componentPath) + '/thirdpartylibs.xml')
|
||||
.map(componentPath => componentPath.replace(/\\/g, '/'))
|
||||
.filter(path => fs.existsSync(path))
|
||||
.sort();
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the name of the component matching the specified path.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {String|null} Name of matching component.
|
||||
*/
|
||||
const getComponentFromPath = path => {
|
||||
const componentList = fetchComponentData().components;
|
||||
|
||||
if (componentList.hasOwnProperty(path)) {
|
||||
return componentList[path];
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether the supplied path, relative to the Gruntfile.js, is in a known component.
|
||||
*
|
||||
* @param {String} checkPath The path to check. This can be with either Windows, or Linux directory separators.
|
||||
* @returns {String|null}
|
||||
*/
|
||||
const getOwningComponentDirectory = checkPath => {
|
||||
const path = require('path');
|
||||
|
||||
// Fetch all components into a reverse sorted array.
|
||||
// This ensures that components which are within the directory of another component match first.
|
||||
const pathList = Object.keys(fetchComponentData().components).sort().reverse();
|
||||
for (const componentPath of pathList) {
|
||||
// If the componentPath is the directory being checked, it will be empty.
|
||||
// If the componentPath is a parent of the directory being checked, the relative directory will not start with ..
|
||||
if (!path.relative(componentPath, checkPath).startsWith('..')) {
|
||||
return componentPath;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getAmdSrcGlobList,
|
||||
getComponentFromPath,
|
||||
getOwningComponentDirectory,
|
||||
getYuiSrcGlobList,
|
||||
getThirdPartyLibsList,
|
||||
};
|
||||
+35
-53
@@ -1,66 +1,48 @@
|
||||
MOODLE TRADEMARKS POLICY
|
||||
========================
|
||||
|
||||
The Moodle Trademark
|
||||
--------------------
|
||||
The word "Moodle" is trademarked in many countries around the world. The word
|
||||
was originally an acronym: Modular Object-Oriented Dynamic Learning
|
||||
Environment. The trademark is owned by Martin Dougiamas, Founder and Director
|
||||
of Moodle.
|
||||
|
||||
The brand and word "Moodle" has trade mark protection in many countries around
|
||||
the world. Various Moodle™ trade marks are owned by either Moodle Pty Ltd or
|
||||
one of its associated entities. The law obligates trade mark owners to police
|
||||
their trade marks and prevent the use of confusingly similar names by
|
||||
third parties.
|
||||
The law obligates trademark owners to police their marks and prevent the use of
|
||||
confusingly similar names by third parties. Through this policy we’d like to
|
||||
make it clear how Moodle-related projects, organisations, and people can use
|
||||
the Moodle trademark. We’d also like to be clear about how use of the word is
|
||||
restricted when used to promote commercial Moodle services. We do this to
|
||||
protect the very business model that allows us to continue developing Moodle
|
||||
for you.
|
||||
|
||||
We have created a more concise and thorough set of Trademark Guidelines
|
||||
(https://moodle.com/wp-content/uploads/2023/02/Moodle-Trademark-Guidelines-2023-4.pdf)
|
||||
to help you understand how to comply with Moodle's trade mark requirements.
|
||||
The Trademark Guidelines will also assist our Moodle Certified Partners and the
|
||||
community to understand some of the principles that inform Moodle's stance
|
||||
whenever potential infringement has been detected by us or our community.
|
||||
Allowed uses
|
||||
------------
|
||||
|
||||
We need to be clear about use of the word "Moodle" and how we restrict its use
|
||||
when promoting commercial Moodle™ branded services. The proper use of
|
||||
trade marks reliably assures consumers about the quality of the associated
|
||||
products or services and where they have been derived from. Because the
|
||||
Moodle LMS is made available under the open source ‘GNU General Public License'
|
||||
that permits you to modify the copyrighted software, the distribution of such
|
||||
modified software in combination with Moodle trade marks can potentially
|
||||
mislead others in the community. To be clear, the GNU GPL does not include an
|
||||
implied right or licence to use Moodle's trade marks.
|
||||
The following uses don’t require any permission at all:
|
||||
|
||||
We do all this to protect the very business model that allows us to continue
|
||||
developing various Moodle software solutions for you.
|
||||
|
||||
Allowed uses of "Moodle"
|
||||
------------------------
|
||||
|
||||
The following uses don't require any permission at all:
|
||||
|
||||
* Referring to the software or the Moodle project as the "Moodle™ software"
|
||||
or the "Moodle™ project"
|
||||
* Describing your own implementation of the Moodle™ software platform
|
||||
(including within corporate settings).
|
||||
* Referring to the software or the Moodle project.
|
||||
* Describing your own Moodle implementation (including within corporate
|
||||
settings).
|
||||
* Describing a Moodle-based community hub.
|
||||
* Describing certain software you've made that integrates with Moodle™
|
||||
branded software (e.g. a Moodle™ integration feature on another system).
|
||||
* Describing some software you’ve made that integrates with Moodle
|
||||
(eg a Moodle integration feature on another system).
|
||||
|
||||
Restricted uses of "Moodle"
|
||||
---------------------------
|
||||
Restricted uses
|
||||
---------------
|
||||
|
||||
The following uses are generally prohibited without explicit and direct
|
||||
permission being granted to you by Moodle Pty Ltd. We do this to protect the
|
||||
Moodle™ project from software and sites which could confuse people. If in
|
||||
doubt, reach out for clarification at <trademarks@moodle.com>
|
||||
Moodle project from software and sites which could confuse people. Please
|
||||
contact us to ask for permission in writing.
|
||||
|
||||
* You can't use the word "Moodle" or any Moodle logos for commercial purposes
|
||||
without prior written permission from Moodle HQ.
|
||||
* You can't use "Moodle" in the name of your software (including Mobile apps).
|
||||
* You can't use "Moodle" in your company name.
|
||||
* You can't use "Moodle" in your domain name.
|
||||
* You can't use "Moodle" in advertising-related keywords (such as Adsense).
|
||||
* You can't use "Moodle" to describe services around Moodle
|
||||
(such as hosting, training, support, consulting, course creation services,
|
||||
theme development, customisation, installation, integration, analytics
|
||||
and certification) that cause consumers to be confused that you are
|
||||
associated with Moodle HQ if you are not.
|
||||
This applies even if you do not charge for the services.
|
||||
Note that usually only Moodle Partners have this permission.
|
||||
* You can’t use "Moodle" in the name of your software (including Mobile apps)
|
||||
* You can’t use "Moodle" in your company name
|
||||
* You can’t use "Moodle" in your domain name
|
||||
* You can’t use "Moodle" in advertising-related keywords (such as Adsense)
|
||||
* You can’t use "Moodle" to describe services around Moodle (such as hosting,
|
||||
training, support, consulting, course creation services, theme development,
|
||||
customisation, installation, integration and certification). This applies
|
||||
even if you do not charge for the services. Note that usually only Moodle
|
||||
Partners have this permission.
|
||||
|
||||
For information about the Moodle Partner Certification Mark as well as for how
|
||||
to contact us, please see <https://moodle.com/trademarks/>.
|
||||
|
||||
+8
-14
@@ -54,19 +54,18 @@ if (!confirm_sesskey()) {
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
$needsupdate = false;
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
// Remove from enabled list.
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('antivirus');
|
||||
$class::enable_plugin($antivirus, false);
|
||||
$key = array_search($antivirus, $activeantiviruses);
|
||||
unset($activeantiviruses[$key]);
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
// Add to enabled list.
|
||||
if (!in_array($antivirus, $activeantiviruses)) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('antivirus');
|
||||
$class::enable_plugin($antivirus, true);
|
||||
$activeantiviruses[] = $antivirus;
|
||||
$activeantiviruses = array_unique($activeantiviruses);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -79,7 +78,6 @@ switch ($action) {
|
||||
$fsave = $activeantiviruses[$key];
|
||||
$activeantiviruses[$key] = $activeantiviruses[$key + 1];
|
||||
$activeantiviruses[$key + 1] = $fsave;
|
||||
$needsupdate = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -93,7 +91,6 @@ switch ($action) {
|
||||
$fsave = $activeantiviruses[$key];
|
||||
$activeantiviruses[$key] = $activeantiviruses[$key - 1];
|
||||
$activeantiviruses[$key - 1] = $fsave;
|
||||
$needsupdate = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -101,13 +98,10 @@ switch ($action) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$new = implode(',', $activeantiviruses);
|
||||
add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core');
|
||||
set_config('antiviruses', $new);
|
||||
|
||||
if ($needsupdate) {
|
||||
$new = implode(',', $activeantiviruses);
|
||||
add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core');
|
||||
set_config('antiviruses', $new);
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
|
||||
core_plugin_manager::reset_caches();
|
||||
|
||||
redirect ($returnurl);
|
||||
|
||||
+24
-12
@@ -40,15 +40,29 @@ if (!confirm_sesskey()) {
|
||||
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
// Remove from enabled list.
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('auth');
|
||||
$class::enable_plugin($auth, false);
|
||||
// remove from enabled list
|
||||
$key = array_search($auth, $authsenabled);
|
||||
if ($key !== false) {
|
||||
unset($authsenabled[$key]);
|
||||
set_config('auth', implode(',', $authsenabled));
|
||||
}
|
||||
|
||||
if ($auth == $CFG->registerauth) {
|
||||
set_config('registerauth', '');
|
||||
}
|
||||
\core\session\manager::gc(); // Remove stale sessions.
|
||||
core_plugin_manager::reset_caches();
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
// Add to enabled list.
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('auth');
|
||||
$class::enable_plugin($auth, true);
|
||||
// add to enabled list
|
||||
if (!in_array($auth, $authsenabled)) {
|
||||
$authsenabled[] = $auth;
|
||||
$authsenabled = array_unique($authsenabled);
|
||||
set_config('auth', implode(',', $authsenabled));
|
||||
}
|
||||
\core\session\manager::gc(); // Remove stale sessions.
|
||||
core_plugin_manager::reset_caches();
|
||||
break;
|
||||
|
||||
case 'down':
|
||||
@@ -62,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;
|
||||
|
||||
@@ -79,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;
|
||||
|
||||
@@ -90,3 +100,5 @@ switch ($action) {
|
||||
}
|
||||
|
||||
redirect($returnurl);
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+15
-16
@@ -30,28 +30,26 @@
|
||||
$strprotect = get_string('blockprotect', 'admin');
|
||||
$strunprotect = get_string('blockunprotect', 'admin');
|
||||
|
||||
/// If data submitted, then process and store.
|
||||
|
||||
// If data submitted, then process and store.
|
||||
if (!empty($hide) && confirm_sesskey()) {
|
||||
if (!$block = $DB->get_record('block', ['id' => $hide])) {
|
||||
throw new \moodle_exception('blockdoesnotexist', 'error');
|
||||
if (!$block = $DB->get_record('block', array('id'=>$hide))) {
|
||||
print_error('blockdoesnotexist', 'error');
|
||||
}
|
||||
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('block');
|
||||
$class::enable_plugin($block->name, false);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
$DB->set_field('block', 'visible', '0', array('id'=>$block->id)); // Hide block
|
||||
add_to_config_log('block_visibility', $block->visible, '0', $block->name);
|
||||
core_plugin_manager::reset_caches();
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
}
|
||||
|
||||
if (!empty($show) && confirm_sesskey() ) {
|
||||
if (!$block = $DB->get_record('block', ['id' => $show])) {
|
||||
throw new \moodle_exception('blockdoesnotexist', 'error');
|
||||
if (!$block = $DB->get_record('block', array('id'=>$show))) {
|
||||
print_error('blockdoesnotexist', 'error');
|
||||
}
|
||||
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('block');
|
||||
$class::enable_plugin($block->name, true);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
$DB->set_field('block', 'visible', '1', array('id'=>$block->id)); // Show block
|
||||
add_to_config_log('block_visibility', $block->visible, '1', $block->name);
|
||||
core_plugin_manager::reset_caches();
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
}
|
||||
|
||||
if (!empty($protect) && confirm_sesskey()) {
|
||||
@@ -69,7 +67,6 @@
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($strmanageblocks);
|
||||
|
||||
echo $OUTPUT->notification(get_string('noteunneededblocks', 'admin'), 'info');
|
||||
/// Main display starts here
|
||||
|
||||
/// Get and sort the existing blocks
|
||||
@@ -237,3 +234,5 @@
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
|
||||
|
||||
+8
-11
@@ -48,12 +48,6 @@ if (!($settingspage->check_access())) {
|
||||
print_error('accessdenied', 'admin');
|
||||
}
|
||||
|
||||
$hassiteconfig = has_capability('moodle/site:config', $PAGE->context);
|
||||
if ($hassiteconfig) {
|
||||
$PAGE->add_header_action($OUTPUT->render_from_template('core_admin/header_search_input', [
|
||||
'action' => new moodle_url('/admin/search.php'),
|
||||
]));
|
||||
}
|
||||
|
||||
$statusmsg = '';
|
||||
$errormsg = '';
|
||||
@@ -81,7 +75,7 @@ if ($PAGE->user_allowed_editing() && $adminediting != -1) {
|
||||
$USER->editing = $adminediting;
|
||||
}
|
||||
$buttons = null;
|
||||
if ($PAGE->user_allowed_editing() && !$PAGE->theme->haseditswitch) {
|
||||
if ($PAGE->user_allowed_editing()) {
|
||||
$url = clone($PAGE->url);
|
||||
if ($PAGE->user_is_editing()) {
|
||||
$caption = get_string('blockseditoff');
|
||||
@@ -146,7 +140,13 @@ if ($errormsg !== '') {
|
||||
echo $OUTPUT->notification($statusmsg, 'notifysuccess');
|
||||
}
|
||||
|
||||
echo $OUTPUT->heading(get_string('admincategory', 'admin', $settingspage->visiblename), 2);
|
||||
$path = array_reverse($settingspage->visiblepath);
|
||||
if (is_array($path)) {
|
||||
$visiblename = join(' / ', $path);
|
||||
} else {
|
||||
$visiblename = $path;
|
||||
}
|
||||
echo $OUTPUT->heading(get_string('admincategory', 'admin', $visiblename), 2);
|
||||
|
||||
echo html_writer::start_tag('form', array('action' => '', 'method' => 'post', 'id' => 'adminsettings'));
|
||||
echo html_writer::start_tag('div');
|
||||
@@ -158,7 +158,4 @@ echo $outputhtml;
|
||||
echo html_writer::end_tag('fieldset');
|
||||
echo html_writer::end_tag('form');
|
||||
|
||||
// Add the form change checker.
|
||||
$PAGE->requires->js_call_amd('core_form/changechecker', 'watchFormById', ['adminsettings']);
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -48,17 +48,6 @@ class testoutgoingmailconf_form extends \moodleform {
|
||||
$mform->setType('recipient', PARAM_EMAIL);
|
||||
$mform->addRule('recipient', get_string('required'), 'required');
|
||||
|
||||
// From user.
|
||||
$options = ['maxlength' => '100', 'size' => '25'];
|
||||
$mform->addElement('text', 'from', get_string('testoutgoingmailconf_fromemail', 'admin'), $options);
|
||||
$mform->setType('from', PARAM_TEXT);
|
||||
$mform->addHelpButton('from', 'testoutgoingmailconf_fromemail', 'admin');
|
||||
|
||||
// Additional subject text.
|
||||
$options = ['size' => '25'];
|
||||
$mform->addElement('text', 'additionalsubject', get_string('testoutgoingmailconf_subjectadditional', 'admin'), $options);
|
||||
$mform->setType('additionalsubject', PARAM_TEXT);
|
||||
|
||||
$buttonarray = array();
|
||||
$buttonarray[] = $mform->createElement('submit', 'send', get_string('testoutgoingmailconf_sendtest', 'admin'));
|
||||
$buttonarray[] = $mform->createElement('cancel');
|
||||
@@ -67,26 +56,4 @@ class testoutgoingmailconf_form extends \moodleform {
|
||||
$mform->closeHeaderBefore('buttonar');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Form field, should be a valid email format or a username that matches with a Moodle user.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $files
|
||||
* @return array
|
||||
* @throws \dml_exception|\coding_exception
|
||||
*/
|
||||
public function validation($data, $files): array {
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
if (isset($data['from']) && $data['from']) {
|
||||
$userfrom = \core_user::get_user_by_username($data['from']);
|
||||
|
||||
if (!$userfrom && !validate_email($data['from'])) {
|
||||
$errors['from'] = get_string('testoutgoingmailconf_fromemail_invalid', 'admin');
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,304 +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/>.
|
||||
|
||||
namespace core_admin\local\entities;
|
||||
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\duration;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\helpers\format;
|
||||
use lang_string;
|
||||
use core_reportbuilder\local\entities\base;
|
||||
use core_reportbuilder\local\report\column;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Task log entity class implementation
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class task_log extends base {
|
||||
|
||||
/** @var int Result success */
|
||||
protected const SUCCESS = 0;
|
||||
|
||||
/** @var int Result failed */
|
||||
protected const FAILED = 1;
|
||||
|
||||
/**
|
||||
* Database tables that this entity uses and their default aliases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_default_table_aliases(): array {
|
||||
return ['task_log' => 'tl'];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default title for this entity in the list of columns/conditions/filters in the report builder
|
||||
*
|
||||
* @return lang_string
|
||||
*/
|
||||
protected function get_default_entity_title(): lang_string {
|
||||
return new lang_string('entitytasklog', 'admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* The default machine-readable name for this entity that will be used in the internal names of the columns/filters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_default_entity_name(): string {
|
||||
return 'task_log';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the entity
|
||||
*
|
||||
* @return base
|
||||
*/
|
||||
public function initialise(): base {
|
||||
$columns = $this->get_all_columns();
|
||||
foreach ($columns as $column) {
|
||||
$this->add_column($column);
|
||||
}
|
||||
|
||||
$filters = $this->get_all_filters();
|
||||
foreach ($filters as $filter) {
|
||||
$this->add_filter($filter);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all available columns
|
||||
*
|
||||
* @return column[]
|
||||
*/
|
||||
protected function get_all_columns(): array {
|
||||
|
||||
$tablealias = $this->get_table_alias('task_log');
|
||||
|
||||
// Name column.
|
||||
$columns[] = (new column(
|
||||
'name',
|
||||
new lang_string('name'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("$tablealias.classname")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(string $value): string {
|
||||
$output = '';
|
||||
if (class_exists($value)) {
|
||||
$task = new $value;
|
||||
if ($task instanceof \core\task\scheduled_task) {
|
||||
$output = $task->get_name();
|
||||
}
|
||||
}
|
||||
$output .= \html_writer::tag('div', "\\{$value}", [
|
||||
'class' => 'task-class',
|
||||
]);
|
||||
return $output;
|
||||
});
|
||||
|
||||
// Type column.
|
||||
$columns[] = (new column(
|
||||
'type',
|
||||
new lang_string('tasktype', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_field("{$tablealias}.type")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(int $value): string {
|
||||
if (\core\task\database_logger::TYPE_SCHEDULED === $value) {
|
||||
return get_string('task_type:scheduled', 'admin');
|
||||
}
|
||||
return get_string('task_type:adhoc', 'admin');
|
||||
});
|
||||
|
||||
// Start time column.
|
||||
$columns[] = (new column(
|
||||
'starttime',
|
||||
new lang_string('task_starttime', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TIMESTAMP)
|
||||
->add_field("{$tablealias}.timestart")
|
||||
->set_is_sortable(true)
|
||||
->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
|
||||
|
||||
// Duration column.
|
||||
$columns[] = (new column(
|
||||
'duration',
|
||||
new lang_string('task_duration', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_FLOAT)
|
||||
->add_field("{$tablealias}.timeend - {$tablealias}.timestart", 'duration')
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(float $value): string {
|
||||
$duration = round($value, 2);
|
||||
if (empty($duration)) {
|
||||
// The format_time function returns 'now' when the difference is exactly 0.
|
||||
// Note: format_time performs concatenation in exactly this fashion so we should do this for consistency.
|
||||
return '0 ' . get_string('secs', 'moodle');
|
||||
}
|
||||
return format_time($duration);
|
||||
});
|
||||
|
||||
// Hostname column.
|
||||
$columns[] = (new column(
|
||||
'hostname',
|
||||
new lang_string('hostname', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("$tablealias.hostname")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// PID column.
|
||||
$columns[] = (new column(
|
||||
'pid',
|
||||
new lang_string('pid', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_field("{$tablealias}.pid")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// Database column.
|
||||
$columns[] = (new column(
|
||||
'database',
|
||||
new lang_string('task_dbstats', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_fields("{$tablealias}.dbreads, {$tablealias}.dbwrites")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(int $value, stdClass $row): string {
|
||||
$output = '';
|
||||
$output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
|
||||
$output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
|
||||
return $output;
|
||||
});
|
||||
|
||||
// Result column.
|
||||
$columns[] = (new column(
|
||||
'result',
|
||||
new lang_string('task_result', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_field("$tablealias.result")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(int $value): string {
|
||||
if ($value) {
|
||||
return get_string('task_result:failed', 'admin');
|
||||
}
|
||||
return get_string('success');
|
||||
});
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of all available filters
|
||||
*
|
||||
* @return filter[]
|
||||
*/
|
||||
protected function get_all_filters(): array {
|
||||
$filters = [];
|
||||
|
||||
$tablealias = $this->get_table_alias('task_log');
|
||||
|
||||
// Name filter (Filter by classname).
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'name',
|
||||
new lang_string('classname', 'tool_task'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.classname"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Output filter (Filter by task output).
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'output',
|
||||
new lang_string('task_logoutput', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.output"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Result filter.
|
||||
$filters[] = (new filter(
|
||||
select::class,
|
||||
'result',
|
||||
new lang_string('task_result', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.result"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_options([
|
||||
self::SUCCESS => get_string('success'),
|
||||
self::FAILED => get_string('task_result:failed', 'admin'),
|
||||
]);
|
||||
|
||||
// Start time filter.
|
||||
$filters[] = (new filter(
|
||||
date::class,
|
||||
'timestart',
|
||||
new lang_string('task_starttime', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.timestart"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_limited_operators([
|
||||
date::DATE_ANY,
|
||||
date::DATE_RANGE,
|
||||
date::DATE_PREVIOUS,
|
||||
date::DATE_CURRENT,
|
||||
]);
|
||||
|
||||
// Duration filter.
|
||||
$filters[] = (new filter(
|
||||
duration::class,
|
||||
'duration',
|
||||
new lang_string('task_duration', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"${tablealias}.timeend - {$tablealias}.timestart"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
return $filters;
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ class filesize extends \admin_setting {
|
||||
if (empty($bytes)) {
|
||||
return get_string('none');
|
||||
}
|
||||
return display_size($bytes, 0);
|
||||
return display_size($bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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,37 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* A settings page which can be viewed with a link directly.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
use moodle_url;
|
||||
|
||||
interface linkable_settings_page {
|
||||
|
||||
/**
|
||||
* Get the URL to view this settings page.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_settings_page_url(): moodle_url;
|
||||
}
|
||||
@@ -1,121 +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/>.
|
||||
|
||||
/**
|
||||
* Admin setting to show current scheduled task's status.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2021 Universitat Rovira i Virgili
|
||||
* @author Jordi Pujol-Ahulló <jpahullo@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/moodlelib.php');
|
||||
|
||||
use admin_setting_description;
|
||||
use core\task\manager;
|
||||
use core\task\scheduled_task;
|
||||
use html_writer;
|
||||
use lang_string;
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* This admin setting tells whether a given scheduled task is enabled, providing a link to its configuration page.
|
||||
*
|
||||
* The goal of this setting is to help contextualizing the configuration settings with related scheduled task status,
|
||||
* providing the big picture of that part of the system.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2021 Universitat Rovira i Virgili
|
||||
* @author Jordi Pujol-Ahulló <jpahullo@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class setting_scheduled_task_status extends admin_setting_description {
|
||||
/**
|
||||
* @var string fully qualified class name of a scheduled task.
|
||||
*/
|
||||
private $classname;
|
||||
/**
|
||||
* @var string additional text to append to the description.
|
||||
*/
|
||||
private $extradescription;
|
||||
|
||||
/**
|
||||
* setting_scheduled_task_status constructor.
|
||||
* @param string $name unique setting name.
|
||||
* @param string $scheduledtaskclassname full classpath class name of the scheduled task.
|
||||
* @param string $extradescription extra detail to append to the scheduled task status to add context in the setting
|
||||
* page.
|
||||
*/
|
||||
public function __construct(string $name, string $scheduledtaskclassname, string $extradescription = '') {
|
||||
$visiblename = new lang_string('task_status', 'admin');
|
||||
$this->classname = $scheduledtaskclassname;
|
||||
$this->extradescription = $extradescription;
|
||||
|
||||
parent::__construct($name, $visiblename, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates lazily the content of the description.
|
||||
* @param mixed $data nothing expected in this case.
|
||||
* @param string $query nothing expected in this case.
|
||||
* @return string the HTML content to print for this setting.
|
||||
*/
|
||||
public function output_html($data, $query = ''): string {
|
||||
if (empty($this->description)) {
|
||||
$this->description = $this->get_task_description();
|
||||
}
|
||||
|
||||
return parent::output_html($data, $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML to print as the description.
|
||||
* @return string description to be printed.
|
||||
*/
|
||||
private function get_task_description(): string {
|
||||
$task = manager::get_scheduled_task($this->classname);
|
||||
if ($task->is_enabled()) {
|
||||
$taskenabled = get_string('enabled', 'admin');
|
||||
} else {
|
||||
$taskenabled = get_string('disabled', 'admin');
|
||||
}
|
||||
$taskenabled = strtolower($taskenabled);
|
||||
$gotourl = new moodle_url(
|
||||
'/admin/tool/task/scheduledtasks.php',
|
||||
[],
|
||||
scheduled_task::get_html_id($this->classname)
|
||||
);
|
||||
if (!empty($this->extradescription)) {
|
||||
$this->extradescription = '<br />' . $this->extradescription;
|
||||
}
|
||||
|
||||
$taskdetail = new stdClass();
|
||||
$taskdetail->class = $this->classname;
|
||||
$taskdetail->name = $task->get_name();
|
||||
$taskdetail->status = $taskenabled;
|
||||
$taskdetail->gotourl = $gotourl->out(false);
|
||||
$taskdetail->extradescription = $this->extradescription;
|
||||
|
||||
return html_writer::tag('p', get_string('task_status_desc', 'admin', $taskdetail));
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\local\systemreports;
|
||||
|
||||
use context_system;
|
||||
use core_admin\local\entities\task_log;
|
||||
use core_reportbuilder\local\entities\user;
|
||||
use core_reportbuilder\local\report\action;
|
||||
use lang_string;
|
||||
use moodle_url;
|
||||
use pix_icon;
|
||||
use core_reportbuilder\system_report;
|
||||
|
||||
/**
|
||||
* Task logs system report class implementation
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class task_logs extends system_report {
|
||||
|
||||
/**
|
||||
* Initialise report, we need to set the main table, load our entities and set columns/filters
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
// Our main entity, it contains all of the column definitions that we need.
|
||||
$entitymain = new task_log();
|
||||
$entitymainalias = $entitymain->get_table_alias('task_log');
|
||||
|
||||
$this->set_main_table('task_log', $entitymainalias);
|
||||
$this->add_entity($entitymain);
|
||||
|
||||
// Any columns required by actions should be defined here to ensure they're always available.
|
||||
$this->add_base_fields("{$entitymainalias}.id");
|
||||
|
||||
// We can join the "user" entity to our "main" entity and use the fullname column from the user entity.
|
||||
$entityuser = new user();
|
||||
$entituseralias = $entityuser->get_table_alias('user');
|
||||
$this->add_entity($entityuser->add_join(
|
||||
"LEFT JOIN {user} {$entituseralias} ON {$entituseralias}.id = {$entitymainalias}.userid"
|
||||
));
|
||||
|
||||
// Now we can call our helper methods to add the content we want to include in the report.
|
||||
$this->add_columns();
|
||||
$this->add_filters();
|
||||
$this->add_actions();
|
||||
|
||||
// Set if report can be downloaded.
|
||||
$this->set_downloadable(true, get_string('tasklogs', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates access to view this report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_view(): bool {
|
||||
return has_capability('moodle/site:config', context_system::instance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the visible name of the report
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name(): string {
|
||||
return get_string('entitytasklog', 'admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the columns we want to display in the report
|
||||
*
|
||||
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
|
||||
* unique identifier
|
||||
*/
|
||||
public function add_columns(): void {
|
||||
$columns = [
|
||||
'task_log:name',
|
||||
'task_log:type',
|
||||
'user:fullname',
|
||||
'task_log:starttime',
|
||||
'task_log:duration',
|
||||
'task_log:hostname',
|
||||
'task_log:pid',
|
||||
'task_log:database',
|
||||
'task_log:result',
|
||||
];
|
||||
|
||||
$this->add_columns_from_entities($columns);
|
||||
|
||||
// It's possible to override the display name of a column, if you don't want to use the value provided by the entity.
|
||||
if ($column = $this->get_column('user:fullname')) {
|
||||
$column->set_title(new lang_string('user', 'admin'));
|
||||
}
|
||||
|
||||
// It's possible to set a default initial sort direction for one column.
|
||||
$this->set_initial_sort_column('task_log:starttime', SORT_DESC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the filters we want to display in the report
|
||||
*
|
||||
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
|
||||
* unique identifier
|
||||
*/
|
||||
protected function add_filters(): void {
|
||||
$filters = [
|
||||
'task_log:name',
|
||||
'task_log:output',
|
||||
'task_log:result',
|
||||
'task_log:timestart',
|
||||
'task_log:duration',
|
||||
];
|
||||
|
||||
$this->add_filters_from_entities($filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the system report actions. An extra column will be appended to each row, containing all actions added here
|
||||
*
|
||||
* Note the use of ":id" placeholder which will be substituted according to actual values in the row
|
||||
*/
|
||||
protected function add_actions(): void {
|
||||
|
||||
// Action to view individual task log on a popup window.
|
||||
$this->add_action((new action(
|
||||
new moodle_url('/admin/tasklogs.php', ['logid' => ':id']),
|
||||
new pix_icon('e/search', ''),
|
||||
[],
|
||||
true,
|
||||
new lang_string('view'),
|
||||
)));
|
||||
|
||||
// Action to download individual task log.
|
||||
$this->add_action((new action(
|
||||
new moodle_url('/admin/tasklogs.php', ['logid' => ':id', 'download' => true]),
|
||||
new pix_icon('t/download', ''),
|
||||
[],
|
||||
false,
|
||||
new lang_string('download'),
|
||||
)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Task log table.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/tablelib.php');
|
||||
|
||||
/**
|
||||
* Table to display list of task logs.
|
||||
*
|
||||
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class task_log_table extends \table_sql {
|
||||
|
||||
/**
|
||||
* Constructor for the task_log table.
|
||||
*
|
||||
* @param string $filter
|
||||
* @param int $resultfilter
|
||||
*/
|
||||
public function __construct(string $filter = '', int $resultfilter = null) {
|
||||
global $DB;
|
||||
|
||||
if (-1 === $resultfilter) {
|
||||
$resultfilter = null;
|
||||
}
|
||||
|
||||
parent::__construct('tasklogs');
|
||||
|
||||
$columnheaders = [
|
||||
'classname' => get_string('name'),
|
||||
'type' => get_string('tasktype', 'admin'),
|
||||
'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' => '',
|
||||
];
|
||||
$this->define_columns(array_keys($columnheaders));
|
||||
$this->define_headers(array_values($columnheaders));
|
||||
|
||||
// The name column is a header.
|
||||
$this->define_header_column('classname');
|
||||
|
||||
// This table is not collapsible.
|
||||
$this->collapsible(false);
|
||||
|
||||
// The actions class should not wrap. Use the BS text utility class.
|
||||
$this->column_class('actions', 'text-nowrap');
|
||||
|
||||
// Allow pagination.
|
||||
$this->pageable(true);
|
||||
|
||||
// Allow sorting. Default to sort by timestarted DESC.
|
||||
$this->sortable(true, 'timestart', SORT_DESC);
|
||||
|
||||
// Add filtering.
|
||||
$where = [];
|
||||
$params = [];
|
||||
if (!empty($filter)) {
|
||||
$orwhere = [];
|
||||
$filter = str_replace('\\', '\\\\', $filter);
|
||||
|
||||
// Check the class name.
|
||||
$orwhere[] = $DB->sql_like('classname', ':classfilter', false, false);
|
||||
$params['classfilter'] = '%' . $DB->sql_like_escape($filter) . '%';
|
||||
|
||||
$orwhere[] = $DB->sql_like('output', ':outputfilter', false, false);
|
||||
$params['outputfilter'] = '%' . $DB->sql_like_escape($filter) . '%';
|
||||
|
||||
$where[] = "(" . implode(' OR ', $orwhere) . ")";
|
||||
}
|
||||
|
||||
if (null !== $resultfilter) {
|
||||
$where[] = 'tl.result = :result';
|
||||
$params['result'] = $resultfilter;
|
||||
}
|
||||
|
||||
$where = implode(' AND ', $where);
|
||||
|
||||
$this->set_sql('', '', $where, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the db. Store results in the table object for use by build_table.
|
||||
*
|
||||
* @param int $pagesize size of page for paginated displayed table.
|
||||
* @param bool $useinitialsbar do you want to use the initials bar. Bar
|
||||
* will only be used if there is a fullname column defined for the table.
|
||||
*/
|
||||
public function query_db($pagesize, $useinitialsbar = true) {
|
||||
global $DB;
|
||||
|
||||
// Fetch the attempts.
|
||||
$sort = $this->get_sql_sort();
|
||||
if ($sort) {
|
||||
$sort = "ORDER BY $sort";
|
||||
}
|
||||
|
||||
$extrafields = get_extra_user_fields(\context_system::instance());
|
||||
$userfields = \user_picture::fields('u', $extrafields, 'userid2', 'user');
|
||||
|
||||
$where = '';
|
||||
if (!empty($this->sql->where)) {
|
||||
$where = "WHERE {$this->sql->where}";
|
||||
}
|
||||
|
||||
$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,
|
||||
{$userfields}
|
||||
FROM {task_log} tl
|
||||
LEFT JOIN {user} u ON u.id = tl.userid
|
||||
{$where}
|
||||
{$sort}";
|
||||
|
||||
$this->pagesize($pagesize, $DB->count_records_sql("SELECT COUNT('x') FROM {task_log} tl {$where}", $this->sql->params));
|
||||
if (!$this->is_downloading()) {
|
||||
$this->rawdata = $DB->get_records_sql($sql, $this->sql->params, $this->get_page_start(), $this->get_page_size());
|
||||
} else {
|
||||
$this->rawdata = $DB->get_records_sql($sql, $this->sql->params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the name cell.
|
||||
*
|
||||
* @param \stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_classname($row) : string {
|
||||
$output = '';
|
||||
if (class_exists($row->classname)) {
|
||||
$task = new $row->classname;
|
||||
if ($task instanceof \core\task\scheduled_task) {
|
||||
$output = $task->get_name();
|
||||
}
|
||||
}
|
||||
|
||||
$output .= \html_writer::tag('div', "\\{$row->classname}", [
|
||||
'class' => 'task-class',
|
||||
]);
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the type cell.
|
||||
*
|
||||
* @param \stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_type($row) : string {
|
||||
if (\core\task\database_logger::TYPE_SCHEDULED == $row->type) {
|
||||
return get_string('task_type:scheduled', 'admin');
|
||||
} else {
|
||||
return get_string('task_type:adhoc', 'admin');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the timestart cell.
|
||||
*
|
||||
* @param \stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_result($row) : string {
|
||||
if ($row->result) {
|
||||
return get_string('task_result:failed', 'admin');
|
||||
} else {
|
||||
return get_string('success');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the timestart cell.
|
||||
*
|
||||
* @param \stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_timestart($row) : string {
|
||||
return userdate($row->timestart, get_string('strftimedatetimeshort', 'langconfig'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the duration cell.
|
||||
*
|
||||
* @param \stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_duration($row) : string {
|
||||
$duration = round($row->timeend - $row->timestart, 2);
|
||||
|
||||
if (empty($duration)) {
|
||||
// The format_time function returns 'now' when the difference is exactly 0.
|
||||
// Note: format_time performs concatenation in exactly this fashion so we should do this for consistency.
|
||||
return '0 ' . get_string('secs', 'moodle');
|
||||
}
|
||||
|
||||
return format_time($duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the DB details cell.
|
||||
*
|
||||
* @param \stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_db($row) : string {
|
||||
$output = '';
|
||||
|
||||
$output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
|
||||
$output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the actions cell.
|
||||
*
|
||||
* @param \stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_actions($row) : string {
|
||||
global $OUTPUT;
|
||||
|
||||
$actions = [];
|
||||
|
||||
$url = new \moodle_url('/admin/tasklogs.php', ['logid' => $row->id]);
|
||||
|
||||
// Quick view.
|
||||
$actions[] = $OUTPUT->action_icon(
|
||||
$url,
|
||||
new \pix_icon('e/search', get_string('view')),
|
||||
new \popup_action('click', $url)
|
||||
);
|
||||
|
||||
// Download.
|
||||
$actions[] = $OUTPUT->action_icon(
|
||||
new \moodle_url($url, ['download' => true]),
|
||||
new \pix_icon('t/download', get_string('download'))
|
||||
);
|
||||
|
||||
return implode(' ', $actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the user cell.
|
||||
*
|
||||
* @param \stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
public function col_userid($row) : string {
|
||||
if (empty($row->userid)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$user = (object) [];
|
||||
username_load_fields_from_object($user, $row, 'user');
|
||||
|
||||
return fullname($user);
|
||||
}
|
||||
}
|
||||
+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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
@@ -74,8 +74,6 @@ Options:
|
||||
--adminpass=PASSWORD Password for the moodle admin account,
|
||||
required in non-interactive mode.
|
||||
--adminemail=STRING Email address for the moodle admin account.
|
||||
--sitepreset=STRING Admin site preset to be applied during the installation process.
|
||||
--supportemail=STRING Email address for support and help.
|
||||
--upgradekey=STRING The upgrade key to be set in the config.php, leave empty to not set it.
|
||||
--non-interactive No interactive questions, installation fails if any
|
||||
problem encountered.
|
||||
@@ -256,8 +254,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'adminuser' => 'admin',
|
||||
'adminpass' => '',
|
||||
'adminemail' => '',
|
||||
'sitepreset' => '',
|
||||
'supportemail' => '',
|
||||
'upgradekey' => '',
|
||||
'non-interactive' => false,
|
||||
'agree-license' => false,
|
||||
@@ -280,12 +276,6 @@ if (array_key_exists($lang, $languages)) {
|
||||
$CFG->lang = $lang;
|
||||
}
|
||||
|
||||
// Set up site admin preset.
|
||||
$sitepreset = clean_param($options['sitepreset'], PARAM_RAW);
|
||||
if (!empty($sitepreset)) {
|
||||
$CFG->setsitepresetduringinstall = $sitepreset;
|
||||
}
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
@@ -741,20 +731,6 @@ if (!$skipdatabase) {
|
||||
$a = (object)['option' => 'adminemail', 'value' => $options['adminemail']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
|
||||
// Ask for the support email address.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('clisupportemail', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['supportemail']);
|
||||
$options['supportemail'] = cli_input($prompt, $options['supportemail']);
|
||||
}
|
||||
|
||||
// Validate that the support email address provided is valid.
|
||||
if (!empty($options['supportemail']) && !validate_email($options['supportemail'])) {
|
||||
$a = (object)['option' => 'supportemail', 'value' => $options['supportemail']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for the upgrade key.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* MySQL engine conversion tool.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2009 Petr Skoda (http://skodak.org)
|
||||
* @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'); // cli only functions
|
||||
|
||||
if ($DB->get_dbfamily() !== 'mysql') {
|
||||
cli_error('This function is designed for MySQL databases only!');
|
||||
}
|
||||
|
||||
// now get cli options
|
||||
list($options, $unrecognized) = cli_get_params(array('help'=>false, 'list'=>false, 'engine'=>false, 'available'=>false),
|
||||
array('h'=>'help', 'l'=>'list', 'a'=>'available'));
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
$help =
|
||||
"MySQL engine conversions script.
|
||||
|
||||
It is recommended to stop the web server before the conversion.
|
||||
Do not use MyISAM if possible, because it is not ACID compliant
|
||||
and does not support transactions.
|
||||
|
||||
Options:
|
||||
--engine=ENGINE Convert MySQL tables to different engine
|
||||
-l, --list Show table information
|
||||
-a, --available Show list of available engines
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/mysql_engine.php --engine=InnoDB
|
||||
";
|
||||
|
||||
if (!empty($options['engine'])) {
|
||||
$engines = mysql_get_engines();
|
||||
$engine = clean_param($options['engine'], PARAM_ALPHA);
|
||||
if (!isset($engines[strtoupper($engine)])) {
|
||||
cli_error("Error: engine '$engine' is not available on this server!");
|
||||
}
|
||||
|
||||
echo "Converting tables to '$engine' for $CFG->wwwroot:\n";
|
||||
$prefix = $DB->get_prefix();
|
||||
$prefix = str_replace('_', '\\_', $prefix);
|
||||
$sql = "SHOW TABLE STATUS WHERE Name LIKE BINARY '$prefix%'";
|
||||
$rs = $DB->get_recordset_sql($sql);
|
||||
$converted = 0;
|
||||
$skipped = 0;
|
||||
$errors = 0;
|
||||
foreach ($rs as $table) {
|
||||
if (strtoupper($table->engine) === strtoupper($engine)) {
|
||||
$newengine = mysql_get_table_engine($table->name);
|
||||
echo str_pad($table->name, 40). " - NO CONVERSION NEEDED ($newengine)\n";
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
echo str_pad($table->name, 40). " - ";
|
||||
|
||||
try {
|
||||
$DB->change_database_structure("ALTER TABLE {$table->name} ENGINE = $engine");
|
||||
$newengine = mysql_get_table_engine($table->name);
|
||||
if (strtoupper($newengine) !== strtoupper($engine)) {
|
||||
echo "ERROR ($newengine)\n";
|
||||
$errors++;
|
||||
continue;
|
||||
}
|
||||
echo "DONE ($newengine)\n";
|
||||
$converted++;
|
||||
} catch (moodle_exception $e) {
|
||||
echo $e->getMessage()."\n";
|
||||
$errors++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$rs->close();
|
||||
echo "Converted: $converted, skipped: $skipped, errors: $errors\n";
|
||||
exit(0); // success
|
||||
|
||||
} else if (!empty($options['list'])) {
|
||||
echo "List of tables for $CFG->wwwroot:\n";
|
||||
$prefix = $DB->get_prefix();
|
||||
$prefix = str_replace('_', '\\_', $prefix);
|
||||
$sql = "SHOW TABLE STATUS WHERE Name LIKE BINARY '$prefix%'";
|
||||
$rs = $DB->get_recordset_sql($sql);
|
||||
$counts = array();
|
||||
foreach ($rs as $table) {
|
||||
if (isset($counts[$table->engine])) {
|
||||
$counts[$table->engine]++;
|
||||
} else {
|
||||
$counts[$table->engine] = 1;
|
||||
}
|
||||
echo str_pad($table->engine, 10);
|
||||
echo $table->name . "\n";
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
echo "\n";
|
||||
echo "Table engines summary for $CFG->wwwroot:\n";
|
||||
foreach ($counts as $engine => $count) {
|
||||
echo "$engine: $count\n";
|
||||
}
|
||||
exit(0); // success
|
||||
|
||||
} else if (!empty($options['available'])) {
|
||||
echo "List of available MySQL engines for $CFG->wwwroot:\n";
|
||||
$engines = mysql_get_engines();
|
||||
foreach ($engines as $engine) {
|
||||
echo " $engine\n";
|
||||
}
|
||||
die;
|
||||
|
||||
} else {
|
||||
echo $help;
|
||||
die;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ========== Some functions ==============
|
||||
|
||||
function mysql_get_engines() {
|
||||
global $DB;
|
||||
|
||||
$sql = "SHOW Engines";
|
||||
$rs = $DB->get_recordset_sql($sql);
|
||||
$engines = array();
|
||||
foreach ($rs as $engine) {
|
||||
if (strtoupper($engine->support) !== 'YES' and strtoupper($engine->support) !== 'DEFAULT') {
|
||||
continue;
|
||||
}
|
||||
$engines[strtoupper($engine->engine)] = $engine->engine;
|
||||
if (strtoupper($engine->support) === 'DEFAULT') {
|
||||
$engines[strtoupper($engine->engine)] .= ' (default)';
|
||||
}
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
return $engines;
|
||||
}
|
||||
|
||||
function mysql_get_table_engine($tablename) {
|
||||
global $DB;
|
||||
|
||||
$engine = null;
|
||||
$sql = "SHOW TABLE STATUS WHERE Name = '$tablename'"; // no special chars expected here
|
||||
$rs = $DB->get_recordset_sql($sql);
|
||||
if ($rs->valid()) {
|
||||
$record = $rs->current();
|
||||
$engine = $record->engine;
|
||||
}
|
||||
$rs->close();
|
||||
return $engine;
|
||||
}
|
||||
@@ -69,11 +69,11 @@ if ($options['help'] or (!$options['list'] and !$options['execute'])) {
|
||||
die;
|
||||
}
|
||||
|
||||
if ($options['showdebugging'] || !empty($CFG->showcrondebugging)) {
|
||||
if ($options['showdebugging']) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if ($options['showsql'] || !empty($CFG->showcronsql)) {
|
||||
if ($options['showsql']) {
|
||||
$DB->set_debug(true);
|
||||
}
|
||||
if ($options['list']) {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -48,14 +48,12 @@ if (!isset($plugins[$name])) {
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
if ($plugins[$name]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('contenttype');
|
||||
$class::enable_plugin($name, false);
|
||||
set_config('disabled', 1, 'contentbank_'. $name);
|
||||
}
|
||||
break;
|
||||
case 'enable':
|
||||
if (!$plugins[$name]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('contenttype');
|
||||
$class::enable_plugin($name, true);
|
||||
unset_config('disabled', 'contentbank_'. $name);
|
||||
}
|
||||
break;
|
||||
case 'up':
|
||||
@@ -65,7 +63,6 @@ switch ($action) {
|
||||
$seq[$currentindex] = $seq[$currentindex - 1];
|
||||
$seq[$currentindex - 1] = $name;
|
||||
set_config('contentbank_plugins_sortorder', implode(',', $seq));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
case 'down':
|
||||
@@ -75,10 +72,10 @@ switch ($action) {
|
||||
$seq[$currentindex] = $seq[$currentindex + 1];
|
||||
$seq[$currentindex + 1] = $name;
|
||||
set_config('contentbank_plugins_sortorder', implode(',', $seq));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
}
|
||||
core_plugin_manager::reset_caches();
|
||||
$cache = cache::make('core', 'contentbank_enabled_extensions');
|
||||
$cache->purge();
|
||||
$cache = cache::make('core', 'contentbank_context_extensions');
|
||||
|
||||
@@ -1,78 +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/>.
|
||||
|
||||
/**
|
||||
* Reset course indentation
|
||||
*
|
||||
* @copyright 2023 Amaia Anabitarte <amaia@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../../config.php');
|
||||
|
||||
require_admin();
|
||||
|
||||
$format = required_param('format', PARAM_PLUGIN);
|
||||
$confirm = optional_param('confirm', false, PARAM_BOOL);
|
||||
$backurl = new moodle_url('/admin/settings.php', ['section' => 'formatsetting'.$format]);
|
||||
|
||||
$PAGE->set_url('/admin/course/resetindentation.php', ['format' => $format]);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
if ($confirm) {
|
||||
require_sesskey();
|
||||
$courses = $DB->get_records('course', ['format' => $format], 'id', 'id');
|
||||
if (!empty($courses)) {
|
||||
$courseids = array_keys($courses);
|
||||
list($courseinsql, $courseparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, 'course');
|
||||
$DB->set_field_select('course_modules', 'indent', '0', "course $courseinsql AND indent <> 0", $courseparams);
|
||||
rebuild_course_cache(0, true);
|
||||
}
|
||||
redirect(
|
||||
$backurl,
|
||||
get_string('resetindentationsuccess', 'admin'),
|
||||
null,
|
||||
\core\output\notification::NOTIFY_SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
$strtitle = get_string('resetindentation', 'admin');
|
||||
|
||||
$PAGE->set_title($strtitle);
|
||||
$PAGE->set_heading($strtitle);
|
||||
|
||||
navigation_node::override_active_url(new moodle_url(
|
||||
'/admin/course/resetindentation.php',
|
||||
['action' => 'confirm', 'format' => $format]
|
||||
));
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$displayoptions = ['confirmtitle' => get_string('resetindentation_title', 'admin')];
|
||||
$confirmbutton = new single_button(
|
||||
new moodle_url('/admin/course/resetindentation.php', ['confirm' => 1, 'format' => $format, 'sesskey' => sesskey()]),
|
||||
get_string('resetindentation', 'admin'),
|
||||
'post'
|
||||
);
|
||||
$cancelbutton = new single_button($backurl, get_string('cancel'));
|
||||
echo $OUTPUT->confirm(
|
||||
get_string('resetindentation_help', 'admin', ['format' => get_string('pluginname', 'format_'.$format)]),
|
||||
$confirmbutton,
|
||||
$cancelbutton,
|
||||
$displayoptions
|
||||
);
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
@@ -47,14 +47,17 @@ if (!isset($formatplugins[$formatname])) {
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
if ($formatplugins[$formatname]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('format');
|
||||
$class::enable_plugin($formatname, false);
|
||||
if (get_config('moodlecourse', 'format') === $formatname) {
|
||||
print_error('cannotdisableformat', 'error', $return);
|
||||
}
|
||||
set_config('disabled', 1, 'format_'. $formatname);
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
case 'enable':
|
||||
if (!$formatplugins[$formatname]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('format');
|
||||
$class::enable_plugin($formatname, true);
|
||||
unset_config('disabled', 'format_'. $formatname);
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
case 'up':
|
||||
|
||||
@@ -47,14 +47,14 @@ if (!isset($customfieldplugins[$customfieldname])) {
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
if ($customfieldplugins[$customfieldname]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('customfield');
|
||||
$class::enable_plugin($customfieldname, false);
|
||||
set_config('disabled', 1, 'customfield_'. $customfieldname);
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
case 'enable':
|
||||
if (!$customfieldplugins[$customfieldname]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('customfield');
|
||||
$class::enable_plugin($customfieldname, true);
|
||||
unset_config('disabled', 'customfield_'. $customfieldname);
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -48,14 +48,14 @@ if (!isset($plugins[$name])) {
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
if ($plugins[$name]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('dataformat');
|
||||
$class::enable_plugin($name, false);
|
||||
set_config('disabled', 1, 'dataformat_'. $name);
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
case 'enable':
|
||||
if (!$plugins[$name]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('dataformat');
|
||||
$class::enable_plugin($name, true);
|
||||
unset_config('disabled', 'dataformat_'. $name);
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
case 'up':
|
||||
@@ -78,3 +78,4 @@ switch ($action) {
|
||||
break;
|
||||
}
|
||||
redirect($return);
|
||||
|
||||
|
||||
+17
-10
@@ -39,19 +39,22 @@ if (!confirm_sesskey()) {
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
|
||||
$return = true;
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
// Remove from enabled list.
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
|
||||
$class::enable_plugin($editor, false);
|
||||
// remove from enabled list
|
||||
$key = array_search($editor, $active_editors);
|
||||
unset($active_editors[$key]);
|
||||
add_to_config_log('editor_visibility', '1', '0', $editor);
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
// Add to enabled list.
|
||||
// add to enabled list
|
||||
if (!in_array($editor, $active_editors)) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
|
||||
$class::enable_plugin($editor, true);
|
||||
$active_editors[] = $editor;
|
||||
$active_editors = array_unique($active_editors);
|
||||
add_to_config_log('editor_visibility', '0', '1', $editor);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -65,8 +68,6 @@ switch ($action) {
|
||||
$active_editors[$key] = $active_editors[$key + 1];
|
||||
$active_editors[$key + 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key + 1, $editor);
|
||||
set_config('texteditors', implode(',', $active_editors));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -81,8 +82,6 @@ switch ($action) {
|
||||
$active_editors[$key] = $active_editors[$key - 1];
|
||||
$active_editors[$key - 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key - 1, $editor);
|
||||
set_config('texteditors', implode(',', $active_editors));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -91,6 +90,14 @@ switch ($action) {
|
||||
break;
|
||||
}
|
||||
|
||||
// at least one editor must be active
|
||||
if (empty($active_editors)) {
|
||||
$active_editors = array('textarea');
|
||||
}
|
||||
|
||||
set_config('texteditors', implode(',', $active_editors));
|
||||
core_plugin_manager::reset_caches();
|
||||
|
||||
if ($return) {
|
||||
redirect ($returnurl);
|
||||
}
|
||||
|
||||
+12
-5
@@ -43,18 +43,25 @@ $all = enrol_get_plugins(false);
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section'=>'manageenrols'));
|
||||
|
||||
$syscontext = context_system::instance();
|
||||
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('enrol');
|
||||
$class::enable_plugin($enrol, false);
|
||||
unset($enabled[$enrol]);
|
||||
set_config('enrol_plugins_enabled', implode(',', array_keys($enabled)));
|
||||
core_plugin_manager::reset_caches();
|
||||
$syscontext->mark_dirty(); // resets all enrol caches
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
if (!isset($all[$enrol])) {
|
||||
break;
|
||||
}
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('enrol');
|
||||
$class::enable_plugin($enrol, true);
|
||||
$enabled = array_keys($enabled);
|
||||
$enabled[] = $enrol;
|
||||
set_config('enrol_plugins_enabled', implode(',', $enabled));
|
||||
core_plugin_manager::reset_caches();
|
||||
$syscontext->mark_dirty(); // resets all enrol caches
|
||||
break;
|
||||
|
||||
case 'up':
|
||||
@@ -122,4 +129,4 @@ switch ($action) {
|
||||
}
|
||||
|
||||
|
||||
redirect($return);
|
||||
redirect($return);
|
||||
@@ -2815,7 +2815,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.1.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -2997,7 +2996,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.2.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -3163,11 +3161,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">
|
||||
@@ -3184,7 +3177,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.2.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -3350,957 +3342,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">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.2.29" />
|
||||
<VENDOR name="mysql" version="5.7" />
|
||||
<VENDOR name="postgres" version="9.6" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.3.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
|
||||
</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_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_xmlrpc_usage" 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">
|
||||
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
|
||||
</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_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.1" requires="3.9">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.4" />
|
||||
<VENDOR name="mysql" version="5.7" />
|
||||
<VENDOR name="postgres" version="12" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="7.4.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_82" message="unsupportedphpversion82" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="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_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.2" requires="3.11.8">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.6.7" />
|
||||
<VENDOR name="mysql" version="8.0" />
|
||||
<VENDOR name="postgres" version="13" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="8.0.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="required"/>
|
||||
<PHP_EXTENSION name="exif" level="optional"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="sixtyfourbitsrequired" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="iscustomadminwarnings" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.3" requires="3.11.8">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.6.7" />
|
||||
<VENDOR name="mysql" version="8.0" />
|
||||
<VENDOR name="postgres" version="13" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="8.0.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="required"/>
|
||||
<PHP_EXTENSION name="exif" level="optional"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="sixtyfourbitsrequired" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="iscustomadminwarnings" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
+33
-43
@@ -31,15 +31,14 @@ $filterpath = optional_param('filterpath', '', PARAM_PLUGIN);
|
||||
admin_externalpage_setup('managefilters');
|
||||
|
||||
// Clean up bogus filter states first.
|
||||
/** @var core\plugininfo\filter[] $plugininfos */
|
||||
$plugininfos = core_plugin_manager::instance()->get_plugins_of_type('filter');
|
||||
$filters = [];
|
||||
$filters = array();
|
||||
$states = filter_get_global_states();
|
||||
foreach ($states as $state) {
|
||||
if (!isset($plugininfos[$state->filter]) and !get_config('filter_'.$state->filter, 'version')) {
|
||||
// Purge messy leftovers after incorrectly uninstalled plugins and unfinished installations.
|
||||
$DB->delete_records('filter_active', ['filter' => $state->filter]);
|
||||
$DB->delete_records('filter_config', ['filter' => $state->filter]);
|
||||
// Purge messy leftovers after incorrectly uninstalled plugins and unfinished installs.
|
||||
$DB->delete_records('filter_active', array('filter' => $state->filter));
|
||||
$DB->delete_records('filter_config', array('filter' => $state->filter));
|
||||
error_log('Deleted bogus "filter_'.$state->filter.'" states and config data.');
|
||||
} else {
|
||||
$filters[$state->filter] = $state;
|
||||
@@ -51,6 +50,7 @@ foreach ($plugininfos as $filter => $info) {
|
||||
if (isset($filters[$filter])) {
|
||||
continue;
|
||||
}
|
||||
/** @var \core\plugininfo\base $info */
|
||||
if ($info->is_installed_and_upgraded()) {
|
||||
filter_set_global_state($filter, TEXTFILTER_DISABLED);
|
||||
$states = filter_get_global_states();
|
||||
@@ -72,9 +72,10 @@ switch ($action) {
|
||||
|
||||
case 'setstate':
|
||||
if (isset($filters[$filterpath]) and $newstate = optional_param('newstate', '', PARAM_INT)) {
|
||||
/** @var \core\plugininfo\filter $class */
|
||||
$class = core_plugin_manager::resolve_plugininfo_class('filter');
|
||||
$class::enable_plugin($filterpath, $newstate);
|
||||
filter_set_global_state($filterpath, $newstate);
|
||||
if ($newstate == TEXTFILTER_DISABLED) {
|
||||
filter_set_applies_to_strings($filterpath, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -82,16 +83,12 @@ switch ($action) {
|
||||
if (isset($filters[$filterpath])) {
|
||||
$applytostrings = optional_param('stringstoo', false, PARAM_BOOL);
|
||||
filter_set_applies_to_strings($filterpath, $applytostrings);
|
||||
reset_text_filters_cache();
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'down':
|
||||
if (isset($filters[$filterpath])) {
|
||||
filter_set_global_state($filterpath, $filters[$filterpath]->active, 1);
|
||||
reset_text_filters_cache();
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -99,14 +96,14 @@ switch ($action) {
|
||||
if (isset($filters[$filterpath])) {
|
||||
$oldpos = $filters[$filterpath]->sortorder;
|
||||
filter_set_global_state($filterpath, $filters[$filterpath]->active, -1);
|
||||
reset_text_filters_cache();
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Return.
|
||||
// Reset caches and return.
|
||||
if ($action) {
|
||||
reset_text_filters_cache();
|
||||
core_plugin_manager::reset_caches();
|
||||
redirect(new moodle_url('/admin/filters.php'));
|
||||
}
|
||||
|
||||
@@ -118,12 +115,12 @@ $states = filter_get_global_states();
|
||||
$stringfilters = filter_get_string_filters();
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = [get_string('filter'), get_string('isactive', 'filters'),
|
||||
get_string('order'), get_string('applyto', 'filters'), get_string('settings'), get_string('uninstallplugin', 'core_admin')];
|
||||
$table->head = array(get_string('filter'), get_string('isactive', 'filters'),
|
||||
get_string('order'), get_string('applyto', 'filters'), get_string('settings'), get_string('uninstallplugin', 'core_admin'));
|
||||
$table->colclasses = array ('leftalign', 'leftalign', 'centeralign', 'leftalign', 'leftalign', 'leftalign');
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$table->id = 'filterssetting';
|
||||
$table->data = [];
|
||||
$table->data = array();
|
||||
|
||||
$lastactive = null;
|
||||
foreach ($states as $state) {
|
||||
@@ -160,16 +157,15 @@ die;
|
||||
/**
|
||||
* Return action URL.
|
||||
*
|
||||
* @param string $filterpath which filter to get the URL for.
|
||||
* @param string $action which action to get the URL for.
|
||||
* @return moodle_url|null the requested URL.
|
||||
* @param string $filterpath
|
||||
* @param string $action
|
||||
* @return moodle_url
|
||||
*/
|
||||
function filters_action_url(string $filterpath, string $action): ?moodle_url {
|
||||
function filters_action_url($filterpath, $action) {
|
||||
if ($action === 'delete') {
|
||||
return core_plugin_manager::instance()->get_uninstall_url('filter_'.$filterpath, 'manage');
|
||||
}
|
||||
return new moodle_url('/admin/filters.php',
|
||||
['sesskey' => sesskey(), 'filterpath' => $filterpath, 'action' => $action]);
|
||||
return new moodle_url('/admin/filters.php', array('sesskey'=>sesskey(), 'filterpath'=>$filterpath, 'action'=>$action));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,25 +178,24 @@ function filters_action_url(string $filterpath, string $action): ?moodle_url {
|
||||
* @param bool $applytostrings
|
||||
* @return array data
|
||||
*/
|
||||
function get_table_row(\core\plugininfo\filter $plugininfo, stdClass $state,
|
||||
bool $isfirstrow, bool $islastactive, bool $applytostrings): array {
|
||||
function get_table_row(\core\plugininfo\filter $plugininfo, $state, $isfirstrow, $islastactive, $applytostrings) {
|
||||
global $OUTPUT;
|
||||
$row = [];
|
||||
$row = array();
|
||||
$filter = $state->filter;
|
||||
$active = $plugininfo->is_installed_and_upgraded();
|
||||
|
||||
static $activechoices;
|
||||
static $applytochoices;
|
||||
if (!isset($activechoices)) {
|
||||
$activechoices = [
|
||||
$activechoices = array(
|
||||
TEXTFILTER_DISABLED => get_string('disabled', 'core_filters'),
|
||||
TEXTFILTER_OFF => get_string('offbutavailable', 'core_filters'),
|
||||
TEXTFILTER_ON => get_string('on', 'core_filters'),
|
||||
];
|
||||
$applytochoices = [
|
||||
);
|
||||
$applytochoices = array(
|
||||
0 => get_string('content', 'core_filters'),
|
||||
1 => get_string('contentandheadings', 'core_filters'),
|
||||
];
|
||||
);
|
||||
}
|
||||
|
||||
// Filter name.
|
||||
@@ -214,7 +209,7 @@ function get_table_row(\core\plugininfo\filter $plugininfo, stdClass $state,
|
||||
|
||||
// Disable/off/on.
|
||||
$select = new single_select(filters_action_url($filter, 'setstate'), 'newstate', $activechoices, $state->active, null, 'active' . $filter);
|
||||
$select->set_label(get_string('isactive', 'filters'), ['class' => 'accesshide']);
|
||||
$select->set_label(get_string('isactive', 'filters'), array('class' => 'accesshide'));
|
||||
$row[] = $OUTPUT->render($select);
|
||||
|
||||
// Re-order.
|
||||
@@ -222,14 +217,12 @@ function get_table_row(\core\plugininfo\filter $plugininfo, stdClass $state,
|
||||
$spacer = $OUTPUT->spacer();
|
||||
if ($state->active != TEXTFILTER_DISABLED) {
|
||||
if (!$isfirstrow) {
|
||||
$updown .= $OUTPUT->action_icon(filters_action_url($filter, 'up'),
|
||||
new pix_icon('t/up', get_string('up'), '', ['class' => 'iconsmall']));
|
||||
$updown .= $OUTPUT->action_icon(filters_action_url($filter, 'up'), new pix_icon('t/up', get_string('up'), '', array('class' => 'iconsmall')));
|
||||
} else {
|
||||
$updown .= $spacer;
|
||||
}
|
||||
if (!$islastactive) {
|
||||
$updown .= $OUTPUT->action_icon(filters_action_url($filter, 'down'),
|
||||
new pix_icon('t/down', get_string('down'), '', ['class' => 'iconsmall']));
|
||||
$updown .= $OUTPUT->action_icon(filters_action_url($filter, 'down'), new pix_icon('t/down', get_string('down'), '', array('class' => 'iconsmall')));
|
||||
} else {
|
||||
$updown .= $spacer;
|
||||
}
|
||||
@@ -237,23 +230,20 @@ function get_table_row(\core\plugininfo\filter $plugininfo, stdClass $state,
|
||||
$row[] = $updown;
|
||||
|
||||
// Apply to strings.
|
||||
$select = new single_select(filters_action_url($filter, 'setapplyto'),
|
||||
'stringstoo', $applytochoices, $applytostrings, null, 'applyto' . $filter);
|
||||
$select->set_label(get_string('applyto', 'filters'), ['class' => 'accesshide']);
|
||||
$select = new single_select(filters_action_url($filter, 'setapplyto'), 'stringstoo', $applytochoices, $applytostrings, null, 'applyto' . $filter);
|
||||
$select->set_label(get_string('applyto', 'filters'), array('class' => 'accesshide'));
|
||||
$select->disabled = ($state->active == TEXTFILTER_DISABLED);
|
||||
$row[] = $OUTPUT->render($select);
|
||||
|
||||
// Settings link, if required.
|
||||
if ($active and filter_has_global_settings($filter)) {
|
||||
$row[] = html_writer::link(new moodle_url('/admin/settings.php',
|
||||
['section' => 'filtersetting'.$filter]), get_string('settings'));
|
||||
$row[] = html_writer::link(new moodle_url('/admin/settings.php', array('section'=>'filtersetting'.$filter)), get_string('settings'));
|
||||
} else {
|
||||
$row[] = '';
|
||||
}
|
||||
|
||||
// Uninstall.
|
||||
$row[] = html_writer::link(filters_action_url($filter, 'delete'),
|
||||
get_string('uninstallplugin', 'core_admin'));
|
||||
$row[] = html_writer::link(filters_action_url($filter, 'delete'), get_string('uninstallplugin', 'core_admin'));
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
+1
-24
@@ -53,12 +53,6 @@ if (!extension_loaded('xml')) {
|
||||
die();
|
||||
}
|
||||
|
||||
// Make sure mbstring extension is available.
|
||||
if (!extension_loaded('mbstring')) {
|
||||
echo 'Moodle requires the mbstring PHP extension. Please install or enable the mbstring extension.';
|
||||
die();
|
||||
}
|
||||
|
||||
define('NO_OUTPUT_BUFFERING', true);
|
||||
|
||||
if (isset($_POST['upgradekey'])) {
|
||||
@@ -725,12 +719,6 @@ if (during_initial_install()) {
|
||||
set_config('rolesactive', 1); // after this, during_initial_install will return false.
|
||||
set_config('adminsetuppending', 1);
|
||||
set_config('registrationpending', 1); // Remind to register site after all other setup is finished.
|
||||
|
||||
// Apply default preset, if it is defined in $CFG and has a valid value.
|
||||
if (!empty($CFG->setsitepresetduringinstall)) {
|
||||
\core_adminpresets\helper::change_default_preset($CFG->setsitepresetduringinstall);
|
||||
}
|
||||
|
||||
// we need this redirect to setup proper session
|
||||
upgrade_finished("index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
}
|
||||
@@ -831,7 +819,6 @@ $insecuredataroot = is_dataroot_insecure(true);
|
||||
$SESSION->admin_critical_warning = ($insecuredataroot==INSECURE_DATAROOT_ERROR);
|
||||
|
||||
$adminroot = admin_get_root();
|
||||
$PAGE->set_primary_active_tab('siteadminnode');
|
||||
|
||||
// Check if there are any new admin settings which have still yet to be set
|
||||
if (any_new_admin_settings($adminroot)) {
|
||||
@@ -920,15 +907,6 @@ $showcampaigncontent = !isset($CFG->showcampaigncontent) || $CFG->showcampaignco
|
||||
// Encourage admins to enable the user feedback feature if it is not enabled already.
|
||||
$showfeedbackencouragement = empty($CFG->enableuserfeedback);
|
||||
|
||||
// Check if the service and support content setting is enabled or not.
|
||||
$servicesandsupportcontent = !isset($CFG->showservicesandsupportcontent) || $CFG->showservicesandsupportcontent;
|
||||
|
||||
// Check whether the XML-RPC protocol is enabled or not.
|
||||
require_once($CFG->libdir . '/environmentlib.php');
|
||||
$result = new environment_results('custom_checks');
|
||||
$result = check_xmlrpc_usage($result);
|
||||
$xmlrpcwarning = !is_null($result) ? get_string($result->getFeedbackStr(), 'admin') : '';
|
||||
|
||||
admin_externalpage_setup('adminnotifications');
|
||||
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
@@ -937,5 +915,4 @@ echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisp
|
||||
$maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
|
||||
$registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir,
|
||||
$mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent,
|
||||
$showcampaigncontent, $showfeedbackencouragement, $servicesandsupportcontent,
|
||||
$xmlrpcwarning);
|
||||
$showcampaigncontent, $showfeedbackencouragement);
|
||||
|
||||
+2
-4
@@ -49,13 +49,11 @@ if (!array_key_exists($media, $plugins)) {
|
||||
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('media');
|
||||
$class::enable_plugin($media, false);
|
||||
$plugins[$media]->set_enabled(false);
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('media');
|
||||
$class::enable_plugin($media, true);
|
||||
$plugins[$media]->set_enabled(true);
|
||||
break;
|
||||
|
||||
case 'up':
|
||||
|
||||
+58
-46
@@ -48,52 +48,69 @@ if (($form = data_submitted()) && confirm_sesskey()) {
|
||||
foreach ($providers as $provider) {
|
||||
$componentproviderbase = $provider->component.'_'.$provider->name;
|
||||
$disableprovidersetting = $componentproviderbase.'_disable';
|
||||
$providerdisabled = false;
|
||||
if (!isset($form->$disableprovidersetting)) {
|
||||
$providerdisabled = true;
|
||||
$newpreferences[$disableprovidersetting] = 1;
|
||||
} else {
|
||||
$newpreferences[$disableprovidersetting] = 0;
|
||||
}
|
||||
|
||||
$componentprovidersetting = $componentproviderbase.'_locked';
|
||||
foreach ($processors as $processor) {
|
||||
$value = 0;
|
||||
if (isset($form->{$componentprovidersetting}[$processor->name])) {
|
||||
$value = $form->{$componentprovidersetting}[$processor->name];
|
||||
if ($value == 'on') {
|
||||
$value = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Record the site preference.
|
||||
$newpreferences[$processor->name.'_provider_'.$componentprovidersetting] = $value;
|
||||
}
|
||||
|
||||
$componentprovidersetting = $componentproviderbase.'_enabled';
|
||||
$newsettings = [];
|
||||
if (isset($form->$componentprovidersetting)) {
|
||||
// Store defined comma-separated processors as setting value.
|
||||
// Using array_filter eliminates elements set to 0 above.
|
||||
$newsettings = array_keys(array_filter($form->{$componentprovidersetting}));
|
||||
}
|
||||
|
||||
// Let's join existing setting values for disabled processors.
|
||||
$property = 'message_provider_'.$componentprovidersetting;
|
||||
if (property_exists($preferences, $property)) {
|
||||
$existingsetting = $preferences->$property;
|
||||
foreach ($disabledprocessors as $disable) {
|
||||
if (strpos($existingsetting, $disable->name) > -1) {
|
||||
$newsettings[] = $disable->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$value = join(',', $newsettings);
|
||||
if (empty($value)) {
|
||||
foreach (array('permitted', 'loggedin', 'loggedoff') as $setting) {
|
||||
$value = null;
|
||||
}
|
||||
$componentprovidersetting = $componentproviderbase.'_'.$setting;
|
||||
if ($setting == 'permitted') {
|
||||
// If we deal with permitted select element, we need to create individual
|
||||
// setting for each possible processor. Note that this block will
|
||||
// always be processed first after entring parental foreach iteration
|
||||
// so we can change form values on this stage.
|
||||
foreach ($processors as $processor) {
|
||||
$value = '';
|
||||
if (isset($form->{$componentprovidersetting}[$processor->name])) {
|
||||
$value = $form->{$componentprovidersetting}[$processor->name];
|
||||
}
|
||||
// Ensure that loggedin loggedoff options are set correctly for this permission.
|
||||
if (($value == 'disallowed') || $providerdisabled) {
|
||||
// It might be better to unset them, but I can't figure out why that cause error.
|
||||
$form->{$componentproviderbase.'_loggedin'}[$processor->name] = 0;
|
||||
$form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 0;
|
||||
} else if ($value == 'forced') {
|
||||
$form->{$componentproviderbase.'_loggedin'}[$processor->name] = 1;
|
||||
$form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 1;
|
||||
}
|
||||
// Record the site preference.
|
||||
$newpreferences[$processor->name.'_provider_'.$componentprovidersetting] = $value;
|
||||
}
|
||||
} else {
|
||||
$newsettings = array();
|
||||
if (property_exists($form, $componentprovidersetting)) {
|
||||
// We must be processing loggedin or loggedoff checkboxes.
|
||||
// Store defained comma-separated processors as setting value.
|
||||
// Using array_filter eliminates elements set to 0 above.
|
||||
$newsettings = array_keys(array_filter($form->{$componentprovidersetting}));
|
||||
}
|
||||
|
||||
// Record the site preference.
|
||||
$newpreferences['message_provider_'.$componentprovidersetting] = $value;
|
||||
// Let's join existing setting values for disabled processors.
|
||||
$property = 'message_provider_'.$componentprovidersetting;
|
||||
if (property_exists($preferences, $property)) {
|
||||
$existingsetting = $preferences->$property;
|
||||
foreach ($disabledprocessors as $disable) {
|
||||
if (strpos($existingsetting, $disable->name) > -1) {
|
||||
$newsettings[] = $disable->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$value = join(',', $newsettings);
|
||||
if (empty($value)) {
|
||||
$value = null;
|
||||
}
|
||||
}
|
||||
if ($setting != 'permitted') {
|
||||
// We have already recoded site preferences for 'permitted' type.
|
||||
$newpreferences['message_provider_'.$componentprovidersetting] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update database.
|
||||
@@ -102,17 +119,10 @@ if (($form = data_submitted()) && confirm_sesskey()) {
|
||||
// Save processors enabled/disabled status.
|
||||
foreach ($allprocessors as $processor) {
|
||||
$enabled = isset($form->{$processor->name});
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('message');
|
||||
$class::enable_plugin($processor->name, $enabled);
|
||||
\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();
|
||||
@@ -125,6 +135,8 @@ if (($form = data_submitted()) && confirm_sesskey()) {
|
||||
|
||||
// Page settings
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->requires->js_init_call('M.core_message.init_defaultoutputs');
|
||||
|
||||
$renderer = $PAGE->get_renderer('core', 'message');
|
||||
|
||||
// Display the page.
|
||||
|
||||
@@ -6,7 +6,7 @@ require_once(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
include_once($CFG->dirroot.'/mnet/lib.php');
|
||||
|
||||
$sort = optional_param('sort', 'username', PARAM_ALPHAEXT);
|
||||
$sort = optional_param('sort', 'username', PARAM_ALPHA);
|
||||
$dir = optional_param('dir', 'ASC', PARAM_ALPHA);
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
$perpage = optional_param('perpage', 30, PARAM_INT);
|
||||
@@ -117,7 +117,6 @@ if ($form = data_submitted() and confirm_sesskey()) {
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render(mnet_get_deprecation_notice());
|
||||
|
||||
// Explain
|
||||
echo $OUTPUT->box(get_string('ssoacldescr','mnet'));
|
||||
@@ -154,15 +153,7 @@ foreach ($columns as $column) {
|
||||
$headings[$column] = "<a href=\"?sort=$column&dir=$columndir&\">".$string[$column]."</a>$columnicon";
|
||||
}
|
||||
$headings['delete'] = '';
|
||||
|
||||
$sortorder = get_safe_orderby([
|
||||
'username' => 'username',
|
||||
'mnet_host_id' => 'mnet_host_id',
|
||||
'access' => 'accessctrl',
|
||||
'default' => 'username',
|
||||
], $sort, $dir, false);
|
||||
|
||||
$acl = $DB->get_records('mnet_sso_access_control', null, $sortorder);
|
||||
$acl = $DB->get_records('mnet_sso_access_control', null, "$sort $dir", '*'); //, $page * $perpage, $perpage);
|
||||
$aclcount = $DB->count_records('mnet_sso_access_control');
|
||||
|
||||
if (!$acl) {
|
||||
|
||||
+3
-19
@@ -46,23 +46,11 @@
|
||||
|
||||
$formcontinue = new single_button(new moodle_url('index.php', array('confirm' => md5($mnet->public_key))), get_string('yes'));
|
||||
$formcancel = new single_button(new moodle_url('index.php', array()), get_string('no'));
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->confirm(get_string("deletekeycheck", "mnet"), $formcontinue, $formcancel);
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
} else {
|
||||
// We're deleting
|
||||
|
||||
// If no/cancel then redirect back to the network setting page.
|
||||
if (!isset($form->confirm)) {
|
||||
redirect(
|
||||
new moodle_url('/admin/mnet/index.php'),
|
||||
get_string('keydeletedcancelled', 'mnet'),
|
||||
null,
|
||||
\core\output\notification::NOTIFY_SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
if (!isset($SESSION->mnet_confirm_delete_key)) {
|
||||
// fail - you're being attacked?
|
||||
@@ -75,12 +63,8 @@
|
||||
|
||||
if($time < time() - 60) {
|
||||
// fail - you're out of time.
|
||||
redirect(
|
||||
new moodle_url('/admin/mnet/index.php'),
|
||||
get_string('deleteoutoftime', 'mnet'),
|
||||
null,
|
||||
\core\output\notification::NOTIFY_WARNING
|
||||
);
|
||||
print_error ('deleteoutoftime', 'mnet', 'index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($key != md5(sha1($mnet->keypair['keypair_PEM']))) {
|
||||
@@ -91,12 +75,12 @@
|
||||
|
||||
$mnet->replace_keys();
|
||||
redirect('index.php', get_string('keydeleted','mnet'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
$hosts = $DB->get_records_select('mnet_host', "id <> ? AND deleted = 0", array($CFG->mnet_localhost_id), 'wwwroot ASC');
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render(mnet_get_deprecation_notice());
|
||||
?>
|
||||
<form method="post" action="index.php">
|
||||
<table align="center" width="635" class="generaltable" border="0" cellpadding="5" cellspacing="0">
|
||||
|
||||
@@ -59,8 +59,9 @@ class mnet_simple_host_form extends moodleform {
|
||||
$wwwroot = 'http://'.$wwwroot;
|
||||
}
|
||||
if ($host = $DB->get_record('mnet_host', array('wwwroot' => $wwwroot))) {
|
||||
$str = get_string('hostexists', 'mnet', (new moodle_url('/admin/mnet/peers.php', ['hostid' => $host->id]))->out());
|
||||
return array('wwwroot' => $str);
|
||||
global $CFG;
|
||||
return array('wwwroot' => get_string('hostexists', 'mnet',
|
||||
new moodle_url('/admin/mnet/peers.php', array('hostid' => $host->id))));
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
@@ -51,8 +51,6 @@ if ($hostid && $DB->get_field('mnet_host', 'deleted', array('id' => $hostid)) !=
|
||||
$PAGE->set_url('/admin/mnet/peers.php');
|
||||
admin_externalpage_setup($adminsection);
|
||||
|
||||
$deprecatenotify = mnet_get_deprecation_notice();
|
||||
|
||||
if (!extension_loaded('openssl')) {
|
||||
print_error('requiresopenssl', 'mnet');
|
||||
}
|
||||
@@ -92,7 +90,6 @@ if ($formdata = $simpleform->get_data()) {
|
||||
$formdata->oldpublickey = $mnet_peer->public_key; // set this so we can confirm on form post without having to recreate the mnet_peer object
|
||||
$reviewform->set_data($mnet_peer);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render($deprecatenotify);
|
||||
echo $OUTPUT->box_start();
|
||||
$reviewform->display();
|
||||
echo $OUTPUT->box_end();
|
||||
@@ -180,7 +177,6 @@ if ($formdata = $reviewform->get_data()) {
|
||||
}
|
||||
} else if ($reviewform->is_submitted()) { // submitted, but errors
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render($deprecatenotify);
|
||||
echo $OUTPUT->box_start();
|
||||
$reviewform->display();
|
||||
echo $OUTPUT->box_end();
|
||||
@@ -191,7 +187,6 @@ if ($formdata = $reviewform->get_data()) {
|
||||
|
||||
// normal flow - just display all hosts with links
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render($deprecatenotify);
|
||||
$hosts = mnet_get_hosts(true);
|
||||
|
||||
// print the table to display the register all hosts setting
|
||||
|
||||
@@ -44,5 +44,4 @@ if (isset($mnet_peer->id) && $mnet_peer->id > 0) {
|
||||
} else {
|
||||
$tabs[] = new tabobject('mnetdetails', '#', $strmnetedithost, $strmnetedithost, false);
|
||||
}
|
||||
echo $OUTPUT->render(mnet_get_deprecation_notice());
|
||||
print_tabs(array($tabs), $currenttab);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?php
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render(mnet_get_deprecation_notice());
|
||||
?>
|
||||
<div id="trustedhosts"><!-- See theme/standard/styles_layout.css #trustedhosts .generaltable for rules -->
|
||||
<table cellspacing="0" cellpadding="5" class="generaltable generalbox" >
|
||||
|
||||
+35
-10
@@ -30,20 +30,43 @@
|
||||
/// If data submitted, then process and store.
|
||||
|
||||
if (!empty($hide) and confirm_sesskey()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('mod');
|
||||
if ($class::enable_plugin($hide, false)) {
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
if (!$module = $DB->get_record("modules", array("name"=>$hide))) {
|
||||
print_error('moduledoesnotexist', 'error');
|
||||
}
|
||||
$DB->set_field("modules", "visible", "0", array("id"=>$module->id)); // Hide main module
|
||||
// Remember the visibility status in visibleold
|
||||
// and hide...
|
||||
$sql = "UPDATE {course_modules}
|
||||
SET visibleold=visible, visible=0
|
||||
WHERE module=?";
|
||||
$DB->execute($sql, array($module->id));
|
||||
// Increment course.cacherev for courses where we just made something invisible.
|
||||
// This will force cache rebuilding on the next request.
|
||||
increment_revision_number('course', 'cacherev',
|
||||
"id IN (SELECT DISTINCT course
|
||||
FROM {course_modules}
|
||||
WHERE visibleold=1 AND module=?)",
|
||||
array($module->id));
|
||||
core_plugin_manager::reset_caches();
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
redirect(new moodle_url('/admin/modules.php'));
|
||||
}
|
||||
|
||||
if (!empty($show) && confirm_sesskey()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('mod');
|
||||
if ($class::enable_plugin($show, true)) {
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
if (!empty($show) and confirm_sesskey()) {
|
||||
if (!$module = $DB->get_record("modules", array("name"=>$show))) {
|
||||
print_error('moduledoesnotexist', 'error');
|
||||
}
|
||||
$DB->set_field("modules", "visible", "1", array("id"=>$module->id)); // Show main module
|
||||
$DB->set_field('course_modules', 'visible', '1', array('visibleold'=>1, 'module'=>$module->id)); // Get the previous saved visible state for the course module.
|
||||
// Increment course.cacherev for courses where we just made something visible.
|
||||
// This will force cache rebuilding on the next request.
|
||||
increment_revision_number('course', 'cacherev',
|
||||
"id IN (SELECT DISTINCT course
|
||||
FROM {course_modules}
|
||||
WHERE visible=1 AND module=?)",
|
||||
array($module->id));
|
||||
core_plugin_manager::reset_caches();
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
redirect(new moodle_url('/admin/modules.php'));
|
||||
}
|
||||
|
||||
@@ -77,7 +100,7 @@
|
||||
$missing = true;
|
||||
} else {
|
||||
// took out hspace="\10\", because it does not validate. don't know what to replace with.
|
||||
$icon = "<img src=\"" . $OUTPUT->image_url('monologo', $module->name) . "\" class=\"icon\" alt=\"\" />";
|
||||
$icon = "<img src=\"" . $OUTPUT->image_url('icon', $module->name) . "\" class=\"icon\" alt=\"\" />";
|
||||
$strmodulename = $icon.' '.get_string('modulename', $module->name);
|
||||
$missing = false;
|
||||
}
|
||||
@@ -140,3 +163,5 @@
|
||||
$table->print_html();
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
|
||||
|
||||
+12
-25
@@ -30,41 +30,28 @@
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
|
||||
// The state parameter we've given (used in moodle as a redirect url).
|
||||
// Per https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1, state is required, even during error responses.
|
||||
$state = required_param('state', PARAM_LOCALURL);
|
||||
$redirecturl = new moodle_url($state);
|
||||
$params = $redirecturl->params();
|
||||
|
||||
$error = optional_param('error', '', PARAM_RAW);
|
||||
|
||||
if ($error) {
|
||||
$message = optional_param('error_description', null, PARAM_RAW);
|
||||
|
||||
// Errors can occur for authenticated users, such as when a user denies authorization for some internal service call.
|
||||
// In such cases, propagate the error to the component redirect URI.
|
||||
if (isloggedin()) {
|
||||
if (isset($params['sesskey']) && confirm_sesskey($params['sesskey'])) {
|
||||
$redirecturl->param('error', $error);
|
||||
if ($message) {
|
||||
$redirecturl->param('error_description', $message);
|
||||
}
|
||||
redirect($redirecturl);
|
||||
}
|
||||
$message = optional_param('error_description', '', PARAM_RAW);
|
||||
if ($message) {
|
||||
print_error($message);
|
||||
} else {
|
||||
print_error($error);
|
||||
}
|
||||
|
||||
// Not logged in or the sesskey verification failed, redirect to login + show errors.
|
||||
$SESSION->loginerrormsg = $message ?? $error;
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
die();
|
||||
}
|
||||
|
||||
// The authorization code generated by the authorization server.
|
||||
$code = required_param('code', PARAM_RAW);
|
||||
// The state parameter we've given (used in moodle as a redirect url).
|
||||
$state = required_param('state', PARAM_LOCALURL);
|
||||
|
||||
$redirecturl = new moodle_url($state);
|
||||
$params = $redirecturl->params();
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
@@ -52,8 +52,6 @@ $pageurl = new moodle_url('/admin/plugins.php', $pageparams);
|
||||
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
|
||||
$PAGE->set_primary_active_tab('siteadminnode');
|
||||
|
||||
if ($uninstall) {
|
||||
|
||||
if (!$confirmed) {
|
||||
|
||||
+9
-3
@@ -102,15 +102,20 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
require_sesskey();
|
||||
|
||||
$instance = portfolio_instance($portfolio);
|
||||
$plugin = $instance->get('plugin');
|
||||
$current = $instance->get('visible');
|
||||
if (empty($current) && $instance->instance_sanity_check()) {
|
||||
print_error('cannotsetvisible', 'portfolio', $baseurl);
|
||||
}
|
||||
|
||||
if ($action == 'show') {
|
||||
$visible = 1;
|
||||
} else {
|
||||
$visible = 0;
|
||||
}
|
||||
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('portfolio');
|
||||
$class::enable_plugin($plugin, $visible);
|
||||
$instance->set('visible', $visible);
|
||||
$instance->save();
|
||||
core_plugin_manager::reset_caches();
|
||||
$return = true;
|
||||
} else if ($action == 'delete') {
|
||||
$instance = portfolio_instance($portfolio);
|
||||
@@ -241,3 +246,4 @@ if ($return) {
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
|
||||
@@ -1,390 +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/>.
|
||||
|
||||
namespace core_adminpresets;
|
||||
|
||||
/**
|
||||
* Admin presets helper class.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Sara Arjona (sara@moodle.com)
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class helper {
|
||||
|
||||
/**
|
||||
* Create an empty preset.
|
||||
*
|
||||
* @param array $data Preset data. Supported values:
|
||||
* - name. To define the preset name.
|
||||
* - comments. To change the comments field.
|
||||
* - author. To update the author field.
|
||||
* - iscore. Whether the preset is a core preset or not. Valid values on \core_adminpresets\manager class.
|
||||
* @return int The identifier of the preset created.
|
||||
*/
|
||||
public static function create_preset(array $data): int {
|
||||
global $CFG, $USER, $DB;
|
||||
|
||||
$name = array_key_exists('name', $data) ? $data['name'] : '';
|
||||
$comments = array_key_exists('comments', $data) ? $data['comments'] : '';
|
||||
$author = array_key_exists('author', $data) ? $data['author'] : fullname($USER);
|
||||
$iscore = array_key_exists('iscore', $data) ? $data['iscore'] : manager::NONCORE_PRESET;
|
||||
|
||||
// Validate iscore value.
|
||||
$allowed = [manager::NONCORE_PRESET, manager::STARTER_PRESET, manager::FULL_PRESET];
|
||||
if (!in_array($iscore, $allowed)) {
|
||||
$iscore = manager::NONCORE_PRESET;
|
||||
}
|
||||
|
||||
$preset = [
|
||||
'userid' => $USER->id,
|
||||
'name' => $name,
|
||||
'comments' => $comments,
|
||||
'site' => $CFG->wwwroot,
|
||||
'author' => $author,
|
||||
'moodleversion' => $CFG->version,
|
||||
'moodlerelease' => $CFG->release,
|
||||
'iscore' => $iscore,
|
||||
'timecreated' => time(),
|
||||
'timeimported' => 0,
|
||||
];
|
||||
|
||||
$presetid = $DB->insert_record('adminpresets', $preset);
|
||||
return $presetid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to add a setting item to a preset.
|
||||
*
|
||||
* @param int $presetid Preset identifier where the item will belong.
|
||||
* @param string $name Item name.
|
||||
* @param string $value Item value.
|
||||
* @param string|null $plugin Item plugin.
|
||||
* @param string|null $advname If the item is an advanced setting, the name of the advanced setting should be specified here.
|
||||
* @param string|null $advvalue If the item is an advanced setting, the value of the advanced setting should be specified here.
|
||||
* @return int The item identificator.
|
||||
*/
|
||||
public static function add_item(int $presetid, string $name, string $value, ?string $plugin = 'none',
|
||||
?string $advname = null, ?string $advvalue = null): int {
|
||||
global $DB;
|
||||
|
||||
$presetitem = [
|
||||
'adminpresetid' => $presetid,
|
||||
'plugin' => $plugin,
|
||||
'name' => $name,
|
||||
'value' => $value,
|
||||
];
|
||||
$itemid = $DB->insert_record('adminpresets_it', $presetitem);
|
||||
|
||||
if (!empty($advname)) {
|
||||
$presetadv = [
|
||||
'itemid' => $itemid,
|
||||
'name' => $advname,
|
||||
'value' => $advvalue,
|
||||
];
|
||||
$DB->insert_record('adminpresets_it_a', $presetadv);
|
||||
}
|
||||
|
||||
return $itemid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to add a plugin to a preset.
|
||||
*
|
||||
* @param int $presetid Preset identifier where the item will belong.
|
||||
* @param string $plugin Plugin type.
|
||||
* @param string $name Plugin name.
|
||||
* @param int $enabled Whether the plugin will be enabled or not.
|
||||
* @return int The plugin identificator.
|
||||
*/
|
||||
public static function add_plugin(int $presetid, string $plugin, string $name, int $enabled): int {
|
||||
global $DB;
|
||||
|
||||
$pluginentry = [
|
||||
'adminpresetid' => $presetid,
|
||||
'plugin' => $plugin,
|
||||
'name' => $name,
|
||||
'enabled' => $enabled,
|
||||
];
|
||||
$pluginid = $DB->insert_record('adminpresets_plug', $pluginentry);
|
||||
|
||||
return $pluginid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the given preset. If it's a filename, the preset will be imported and then applied.
|
||||
*
|
||||
* @param string $presetnameorfile The preset name to be applied or a valid preset file to be imported and applied.
|
||||
* @return int|null The preset identifier that has been applied or null if the given value was not valid.
|
||||
*/
|
||||
public static function change_default_preset(string $presetnameorfile): ?int {
|
||||
global $DB;
|
||||
|
||||
$presetid = null;
|
||||
|
||||
// Check if the given variable points to a valid preset file to be imported and applied.
|
||||
if (is_readable($presetnameorfile)) {
|
||||
$xmlcontent = file_get_contents($presetnameorfile);
|
||||
$manager = new manager();
|
||||
list($xmlnotused, $preset) = $manager->import_preset($xmlcontent);
|
||||
if (!is_null($preset)) {
|
||||
list($applied) = $manager->apply_preset($preset->id);
|
||||
if (!empty($applied)) {
|
||||
$presetid = $preset->id;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check if the given preset exists; if that's the case, it will be applied.
|
||||
$stringmanager = get_string_manager();
|
||||
if ($stringmanager->string_exists($presetnameorfile . 'preset', 'core_adminpresets')) {
|
||||
$params = ['name' => get_string($presetnameorfile . 'preset', 'core_adminpresets')];
|
||||
} else {
|
||||
$params = ['name' => $presetnameorfile];
|
||||
}
|
||||
if ($preset = $DB->get_record('adminpresets', $params)) {
|
||||
$manager = new manager();
|
||||
list($applied) = $manager->apply_preset($preset->id);
|
||||
if (!empty($applied)) {
|
||||
$presetid = $preset->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $presetid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create default site admin presets and initialize them.
|
||||
*/
|
||||
public static function create_default_presets(): void {
|
||||
// Create the "Starter" site admin preset.
|
||||
$data = [
|
||||
'name' => get_string('starterpreset', 'core_adminpresets'),
|
||||
'comments' => get_string('starterpresetdescription', 'core_adminpresets'),
|
||||
'iscore' => manager::STARTER_PRESET,
|
||||
];
|
||||
$presetid = static::create_preset($data);
|
||||
|
||||
// Add settings to the "Starter" site admin preset.
|
||||
static::add_item($presetid, 'usecomments', '0');
|
||||
static::add_item($presetid, 'usetags', '0');
|
||||
static::add_item($presetid, 'enablenotes', '0');
|
||||
static::add_item($presetid, 'enableblogs', '0');
|
||||
static::add_item($presetid, 'enablebadges', '0');
|
||||
static::add_item($presetid, 'enableanalytics', '0');
|
||||
static::add_item($presetid, 'enabled', '0', 'core_competency');
|
||||
static::add_item($presetid, 'pushcourseratingstouserplans', '0', 'core_competency');
|
||||
static::add_item($presetid, 'showdataretentionsummary', '0', 'tool_dataprivacy');
|
||||
static::add_item($presetid, 'forum_maxattachments', '3');
|
||||
static::add_item($presetid, 'guestloginbutton', '0');
|
||||
// Set Activity chooser tabs to "Starred, All, Recommended".
|
||||
static::add_item($presetid, 'activitychoosertabmode', '1');
|
||||
|
||||
// Modules: Hide chat, database, external tool (lti), IMS content package (imscp), lesson, SCORM, survey, wiki, workshop.
|
||||
static::add_plugin($presetid, 'mod', 'chat', false);
|
||||
static::add_plugin($presetid, 'mod', 'data', false);
|
||||
static::add_plugin($presetid, 'mod', 'lti', false);
|
||||
static::add_plugin($presetid, 'mod', 'imscp', false);
|
||||
static::add_plugin($presetid, 'mod', 'lesson', false);
|
||||
static::add_plugin($presetid, 'mod', 'scorm', false);
|
||||
static::add_plugin($presetid, 'mod', 'survey', false);
|
||||
static::add_plugin($presetid, 'mod', 'wiki', false);
|
||||
static::add_plugin($presetid, 'mod', 'workshop', false);
|
||||
|
||||
// Availability restrictions: Hide Grouping, User profile.
|
||||
static::add_plugin($presetid, 'availability', 'grouping', false);
|
||||
static::add_plugin($presetid, 'availability', 'profile', false);
|
||||
|
||||
// Blocks: Hide Activities, Blog menu, Blog tags, Comments, Course completion status, Courses, Flickr,
|
||||
// Global search, Latest badges, Learning plans, Logged in user, Login, Main menu, Mentees, Network servers, Online users,
|
||||
// Private files, Recent blog entries, Recently accessed courses, Search forums, Section links, Social activities,
|
||||
// Starred courses, Tags, YouTube.
|
||||
// Hidden by default: Course/site summary, RSS feeds, Self completion, Feedback.
|
||||
static::add_plugin($presetid, 'block', 'activity_modules', false);
|
||||
static::add_plugin($presetid, 'block', 'blog_menu', false);
|
||||
static::add_plugin($presetid, 'block', 'blog_tags', false);
|
||||
static::add_plugin($presetid, 'block', 'comments', false);
|
||||
static::add_plugin($presetid, 'block', 'completionstatus', false);
|
||||
static::add_plugin($presetid, 'block', 'course_summary', false);
|
||||
static::add_plugin($presetid, 'block', 'course_list', false);
|
||||
static::add_plugin($presetid, 'block', 'tag_flickr', false);
|
||||
static::add_plugin($presetid, 'block', 'globalsearch', false);
|
||||
static::add_plugin($presetid, 'block', 'badges', false);
|
||||
static::add_plugin($presetid, 'block', 'lp', false);
|
||||
static::add_plugin($presetid, 'block', 'myprofile', false);
|
||||
static::add_plugin($presetid, 'block', 'login', false);
|
||||
static::add_plugin($presetid, 'block', 'site_main_menu', false);
|
||||
static::add_plugin($presetid, 'block', 'mentees', false);
|
||||
static::add_plugin($presetid, 'block', 'mnet_hosts', false);
|
||||
static::add_plugin($presetid, 'block', 'private_files', false);
|
||||
static::add_plugin($presetid, 'block', 'blog_recent', false);
|
||||
static::add_plugin($presetid, 'block', 'rss_client', false);
|
||||
static::add_plugin($presetid, 'block', 'search_forums', false);
|
||||
static::add_plugin($presetid, 'block', 'section_links', false);
|
||||
static::add_plugin($presetid, 'block', 'selfcompletion', false);
|
||||
static::add_plugin($presetid, 'block', 'social_activities', false);
|
||||
static::add_plugin($presetid, 'block', 'tags', false);
|
||||
static::add_plugin($presetid, 'block', 'tag_youtube', false);
|
||||
static::add_plugin($presetid, 'block', 'feedback', false);
|
||||
static::add_plugin($presetid, 'block', 'online_users', false);
|
||||
static::add_plugin($presetid, 'block', 'recentlyaccessedcourses', false);
|
||||
static::add_plugin($presetid, 'block', 'starredcourses', false);
|
||||
|
||||
// Course formats: Disable Social format.
|
||||
static::add_plugin($presetid, 'format', 'social', false);
|
||||
|
||||
// Data formats: Disable Javascript Object Notation (.json).
|
||||
static::add_plugin($presetid, 'dataformat', 'json', false);
|
||||
|
||||
// Enrolments: Disable Cohort sync, Guest access.
|
||||
static::add_plugin($presetid, 'enrol', 'cohort', false);
|
||||
static::add_plugin($presetid, 'enrol', 'guest', false);
|
||||
|
||||
// Filter: Disable MathJax, Activity names auto-linking.
|
||||
static::add_plugin($presetid, 'filter', 'mathjaxloader', TEXTFILTER_DISABLED);
|
||||
static::add_plugin($presetid, 'filter', 'activitynames', TEXTFILTER_DISABLED);
|
||||
|
||||
// Question behaviours: Disable Adaptive mode (no penalties), Deferred feedback with CBM, Immediate feedback with CBM.
|
||||
static::add_plugin($presetid, 'qbehaviour', 'adaptivenopenalty', false);
|
||||
static::add_plugin($presetid, 'qbehaviour', 'deferredcbm', false);
|
||||
static::add_plugin($presetid, 'qbehaviour', 'immediatecbm', false);
|
||||
|
||||
// Question types: Disable Calculated, Calculated multichoice, Calculated simple, Drag and drop markers,
|
||||
// Drag and drop onto image, Embedded answers (Cloze), Numerical, Random short-answer matching.
|
||||
static::add_plugin($presetid, 'qtype', 'calculated', false);
|
||||
static::add_plugin($presetid, 'qtype', 'calculatedmulti', false);
|
||||
static::add_plugin($presetid, 'qtype', 'calculatedsimple', false);
|
||||
static::add_plugin($presetid, 'qtype', 'ddmarker', false);
|
||||
static::add_plugin($presetid, 'qtype', 'ddimageortext', false);
|
||||
static::add_plugin($presetid, 'qtype', 'multianswer', false);
|
||||
static::add_plugin($presetid, 'qtype', 'numerical', false);
|
||||
static::add_plugin($presetid, 'qtype', 'randomsamatch', false);
|
||||
|
||||
// Repositories: Disable Server files, URL downloader, Wikimedia.
|
||||
static::add_plugin($presetid, 'repository', 'local', false);
|
||||
static::add_plugin($presetid, 'repository', 'url', false);
|
||||
static::add_plugin($presetid, 'repository', 'wikimedia', false);
|
||||
|
||||
// Text editors: Disable TinyMCE HTML editor.
|
||||
static::add_plugin($presetid, 'editor', 'tinymce', false);
|
||||
|
||||
// Create the "Full" site admin preset.
|
||||
$data = [
|
||||
'name' => get_string('fullpreset', 'core_adminpresets'),
|
||||
'comments' => get_string('fullpresetdescription', 'core_adminpresets'),
|
||||
'iscore' => manager::FULL_PRESET,
|
||||
];
|
||||
$presetid = static::create_preset($data);
|
||||
|
||||
// Add settings to the "Full" site admin preset.
|
||||
static::add_item($presetid, 'usecomments', '1');
|
||||
static::add_item($presetid, 'usetags', '1');
|
||||
static::add_item($presetid, 'enablenotes', '1');
|
||||
static::add_item($presetid, 'enableblogs', '1');
|
||||
static::add_item($presetid, 'enablebadges', '1');
|
||||
static::add_item($presetid, 'enableanalytics', '1');
|
||||
static::add_item($presetid, 'enabled', '1', 'core_competency');
|
||||
static::add_item($presetid, 'pushcourseratingstouserplans', '1', 'core_competency');
|
||||
static::add_item($presetid, 'showdataretentionsummary', '1', 'tool_dataprivacy');
|
||||
static::add_item($presetid, 'forum_maxattachments', '9');
|
||||
static::add_item($presetid, 'guestloginbutton', '1');
|
||||
// Set Activity chooser tabs to the default value ("Starred, All, Activities, Resources, Recommended").
|
||||
static::add_item($presetid, 'activitychoosertabmode', '0');
|
||||
|
||||
// Modules: Enable chat, database, external tool (lti), IMS content package (imscp), lesson, SCORM, survey, wiki, workshop.
|
||||
static::add_plugin($presetid, 'mod', 'chat', true);
|
||||
static::add_plugin($presetid, 'mod', 'data', true);
|
||||
static::add_plugin($presetid, 'mod', 'lti', true);
|
||||
static::add_plugin($presetid, 'mod', 'imscp', true);
|
||||
static::add_plugin($presetid, 'mod', 'lesson', true);
|
||||
static::add_plugin($presetid, 'mod', 'scorm', true);
|
||||
static::add_plugin($presetid, 'mod', 'survey', true);
|
||||
static::add_plugin($presetid, 'mod', 'wiki', true);
|
||||
static::add_plugin($presetid, 'mod', 'workshop', true);
|
||||
|
||||
// Availability restrictions: Enable Grouping, User profile.
|
||||
static::add_plugin($presetid, 'availability', 'grouping', true);
|
||||
static::add_plugin($presetid, 'availability', 'profile', true);
|
||||
|
||||
// Blocks: Enable Activities, Blog menu, Blog tags, Comments, Course completion status, Courses, Flickr,
|
||||
// Global search, Latest badges, Learning plans, Logged in user, Login, Main menu, Mentees, Network servers, Online users,
|
||||
// Private files, Recent blog entries, Recently accessed courses, Search forums, Section links, Social activities,
|
||||
// Starred courses, Tags, YouTube.
|
||||
// Hidden by default: Course/site summary, RSS feeds, Self completion, Feedback.
|
||||
static::add_plugin($presetid, 'block', 'activity_modules', true);
|
||||
static::add_plugin($presetid, 'block', 'blog_menu', true);
|
||||
static::add_plugin($presetid, 'block', 'blog_tags', true);
|
||||
static::add_plugin($presetid, 'block', 'comments', true);
|
||||
static::add_plugin($presetid, 'block', 'completionstatus', true);
|
||||
static::add_plugin($presetid, 'block', 'course_list', true);
|
||||
static::add_plugin($presetid, 'block', 'tag_flickr', true);
|
||||
static::add_plugin($presetid, 'block', 'globalsearch', true);
|
||||
static::add_plugin($presetid, 'block', 'badges', true);
|
||||
static::add_plugin($presetid, 'block', 'lp', true);
|
||||
static::add_plugin($presetid, 'block', 'myprofile', true);
|
||||
static::add_plugin($presetid, 'block', 'login', true);
|
||||
static::add_plugin($presetid, 'block', 'site_main_menu', true);
|
||||
static::add_plugin($presetid, 'block', 'mentees', true);
|
||||
static::add_plugin($presetid, 'block', 'mnet_hosts', true);
|
||||
static::add_plugin($presetid, 'block', 'private_files', true);
|
||||
static::add_plugin($presetid, 'block', 'blog_recent', true);
|
||||
static::add_plugin($presetid, 'block', 'search_forums', true);
|
||||
static::add_plugin($presetid, 'block', 'section_links', true);
|
||||
static::add_plugin($presetid, 'block', 'social_activities', true);
|
||||
static::add_plugin($presetid, 'block', 'tags', true);
|
||||
static::add_plugin($presetid, 'block', 'online_users', true);
|
||||
static::add_plugin($presetid, 'block', 'recentlyaccessedcourses', true);
|
||||
static::add_plugin($presetid, 'block', 'starredcourses', true);
|
||||
|
||||
// Course formats: Enable Social format.
|
||||
static::add_plugin($presetid, 'format', 'social', true);
|
||||
|
||||
// Data formats: Enable Javascript Object Notation (.json).
|
||||
static::add_plugin($presetid, 'dataformat', 'json', true);
|
||||
|
||||
// Enrolments: Enable Cohort sync, Guest access.
|
||||
static::add_plugin($presetid, 'enrol', 'cohort', true);
|
||||
static::add_plugin($presetid, 'enrol', 'guest', true);
|
||||
|
||||
// Filter: Enable MathJax, Activity names auto-linking.
|
||||
static::add_plugin($presetid, 'filter', 'mathjaxloader', TEXTFILTER_ON);
|
||||
static::add_plugin($presetid, 'filter', 'activitynames', TEXTFILTER_ON);
|
||||
|
||||
// Question behaviours: Enable Adaptive mode (no penalties), Deferred feedback with CBM, Immediate feedback with CBM.
|
||||
static::add_plugin($presetid, 'qbehaviour', 'adaptivenopenalty', true);
|
||||
static::add_plugin($presetid, 'qbehaviour', 'deferredcbm', true);
|
||||
static::add_plugin($presetid, 'qbehaviour', 'immediatecbm', true);
|
||||
|
||||
// Question types: Enable Calculated, Calculated multichoice, Calculated simple, Drag and drop markers,
|
||||
// Drag and drop onto image, Embedded answers (Cloze), Numerical, Random short-answer matching.
|
||||
static::add_plugin($presetid, 'qtype', 'calculated', true);
|
||||
static::add_plugin($presetid, 'qtype', 'calculatedmulti', true);
|
||||
static::add_plugin($presetid, 'qtype', 'calculatedsimple', true);
|
||||
static::add_plugin($presetid, 'qtype', 'ddmarker', true);
|
||||
static::add_plugin($presetid, 'qtype', 'ddimageortext', true);
|
||||
static::add_plugin($presetid, 'qtype', 'multianswer', true);
|
||||
static::add_plugin($presetid, 'qtype', 'numerical', true);
|
||||
static::add_plugin($presetid, 'qtype', 'randomsamatch', true);
|
||||
|
||||
// Repositories: Enable Server files, URL downloader, Wikimedia.
|
||||
static::add_plugin($presetid, 'repository', 'local', true);
|
||||
static::add_plugin($presetid, 'repository', 'url', true);
|
||||
static::add_plugin($presetid, 'repository', 'wikimedia', true);
|
||||
|
||||
// Text editors: Enable TinyMCE HTML editor.
|
||||
static::add_plugin($presetid, 'editor', 'tinymce', true);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Select setting for blog's bloglevel setting.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_bloglevel extends adminpresets_admin_setting_configselect {
|
||||
|
||||
/**
|
||||
* Extended to change the block visibility.
|
||||
*
|
||||
* @param bool $name Setting name to store.
|
||||
* @param mixed $value Setting value to store.
|
||||
* @return int|false config_log inserted id or false whenever the value has not been saved.
|
||||
*/
|
||||
public function save_value($name = false, $value = null) {
|
||||
global $DB;
|
||||
|
||||
if (!$id = parent::save_value($name, $value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Object values if no arguments.
|
||||
if ($value === null) {
|
||||
$value = $this->value;
|
||||
}
|
||||
|
||||
// Pasted from admin_setting_bloglevel (can't use write_config).
|
||||
if ($value == 0) {
|
||||
$DB->set_field('block', 'visible', 0, ['name' => 'blog_menu']);
|
||||
} else {
|
||||
$DB->set_field('block', 'visible', 1, ['name' => 'blog_menu']);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
use admin_setting_configcheckbox;
|
||||
|
||||
/**
|
||||
* Checkbox setting.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configcheckbox extends adminpresets_setting {
|
||||
|
||||
/**
|
||||
* Sets the visible name for the setting selected value
|
||||
*/
|
||||
protected function set_visiblevalue() {
|
||||
/** @var admin_setting_configcheckbox $settingdata */
|
||||
$settingdata = $this->get_settingdata();
|
||||
|
||||
// We need to compare the "yes" value of the inner checkbox, which isn't necessarily boolean.
|
||||
if ($this->value == $settingdata->yes) {
|
||||
$str = get_string('yes');
|
||||
} else {
|
||||
$str = get_string('no');
|
||||
}
|
||||
|
||||
$this->visiblevalue = $str;
|
||||
}
|
||||
}
|
||||
-48
@@ -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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
use admin_setting;
|
||||
|
||||
/**
|
||||
* Checkbox with an advanced checkbox that controls an additional $name.'_adv' config setting.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configcheckbox_with_advanced extends adminpresets_admin_setting_configcheckbox {
|
||||
|
||||
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
|
||||
// To look for other values.
|
||||
$this->attributes = ['adv' => $settingdata->name . '_adv'];
|
||||
parent::__construct($settingdata, $dbsettingvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses delegation
|
||||
*/
|
||||
protected function set_visiblevalue() {
|
||||
parent::set_visiblevalue();
|
||||
|
||||
if (!is_null($this->attributesvalues) && array_key_exists($this->attributes['adv'], $this->attributesvalues)) {
|
||||
$value = $this->attributesvalues[$this->attributes['adv']];
|
||||
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($value, 'advanced');
|
||||
}
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
use admin_setting;
|
||||
|
||||
/**
|
||||
* Checkbox with an advanced checkbox that controls an additional $name.'_locked' config setting.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configcheckbox_with_lock extends adminpresets_admin_setting_configcheckbox {
|
||||
|
||||
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
|
||||
// To look for other values.
|
||||
$this->attributes = ['locked' => $settingdata->name . '_locked'];
|
||||
parent::__construct($settingdata, $dbsettingvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses delegation
|
||||
*/
|
||||
protected function set_visiblevalue() {
|
||||
parent::set_visiblevalue();
|
||||
if (!is_null($this->attributesvalues) && array_key_exists($this->attributes['locked'], $this->attributesvalues)) {
|
||||
$value = $this->attributesvalues[$this->attributes['locked']];
|
||||
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($value, 'locked');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Used to validate a textarea used for ip addresses.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configiplist extends adminpresets_admin_setting_configtext {
|
||||
|
||||
protected function set_value($value) {
|
||||
// Check ip format.
|
||||
if ($this->settingdata->validate($value) !== true) {
|
||||
$this->value = false;
|
||||
$this->set_visiblevalue();
|
||||
return false;
|
||||
}
|
||||
$this->value = $value;
|
||||
$this->set_visiblevalue();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Class to be extended by multicheckbox settings.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configmulticheckbox extends adminpresets_admin_setting_configmultiselect {
|
||||
|
||||
public function set_behaviors() {
|
||||
$this->behaviors['loadchoices'] = &$this->settingdata;
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Extends the base class and lists the selected values separated by comma.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configmultiselect extends adminpresets_setting {
|
||||
|
||||
/**
|
||||
* Ensure that the $value values are setting choices.
|
||||
*
|
||||
* @param mixed $value Setting value
|
||||
* @return mixed Returns false if wrong param value
|
||||
*/
|
||||
protected function set_value($value) {
|
||||
if ($value) {
|
||||
$options = explode(',', $value);
|
||||
foreach ($options as $option) {
|
||||
|
||||
foreach ($this->settingdata->choices as $key => $choice) {
|
||||
|
||||
if ($key == $option) {
|
||||
$this->value = $option;
|
||||
$this->set_visiblevalue();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$value = implode(',', $options);
|
||||
}
|
||||
$this->value = $value;
|
||||
$this->set_visiblevalue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function set_visiblevalue() {
|
||||
$values = explode(',', $this->value);
|
||||
$visiblevalues = [];
|
||||
|
||||
foreach ($values as $value) {
|
||||
|
||||
if (!empty($this->settingdata->choices[$value])) {
|
||||
$visiblevalues[] = $this->settingdata->choices[$value];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($visiblevalues)) {
|
||||
$this->visiblevalue = '';
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->visiblevalue = implode(', ', $visiblevalues);
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Generalizes a configmultipleselect with load_choices().
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configmultiselect_with_loader extends adminpresets_admin_setting_configmultiselect {
|
||||
|
||||
public function set_behaviors() {
|
||||
$this->behaviors['loadchoices'] = &$this->settingdata;
|
||||
}
|
||||
}
|
||||
@@ -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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Select one value from list.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configselect extends adminpresets_setting {
|
||||
|
||||
/**
|
||||
* Sets the setting value cleaning it.
|
||||
*
|
||||
* @param mixed $value must be one of the setting choices.
|
||||
* @return bool true if the value one of the setting choices
|
||||
*/
|
||||
protected function set_value($value) {
|
||||
// When we intantiate the class we need the choices.
|
||||
if (empty($this->settingdata->choices) && method_exists($this->settingdata, 'load_choices')) {
|
||||
$this->settingdata->load_choices();
|
||||
}
|
||||
|
||||
if (!is_null($this->settingdata->choices) and is_array($this->settingdata->choices)) {
|
||||
foreach ($this->settingdata->choices as $key => $choice) {
|
||||
|
||||
if ($key == $value) {
|
||||
$this->value = $value;
|
||||
$this->set_visiblevalue();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->value = false;
|
||||
$this->set_visiblevalue();
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function set_visiblevalue() {
|
||||
// Just to avoid heritage problems.
|
||||
if (empty($this->settingdata->choices[$this->value])) {
|
||||
$this->visiblevalue = '';
|
||||
} else {
|
||||
$this->visiblevalue = $this->settingdata->choices[$this->value];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-59
@@ -1,59 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
use admin_setting;
|
||||
|
||||
/**
|
||||
* Adds support for the "advanced" attribute.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configselect_with_advanced extends adminpresets_admin_setting_configselect {
|
||||
|
||||
/** @var string Name of the advanced setting. **/
|
||||
protected $advancedkey;
|
||||
|
||||
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
|
||||
// Getting the advanced defaultsetting attribute name.
|
||||
if (is_array($settingdata->defaultsetting)) {
|
||||
foreach ($settingdata->defaultsetting as $key => $defaultvalue) {
|
||||
if ($key != 'value') {
|
||||
$this->advancedkey = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To look for other values.
|
||||
$this->attributes = [$this->advancedkey => $settingdata->name . '_adv'];
|
||||
parent::__construct($settingdata, $dbsettingvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Funcionality used by other _with_advanced settings
|
||||
*/
|
||||
protected function set_visiblevalue() {
|
||||
parent::set_visiblevalue();
|
||||
if (!is_null($this->attributesvalues)) {
|
||||
$attribute = $this->attributes[$this->advancedkey];
|
||||
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($this->attributesvalues[$attribute], 'advanced');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Basic text setting, cleans the param using the admin_setting paramtext attribute.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configtext extends adminpresets_setting {
|
||||
|
||||
/**
|
||||
* Validates the value using paramtype attribute
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return boolean Cleaned or not, but always true.
|
||||
*/
|
||||
protected function set_value($value) {
|
||||
$this->value = $value;
|
||||
|
||||
if (empty($this->settingdata->paramtype)) {
|
||||
|
||||
// For configfile, configpasswordunmask....
|
||||
$this->settingdata->paramtype = 'RAW';
|
||||
}
|
||||
|
||||
$paramtype = 'PARAM_' . strtoupper($this->settingdata->paramtype);
|
||||
|
||||
// Regexp.
|
||||
if (!defined($paramtype)) {
|
||||
$this->value = preg_replace($this->settingdata->paramtype, '', $this->value);
|
||||
|
||||
// Standard moodle param type.
|
||||
} else {
|
||||
$this->value = clean_param($this->value, constant($paramtype));
|
||||
}
|
||||
$this->set_visiblevalue();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
use admin_setting;
|
||||
|
||||
/**
|
||||
* Adds the advanced attribute.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configtext_with_advanced extends adminpresets_admin_setting_configtext {
|
||||
|
||||
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
|
||||
// To look for other values.
|
||||
$this->attributes = ['fix' => $settingdata->name . '_adv'];
|
||||
parent::__construct($settingdata, $dbsettingvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates
|
||||
*/
|
||||
protected function set_visiblevalue() {
|
||||
parent::set_visiblevalue();
|
||||
if (!is_null($this->attributesvalues) && array_key_exists($this->attributes['fix'], $this->attributesvalues)) {
|
||||
$value = $this->attributesvalues[$this->attributes['fix']];
|
||||
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($value, 'advanced');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Time selector.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_configtime extends adminpresets_setting {
|
||||
|
||||
/**
|
||||
* To check that the value is one of the options
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function set_attribute_value($name, $value) {
|
||||
for ($i = 0; $i < 60; $i = $i + 5) {
|
||||
$minutes[$i] = $i;
|
||||
}
|
||||
|
||||
if (!empty($minutes[$value])) {
|
||||
$this->attributesvalues[$name] = $value;
|
||||
} else {
|
||||
$this->attributesvalues[$name] = $this->settingdata->defaultsetting['m'];
|
||||
}
|
||||
}
|
||||
|
||||
protected function set_value($value) {
|
||||
$this->attributes = ['m' => $this->settingdata->name2];
|
||||
|
||||
for ($i = 0; $i < 24; $i++) {
|
||||
$hours[$i] = $i;
|
||||
}
|
||||
|
||||
if (empty($hours[$value])) {
|
||||
$this->value = false;
|
||||
}
|
||||
|
||||
$this->value = $value;
|
||||
$this->set_visiblevalue();
|
||||
}
|
||||
|
||||
protected function set_visiblevalue() {
|
||||
if (!is_null($this->attributesvalues) && array_key_exists($this->settingdata->name2, $this->attributesvalues)) {
|
||||
$this->visiblevalue = $this->value . ':' . $this->attributesvalues[$this->settingdata->name2];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Reimplementation to allow human friendly view of the selected regexps.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_devicedetectregex extends adminpresets_admin_setting_configtext {
|
||||
|
||||
public function set_visiblevalue() {
|
||||
$values = json_decode($this->get_value());
|
||||
|
||||
if (!$values) {
|
||||
parent::set_visiblevalue();
|
||||
return;
|
||||
}
|
||||
|
||||
$this->visiblevalue = '';
|
||||
foreach ($values as $key => $value) {
|
||||
$this->visiblevalue .= $key . ' = ' . $value . ', ';
|
||||
}
|
||||
$this->visiblevalue = rtrim($this->visiblevalue, ', ');
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
use admin_setting;
|
||||
|
||||
/**
|
||||
* A select with force and advanced options
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_gradecat_combo extends adminpresets_admin_setting_configselect {
|
||||
|
||||
/**
|
||||
* One db value for two setting attributes
|
||||
*
|
||||
* @param admin_setting $settingdata
|
||||
* @param mixed $dbsettingvalue
|
||||
*/
|
||||
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
|
||||
// The set_attribute_value() method will mod the VARNAME_flag value.
|
||||
$this->attributes = ['forced' => $settingdata->name . '_flag', 'adv' => $settingdata->name . '_flag'];
|
||||
parent::__construct($settingdata, $dbsettingvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Special treatment! the value be extracted from the $value argument
|
||||
*/
|
||||
protected function set_visiblevalue() {
|
||||
parent::set_visiblevalue();
|
||||
|
||||
if (!is_null($this->attributesvalues) && array_key_exists($this->settingdata->name . '_flag', $this->attributesvalues)) {
|
||||
$flagvalue = $this->attributesvalues[$this->settingdata->name . '_flag'];
|
||||
|
||||
if (isset($flagvalue)) {
|
||||
$forcedvalue = (($flagvalue % 2) == 1);
|
||||
$advancedvalue = ($flagvalue >= 2);
|
||||
|
||||
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($forcedvalue, 'forced');
|
||||
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($advancedvalue, 'advanced');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Reimplemented to store values in course table, not in config or config_plugins.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_sitesettext extends adminpresets_admin_setting_configtext {
|
||||
|
||||
/**
|
||||
* Overwritten to store the value in the course table
|
||||
*
|
||||
* @param bool $name
|
||||
* @param mixed $value
|
||||
* @return int|false config_log inserted id or false whenever the new value is the same as old value.
|
||||
*/
|
||||
public function save_value($name = false, $value = null) {
|
||||
global $DB;
|
||||
|
||||
// Object values if no arguments.
|
||||
if ($value === null) {
|
||||
$value = $this->value;
|
||||
}
|
||||
if (!$name) {
|
||||
$name = $this->settingdata->name;
|
||||
}
|
||||
|
||||
$sitecourse = $DB->get_record('course', ['id' => 1]);
|
||||
$actualvalue = $sitecourse->{$name};
|
||||
|
||||
// If it's the same value skip.
|
||||
if ($actualvalue == $value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Plugin name or ''.
|
||||
$plugin = $this->settingdata->plugin;
|
||||
if ($plugin == 'none' || $plugin == '') {
|
||||
$plugin = null;
|
||||
}
|
||||
|
||||
// Updating mdl_course.
|
||||
$sitecourse->{$name} = $value;
|
||||
$DB->update_record('course', $sitecourse);
|
||||
|
||||
return $this->to_log($plugin, $name, $this->value, $actualvalue);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Special control for selecting days to backup.
|
||||
*
|
||||
* It doesn't specify loadchoices behavior because is set_visiblevalue who needs it.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_special_backupdays extends adminpresets_setting {
|
||||
|
||||
protected function set_value($value) {
|
||||
$this->value = clean_param($value, PARAM_SEQUENCE);
|
||||
$this->set_visiblevalue();
|
||||
}
|
||||
|
||||
protected function set_visiblevalue() {
|
||||
$this->settingdata->load_choices();
|
||||
|
||||
$days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
|
||||
|
||||
$selecteddays = [];
|
||||
|
||||
$week = str_split($this->value);
|
||||
foreach ($week as $key => $day) {
|
||||
if ($day) {
|
||||
$index = $days[$key];
|
||||
$selecteddays[] = $this->settingdata->choices[$index];
|
||||
}
|
||||
}
|
||||
|
||||
$this->visiblevalue = implode(', ', $selecteddays);
|
||||
}
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Special admin control for calendar weekend.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_special_calendar_weekend extends adminpresets_setting {
|
||||
|
||||
protected function set_visiblevalue() {
|
||||
if (!$this->value) {
|
||||
parent::set_visiblevalue();
|
||||
return;
|
||||
}
|
||||
|
||||
$days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
|
||||
for ($i = 0; $i < 7; $i++) {
|
||||
if ($this->value & (1 << $i)) {
|
||||
$settings[] = get_string($days[$i], 'calendar');
|
||||
}
|
||||
}
|
||||
|
||||
$this->visiblevalue = implode(', ', $settings);
|
||||
}
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
/**
|
||||
* Extends configselect to reuse set_valuevisible.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_admin_setting_users_with_capability extends adminpresets_admin_setting_configmultiselect {
|
||||
|
||||
protected function set_behaviors() {
|
||||
$this->behaviors['loadchoices'] = &$this->settingdata;
|
||||
}
|
||||
|
||||
protected function set_value($value) {
|
||||
// Dirty hack (the value stored in the DB is '').
|
||||
$this->settingdata->choices[''] = $this->settingdata->choices['$@NONE@$'];
|
||||
|
||||
return parent::set_value($value);
|
||||
}
|
||||
}
|
||||
@@ -1,268 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
use admin_setting;
|
||||
use moodle_exception;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Admin tool presets plugin to load some settings.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class adminpresets_setting {
|
||||
|
||||
/**
|
||||
* @var admin_setting
|
||||
*/
|
||||
protected $settingdata;
|
||||
|
||||
/**
|
||||
* @var delegation
|
||||
*/
|
||||
protected $delegation;
|
||||
|
||||
/**
|
||||
* The setting DB value
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Stores the visible value of the setting DB value
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $visiblevalue;
|
||||
|
||||
/**
|
||||
* For multiple value settings, used to look for the other values
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $attributes = false;
|
||||
|
||||
/**
|
||||
* To store the setting attributes
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $attributesvalues;
|
||||
|
||||
/**
|
||||
* Stores the setting data and the selected value
|
||||
*
|
||||
* @param admin_setting $settingdata admin_setting subclass
|
||||
* @param mixed $dbsettingvalue Actual value
|
||||
*/
|
||||
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
|
||||
$this->settingdata = $settingdata;
|
||||
$this->delegation = new delegation();
|
||||
|
||||
if ($this->settingdata->plugin == '') {
|
||||
$this->settingdata->plugin = 'none';
|
||||
}
|
||||
|
||||
// Applies specific children behaviors.
|
||||
$this->set_behaviors();
|
||||
$this->apply_behaviors();
|
||||
|
||||
// Cleaning value.
|
||||
$this->set_value($dbsettingvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each class can overwrite this method to specify extra processes
|
||||
*/
|
||||
protected function set_behaviors() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the children class specific behaviors
|
||||
*
|
||||
* See delegation class for the available extra behaviors
|
||||
*/
|
||||
protected function apply_behaviors() {
|
||||
if (!empty($this->behaviors)) {
|
||||
|
||||
foreach ($this->behaviors as $behavior => $arguments) {
|
||||
|
||||
// The arguments of the behavior depends on the caller.
|
||||
$methodname = 'extra_' . $behavior;
|
||||
$this->delegation->{$methodname}($arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the setting value.
|
||||
*
|
||||
* @return mixed The setting value
|
||||
*/
|
||||
public function get_value() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the setting value cleaning it
|
||||
*
|
||||
* Child classes should overwrite method to clean more acurately
|
||||
*
|
||||
* @param mixed $value Setting value
|
||||
* @return mixed Returns false if wrong param value
|
||||
*/
|
||||
protected function set_value($value) {
|
||||
$this->value = $value;
|
||||
$this->set_visiblevalue();
|
||||
}
|
||||
|
||||
public function get_visiblevalue() {
|
||||
return $this->visiblevalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the visible name for the setting selected value
|
||||
*
|
||||
* In most cases the child classes will overwrite
|
||||
*/
|
||||
protected function set_visiblevalue() {
|
||||
$this->visiblevalue = $this->value;
|
||||
}
|
||||
|
||||
public function get_attributes() {
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
public function get_attributes_values() {
|
||||
return $this->attributesvalues;
|
||||
}
|
||||
|
||||
public function get_settingdata() {
|
||||
return $this->settingdata;
|
||||
}
|
||||
|
||||
public function set_attribute_value($name, $value) {
|
||||
$this->attributesvalues[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the setting attributes values
|
||||
*
|
||||
* @return array Array of inserted ids (in config_log)
|
||||
*/
|
||||
public function save_attributes_values() {
|
||||
// Plugin name or null.
|
||||
$plugin = $this->settingdata->plugin;
|
||||
if ($plugin == 'none' || $plugin == '') {
|
||||
$plugin = null;
|
||||
}
|
||||
|
||||
if (!$this->attributesvalues) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// To store inserted ids.
|
||||
$ids = [];
|
||||
foreach ($this->attributesvalues as $name => $value) {
|
||||
|
||||
// Getting actual setting.
|
||||
$actualsetting = get_config($plugin, $name);
|
||||
|
||||
// If it's the actual setting get off.
|
||||
if ($value == $actualsetting) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($id = $this->save_value($name, $value)) {
|
||||
$ids[] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the setting into database, logs the change and returns the config_log inserted id
|
||||
*
|
||||
* @param bool $name Setting name to store.
|
||||
* @param mixed $value Setting value to store.
|
||||
* @return int|false config_log inserted id or false whenever the new value is the same as old value.
|
||||
* @throws dml_exception
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public function save_value($name = false, $value = null) {
|
||||
// Object values if no arguments.
|
||||
if ($value === null) {
|
||||
$value = $this->value;
|
||||
}
|
||||
if (!$name) {
|
||||
$name = $this->settingdata->name;
|
||||
}
|
||||
|
||||
// Plugin name or null.
|
||||
$plugin = $this->settingdata->plugin;
|
||||
if ($plugin == 'none' || $plugin == '') {
|
||||
$plugin = null;
|
||||
}
|
||||
|
||||
// Getting the actual value.
|
||||
$actualvalue = get_config($plugin, $name);
|
||||
|
||||
// If it's the same it's not necessary.
|
||||
if ($actualvalue == $value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_config($name, $value, $plugin);
|
||||
|
||||
return $this->to_log($plugin, $name, $value, $actualvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy of config_write method of the admin_setting class
|
||||
*
|
||||
* @param string $plugin
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @param mixed $actualvalue
|
||||
* @return integer The stored config_log id
|
||||
*/
|
||||
protected function to_log($plugin, $name, $value, $actualvalue) {
|
||||
global $DB, $USER;
|
||||
|
||||
// Log the change (pasted from admin_setting class).
|
||||
$log = new stdClass();
|
||||
$log->userid = during_initial_install() ? 0 : $USER->id; // 0 as user id during install.
|
||||
$log->timemodified = time();
|
||||
$log->plugin = $plugin;
|
||||
$log->name = $name;
|
||||
$log->value = $value;
|
||||
$log->oldvalue = $actualvalue;
|
||||
|
||||
// Getting the inserted config_log id.
|
||||
if (!$id = $DB->insert_record('config_log', $log)) {
|
||||
throw new moodle_exception('errorinserting', 'core_adminpresets');
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +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/>.
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
use admin_setting;
|
||||
|
||||
/**
|
||||
* Cross-class methods
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class delegation {
|
||||
|
||||
/**
|
||||
* Adds a piece of string to the $type setting
|
||||
*
|
||||
* @param boolean $value
|
||||
* @param string $type Indicates the "extra" setting
|
||||
* @return string
|
||||
*/
|
||||
public function extra_set_visiblevalue(bool $value, string $type): string {
|
||||
// Adding the advanced value to the text string if present.
|
||||
if ($value) {
|
||||
$string = get_string('markedas' . $type, 'core_adminpresets');
|
||||
} else {
|
||||
$string = get_string('markedasnon' . $type, 'core_adminpresets');
|
||||
}
|
||||
|
||||
// Adding the advanced state.
|
||||
return ', ' . $string;
|
||||
}
|
||||
|
||||
public function extra_loadchoices(admin_setting &$adminsetting) {
|
||||
$adminsetting->load_choices();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,125 +0,0 @@
|
||||
<?php
|
||||
// This file is part of The Course Module Navigation Block
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_adminpresets\privacy;
|
||||
|
||||
use core_privacy\local\metadata\collection;
|
||||
use core_privacy\local\request\approved_contextlist;
|
||||
use core_privacy\local\request\approved_userlist;
|
||||
use core_privacy\local\request\contextlist;
|
||||
use core_privacy\local\request\userlist;
|
||||
|
||||
/**
|
||||
* Admin presets this file handle privacy provider.
|
||||
*
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements
|
||||
\core_privacy\local\metadata\provider,
|
||||
\core_privacy\local\request\subsystem\provider,
|
||||
\core_privacy\local\request\core_userlist_provider {
|
||||
|
||||
/**
|
||||
* Returns information about the user data stored in this component.
|
||||
*
|
||||
* @param collection $collection A list of information about this component
|
||||
* @return collection The collection object filled out with information about this component.
|
||||
*/
|
||||
public static function get_metadata(collection $collection) : collection {
|
||||
// These tables are really data about site configuration and not user data.
|
||||
|
||||
// The adminpresets includes information about which user performed a configuration change using the admin_presets
|
||||
// tool.
|
||||
// This is not considered to be user data.
|
||||
$collection->add_database_table('adminpresets', [
|
||||
'userid' => 'privacy:metadata:adminpresets:userid',
|
||||
'name' => 'privacy:metadata:adminpresets:name',
|
||||
'comments' => 'privacy:metadata:adminpresets:comments',
|
||||
'site' => 'privacy:metadata:adminpresets:site',
|
||||
'moodlerelease' => 'privacy:metadata:adminpresets:moodlerelease',
|
||||
'timecreated' => 'privacy:metadata:adminpresets:timecreated',
|
||||
], 'privacy:metadata:adminpresets');
|
||||
|
||||
// The adminpresets_app includes information about which user performed configuration change using the admin_presets
|
||||
// tool.
|
||||
// This is not considered to be user data.
|
||||
$collection->add_database_table('adminpresets_app', [
|
||||
'adminpresetid' => 'privacy:metadata:adminpresets_app:adminpresetid',
|
||||
'userid' => 'privacy:metadata:adminpresets_app:userid',
|
||||
'time' => 'privacy:metadata:adminpresets_app:time',
|
||||
], 'privacy:metadata:adminpresets_app');
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of contexts that contain user information for the specified user.
|
||||
*
|
||||
* @param int $userid The user to search.
|
||||
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
|
||||
*/
|
||||
public static function get_contexts_for_userid(int $userid) : contextlist {
|
||||
return new contextlist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of users who have data within a context.
|
||||
*
|
||||
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
|
||||
*/
|
||||
public static function get_users_in_context(userlist $userlist) {
|
||||
// Don't add any user.
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts to export information for.
|
||||
*/
|
||||
public static function export_user_data(approved_contextlist $contextlist) {
|
||||
// None of the core tables should be exported.
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data for all users in the specified context.
|
||||
*
|
||||
* @param context $context The specific context to delete data for.
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||
// None of the the data from these tables should be deleted.
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
|
||||
*/
|
||||
public static function delete_data_for_user(approved_contextlist $contextlist) {
|
||||
// None of the the data from these tables should be deleted.
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete multiple users within a single context.
|
||||
*
|
||||
* @param approved_userlist $userlist The approved context and user information to delete information for.
|
||||
*/
|
||||
public static function delete_data_for_users(approved_userlist $userlist) {
|
||||
// None of the the data from these tables should be deleted.
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<PRESET>
|
||||
<NAME>Imported preset</NAME>
|
||||
<COMMENTS><p dir="ltr" style="text-align:left;">Porfolios enabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced</p></COMMENTS>
|
||||
<PRESET_DATE>1631615985</PRESET_DATE>
|
||||
<SITE_URL>http://demo.moodle</SITE_URL>
|
||||
<AUTHOR>Ada Lovelace</AUTHOR>
|
||||
<MOODLE_VERSION>2021091100</MOODLE_VERSION>
|
||||
<MOODLE_RELEASE>4.0dev (Build: 20210911)</MOODLE_RELEASE>
|
||||
<ADMIN_SETTINGS>
|
||||
<MOD_LESSON>
|
||||
<SETTINGS>
|
||||
<MAXANSWERS maxanswers_adv="">2</MAXANSWERS>
|
||||
<MEDIAWIDTH>900</MEDIAWIDTH>
|
||||
</SETTINGS>
|
||||
</MOD_LESSON>
|
||||
<NONE>
|
||||
<SETTINGS>
|
||||
<ALLOWEMOJIPICKER>1</ALLOWEMOJIPICKER>
|
||||
<ENABLEPORTFOLIOS>1</ENABLEPORTFOLIOS>
|
||||
</SETTINGS>
|
||||
</NONE>
|
||||
</ADMIN_SETTINGS>
|
||||
</PRESET>
|
||||
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<PRESET>
|
||||
<NAME>Imported preset</NAME>
|
||||
<COMMENTS><p dir="ltr" style="text-align:left;">Porfolios enabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced. Plugins: disabled block_html, mod_database and mod_chat plugins and enabled atto_html, block_activity_modules and mod_lesson.</p></COMMENTS>
|
||||
<PRESET_DATE>1631615985</PRESET_DATE>
|
||||
<SITE_URL>http://demo.moodle</SITE_URL>
|
||||
<AUTHOR>Ada Lovelace</AUTHOR>
|
||||
<MOODLE_VERSION>2021091100</MOODLE_VERSION>
|
||||
<MOODLE_RELEASE>4.0dev (Build: 20210911)</MOODLE_RELEASE>
|
||||
<ADMIN_SETTINGS>
|
||||
<MOD_LESSON>
|
||||
<SETTINGS>
|
||||
<MAXANSWERS maxanswers_adv="">2</MAXANSWERS>
|
||||
<MEDIAWIDTH>900</MEDIAWIDTH>
|
||||
</SETTINGS>
|
||||
</MOD_LESSON>
|
||||
<NONE>
|
||||
<SETTINGS>
|
||||
<ALLOWEMOJIPICKER>1</ALLOWEMOJIPICKER>
|
||||
<ENABLEPORTFOLIOS>1</ENABLEPORTFOLIOS>
|
||||
</SETTINGS>
|
||||
</NONE>
|
||||
</ADMIN_SETTINGS>
|
||||
<PLUGINS>
|
||||
<ATTO>
|
||||
<HTML>1</HTML>
|
||||
</ATTO>
|
||||
<BLOCK>
|
||||
<HTML>0</HTML>
|
||||
<ACTIVITY_MODULES>1</ACTIVITY_MODULES>
|
||||
</BLOCK>
|
||||
<MOD>
|
||||
<CHAT>0</CHAT>
|
||||
<DATA>0</DATA>
|
||||
<LESSON>1</LESSON>
|
||||
</MOD>
|
||||
</PLUGINS>
|
||||
</PRESET>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<PRESET>
|
||||
<NAME>Imported preset</NAME>
|
||||
<COMMENTS><p dir="ltr" style="text-align:left;">Porfolios enabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced</p></COMMENTS>
|
||||
<PRESET_DATE>1631615985</PRESET_DATE>
|
||||
<SITE_URL>http://demo.moodle</SITE_URL>
|
||||
<AUTHOR>Ada Lovelace</AUTHOR>
|
||||
<MOODLE_VERSION>2021091100</MOODLE_VERSION>
|
||||
<MOODLE_RELEASE>4.0dev (Build: 20210911)</MOODLE_RELEASE>
|
||||
<ADMIN_SETTINGS>
|
||||
<MOD_LESSON>
|
||||
<SETTINGS>
|
||||
<MAXANSWERS maxanswers_adv="">2</MAXANSWERS>
|
||||
<MEDIAWIDTH>900</MEDIAWIDTH>
|
||||
</SETTINGS>
|
||||
</MOD_LESSON>
|
||||
<NONE>
|
||||
<SETTINGS>
|
||||
<UNEXISTINGSETTING>0</UNEXISTINGSETTING>
|
||||
<ALLOWEMOJIPICKER>1</ALLOWEMOJIPICKER>
|
||||
<ENABLEPORTFOLIOS>1</ENABLEPORTFOLIOS>
|
||||
</SETTINGS>
|
||||
</NONE>
|
||||
</ADMIN_SETTINGS>
|
||||
</PRESET>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user