Compare commits
843 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 896ce9b4e6 | |||
| c41605e282 | |||
| 70ae23829f | |||
| f29a819640 | |||
| c89d29f8e0 | |||
| dc5cbf1532 | |||
| 08c1b6eff4 | |||
| 02660c64ff | |||
| 787573a007 | |||
| 6585f80f29 | |||
| 7bcc28ac2f | |||
| cc22e91f8f | |||
| 3b2ea17ec4 | |||
| ce37064429 | |||
| 6aa0203deb | |||
| d6d9c4a9c3 | |||
| 993a1ac38f | |||
| e76a83ebf9 | |||
| e6d2eb3792 | |||
| 0f11ec17ca | |||
| c09577b5f3 | |||
| 68124fe0af | |||
| 5611053587 | |||
| c493c6ba2a | |||
| ce589fb4fe | |||
| d8564f56f0 | |||
| e17ee1e9c5 | |||
| 9ddd0bd72a | |||
| fba8a2e290 | |||
| 6f4f3946f6 | |||
| b6098b92b0 | |||
| a42ebf3385 | |||
| 6acdd1f3ab | |||
| 602b3815a0 | |||
| b06b50cf1a | |||
| 9c2f96a13d | |||
| 9214bc50a2 | |||
| 45e0bc6372 | |||
| b1e73801d1 | |||
| 445308fc3b | |||
| 3179ca58b7 | |||
| 86cbb2c450 | |||
| 0c4220fba5 | |||
| 743ad4f126 | |||
| 4a5e209d8c | |||
| 6b50178e4e | |||
| db4031fa52 | |||
| 9a68e396e8 | |||
| b5cc09d20b | |||
| 75528e9305 | |||
| 1082da020e | |||
| 7d085745be | |||
| d46c89d4e7 | |||
| 8817bcf7ba | |||
| 00b7c8a2fd | |||
| c1d089b1be | |||
| 3bbd2e7892 | |||
| c35f42e679 | |||
| 070262c8f9 | |||
| ac3022fb0e | |||
| eed84bfd4b | |||
| 133c06b2e1 | |||
| 6c18a3c802 | |||
| e7c4f87a5d | |||
| 2e95bfa5f2 | |||
| f8ca828c02 | |||
| 22e22a39af | |||
| 6823ac39cc | |||
| 1e5a1eb77b | |||
| 910247b15e | |||
| b94131a90e | |||
| cfe4df185c | |||
| 41c817ef38 | |||
| 32549792c2 | |||
| b6c6b99470 | |||
| 72f7cc6a07 | |||
| a6757673a2 | |||
| e47c42f4a8 | |||
| c51e98722b | |||
| d513f79a24 | |||
| e7048861a6 | |||
| a188724a19 | |||
| d165d2cf24 | |||
| 6db0ef42d4 | |||
| 0e526f9ea6 | |||
| f2520ef454 | |||
| 9fd041ad16 | |||
| 608923c445 | |||
| ec3ade054f | |||
| 0edc92e6bf | |||
| ebdcc591a2 | |||
| 029a29a3cf | |||
| 856dbae2cb | |||
| 729c7f143b | |||
| 5f42866391 | |||
| e0b69258fb | |||
| e684411988 | |||
| 1e15527fa5 | |||
| 0373f42728 | |||
| 864cf11c2f | |||
| ba6e9f22b4 | |||
| 554afbe2cd | |||
| a0f9277b51 | |||
| ebda22d612 | |||
| 0ad03ab13c | |||
| 4dcdab69f6 | |||
| a8321fc3ac | |||
| 167a73cffc | |||
| b19bf809dc | |||
| d2f333357d | |||
| a1d78eac23 | |||
| 937831c736 | |||
| de7951b817 | |||
| 0e1c96a44c | |||
| cdabef710d | |||
| 2a7b253e82 | |||
| b87f4d1ea5 | |||
| c3606bf9ba | |||
| 6806700b01 | |||
| 071633c194 | |||
| ef01fb49a6 | |||
| b9fb0ede39 | |||
| 3567a37302 | |||
| 34770e55b2 | |||
| f7e9dbcbe2 | |||
| e353a80475 | |||
| 8226afc20e | |||
| 535abb009d | |||
| 3125397713 | |||
| 9ce8250f77 | |||
| 1eefc40296 | |||
| a3d444a3af | |||
| 3509e3771a | |||
| d7dd9aa732 | |||
| 2335a0018d | |||
| 6cb68d8d3a | |||
| a3b99f1c03 | |||
| 139c549e3c | |||
| 8336d2be91 | |||
| 46629407c2 | |||
| f1996f596b | |||
| db2718a65d | |||
| 2e26127821 | |||
| ccbc8fadf8 | |||
| 0905763270 | |||
| 558d773213 | |||
| 4288a75a48 | |||
| cdcb157b7e | |||
| 12d454cb4c | |||
| c1d1c098f4 | |||
| 402ce4d5f5 | |||
| f8db8073a2 | |||
| 2eb6dd8cdc | |||
| 32cf700c31 | |||
| c2542c35f6 | |||
| a563739951 | |||
| 04d312fbcc | |||
| e82c98f26d | |||
| f40585c94d | |||
| b91250e430 | |||
| ea3f8fa0cb | |||
| e1f11ce7b1 | |||
| 7c920b5706 | |||
| 3abc7d1c4e | |||
| d2decc7fb0 | |||
| 784e8588ee | |||
| d00a536a0c | |||
| 9a9a841497 | |||
| e319e5a2d0 | |||
| 90574fd1c8 | |||
| 67e8ddc65f | |||
| a41f004fb7 | |||
| 22c756c644 | |||
| b42298d3fa | |||
| e13c169ded | |||
| 766a5891b6 | |||
| 5108b3e7c1 | |||
| 87f417f510 | |||
| 7a75832faa | |||
| 8b2d2a5fc6 | |||
| 5b9dead542 | |||
| 50b024746e | |||
| c0ab266dd0 | |||
| a90270455e | |||
| f0be825426 | |||
| dce24b2a5a | |||
| 985b62f3a9 | |||
| d92499f4c4 | |||
| 6c61222fbb | |||
| 6e19e0c175 | |||
| 92ae0fda60 | |||
| 9702e72bd7 | |||
| 1401dd8f47 | |||
| aae0a865bb | |||
| fed7bdfa96 | |||
| 57a38cf813 | |||
| ed6478fb7e | |||
| 26ce8a1f15 | |||
| f2ceab9582 | |||
| 02151fbe85 | |||
| 6db9bc560d | |||
| 440b00b7d3 | |||
| ba0bd5b9ab | |||
| cf2cda4b31 | |||
| 3cc6435b18 | |||
| e0b383aae0 | |||
| 2121f50755 | |||
| 121c9d3099 | |||
| 32e709a9dc | |||
| 397a8936cb | |||
| 4e3551004e | |||
| e48dd18997 | |||
| 6d36432f2f | |||
| aaf67d012b | |||
| 316706511d | |||
| b407285890 | |||
| 042b90d078 | |||
| c2465fa0e3 | |||
| 4b4f760bfa | |||
| 9ec4ffe9be | |||
| 08e1b1e49e | |||
| 8bf0e602c6 | |||
| 4583242dd6 | |||
| af97a17395 | |||
| 89574179da | |||
| 6ee2dd680e | |||
| 72fce6fc46 | |||
| 3c57ce6e72 | |||
| 79d55f5dee | |||
| d9864df62c | |||
| a04b4d89b2 | |||
| 21735b6075 | |||
| 156371af9c | |||
| a3a8a4a970 | |||
| 3848d57eef | |||
| 4afdece091 | |||
| 649bad89a2 | |||
| 886ce4cfcb | |||
| 8da74658b5 | |||
| 59f2ef03ae | |||
| d1b41e0a34 | |||
| c2e2d38d99 | |||
| 7bde88208c | |||
| 2e2686acf2 | |||
| ed532e8f3b | |||
| 94535cbc8a | |||
| 12d3875811 | |||
| be52d0dace | |||
| e078aa1351 | |||
| 1b13df8f65 | |||
| 3111a4f120 | |||
| aacfdda594 | |||
| 349027033c | |||
| 4ca5db7c0b | |||
| 4c72716d43 | |||
| 733e84fc26 | |||
| 594253c322 | |||
| 1cf3129e86 | |||
| 6178a8c820 | |||
| 4c22adddef | |||
| 91b779aa02 | |||
| 27946d0c65 | |||
| 9ac0280f80 | |||
| b2931bc620 | |||
| 7acd833a3c | |||
| 8f48fbf6f6 | |||
| 81636e4694 | |||
| 91df0eb289 | |||
| 27e0254e8f | |||
| 1929107b8c | |||
| e587b9be09 | |||
| 80ff09db28 | |||
| 61495ffbcb | |||
| 3bc489a0ec | |||
| 6d3a686c2c | |||
| e9fe4cc37c | |||
| 4457c6605b | |||
| d82b0d8ed9 | |||
| f16b97eb8c | |||
| dda3512514 | |||
| f4fe47705e | |||
| 3ec84d746a | |||
| 330f45b6e2 | |||
| cddbbc1752 | |||
| 9407afa0ba | |||
| a62863c658 | |||
| 1164882eff | |||
| 7b0a42b20c | |||
| ff14679150 | |||
| e79a53e370 | |||
| e78f6b391a | |||
| 5a04868aec | |||
| b3a6face59 | |||
| e7714135a4 | |||
| e2b2fad613 | |||
| b85bdc91d4 | |||
| 70fa678586 | |||
| 0c6de97371 | |||
| 63981e5a82 | |||
| 6a0dfc60d6 | |||
| 38c4435a37 | |||
| 3cc4e2f725 | |||
| ca3cbbc233 | |||
| 7d196ef3b3 | |||
| 069b9d5820 | |||
| 454a3d34d5 | |||
| db3a985faf | |||
| c535520966 | |||
| e35ad40de1 | |||
| 436acc27fe | |||
| 39f02182de | |||
| 73fd6f2928 | |||
| 84e17f59c5 | |||
| 63464df041 | |||
| 17c82085fc | |||
| 5e3ce67f37 | |||
| ec02a34e1f | |||
| 1e1e1b8229 | |||
| f7af2c5fc7 | |||
| 92194c1c8d | |||
| 7bbe8a1c76 | |||
| 22ee65c275 | |||
| 9354f9de64 | |||
| 04d2305788 | |||
| e21e294072 | |||
| 19b7ac05ad | |||
| 4294bbd50f | |||
| b1ffb73177 | |||
| cde1ac3eea | |||
| 059759aab9 | |||
| 188d41ccc9 | |||
| fc73f127eb | |||
| 0b5f9f6e60 | |||
| fa60a11522 | |||
| 29cdf58116 | |||
| 3db24b8015 | |||
| b21b210f41 | |||
| 79482e3fe8 | |||
| 3935371599 | |||
| 14026572ae | |||
| ee66d63054 | |||
| af2d6085cd | |||
| e35a24916f | |||
| e615d70923 | |||
| ae8388d51c | |||
| 962e3eb662 | |||
| 4c586b025e | |||
| 8612c8aa3e | |||
| a7db91030b | |||
| d807d3c603 | |||
| 8f61b909e8 | |||
| e44ce23c9f | |||
| 6c87b08240 | |||
| 9afdc8fc12 | |||
| e30a500fb9 | |||
| 121d3e0d29 | |||
| 5b7356cdde | |||
| 169d972bf6 | |||
| 4fef0dadf0 | |||
| 96a0d1bc7a | |||
| 01c2ca76c0 | |||
| 46c68c1b42 | |||
| e65f6a7e40 | |||
| 800da1b13d | |||
| a53008f1f0 | |||
| f1a117b86b | |||
| bcbd4140a1 | |||
| c99c5a436e | |||
| b7d36bdbaf | |||
| c21f12e786 | |||
| 2dd1bb44c2 | |||
| 63de9b5cdb | |||
| 24a00cadec | |||
| 3f709d3272 | |||
| def32a798d | |||
| b63524492f | |||
| 46f0136a5a | |||
| 83dbc72f38 | |||
| c6911cefb4 | |||
| dfbdf40af9 | |||
| 3e0fb6862e | |||
| 0e8eba7e1f | |||
| d0209e611f | |||
| ec9ed6d067 | |||
| 3e340aba45 | |||
| de80be59bb | |||
| 310172571b | |||
| 36916193d2 | |||
| c85f8d3f93 | |||
| a550b70a94 | |||
| 4bdc05f059 | |||
| 3cd6842501 | |||
| f17c1aadb3 | |||
| 043dffdd34 | |||
| 6fef2ab3db | |||
| 9ffcf8a3e9 | |||
| 56b8f8c8be | |||
| fede68a0ac | |||
| 6588079c5d | |||
| f7e4c3627c | |||
| 6c3f7e0ae6 | |||
| 89d948d86b | |||
| e1dcad3d13 | |||
| 07d000c51e | |||
| 636e7a13b6 | |||
| a57bdfa055 | |||
| 80a57cf924 | |||
| 059d6ffd9f | |||
| fd13953a8a | |||
| 488e115027 | |||
| 72e3ff3c15 | |||
| bd4f6ce186 | |||
| 5416d932d7 | |||
| 27e719e709 | |||
| b577d34861 | |||
| dcd27d9cee | |||
| 863dcb14a8 | |||
| 1a754e8446 | |||
| 95e9f4cc02 | |||
| bac13609ca | |||
| df90a44f3f | |||
| 23fd4f3afc | |||
| 9b39a92170 | |||
| 69c5e60f8c | |||
| cc36a37ea4 | |||
| 2678ee4e81 | |||
| 5a9f3039a7 | |||
| 667784420f | |||
| f628e0ecf6 | |||
| 9ae3b89cc5 | |||
| 098a875e4e | |||
| 9d64f4f078 | |||
| 5fac573391 | |||
| def9c15904 | |||
| d4e9fe521e | |||
| 343cdba46b | |||
| aca74d0d74 | |||
| ce01dbab40 | |||
| 21cf201536 | |||
| dfefe26665 | |||
| de70bc556c | |||
| 7b06a12ef3 | |||
| a415eb505e | |||
| 54a20ea8fc | |||
| a1740aad65 | |||
| 3680b1efa0 | |||
| b90c2e2627 | |||
| 5c53893f97 | |||
| 3049c086a3 | |||
| c644b03f02 | |||
| 7693409caa | |||
| eac59c38f8 | |||
| cd6612b079 | |||
| 7d88829470 | |||
| 9fde80dfa0 | |||
| e787fa6ab4 | |||
| 24cfd4c7d8 | |||
| de33f85405 | |||
| 57e38e1d12 | |||
| ddbf8c29ae | |||
| f265312fcf | |||
| 7dc6674cc4 | |||
| c1b9c51914 | |||
| 14da7f58a4 | |||
| 18221902bc | |||
| 7d9ee66a2f | |||
| de60425a16 | |||
| 4eb3f8d9b7 | |||
| 994e94bf76 | |||
| 2f9f8b5903 | |||
| 3923610e6c | |||
| 0913eb3c2a | |||
| f5b50e0472 | |||
| 09261027b6 | |||
| e0c4e6496f | |||
| 672ce4c6cd | |||
| 13a2a8344c | |||
| 8184f47d6c | |||
| 7a7320af90 | |||
| 70fd9fbb39 | |||
| e16448d3f1 | |||
| 2b4eb2cb71 | |||
| ed798679bb | |||
| 299dcca1b1 | |||
| c16c53d137 | |||
| 52723e1e3f | |||
| 0bcbd5b205 | |||
| ec319d13df | |||
| 0c4422af0b | |||
| 40dcbac3d6 | |||
| 62eb5ef8eb | |||
| 434e8abac8 | |||
| 28add18d9b | |||
| f9220d8138 | |||
| 32237b8308 | |||
| c2ae90c553 | |||
| 7035e0f5b5 | |||
| 6a3777f90c | |||
| de7a6ff47e | |||
| 46e26a1b69 | |||
| 0db0a63e50 | |||
| 120798e85f | |||
| 4679634e36 | |||
| 1c0462deb3 | |||
| 7dc8cc1ab6 | |||
| 170cd579ff | |||
| 6c83de1d51 | |||
| 0ef42d5f6d | |||
| ffc60d23b4 | |||
| 4f5a6ca40e | |||
| a669c6b21e | |||
| e7734513b8 | |||
| 44b4f83298 | |||
| 49053808a2 | |||
| 8ea5d72218 | |||
| e33b7b342a | |||
| f33a8d4eee | |||
| 6a4a1d812c | |||
| c94dce9c89 | |||
| a551ea0210 | |||
| 72b489ef65 | |||
| 827d93f88a | |||
| 884f4d3ec3 | |||
| a072271853 | |||
| 95c794075a | |||
| 890f84cdb2 | |||
| b4e1bbef47 | |||
| 678d051bee | |||
| c83ef7e25b | |||
| 1ee447d3a4 | |||
| 217d523d43 | |||
| 76cebe50cb | |||
| 7dfc04ff98 | |||
| ff037d9698 | |||
| 39dc183d9f | |||
| f7ddcd23f8 | |||
| 92f57f8397 | |||
| 98f246ae97 | |||
| f9e7ee4534 | |||
| b14507a31f | |||
| 4436b9e9dd | |||
| 2568183232 | |||
| bcca23f9c5 | |||
| bab24efe70 | |||
| 45a46ecbd8 | |||
| 64cfe467f8 | |||
| 48f0ebcd49 | |||
| 6537c557b5 | |||
| 225e039e73 | |||
| c8dddb5ccb | |||
| 3e276d6efa | |||
| adf2ea6166 | |||
| fd90d0e925 | |||
| 58a4ce4774 | |||
| b44972cc8b | |||
| 655570df00 | |||
| dbf70dec42 | |||
| c40ed5f6ff | |||
| 2827c7f997 | |||
| 2259fb5f36 | |||
| 6dc7039af9 | |||
| ee7b977a8b | |||
| f4841f394c | |||
| 6973e38a91 | |||
| c1b158b569 | |||
| 21a8a95869 | |||
| 359914c8f6 | |||
| 95208fe135 | |||
| df428648ee | |||
| 9148905e9a | |||
| 64df3fed13 | |||
| ed4aaea57b | |||
| 163fc8588d | |||
| 39e34b9586 | |||
| 5c63ab7ee8 | |||
| 3e3068cd11 | |||
| a27dde0ba7 | |||
| b92400a49f | |||
| a477c8b752 | |||
| 7f52d5c740 | |||
| f52bdbb885 | |||
| 7c519588f1 | |||
| 7345917de4 | |||
| 8a71b10a68 | |||
| 18907a51d5 | |||
| 11d04ffe8a | |||
| 5e1014a76e | |||
| 6e497e6e7d | |||
| 66a4a376ee | |||
| 3563244314 | |||
| bf02dc9819 | |||
| 8e8c066448 | |||
| 67f83d9279 | |||
| bcd1915dd0 | |||
| 992ffccfd2 | |||
| 97fd5a9841 | |||
| 6b47a070e7 | |||
| b4cfb7d733 | |||
| a9fa51024f | |||
| 2eec6ffc6c | |||
| 3f1574f849 | |||
| 40b78a23e9 | |||
| fb5655b5c2 | |||
| 405dcba6f3 | |||
| 7f32c5a447 | |||
| ec3eeb7ace | |||
| 1af3d13bf3 | |||
| 84122523ba | |||
| 382c069e52 | |||
| 3f58a36504 | |||
| 9e41e4e8ea | |||
| 7523d99558 | |||
| 9a375bdf6c | |||
| 07f6358b03 | |||
| 7ffb98d0f5 | |||
| dda99bb3f2 | |||
| 9cff26295b | |||
| 2fd5ceadb5 | |||
| 5865a6875b | |||
| ef2eed1b3c | |||
| 6601017d02 | |||
| a204d7d921 | |||
| bf345fc4ca | |||
| 2722404791 | |||
| 256f820dfd | |||
| 173f5515e3 | |||
| 7ed6f330c6 | |||
| 418d01aaf4 | |||
| 11f9ff55e1 | |||
| 04d4796089 | |||
| e889aee562 | |||
| 228157ebf5 | |||
| c77ae4e017 | |||
| 1da3022e50 | |||
| f6507b8e35 | |||
| d52b937932 | |||
| ce36e3626f | |||
| 063f7c198b | |||
| 83dedbcd33 | |||
| 0ad466926d | |||
| ced9a33352 | |||
| 3b4fba5588 | |||
| 926d5a53ff | |||
| 9cc9dabf17 | |||
| cb8be0b6b8 | |||
| c6bd4c1a45 | |||
| 31e4c05002 | |||
| c5f11c0f3c | |||
| 6158379f75 | |||
| bc076bf1b8 | |||
| 27a3a42efd | |||
| b0c2ea4640 | |||
| 00ef7b1caa | |||
| 7914b0035f | |||
| cb358279b7 | |||
| 339edb47e2 | |||
| bd6bc508df | |||
| c53194f3f9 | |||
| c477dc23c0 | |||
| 8cd421e941 | |||
| f18c2a9d15 | |||
| 403e0d96e5 | |||
| 5984ffded4 | |||
| cd9a925e6a | |||
| 40471ed54c | |||
| 000b0949e6 | |||
| 6c7f60dbc0 | |||
| 3b37e372f2 | |||
| 44b94d9324 | |||
| e5bc84f84f | |||
| a38d0650d4 | |||
| 8d9edc0e7c | |||
| 4e0357c1e3 | |||
| 9efd73abec | |||
| c31b5bbf9d | |||
| 7606ba2133 | |||
| 88c0fcb03f | |||
| 51b7f8f0a4 | |||
| 40fdf0f84f | |||
| 3e99f4f642 | |||
| 324e613b48 | |||
| 502397dcbc | |||
| f1f83c3ba1 | |||
| 2c3f09ccf7 | |||
| e2f5592b8f | |||
| 522fcf2ffc | |||
| 96e743ff78 | |||
| e514ae345e | |||
| 2659b808ab | |||
| 54037cf3e2 | |||
| b0773d70c6 | |||
| 4348fffe0c | |||
| 216c68b834 | |||
| a3c1bd86ed | |||
| e0006399ff | |||
| 2084c59b82 | |||
| a09a9879e5 | |||
| a3a095b6eb | |||
| 0edf724367 | |||
| a953ac5942 | |||
| 5627b0b1a1 | |||
| 5d3a7be453 | |||
| 8f27fdf1ab | |||
| 1d5c2c6560 | |||
| 18317c7c1c | |||
| b83fd5b1fe | |||
| 972304f4cb | |||
| 11eeb2e347 | |||
| 0aa8b11f5c | |||
| 829cafc050 | |||
| 25474b5e84 | |||
| b7f902b5b3 | |||
| 11488775eb | |||
| 32ec7e3d30 | |||
| 1a1eef4345 | |||
| 4942dfc7cd | |||
| d469fb2181 | |||
| 0213ce081c | |||
| 70b6a6618a | |||
| 089cf944f3 | |||
| 68d9adcba8 | |||
| 32636d1757 | |||
| 48ff43d3bd | |||
| 725863abe4 | |||
| 9de4bbf8a8 | |||
| cd7ca81fdd | |||
| 1ca30f2503 | |||
| c47a9439d3 | |||
| 2ce5b1d637 | |||
| c4ade76ee5 | |||
| 62fc665ff6 | |||
| 263865899e | |||
| f927f3e196 | |||
| 70f5e9ba61 | |||
| 3b7bf2cee0 | |||
| a57a9053d7 | |||
| 0292245755 | |||
| dd7aa695b2 | |||
| 2626dce64c | |||
| 7e2e135943 | |||
| cc15b9d46f | |||
| ce47bacfe9 | |||
| 7c89091995 | |||
| 7766ffc618 | |||
| 75efa0860c | |||
| d31412392c | |||
| da694c75ff | |||
| 76f5d7b9ab | |||
| e7d8926583 | |||
| c87f1ac4c7 | |||
| 75c4f5b0ca | |||
| f7b3774380 | |||
| 78293c74bf | |||
| 406fc019c1 | |||
| 903cd37434 | |||
| 6fd8b0098a | |||
| 34954a6050 | |||
| 949d8ae04e | |||
| 1c7cbed23c | |||
| 9156498826 | |||
| 71adc9a9a3 | |||
| 49612b733f | |||
| bc0721c7d9 | |||
| c5452484ee | |||
| 74eecb6078 | |||
| 725be51c11 | |||
| d0d8a7f984 | |||
| 4a50811ae3 | |||
| b82ddcbcac | |||
| 6e4cc6caf4 | |||
| fe8e9b1b4e | |||
| 72770e9a60 | |||
| a847efc70b | |||
| 9e99327888 | |||
| 9973eebb91 | |||
| a162f636d8 | |||
| 8ff8d598fe | |||
| 8704d2e5fc | |||
| f9dd21a17a | |||
| eb349bdfc4 | |||
| 89d186af72 | |||
| 65de977483 | |||
| e167481759 | |||
| 457c913461 | |||
| 422449dca8 | |||
| 53c8f0ca3c | |||
| b094b88a9a | |||
| 49e5d04a8d | |||
| 38e28dfbcd | |||
| 44047dc78d | |||
| c06b8145b1 | |||
| 79da2c5bfa | |||
| a5800adaf0 | |||
| c1c3f50965 | |||
| cff14cf0d1 | |||
| c95ea731bc | |||
| b98f14632b | |||
| a1e1b45ae7 | |||
| 2d44bb544b | |||
| c60d333578 | |||
| 182690b018 | |||
| b36b54179d | |||
| fc4b768e25 | |||
| 7e0f1972f1 | |||
| 93e64c823c | |||
| 20d598f094 | |||
| e376549179 | |||
| 163a317bcc | |||
| 7ecf13ac1d | |||
| 2fbe4fca87 | |||
| d07a8ebd7e | |||
| d4feb70e17 | |||
| f477809e38 | |||
| 94caed45db | |||
| 8c4fdb1073 | |||
| e5bbe44230 | |||
| d0a58fe035 | |||
| 9c68157292 | |||
| 44f71599df | |||
| 1fac7b914b | |||
| cede73411f | |||
| 47deb83b5c | |||
| 4ea56c1c80 | |||
| 311121b16c | |||
| 5863f1b073 | |||
| 2bb195f64f | |||
| f6b50d9901 | |||
| a0b0234a18 | |||
| f8b8a363ae | |||
| b197272987 | |||
| e4976aefc5 | |||
| dcd408b81f | |||
| 4a564ca40b | |||
| 5da06d632a | |||
| d797e57255 | |||
| 55d2042f0a | |||
| 8cd6972966 | |||
| 9cbc0a0cdb | |||
| 931d12b589 | |||
| 0beeb95a8a | |||
| 617f8bb911 | |||
| 75dd21a002 | |||
| a0c13477ab |
@@ -0,0 +1,79 @@
|
||||
# Generated by "grunt ignorefiles"
|
||||
*/**/yui/src/*/meta/
|
||||
*/**/build/
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
auth/fc/fcFPP.php
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
filter/tex/mimetex.*
|
||||
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/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
lib/lessphp/
|
||||
lib/phpexcel/
|
||||
lib/google/
|
||||
lib/htmlpurifier/
|
||||
lib/jabber/
|
||||
lib/minify/matthiasmullie-minify/
|
||||
lib/minify/matthiasmullie-pathconverter/
|
||||
lib/pear/Auth/RADIUS.php
|
||||
lib/pear/Crypt/CHAP.php
|
||||
lib/pear/HTML/Common.php
|
||||
lib/pear/HTML/QuickForm.php
|
||||
lib/pear/HTML/QuickForm/
|
||||
lib/pear/PEAR.php
|
||||
lib/phpmailer/
|
||||
lib/simplepie/
|
||||
lib/tcpdf/
|
||||
lib/typo3/
|
||||
lib/yuilib/
|
||||
lib/yuilib/gallery/
|
||||
lib/jquery/
|
||||
lib/html2text/
|
||||
lib/markdown/
|
||||
lib/recaptchalib.php
|
||||
lib/xhprof/
|
||||
lib/xmlize.php
|
||||
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/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
mod/assign/feedback/editpdf/fpdi/
|
||||
repository/s3/S3.php
|
||||
theme/boost/scss/bootstrap/
|
||||
theme/boost/amd/src/alert.js
|
||||
theme/boost/amd/src/button.js
|
||||
theme/boost/amd/src/carousel.js
|
||||
theme/boost/amd/src/collapse.js
|
||||
theme/boost/amd/src/dropdown.js
|
||||
theme/boost/amd/src/modal.js
|
||||
theme/boost/amd/src/popover.js
|
||||
theme/boost/amd/src/scrollspy.js
|
||||
theme/boost/amd/src/tab.js
|
||||
theme/boost/amd/src/tooltip.js
|
||||
theme/boost/amd/src/util.js
|
||||
theme/boost/amd/src/tether.js
|
||||
theme/bootstrapbase/less/bootstrap/
|
||||
theme/bootstrapbase/javascript/html5shiv.js
|
||||
theme/bootstrapbase/amd/src/bootstrap.js
|
||||
@@ -1,15 +1,6 @@
|
||||
{
|
||||
'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': {
|
||||
@@ -22,7 +13,6 @@
|
||||
|
||||
// === Possible Errors ===
|
||||
'comma-dangle': 'off',
|
||||
'no-compare-neg-zero': 'error',
|
||||
'no-cond-assign': 'error',
|
||||
'no-console': 'error',
|
||||
'no-constant-condition': 'error',
|
||||
@@ -74,6 +64,7 @@
|
||||
'no-fallthrough': 'error',
|
||||
'no-floating-decimal': 'warn',
|
||||
'no-global-assign': 'warn',
|
||||
// Enabled by grunt for AMD modules: 'no-implicit-globals': 'error',
|
||||
'no-implied-eval': 'error',
|
||||
'no-invalid-this': 'error',
|
||||
'no-iterator': 'error',
|
||||
@@ -87,7 +78,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',
|
||||
@@ -113,7 +103,6 @@
|
||||
'block-spacing': 'warn',
|
||||
'brace-style': ['warn', '1tbs'],
|
||||
'camelcase': 'warn',
|
||||
'capitalized-comments': ['warn', 'always', { 'ignoreConsecutiveComments': true }],
|
||||
'comma-spacing': ['warn', { 'before': false, 'after': true }],
|
||||
'comma-style': ['warn', 'last'],
|
||||
'computed-property-spacing': 'error',
|
||||
@@ -181,132 +170,11 @@
|
||||
'unicode-bom': 'error',
|
||||
'wrap-regex': 'off',
|
||||
|
||||
// === Promises ===
|
||||
'promise/always-return': 'warn',
|
||||
'promise/no-return-wrap': 'warn',
|
||||
'promise/param-names': 'warn',
|
||||
'promise/catch-or-return': ['warn', {terminationMethod: ['catch', 'fail']}],
|
||||
'promise/no-native': 'warn',
|
||||
'promise/no-promise-in-callback': 'warn',
|
||||
'promise/no-callback-in-promise': 'warn',
|
||||
'promise/avoid-new': 'warn',
|
||||
|
||||
// === Deprecations ===
|
||||
"no-restricted-properties": ['warn', {
|
||||
'object': 'M',
|
||||
'property': 'str',
|
||||
'message': 'Use AMD module "core/str" or M.util.get_string()'
|
||||
}],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/yui/src/**/*.js"],
|
||||
'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',
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile.js", ".grunt/*.js", ".grunt/tasks/*.js", "jsdoc.conf.js"],
|
||||
// We're using babel transpiling so use their parser
|
||||
// for linting.
|
||||
parser: '@babel/eslint-parser',
|
||||
// Check AMD with some slightly stricter rules.
|
||||
rules: {
|
||||
'no-unused-vars': 'error',
|
||||
'no-implicit-globals': 'error',
|
||||
// Disable all of the rules that have babel versions.
|
||||
'new-cap': 'off',
|
||||
// Not using this rule for the time being because it isn't
|
||||
// compatible with jQuery and ES6.
|
||||
'no-invalid-this': 'off',
|
||||
'object-curly-spacing': 'off',
|
||||
'quotes': 'off',
|
||||
'semi': 'off',
|
||||
'no-unused-expressions': 'off',
|
||||
// Enable all of the babel version of these rules.
|
||||
'babel/new-cap': ['warn', { 'properties': false }],
|
||||
// Not using this rule for the time being because it isn't
|
||||
// compatible with jQuery and ES6.
|
||||
'babel/no-invalid-this': 'off',
|
||||
'babel/object-curly-spacing': 'warn',
|
||||
// This is off in the original style int.
|
||||
'babel/quotes': 'off',
|
||||
'babel/semi': 'error',
|
||||
'babel/no-unused-expressions': 'error',
|
||||
// === Promises ===
|
||||
// We have Promise now that we're using ES6.
|
||||
'promise/no-native': 'off',
|
||||
'promise/avoid-new': 'off',
|
||||
|
||||
// === 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',
|
||||
],
|
||||
},
|
||||
parserOptions: {
|
||||
'sourceType': 'module',
|
||||
'requireConfigFile': false,
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"indentation": ["on",{
|
||||
"Feature": 0,
|
||||
"Background": 2,
|
||||
"Scenario": 2,
|
||||
"Examples": 4,
|
||||
"example": 6,
|
||||
"Step": 4,
|
||||
"given": 4,
|
||||
"and": 4
|
||||
}],
|
||||
"no-dupe-feature-names": "on",
|
||||
"no-dupe-scenario-names": "off",
|
||||
"no-empty-file": "on",
|
||||
"no-files-without-scenarios": "on",
|
||||
"no-multiple-empty-lines": "on",
|
||||
"no-partially-commented-tag-lines": "on",
|
||||
"no-trailing-spaces": "on",
|
||||
"no-unnamed-features": "on",
|
||||
"no-unnamed-scenarios": "on",
|
||||
"no-scenario-outlines-without-examples": "on",
|
||||
"no-examples-in-scenarios": "on",
|
||||
"new-line-at-eof": ["on", "yes"]
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
**/yui/build/** -diff
|
||||
**/amd/build/** -diff
|
||||
lib/dml/oci_native_moodle_package.sql text eol=lf
|
||||
theme/bootstrapbase/style/editor.css -diff
|
||||
theme/bootstrapbase/style/moodle.css -diff
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
# Primary donations pages.
|
||||
custom: ["https://moodle.com/donations/", moodle.org]
|
||||
@@ -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,116 +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.1
|
||||
|
||||
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.4
|
||||
extensions:
|
||||
db: mysqli
|
||||
- os: ubuntu-22.04
|
||||
php: 8.1
|
||||
db: pgsql
|
||||
|
||||
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: 12
|
||||
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
|
||||
@@ -1,144 +0,0 @@
|
||||
name: Windows Testing
|
||||
|
||||
on:
|
||||
workflow_dispatch
|
||||
env:
|
||||
php: 8.1
|
||||
|
||||
jobs:
|
||||
Grunt:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Set git to use LF
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
git config --global core.eol lf
|
||||
|
||||
- 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 ci
|
||||
|
||||
- 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 }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
php: 8.1
|
||||
# Ideally we should use mysql/mariadb, but they are 4x slower without tweaks and configuration
|
||||
# so let's run only postgres (1.5h vs 6h) only, If some day we want to improve the mysql runs,
|
||||
# this is the place to enable them.
|
||||
# db: mysqli
|
||||
db: pgsql
|
||||
extensions: exif, fileinfo, gd, intl, pgsql, mysql, redis, soap, sodium
|
||||
- os: windows-latest
|
||||
php: 8.0
|
||||
db: pgsql
|
||||
extensions: exif, fileinfo, gd, intl, pgsql, mysql, redis, soap, sodium
|
||||
|
||||
steps:
|
||||
- name: Setting up DB mysql
|
||||
if: ${{ matrix.db == 'mysqli' }}
|
||||
uses: shogo82148/actions-setup-mysql@v1
|
||||
with:
|
||||
mysql-version: 8.0
|
||||
user: test
|
||||
password: test
|
||||
|
||||
- name: Creating DB mysql
|
||||
if: ${{ matrix.db == 'mysqli' }}
|
||||
run: mysql --host 127.0.0.1 -utest -ptest -e 'CREATE DATABASE IF NOT EXISTS test COLLATE = utf8mb4_bin;';
|
||||
|
||||
- name: Setting up DB pgsql
|
||||
if: ${{ matrix.db == 'pgsql' }}
|
||||
run: |
|
||||
# TODO: Remove these conf. modifications when php74 or php80 are lowest.
|
||||
# Change to old md5 auth, because php73 does not support it.
|
||||
# #password_encryption = scram-sha-256
|
||||
(Get-Content "$env:PGDATA\postgresql.conf"). `
|
||||
replace('#password_encryption = scram-sha-256', 'password_encryption = md5') | `
|
||||
Set-Content "$env:PGDATA\postgresql.conf"
|
||||
(Get-Content "$env:PGDATA\pg_hba.conf"). `
|
||||
replace('scram-sha-256', 'md5') | `
|
||||
Set-Content "$env:PGDATA\pg_hba.conf"
|
||||
$pgService = Get-Service -Name postgresql*
|
||||
Set-Service -InputObject $pgService -Status running -StartupType automatic
|
||||
Start-Process -FilePath "$env:PGBIN\pg_isready" -Wait -PassThru
|
||||
& $env:PGBIN\psql --command="CREATE USER test PASSWORD 'test'" --command="\du"
|
||||
|
||||
- name: Creating DB pgsql
|
||||
if: ${{ matrix.db == 'pgsql' }}
|
||||
run: |
|
||||
& $env:PGBIN\createdb --owner=test test
|
||||
$env:PGPASSWORD = 'test'
|
||||
& $env:PGBIN\psql --username=test --host=localhost --list 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: Set git to use LF
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
git config --global core.eol lf
|
||||
|
||||
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Needs to be done after php is available, git configured and Moodle checkout has happened.
|
||||
- name: Setting up moodle-exttests service
|
||||
run: |
|
||||
git clone https://github.com/moodlehq/moodle-exttests.git
|
||||
nssm install php-built-in C:\tools\php\php.exe -S localhost:8080 -t D:\a\moodle\moodle\moodle-exttests
|
||||
nssm start php-built-in
|
||||
|
||||
- name: Setting up redis service
|
||||
run: |
|
||||
choco install redis-64 --version 3.0.503 --no-progress
|
||||
nssm install redis redis-server
|
||||
nssm start redis
|
||||
|
||||
- name: Setting up PHPUnit
|
||||
env:
|
||||
dbtype: ${{ matrix.db }}
|
||||
shell: bash
|
||||
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
|
||||
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
|
||||
+2
-22
@@ -9,24 +9,15 @@
|
||||
#
|
||||
# See gitignore(5) man page for more details
|
||||
#
|
||||
|
||||
# Swap files (vim)
|
||||
[._]*.s[a-v][a-z]
|
||||
[._]*.sw[a-p]
|
||||
[._]s[a-rt-v][a-z]
|
||||
[._]ss[a-gi-z]
|
||||
[._]sw[a-p]
|
||||
# Temporary files including undo
|
||||
*~
|
||||
#
|
||||
/config.php
|
||||
/lib/editor/tinymce/extra/tools/temp/
|
||||
*~
|
||||
*.swp
|
||||
/tags
|
||||
/TAGS
|
||||
/cscope.*
|
||||
/.patches/
|
||||
/.idea/
|
||||
.phpstorm.*
|
||||
/nbproject/
|
||||
CVS
|
||||
.DS_Store
|
||||
@@ -34,7 +25,6 @@ CVS
|
||||
/.project
|
||||
/.buildpath
|
||||
/.cache
|
||||
.phpunit.result.cache
|
||||
phpunit.xml
|
||||
# Composer support. Do not ignore composer.json, or composer.lock. These should be shipped by us.
|
||||
composer.phar
|
||||
@@ -46,13 +36,3 @@ composer.phar
|
||||
/lib/yuilib/*/*/*-coverage.js
|
||||
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,169 +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/>.
|
||||
|
||||
/**
|
||||
* This is a babel plugin to add the Moodle module names to the AMD modules
|
||||
* as part of the transpiling process.
|
||||
*
|
||||
* In addition it will also add a return statement for the default export if the
|
||||
* module is using default exports. This is a highly specific Moodle thing because
|
||||
* we're transpiling to AMD and none of the existing Babel 7 plugins work correctly.
|
||||
*
|
||||
* This will fix the issue where an ES6 module using "export default Foo" will be
|
||||
* transpiled into an AMD module that returns {default: Foo}; Instead it will now
|
||||
* just simply return Foo.
|
||||
*
|
||||
* Note: This means all other named exports in that module are ignored and won't be
|
||||
* exported.
|
||||
*
|
||||
* @copyright 2018 Ryan Wyllie <ryan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
/* eslint-env node */
|
||||
|
||||
module.exports = ({template, types}) => {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const cwd = process.cwd();
|
||||
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
|
||||
|
||||
/**
|
||||
* Search the list of components that match the given file name
|
||||
* and return the Moodle component for that file, if found.
|
||||
*
|
||||
* Throw an exception if no matching component is found.
|
||||
*
|
||||
* @throws {Error}
|
||||
* @param {string} searchFileName The file name to look for.
|
||||
* @return {string} Moodle component
|
||||
*/
|
||||
function getModuleNameFromFileName(searchFileName) {
|
||||
searchFileName = fs.realpathSync(searchFileName);
|
||||
const relativeFileName = searchFileName.replace(`${cwd}${path.sep}`, '').replace(/\\/g, '/');
|
||||
const [componentPath, file] = relativeFileName.split('/amd/src/');
|
||||
const fileName = file.replace('.js', '');
|
||||
|
||||
// Check subsystems first which require an exact match.
|
||||
const componentName = ComponentList.getComponentFromPath(componentPath);
|
||||
if (componentName) {
|
||||
return `${componentName}/${fileName}`;
|
||||
}
|
||||
|
||||
// This matches the previous PHP behaviour that would throw an exception
|
||||
// if it couldn't parse an AMD file.
|
||||
throw new Error(`Unable to find module name for ${searchFileName} (${componentPath}::${file}}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is heavily inspired by the babel-plugin-add-module-exports plugin.
|
||||
* See: https://github.com/59naga/babel-plugin-add-module-exports
|
||||
*
|
||||
* This is used when we detect a module using "export default Foo;" to make
|
||||
* sure the transpiled code just returns Foo directly rather than an object
|
||||
* with the default property (i.e. {default: Foo}).
|
||||
*
|
||||
* Note: This means that we can't support modules that combine named exports
|
||||
* with a default export.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {String} exportObjectName
|
||||
*/
|
||||
function addModuleExportsDefaults(path, exportObjectName) {
|
||||
const rootPath = path.findParent(path => {
|
||||
return path.key === 'body' || !path.parentPath;
|
||||
});
|
||||
|
||||
// HACK: `path.node.body.push` instead of path.pushContainer(due doesn't work in Plugin.post).
|
||||
// This is hardcoded to work specifically with AMD.
|
||||
rootPath.node.body.push(template(`return ${exportObjectName}.default`)());
|
||||
}
|
||||
|
||||
return {
|
||||
pre() {
|
||||
this.seenDefine = false;
|
||||
this.addedReturnForDefaultExport = false;
|
||||
},
|
||||
visitor: {
|
||||
// Plugin ordering is only respected if we visit the "Program" node.
|
||||
// See: https://babeljs.io/docs/en/plugins.html#plugin-preset-ordering
|
||||
//
|
||||
// We require this to run after the other AMD module transformation so
|
||||
// let's visit the "Program" node.
|
||||
Program: {
|
||||
exit(path) {
|
||||
path.traverse({
|
||||
CallExpression(path) {
|
||||
// If we find a "define" function call.
|
||||
if (!this.seenDefine && path.get('callee').isIdentifier({name: 'define'})) {
|
||||
// We only want to modify the first instance of define that we find.
|
||||
this.seenDefine = true;
|
||||
|
||||
// Get the Moodle component for the file being processed.
|
||||
var moduleName = getModuleNameFromFileName(this.file.opts.filename);
|
||||
|
||||
// The function signature of `define()` is:
|
||||
// define = function (name, deps, callback) {...}
|
||||
// Ensure that if the moduel supplied its own name that it is replaced.
|
||||
if (path.node.arguments.length > 0) {
|
||||
// Ensure that there is only one name.
|
||||
if (path.node.arguments[0].type === 'StringLiteral') {
|
||||
// eslint-disable-next-line
|
||||
console.log(`Replacing module name '${path.node.arguments[0].extra.rawValue}' with ${moduleName}`);
|
||||
path.node.arguments.shift();
|
||||
}
|
||||
}
|
||||
|
||||
// Add the module name as the first argument to the define function.
|
||||
path.node.arguments.unshift(types.stringLiteral(moduleName));
|
||||
// Add a space after the define function in the built file so that previous versions
|
||||
// of Moodle will not try to add the module name to the file when it's being served
|
||||
// by PHP. This forces the regex in PHP to not match for this file.
|
||||
path.node.callee.name = 'define ';
|
||||
}
|
||||
|
||||
// Check for any Object.defineProperty('exports', 'default') calls.
|
||||
if (!this.addedReturnForDefaultExport && path.get('callee').matchesPattern('Object.defineProperty')) {
|
||||
const [identifier, prop] = path.get('arguments');
|
||||
const objectName = identifier.get('name').node;
|
||||
const propertyName = prop.get('value').node;
|
||||
|
||||
if ((objectName === 'exports' || objectName === '_exports') && propertyName === 'default') {
|
||||
addModuleExportsDefaults(path, objectName);
|
||||
this.addedReturnForDefaultExport = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
AssignmentExpression(path) {
|
||||
// Check for an exports.default assignments.
|
||||
if (
|
||||
!this.addedReturnForDefaultExport &&
|
||||
(
|
||||
path.get('left').matchesPattern('exports.default') ||
|
||||
path.get('left').matchesPattern('_exports.default')
|
||||
)
|
||||
) {
|
||||
const objectName = path.get('left.object.name').node;
|
||||
addModuleExportsDefaults(path, objectName);
|
||||
this.addedReturnForDefaultExport = true;
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -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://moodledev.io](https://moodledev.io) 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://moodledev.io",
|
||||
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,142 +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) {
|
||||
grunt.log.error(result.stdout);
|
||||
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/sass/sass.js',
|
||||
'--style', 'expanded',
|
||||
'--source-map',
|
||||
'--embed-sources',
|
||||
'--precision', 6,
|
||||
'--load-path', process.cwd(),
|
||||
getCLPath('hugo/scss/docs.scss'),
|
||||
getCLPath('hugo/dist/css/docs.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('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;
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
**/amd/**
|
||||
/*.js
|
||||
@@ -0,0 +1,80 @@
|
||||
# Generated by "grunt ignorefiles"
|
||||
theme/bootstrapbase/style/
|
||||
theme/clean/style/custom.css
|
||||
theme/more/style/custom.css
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
auth/fc/fcFPP.php
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
filter/tex/mimetex.*
|
||||
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/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
lib/lessphp/
|
||||
lib/phpexcel/
|
||||
lib/google/
|
||||
lib/htmlpurifier/
|
||||
lib/jabber/
|
||||
lib/minify/matthiasmullie-minify/
|
||||
lib/minify/matthiasmullie-pathconverter/
|
||||
lib/pear/Auth/RADIUS.php
|
||||
lib/pear/Crypt/CHAP.php
|
||||
lib/pear/HTML/Common.php
|
||||
lib/pear/HTML/QuickForm.php
|
||||
lib/pear/HTML/QuickForm/
|
||||
lib/pear/PEAR.php
|
||||
lib/phpmailer/
|
||||
lib/simplepie/
|
||||
lib/tcpdf/
|
||||
lib/typo3/
|
||||
lib/yuilib/
|
||||
lib/yuilib/gallery/
|
||||
lib/jquery/
|
||||
lib/html2text/
|
||||
lib/markdown/
|
||||
lib/recaptchalib.php
|
||||
lib/xhprof/
|
||||
lib/xmlize.php
|
||||
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/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
mod/assign/feedback/editpdf/fpdi/
|
||||
repository/s3/S3.php
|
||||
theme/boost/scss/bootstrap/
|
||||
theme/boost/amd/src/alert.js
|
||||
theme/boost/amd/src/button.js
|
||||
theme/boost/amd/src/carousel.js
|
||||
theme/boost/amd/src/collapse.js
|
||||
theme/boost/amd/src/dropdown.js
|
||||
theme/boost/amd/src/modal.js
|
||||
theme/boost/amd/src/popover.js
|
||||
theme/boost/amd/src/scrollspy.js
|
||||
theme/boost/amd/src/tab.js
|
||||
theme/boost/amd/src/tooltip.js
|
||||
theme/boost/amd/src/util.js
|
||||
theme/boost/amd/src/tether.js
|
||||
theme/bootstrapbase/less/bootstrap/
|
||||
theme/bootstrapbase/javascript/html5shiv.js
|
||||
theme/bootstrapbase/amd/src/bootstrap.js
|
||||
+10
-11
@@ -1,22 +1,18 @@
|
||||
{
|
||||
"plugins": [
|
||||
"stylelint-csstree-validator"
|
||||
],
|
||||
"rules": {
|
||||
"csstree/validator": true,
|
||||
"at-rule-empty-line-before": [ "always",
|
||||
{"except": [ "blockless-after-blockless"], ignore: ["after-comment", "inside-block"]}
|
||||
{"except": [ "blockless-group"], ignore: ["after-comment", "all-nested"]}
|
||||
],
|
||||
"at-rule-name-case": "lower",
|
||||
"at-rule-name-space-after": "always-single-line",
|
||||
"at-rule-no-unknown": null, # Enabled for non-scss in grunt.
|
||||
"at-rule-semicolon-newline-after": "always",
|
||||
"at-rule-semicolon-space-before": "never",
|
||||
"block-closing-brace-newline-after": "always",
|
||||
"block-closing-brace-newline-before": "always",
|
||||
"block-closing-brace-newline-before": "always-multi-line",
|
||||
"block-closing-brace-space-before": "always-single-line",
|
||||
"block-no-empty": true,
|
||||
"block-opening-brace-newline-after": "always",
|
||||
"block-no-single-line": true,
|
||||
"block-opening-brace-newline-after": "always-multi-line",
|
||||
"block-opening-brace-space-after": "always-single-line",
|
||||
"block-opening-brace-space-before": "always",
|
||||
"color-hex-case": ["lower", { "severity": "warning" }],
|
||||
@@ -25,6 +21,7 @@
|
||||
"declaration-bang-space-after": "never",
|
||||
"declaration-bang-space-before": "always",
|
||||
"declaration-block-no-duplicate-properties": true,
|
||||
"declaration-block-no-ignored-properties": true,
|
||||
"declaration-block-no-shorthand-property-overrides": true,
|
||||
"declaration-block-semicolon-newline-after": "always-multi-line",
|
||||
"declaration-block-semicolon-space-after": "always-single-line",
|
||||
@@ -35,7 +32,6 @@
|
||||
"declaration-colon-space-after": "always-single-line",
|
||||
"declaration-colon-space-before": "never",
|
||||
"declaration-no-important": true,
|
||||
"font-family-no-duplicate-names": true,
|
||||
"function-calc-no-unspaced-operator": true,
|
||||
"function-comma-newline-after": "always-multi-line",
|
||||
"function-comma-space-after": "always-single-line",
|
||||
@@ -45,7 +41,7 @@
|
||||
"function-name-case": "lower",
|
||||
"function-parentheses-newline-inside": "always-multi-line",
|
||||
"function-parentheses-space-inside": "never-single-line",
|
||||
"function-url-scheme-blacklist": ["data"],
|
||||
"function-url-data-uris": never,
|
||||
"function-whitespace-after": "always",
|
||||
"indentation": 4,
|
||||
"keyframe-declaration-no-important": true,
|
||||
@@ -54,12 +50,14 @@
|
||||
"max-line-length": [132, { "severity": "warning" }],
|
||||
"media-feature-colon-space-after": "always",
|
||||
"media-feature-colon-space-before": "never",
|
||||
"media-feature-no-missing-punctuation": true,
|
||||
"media-feature-parentheses-space-inside": "never",
|
||||
"media-feature-range-operator-space-after": "always",
|
||||
"media-feature-range-operator-space-before": "always",
|
||||
"media-query-list-comma-newline-after": "always-multi-line",
|
||||
"media-query-list-comma-space-after": "always-single-line",
|
||||
"media-query-list-comma-space-before": "never",
|
||||
"no-browser-hacks": null, # Enabled for non-scss in grunt.
|
||||
"no-empty-source": true,
|
||||
"no-eol-whitespace": true,
|
||||
"no-extra-semicolons": [true, { "severity": "warning" }],
|
||||
@@ -80,10 +78,11 @@
|
||||
"selector-pseudo-class-parentheses-space-inside": "never",
|
||||
"selector-pseudo-element-case": "lower",
|
||||
"selector-pseudo-element-no-unknown": true,
|
||||
"selector-root-no-composition": true,
|
||||
"selector-type-case": "lower",
|
||||
"selector-type-no-unknown": true,
|
||||
"string-no-newline": true,
|
||||
"time-min-milliseconds": 100,
|
||||
"time-no-imperceptible": true,
|
||||
"unit-blacklist": ["pt"],
|
||||
"unit-case": "lower",
|
||||
"unit-no-unknown": true,
|
||||
|
||||
+91
-106
@@ -2,108 +2,74 @@
|
||||
# process (which uses our internal CI system) this file is here for the benefit
|
||||
# of community developers git clones - see MDL-51458.
|
||||
|
||||
sudo: false
|
||||
|
||||
# We currently disable Travis notifications entirely until https://github.com/travis-ci/travis-ci/issues/4976
|
||||
# is fixed.
|
||||
notifications:
|
||||
email:
|
||||
if: env(MOODLE_EMAIL) != no
|
||||
email: false
|
||||
|
||||
language: php
|
||||
|
||||
os: linux
|
||||
|
||||
dist: focal
|
||||
php:
|
||||
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
|
||||
- 7.1
|
||||
- 5.6
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- docker
|
||||
- redis-server
|
||||
|
||||
addons:
|
||||
postgresql: "12"
|
||||
apt:
|
||||
packages:
|
||||
- postgresql-12
|
||||
- postgresql-client-12
|
||||
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.1, so run that first.
|
||||
# CI Tests should be second-highest in priority as these only take <= 60 seconds to run under normal circumstances.
|
||||
# Postgres is significantly is pretty reasonable in its run-time.
|
||||
|
||||
branches:
|
||||
except:
|
||||
- master
|
||||
- /MOODLE_[0-9]+_STABLE/
|
||||
- /^v[0-9]+\.[0-9]+\.[0-9]+.*/
|
||||
# Run unit tests on MySQL
|
||||
- DB=mysqli TASK=PHPUNIT
|
||||
|
||||
jobs:
|
||||
# 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
|
||||
|
||||
matrix:
|
||||
# Enable fast finish.
|
||||
# This will fail the build if a single job fails (except those in allow_failures).
|
||||
# It will not stop the jobs from running.
|
||||
fast_finish: true
|
||||
|
||||
include:
|
||||
# First all the lowest php ones (7.4)
|
||||
- php: 7.4
|
||||
env: DB=none TASK=CITEST
|
||||
- php: 7.4
|
||||
env: DB=none TASK=GRUNT
|
||||
# Run grunt/npm install on lowest supported npm version
|
||||
- php: 7.1
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='4'
|
||||
# Run grunt/npm install on highest version ('node' is an alias for the latest node.js version.)
|
||||
- php: 7.1
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='node'
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present
|
||||
php: 7.4
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
exclude:
|
||||
# MySQL - it's just too slow.
|
||||
# Exclude it on all versions except for 7.1
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
|
||||
php: 7.4
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
- env: DB=mysqli TASK=PHPUNIT
|
||||
php: 5.6
|
||||
|
||||
# Then, conditionally, all the highest php ones (8.1)
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 8.1
|
||||
env: DB=none TASK=CITEST
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 8.1
|
||||
env: DB=none TASK=GRUNT
|
||||
|
||||
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present)
|
||||
php: 8.1
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
|
||||
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
|
||||
php: 8.1
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
# Moodle 2.7 is not compatible with PHP 7 for the upgrade test.
|
||||
- env: DB=pgsql TASK=UPGRADE
|
||||
php: 7.1
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
- $HOME/.npm
|
||||
|
||||
before_install:
|
||||
- docker run -d -p 127.0.0.1:8080:80 --name exttests moodlehq/moodle-exttests
|
||||
# Avoid IPv6 default binding as service (causes redis not to start).
|
||||
- sudo service redis-server start --bind 127.0.0.1
|
||||
|
||||
env:
|
||||
global:
|
||||
- PGVER=12
|
||||
- PGPORT=5433
|
||||
|
||||
install:
|
||||
- >
|
||||
if [ "$DB" = 'mysqli' ];
|
||||
then
|
||||
sudo mkdir /mnt/ramdisk
|
||||
sudo mount -t tmpfs -o size=1024m tmpfs /mnt/ramdisk
|
||||
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
|
||||
fi
|
||||
- >
|
||||
if [ "$DB" = 'pgsql' ];
|
||||
then
|
||||
sudo mkdir /mnt/ramdisk
|
||||
sudo mount -t tmpfs -o size=1024m tmpfs /mnt/ramdisk
|
||||
sudo service postgresql stop
|
||||
sudo mv /var/lib/postgresql /mnt/ramdisk
|
||||
sudo ln -s /mnt/ramdisk/postgresql /var/lib/postgresql
|
||||
sudo service postgresql start
|
||||
sh -c 'until pg_isready -p $PGPORT; do echo "Waiting for the DB to be up..."; sleep 2; done'
|
||||
fi
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
@@ -112,6 +78,7 @@ install:
|
||||
echo 'auth.json' >> .git/info/exclude
|
||||
fi
|
||||
|
||||
# Enable Redis.
|
||||
echo 'extension="redis.so"' > /tmp/redis.ini
|
||||
phpenv config-add /tmp/redis.ini
|
||||
|
||||
@@ -124,15 +91,14 @@ install:
|
||||
- >
|
||||
if [ "$TASK" = 'GRUNT' ];
|
||||
then
|
||||
nvm install
|
||||
nvm use
|
||||
nvm install $NVM_VERSION ;
|
||||
nvm use $NVM_VERSION ;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- 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 ;
|
||||
@@ -148,7 +114,7 @@ before_script:
|
||||
|
||||
# The wwwroot and dataroot.
|
||||
sed -i \
|
||||
-e "s%http://example.com/moodle%https://localhost%" \
|
||||
-e "s%http://example.com/moodle%http://localhost%" \
|
||||
-e "s%/home/example/moodledata%/home/travis/roots/base%" \
|
||||
config.php ;
|
||||
|
||||
@@ -156,11 +122,10 @@ before_script:
|
||||
then
|
||||
# Postgres-specific setup.
|
||||
sed -i \
|
||||
-e "s%= 'username'%= 'travis'%" \
|
||||
-e "s%'dbsocket' => false%'dbsocket' => true%" \
|
||||
-e "s%= 'username'%= 'postgres'%" \
|
||||
config.php ;
|
||||
|
||||
psql -c 'CREATE DATABASE travis_ci_test;' -U travis;
|
||||
psql -c 'CREATE DATABASE travis_ci_test;' -U postgres;
|
||||
fi
|
||||
|
||||
if [ "$DB" = 'mysqli' ];
|
||||
@@ -189,19 +154,6 @@ before_script:
|
||||
sed -i \
|
||||
-e "/require_once/i \\\$CFG->phpunit_dataroot = '\/home\/travis\/roots\/phpunit';" \
|
||||
-e "/require_once/i \\\$CFG->phpunit_prefix = 'p_';" \
|
||||
config.php ;
|
||||
# Enable test external resources
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://127.0.0.1:8080');" \
|
||||
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://127.0.0.1:8080');" \
|
||||
config.php ;
|
||||
|
||||
# Redis cache store tests
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
|
||||
config.php ;
|
||||
# Redis session tests
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
|
||||
config.php ;
|
||||
|
||||
@@ -232,7 +184,7 @@ before_script:
|
||||
# We need the official upstream for comparison
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
git fetch upstream MOODLE_401_STABLE;
|
||||
git fetch upstream MOODLE_32_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`
|
||||
@@ -243,11 +195,37 @@ 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 27 STABLE branch.
|
||||
git fetch upstream MOODLE_27_STABLE;
|
||||
git checkout MOODLE_27_STABLE;
|
||||
|
||||
# Perform the upgrade
|
||||
php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
|
||||
|
||||
# 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' ];
|
||||
then
|
||||
vendor/bin/phpunit --fail-on-risky --disallow-test-output --verbose;
|
||||
vendor/bin/phpunit;
|
||||
fi
|
||||
|
||||
- >
|
||||
@@ -262,16 +240,23 @@ script:
|
||||
grunt ;
|
||||
# Add all files to the git index and then run diff --cached to see all changes.
|
||||
# This ensures that we get the status of all files, including new files.
|
||||
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
|
||||
git add . ;
|
||||
git reset -- npm-shrinkwrap.json ;
|
||||
git diff --cached --exit-code ;
|
||||
fi
|
||||
|
||||
after_script:
|
||||
########################################################################
|
||||
# Upgrade test
|
||||
########################################################################
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
if [ "$TASK" = 'UPGRADE' ];
|
||||
then
|
||||
EXTTESTS_HITS=$(docker logs exttests 2>&1 | grep -Fv -e 'AH00558' -e '[pid 1]' | wc -l)
|
||||
echo -e "\nTest local resources number of hits: ${EXTTESTS_HITS}.\n"
|
||||
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
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ of developers, designers, teachers, testers, translators and other users. We
|
||||
work in universities, schools, companies and other places. You are very welcome
|
||||
to join us and contribute to the project.
|
||||
|
||||
See <https://moodledev.io/general/community/contribute> for the many ways you
|
||||
See <https://docs.moodle.org/dev/Contributing_to_Moodle> for the many ways you
|
||||
can help, not only with coding.
|
||||
|
||||
Moodle is open to community contributions to core, though all code must go
|
||||
@@ -35,7 +35,7 @@ submitted patches has evolved.
|
||||
* New features are developed on the master branch. Bug fixes are also
|
||||
backported to currently supported maintenance (stable) branches.
|
||||
|
||||
For further details, see <https://moodledev.io/general/development/process>.
|
||||
For further details, see <https://docs.moodle.org/dev/Process>.
|
||||
|
||||
Moodle plugins
|
||||
--------------
|
||||
@@ -53,4 +53,4 @@ be easily installed and updated via the Moodle administration interface.
|
||||
the plugins directory. We do not pull from your code repository; you must do
|
||||
it explicitly.
|
||||
|
||||
For further details, see <https://moodledev.io/general/community/plugincontribution>.
|
||||
For further details, see <https://docs.moodle.org/dev/Plugin_contribution>.
|
||||
|
||||
+330
-219
@@ -16,249 +16,360 @@
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* Grunt configuration for Moodle.
|
||||
*
|
||||
* @copyright 2014 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Setup the Grunt Moodle environment.
|
||||
*
|
||||
* @param {Grunt} grunt
|
||||
* @returns {Object}
|
||||
* Grunt configuration
|
||||
*/
|
||||
const setupMoodleEnvironment = 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('..');
|
||||
|
||||
// Globbing pattern for matching all AMD JS source files.
|
||||
let amdSrc = [];
|
||||
if (inComponent) {
|
||||
amdSrc.push(
|
||||
componentDirectory + "/amd/src/*.js",
|
||||
componentDirectory + "/amd/src/**/*.js"
|
||||
);
|
||||
} else {
|
||||
amdSrc = ComponentList.getAmdSrcGlobList();
|
||||
}
|
||||
|
||||
return {
|
||||
inAMD,
|
||||
amdSrc,
|
||||
};
|
||||
};
|
||||
|
||||
const getYuiConfiguration = () => {
|
||||
let yuiSrc = [];
|
||||
if (inComponent) {
|
||||
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
|
||||
} else {
|
||||
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
|
||||
}
|
||||
|
||||
return {
|
||||
yuiSrc,
|
||||
};
|
||||
};
|
||||
|
||||
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);
|
||||
} else {
|
||||
ComponentList.getComponentPaths(`${gruntFilePath}/`).forEach(componentPath => {
|
||||
checkComponentDirectory(componentPath);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
cssSrc,
|
||||
scssSrc,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 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());
|
||||
|
||||
// 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');
|
||||
}
|
||||
}
|
||||
|
||||
return cwd;
|
||||
};
|
||||
|
||||
// Detect directories:
|
||||
// * gruntFilePath The real path on disk to this Gruntfile.js
|
||||
// * cwd The current working directory, which can be overridden by the `root` option
|
||||
// * relativeCwd The cwd, relative to the Gruntfile.js
|
||||
// * componentDirectory The root directory of the component if the cwd is in a valid component
|
||||
// * inComponent Whether the cwd is in a valid component
|
||||
// * runDir The componentDirectory or cwd if not in a component, relative to Gruntfile.js
|
||||
// * fullRunDir The full path to the runDir
|
||||
const gruntFilePath = fs.realpathSync(process.cwd());
|
||||
const cwd = getCwd(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}`);
|
||||
grunt.log.debug(`= process.cwd: '` + process.cwd() + `'`);
|
||||
grunt.log.debug(`= process.env.PWD: '${process.env.PWD}'`);
|
||||
grunt.log.debug(`= path.sep '${path.sep}'`);
|
||||
grunt.log.debug('============================================================================');
|
||||
grunt.log.debug(`= gruntFilePath: '${gruntFilePath}'`);
|
||||
grunt.log.debug(`= relativeCwd: '${relativeCwd}'`);
|
||||
grunt.log.debug(`= componentDirectory: '${componentDirectory}'`);
|
||||
grunt.log.debug(`= inComponent: '${inComponent}'`);
|
||||
grunt.log.debug(`= runDir: '${runDir}'`);
|
||||
grunt.log.debug(`= fullRunDir: '${fullRunDir}'`);
|
||||
grunt.log.debug('============================================================================');
|
||||
|
||||
if (inComponent) {
|
||||
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');
|
||||
module.exports = function(grunt) {
|
||||
var path = require('path'),
|
||||
tasks = {},
|
||||
cwd = process.env.PWD || process.cwd(),
|
||||
async = require('async'),
|
||||
DOMParser = require('xmldom').DOMParser,
|
||||
xpath = require('xpath'),
|
||||
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);
|
||||
grunt.fail.fatal('Node version too old. Require ' + expected + ', version installed: ' + actual);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Grunt configuration.
|
||||
*
|
||||
* @param {Grunt} grunt
|
||||
*/
|
||||
module.exports = function(grunt) {
|
||||
// Verify that the Node version meets our requirements.
|
||||
verifyNodeVersion(grunt);
|
||||
// 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')) {
|
||||
var root = grunt.option('root');
|
||||
if (grunt.file.exists(__dirname, root)) {
|
||||
cwd = path.join(__dirname, root);
|
||||
grunt.log.ok('Setting root to ' + cwd);
|
||||
} else {
|
||||
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the Moodle environemnt within the Grunt object.
|
||||
grunt.moodleEnv = setupMoodleEnvironment(grunt);
|
||||
var inAMD = path.basename(cwd) == 'amd';
|
||||
|
||||
// Globbing pattern for matching all AMD JS source files.
|
||||
var amdSrc = [inAMD ? cwd + '/src/*.js' : '**/amd/src/*.js'];
|
||||
|
||||
/**
|
||||
* 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 uglifyRename = function(destPath, srcPath) {
|
||||
destPath = srcPath.replace('src', 'build');
|
||||
destPath = destPath.replace('.js', '.min.js');
|
||||
destPath = path.resolve(cwd, destPath);
|
||||
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() {
|
||||
var thirdpartyfiles = grunt.file.expand('*/**/thirdpartylibs.xml');
|
||||
var libs = ['node_modules/', 'vendor/'];
|
||||
|
||||
// Add Moodle task configuration.
|
||||
addTask('gherkinlint', grunt);
|
||||
addTask('ignorefiles', grunt);
|
||||
thirdpartyfiles.forEach(function(file) {
|
||||
var dirname = path.dirname(file);
|
||||
|
||||
addTask('javascript', grunt);
|
||||
addTask('style', grunt);
|
||||
addTask('componentlibrary', grunt);
|
||||
var doc = new DOMParser().parseFromString(grunt.file.read(file));
|
||||
var nodes = xpath.select("/libraries/library/location/text()", doc);
|
||||
|
||||
addTask('watch', grunt);
|
||||
addTask('startup', grunt);
|
||||
nodes.forEach(function(node) {
|
||||
var lib = path.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;
|
||||
};
|
||||
|
||||
|
||||
// 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.
|
||||
options: {quiet: !grunt.option('show-lint-warnings')},
|
||||
amd: {
|
||||
src: amdSrc,
|
||||
// Check AMD with some slightly stricter rules.
|
||||
rules: {
|
||||
'no-unused-vars': 'error',
|
||||
'no-implicit-globals': 'error'
|
||||
}
|
||||
},
|
||||
// Check YUI module source files.
|
||||
yui: {
|
||||
src: ['**/yui/src/**/*.js', '!*/**/yui/src/*/meta/*.js'],
|
||||
options: {
|
||||
// Disable some rules which we can't safely define for YUI rollups.
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'no-unused-expressions': 'off'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
amd: {
|
||||
files: [{
|
||||
expand: true,
|
||||
src: amdSrc,
|
||||
rename: uglifyRename
|
||||
}],
|
||||
options: {report: 'none'}
|
||||
}
|
||||
},
|
||||
less: {
|
||||
bootstrapbase: {
|
||||
files: {
|
||||
"theme/bootstrapbase/style/moodle.css": "theme/bootstrapbase/less/moodle.less",
|
||||
"theme/bootstrapbase/style/editor.css": "theme/bootstrapbase/less/editor.less",
|
||||
},
|
||||
options: {
|
||||
compress: false // We must not compress to keep the comments.
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
options: {
|
||||
nospawn: true // We need not to spawn so config can be changed dynamically.
|
||||
},
|
||||
amd: {
|
||||
files: ['**/amd/src/**/*.js'],
|
||||
tasks: ['amd']
|
||||
},
|
||||
bootstrapbase: {
|
||||
files: ["theme/bootstrapbase/less/**/*.less"],
|
||||
tasks: ["css"]
|
||||
},
|
||||
yui: {
|
||||
files: ['**/yui/src/**/*.js'],
|
||||
tasks: ['yui']
|
||||
},
|
||||
},
|
||||
shifter: {
|
||||
options: {
|
||||
recursive: true,
|
||||
paths: [cwd]
|
||||
}
|
||||
},
|
||||
stylelint: {
|
||||
less: {
|
||||
options: {
|
||||
syntax: 'less',
|
||||
configOverrides: {
|
||||
rules: {
|
||||
// These rules have to be disabled in .stylelintrc for scss compat.
|
||||
"at-rule-no-unknown": true,
|
||||
"no-browser-hacks": [true, {"severity": "warning"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
src: ['theme/**/*.less']
|
||||
},
|
||||
scss: {
|
||||
options: {syntax: 'scss'},
|
||||
src: ['*/**/*.scss']
|
||||
},
|
||||
css: {
|
||||
src: ['*/**/*.css'],
|
||||
options: {
|
||||
configOverrides: {
|
||||
rules: {
|
||||
// These rules have to be disabled in .stylelintrc for scss compat.
|
||||
"at-rule-no-unknown": true,
|
||||
"no-browser-hacks": [true, {"severity": "warning"}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Generate ignore files (utilising thirdpartylibs.xml data)
|
||||
*/
|
||||
tasks.ignorefiles = function() {
|
||||
// An array of paths to third party directories.
|
||||
var thirdPartyPaths = getThirdPartyPathsFromXML();
|
||||
// Generate .eslintignore.
|
||||
var eslintIgnores = ['# Generated by "grunt ignorefiles"', '*/**/yui/src/*/meta/', '*/**/build/'].concat(thirdPartyPaths);
|
||||
grunt.file.write('.eslintignore', eslintIgnores.join('\n'));
|
||||
// Generate .stylelintignore.
|
||||
var stylelintIgnores = [
|
||||
'# Generated by "grunt ignorefiles"',
|
||||
'theme/bootstrapbase/style/',
|
||||
'theme/clean/style/custom.css',
|
||||
'theme/more/style/custom.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.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');
|
||||
}
|
||||
};
|
||||
|
||||
// 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('uglify.amd.files', [{expand: true, src: files, rename: uglifyRename}]);
|
||||
grunt.config('shifter.options.paths', files);
|
||||
grunt.config('stylelint.less.src', files);
|
||||
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-less');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
grunt.loadNpmTasks('grunt-stylelint');
|
||||
|
||||
// Register JS tasks.
|
||||
grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter);
|
||||
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles);
|
||||
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
|
||||
grunt.registerTask('amd', ['eslint:amd', 'uglify']);
|
||||
grunt.registerTask('js', ['amd', 'yui']);
|
||||
|
||||
// Register CSS taks.
|
||||
grunt.registerTask('css', ['stylelint:scss', 'stylelint:less', 'less:bootstrapbase', 'stylelint:css']);
|
||||
|
||||
// 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']);
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ Moodle is widely used around the world by universities, schools, companies and
|
||||
all manner of organisations and individuals.
|
||||
|
||||
Moodle is provided freely as open source software, under the GNU General Public
|
||||
License <https://moodledev.io/general/license>.
|
||||
License <https://docs.moodle.org/dev/License>.
|
||||
|
||||
Moodle is written in PHP and JavaScript and uses an SQL database for storing
|
||||
the data.
|
||||
|
||||
+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/>.
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?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 settings search form
|
||||
*
|
||||
* @package admin
|
||||
* @copyright 2016 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once $CFG->libdir.'/formslib.php';
|
||||
|
||||
/**
|
||||
* Admin settings search form
|
||||
*
|
||||
* @package admin
|
||||
* @copyright 2016 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class admin_settings_search_form extends moodleform {
|
||||
function definition () {
|
||||
$mform = $this->_form;
|
||||
|
||||
//$mform->addElement('header', 'settingsheader', get_string('search', 'admin'));
|
||||
$elements = [];
|
||||
$elements[] = $mform->createElement('text', 'query', get_string('query', 'admin'));
|
||||
$elements[] = $mform->createElement('submit', 'search', get_string('search'));
|
||||
$mform->addGroup($elements);
|
||||
$mform->setType('query', PARAM_RAW);
|
||||
$mform->setDefault('query', optional_param('query', '', PARAM_RAW));
|
||||
}
|
||||
}
|
||||
+9
-16
@@ -33,7 +33,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$PAGE->set_url('/admin/antiviruses.php', array('action' => $action, 'antivirus' => $antivirus));
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageantiviruses";
|
||||
|
||||
@@ -54,19 +55,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 +79,6 @@ switch ($action) {
|
||||
$fsave = $activeantiviruses[$key];
|
||||
$activeantiviruses[$key] = $activeantiviruses[$key + 1];
|
||||
$activeantiviruses[$key + 1] = $fsave;
|
||||
$needsupdate = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -93,7 +92,6 @@ switch ($action) {
|
||||
$fsave = $activeantiviruses[$key];
|
||||
$activeantiviruses[$key] = $activeantiviruses[$key - 1];
|
||||
$activeantiviruses[$key - 1] = $fsave;
|
||||
$needsupdate = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -102,12 +100,7 @@ switch ($action) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($needsupdate) {
|
||||
$new = implode(',', $activeantiviruses);
|
||||
add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core');
|
||||
set_config('antiviruses', $new);
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
set_config('antiviruses', implode(',', $activeantiviruses));
|
||||
core_plugin_manager::reset_caches();
|
||||
|
||||
|
||||
redirect ($returnurl);
|
||||
redirect ($returnurl);
|
||||
+29
-16
@@ -11,7 +11,8 @@ require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$returnurl = new moodle_url('/admin/settings.php', array('section'=>'manageauths'));
|
||||
|
||||
@@ -28,7 +29,7 @@ if (empty($CFG->auth)) {
|
||||
}
|
||||
|
||||
if (!empty($auth) and !exists_auth_plugin($auth)) {
|
||||
throw new \moodle_exception('pluginnotinstalled', 'auth', $returnurl, $auth);
|
||||
print_error('pluginnotinstalled', 'auth', $returnurl, $auth);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -40,31 +41,43 @@ 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':
|
||||
$key = array_search($auth, $authsenabled);
|
||||
// check auth plugin is valid
|
||||
if ($key === false) {
|
||||
throw new \moodle_exception('pluginnotenabled', 'auth', $returnurl, $auth);
|
||||
print_error('pluginnotenabled', 'auth', $returnurl, $auth);
|
||||
}
|
||||
// move down the list
|
||||
if ($key < (count($authsenabled) - 1)) {
|
||||
$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;
|
||||
|
||||
@@ -72,16 +85,14 @@ switch ($action) {
|
||||
$key = array_search($auth, $authsenabled);
|
||||
// check auth is valid
|
||||
if ($key === false) {
|
||||
throw new \moodle_exception('pluginnotenabled', 'auth', $returnurl, $auth);
|
||||
print_error('pluginnotenabled', 'auth', $returnurl, $auth);
|
||||
}
|
||||
// move up the list
|
||||
if ($key >= 1) {
|
||||
$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 +101,5 @@ switch ($action) {
|
||||
}
|
||||
|
||||
redirect($returnurl);
|
||||
|
||||
|
||||
|
||||
+6
-29
@@ -16,9 +16,6 @@ $err = array();
|
||||
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageauths";
|
||||
|
||||
debugging("Use of config.html files in authentication plugins have been deprecated. " .
|
||||
" Please migrate your plugin to use the admin settings API", DEBUG_DEVELOPER);
|
||||
|
||||
// save configuration changes
|
||||
if ($frm = data_submitted() and confirm_sesskey()) {
|
||||
|
||||
@@ -89,28 +86,12 @@ exit;
|
||||
|
||||
/// Functions /////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* auth field locking
|
||||
* Good enough for most auth plugins
|
||||
* but some may want a custom one if they are offering
|
||||
* other options
|
||||
* Note: lockconfig_ fields have special handling.
|
||||
*
|
||||
* @param string $auth authentication plugin shortname
|
||||
* @param array $user_fields user profile fields
|
||||
* @param string $helptext help text to be displayed at top of form
|
||||
* @param boolean $retrieveopts Map fields or lock only.
|
||||
* @param boolean $updateopts Allow remote updates
|
||||
* @param array $customfields list of custom profile fields
|
||||
* @deprecated since Moodle 3.3
|
||||
*/
|
||||
// Good enough for most auth plugins
|
||||
// but some may want a custom one if they are offering
|
||||
// other options
|
||||
// Note: lockconfig_ fields have special handling.
|
||||
function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts, $updateopts, $customfields = array()) {
|
||||
global $DB, $OUTPUT;
|
||||
debugging("The function 'print_auth_lock_options' has been deprecated, " .
|
||||
"Please migrate your code to use the admin settings API and use the function 'display_auth_lock_options' instead. ",
|
||||
DEBUG_DEVELOPER);
|
||||
|
||||
echo '<tr><td colspan="3">';
|
||||
if ($retrieveopts) {
|
||||
echo $OUTPUT->heading(get_string('auth_data_mapping', 'auth'));
|
||||
@@ -165,12 +146,8 @@ function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts,
|
||||
// If custom field then pick name from database.
|
||||
$fieldshortname = str_replace('profile_field_', '', $fieldname);
|
||||
$fieldname = $customfieldname[$fieldshortname]->name;
|
||||
if (core_text::strlen($fieldshortname) > 67) {
|
||||
// If custom profile field name is longer than 67 characters we will not be able to store the setting
|
||||
// such as 'field_updateremote_profile_field_NOTSOSHORTSHORTNAME' in the database because the character
|
||||
// limit for the setting name is 100.
|
||||
continue;
|
||||
}
|
||||
} elseif ($fieldname == 'url') {
|
||||
$fieldname = get_string('webpage');
|
||||
} else {
|
||||
$fieldname = get_string($fieldname);
|
||||
}
|
||||
|
||||
+20
-21
@@ -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,13 +67,12 @@
|
||||
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
|
||||
|
||||
if (!$blocks = $DB->get_records('block', array(), 'name ASC')) {
|
||||
throw new \moodle_exception('noblocks', 'error'); // Should never happen.
|
||||
print_error('noblocks', 'error'); // Should never happen
|
||||
}
|
||||
|
||||
$incompatible = array();
|
||||
@@ -171,10 +168,10 @@
|
||||
$visible = '';
|
||||
} else if ($blocks[$blockid]->visible) {
|
||||
$visible = '<a href="blocks.php?hide='.$blockid.'&sesskey='.sesskey().'" title="'.$strhide.'">'.
|
||||
$OUTPUT->pix_icon('t/hide', $strhide) . '</a>';
|
||||
'<img src="'.$OUTPUT->pix_url('t/hide') . '" class="iconsmall" alt="'.$strhide.'" /></a>';
|
||||
} else {
|
||||
$visible = '<a href="blocks.php?show='.$blockid.'&sesskey='.sesskey().'" title="'.$strshow.'">'.
|
||||
$OUTPUT->pix_icon('t/show', $strshow) . '</a>';
|
||||
'<img src="'.$OUTPUT->pix_url('t/show') . '" class="iconsmall" alt="'.$strshow.'" /></a>';
|
||||
$class = 'dimmed_text';
|
||||
}
|
||||
|
||||
@@ -189,10 +186,10 @@
|
||||
$undeletable = '';
|
||||
} else if (in_array($blockname, $undeletableblocktypes)) {
|
||||
$undeletable = '<a href="blocks.php?unprotect='.$blockid.'&sesskey='.sesskey().'" title="'.$strunprotect.'">'.
|
||||
$OUTPUT->pix_icon('t/unlock', $strunprotect) . '</a>';
|
||||
'<img src="'.$OUTPUT->pix_url('t/unlock') . '" class="iconsmall" alt="'.$strunprotect.'" /></a>';
|
||||
} else {
|
||||
$undeletable = '<a href="blocks.php?protect='.$blockid.'&sesskey='.sesskey().'" title="'.$strprotect.'">'.
|
||||
$OUTPUT->pix_icon('t/lock', $strprotect) . '</a>';
|
||||
'<img src="'.$OUTPUT->pix_url('t/lock') . '" class="iconsmall" alt="'.$strprotect.'" /></a>';
|
||||
}
|
||||
|
||||
$row = array(
|
||||
@@ -237,3 +234,5 @@
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
|
||||
|
||||
+23
-28
@@ -30,6 +30,7 @@ $category = required_param('category', PARAM_SAFEDIR);
|
||||
$return = optional_param('return','', PARAM_ALPHA);
|
||||
$adminediting = optional_param('adminedit', -1, PARAM_BOOL);
|
||||
|
||||
/// no guest autologin
|
||||
require_login(0, false);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_url('/admin/category.php', array('category' => $category));
|
||||
@@ -41,34 +42,26 @@ $adminroot = admin_get_root(); // need all settings
|
||||
$settingspage = $adminroot->locate($category, true);
|
||||
|
||||
if (empty($settingspage) or !($settingspage instanceof admin_category)) {
|
||||
throw new \moodle_exception('categoryerror', 'error', "$CFG->wwwroot/$CFG->admin/");
|
||||
print_error('categoryerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
|
||||
}
|
||||
|
||||
if (!($settingspage->check_access())) {
|
||||
throw new \moodle_exception('accessdenied', 'admin');
|
||||
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 = '';
|
||||
|
||||
if ($data = data_submitted() and confirm_sesskey()) {
|
||||
$count = admin_write_settings($data);
|
||||
if (admin_write_settings($data)) {
|
||||
$statusmsg = get_string('changessaved');
|
||||
}
|
||||
|
||||
if (empty($adminroot->errors)) {
|
||||
// No errors. Did we change any setting? If so, then indicate success.
|
||||
if ($count) {
|
||||
$statusmsg = get_string('changessaved');
|
||||
} else {
|
||||
switch ($return) {
|
||||
case 'site': redirect("$CFG->wwwroot/");
|
||||
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
|
||||
}
|
||||
switch ($return) {
|
||||
case 'site': redirect("$CFG->wwwroot/");
|
||||
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
|
||||
}
|
||||
} else {
|
||||
$errormsg = get_string('errorwithsettings', 'admin');
|
||||
@@ -80,8 +73,8 @@ if ($data = data_submitted() and confirm_sesskey()) {
|
||||
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');
|
||||
@@ -96,7 +89,7 @@ if ($PAGE->user_allowed_editing() && !$PAGE->theme->haseditswitch) {
|
||||
$savebutton = false;
|
||||
$outputhtml = '';
|
||||
foreach ($settingspage->children as $childpage) {
|
||||
if ($childpage->is_hidden() || !$childpage->check_access()) {
|
||||
if ($childpage->is_hidden()) {
|
||||
continue;
|
||||
}
|
||||
if ($childpage instanceof admin_externalpage) {
|
||||
@@ -131,11 +124,10 @@ if ($savebutton) {
|
||||
$outputhtml .= html_writer::end_tag('div');
|
||||
}
|
||||
|
||||
$PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $settingspage->visiblepath));
|
||||
$visiblepathtosection = array_reverse($settingspage->visiblepath);
|
||||
$PAGE->set_title("$SITE->shortname: " . implode(": ",$visiblepathtosection));
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
if ($buttons) {
|
||||
$PAGE->set_button($buttons);
|
||||
}
|
||||
$PAGE->set_button($buttons);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
@@ -145,7 +137,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');
|
||||
@@ -157,7 +155,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();
|
||||
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Form for selective purging of caches.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2018 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\form;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir.'/formslib.php');
|
||||
|
||||
/**
|
||||
* Form for selecting which caches to purge on admin/purgecaches.php
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2018 The Open University
|
||||
* @author Mark Johnson <mark.johnson@open.ac.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class purge_caches extends \moodleform {
|
||||
/**
|
||||
* Define a "Purge all caches" button, and a fieldset with checkboxes for selectively purging separate caches.
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
$mform->addElement('hidden', 'returnurl', $this->_customdata['returnurl']);
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
$mform->addElement('submit', 'all', get_string('purgecaches', 'admin'));
|
||||
$mform->addElement('header', 'purgecacheheader', get_string('purgeselectedcaches', 'admin'));
|
||||
$checkboxes = [
|
||||
$mform->createElement('advcheckbox', 'theme', '', get_string('purgethemecache', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'lang', '', get_string('purgelangcache', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'js', '', get_string('purgejscache', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'template', '', get_string('purgetemplates', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'filter', '', get_string('purgefiltercache', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'muc', '', get_string('purgemuc', 'admin')),
|
||||
$mform->createElement('advcheckbox', 'other', '', get_string('purgeothercaches', 'admin'))
|
||||
];
|
||||
$mform->addGroup($checkboxes, 'purgeselectedoptions');
|
||||
$mform->addElement('submit', 'purgeselectedcaches', get_string('purgeselectedcaches', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* If the "Purge selected caches" button was pressed, ensure at least one cache was selected.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $files
|
||||
* @return array Error messages
|
||||
*/
|
||||
public function validation($data, $files) {
|
||||
$errors = [];
|
||||
if (isset($data['purgeselectedcaches']) && empty(array_filter($data['purgeselectedoptions']))) {
|
||||
$errors['purgeselectedoptions'] = get_string('purgecachesnoneselected', 'admin');
|
||||
}
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
@@ -1,92 +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/>.
|
||||
|
||||
/**
|
||||
* Testing outgoing mail configuration form
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2019 Victor Deniz <victor@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\form;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir.'/formslib.php');
|
||||
|
||||
/**
|
||||
* Test mail form
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2019 Victor Deniz <victor@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class testoutgoingmailconf_form extends \moodleform {
|
||||
/**
|
||||
* Add elements to form
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
// Recipient.
|
||||
$options = ['maxlength' => '100', 'size' => '25', 'autocomplete' => 'email'];
|
||||
$mform->addElement('text', 'recipient', get_string('testoutgoingmailconf_toemail', 'admin'), $options);
|
||||
$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');
|
||||
|
||||
$mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
|
||||
$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,71 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* External admin page class that allows a callback to be provided to determine whether page can be accessed
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2019 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\externalpage;
|
||||
|
||||
use admin_externalpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
|
||||
/**
|
||||
* Admin externalpage class
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2019 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class accesscallback extends admin_externalpage {
|
||||
|
||||
/** @var callable $accesscheckcallback */
|
||||
protected $accesscheckcallback;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $visiblename
|
||||
* @param string $url
|
||||
* @param callable $accesscheckcallback The callback method that will be executed to check whether user has access to
|
||||
* this page. The setting instance ($this) is passed as an argument to the callback. Should return boolean value
|
||||
* @param bool $hidden
|
||||
*/
|
||||
public function __construct(string $name, string $visiblename, string $url, callable $accesscheckcallback,
|
||||
bool $hidden = false) {
|
||||
|
||||
$this->accesscheckcallback = $accesscheckcallback;
|
||||
|
||||
parent::__construct($name, $visiblename, $url, [], $hidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the current user has access to this external page based on access callback
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function check_access() {
|
||||
return ($this->accesscheckcallback)($this);
|
||||
}
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Auto complete admin setting.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2020 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
/**
|
||||
* Auto complete setting class.
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @copyright 2020 The Open University
|
||||
*/
|
||||
class autocomplete extends \admin_setting_configmultiselect {
|
||||
/** @var boolean Should we allow typing new entries to the field? */
|
||||
protected $tags = false;
|
||||
/** @var string Name of an AMD module to send/process ajax requests. */
|
||||
protected $ajax = '';
|
||||
/** @var string Placeholder text for an empty list. */
|
||||
protected $placeholder = '';
|
||||
/** @var bool Whether the search has to be case-sensitive. */
|
||||
protected $casesensitive = false;
|
||||
/** @var bool Show suggestions by default - but this can be turned off. */
|
||||
protected $showsuggestions = true;
|
||||
/** @var string String that is shown when there are no selections. */
|
||||
protected $noselectionstring = '';
|
||||
/** @var string Delimiter to store values in database. */
|
||||
protected $delimiter = ',';
|
||||
/** @var string Should be multiple choices? */
|
||||
protected $multiple = true;
|
||||
/** @var string The link to manage choices. */
|
||||
protected $manageurl = true;
|
||||
/** @var string The text to display in manage link. */
|
||||
protected $managetext = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting'
|
||||
* for ones in config_plugins.
|
||||
* @param string $visiblename localised
|
||||
* @param string $description long localised info
|
||||
* @param array $defaultsetting array of selected items
|
||||
* @param array $choices options for autocomplete field
|
||||
* @param array $attributes settings for autocomplete field
|
||||
*/
|
||||
public function __construct($name, $visiblename, $description, $defaultsetting, $choices, $attributes = null) {
|
||||
|
||||
if ($attributes === null) {
|
||||
$attributes = [];
|
||||
}
|
||||
|
||||
$this->placeholder = get_string('search');
|
||||
$this->noselectionstring = get_string('noselection', 'form');
|
||||
$defaultattributes = [
|
||||
'tags',
|
||||
'showsuggestions',
|
||||
'placeholder',
|
||||
'noselectionstring',
|
||||
'ajax',
|
||||
'casesensitive',
|
||||
'delimiter',
|
||||
'multiple',
|
||||
'manageurl',
|
||||
'managetext'
|
||||
];
|
||||
|
||||
foreach ($defaultattributes as $attributename) {
|
||||
if (isset($attributes[$attributename])) {
|
||||
$this->$attributename = $attributes[$attributename];
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting, $choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the select setting(s)
|
||||
*
|
||||
* @return mixed null or array. Null if no settings else array of setting(s)
|
||||
*/
|
||||
public function get_setting() {
|
||||
$result = $this->config_read($this->name);
|
||||
if (is_null($result)) {
|
||||
return null;
|
||||
}
|
||||
if ($result === '') {
|
||||
return [];
|
||||
}
|
||||
return explode($this->delimiter, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves setting(s) provided through $data
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function write_setting($data) {
|
||||
if (!is_array($data)) {
|
||||
return ''; // Ignore it.
|
||||
}
|
||||
if (!$this->load_choices() || empty($this->choices)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
unset($data['xxxxx']);
|
||||
|
||||
$save = [];
|
||||
foreach ($data as $value) {
|
||||
if (!array_key_exists($value, $this->choices)) {
|
||||
continue; // Ignore it.
|
||||
}
|
||||
$save[] = $value;
|
||||
}
|
||||
|
||||
return ($this->config_write($this->name, implode($this->delimiter, $save)) ? '' : get_string('errorsetting', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns XHTML autocomplete field
|
||||
*
|
||||
* @param array $data Array of values to select by default
|
||||
* @param string $query
|
||||
* @return string XHTML autocomplete field
|
||||
*/
|
||||
public function output_html($data, $query = '') {
|
||||
global $OUTPUT;
|
||||
|
||||
if (!$this->load_choices() or empty($this->choices)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$default = $this->get_defaultsetting();
|
||||
if (empty($default)) {
|
||||
$default = [];
|
||||
}
|
||||
|
||||
if (is_null($data)) {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
$context = [
|
||||
'id' => $this->get_id(),
|
||||
'name' => $this->get_full_name()
|
||||
];
|
||||
|
||||
$defaults = [];
|
||||
$options = [];
|
||||
$template = 'core_admin/local/settings/autocomplete';
|
||||
|
||||
foreach ($this->choices as $value => $name) {
|
||||
if (in_array($value, $default)) {
|
||||
$defaults[] = $name;
|
||||
}
|
||||
$options[] = [
|
||||
'value' => $value,
|
||||
'text' => $name,
|
||||
'selected' => in_array($value, $data),
|
||||
'disabled' => false
|
||||
];
|
||||
}
|
||||
|
||||
$context['options'] = $options;
|
||||
$context['tags'] = $this->tags;
|
||||
$context['placeholder'] = $this->placeholder;
|
||||
$context['casesensitive'] = $this->casesensitive;
|
||||
$context['multiple'] = $this->multiple;
|
||||
$context['showsuggestions'] = $this->showsuggestions;
|
||||
$context['manageurl'] = $this->manageurl;
|
||||
$context['managetext'] = $this->managetext;
|
||||
|
||||
if (is_null($default)) {
|
||||
$defaultinfo = null;
|
||||
} if (!empty($defaults)) {
|
||||
$defaultinfo = implode(', ', $defaults);
|
||||
} else {
|
||||
$defaultinfo = get_string('none');
|
||||
}
|
||||
|
||||
$element = $OUTPUT->render_from_template($template, $context);
|
||||
|
||||
return format_admin_setting($this, $this->visiblename, $element, $this->description, true, '', $defaultinfo, $query);
|
||||
}
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* File size admin setting.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2019 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
/**
|
||||
* An admin setting to support entering and displaying of file sizes in Bytes, KB, MB or GB.
|
||||
*
|
||||
* @copyright 2019 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class filesize extends \admin_setting {
|
||||
|
||||
/** @var int The byte unit. Number of bytes in a byte */
|
||||
const UNIT_B = 1;
|
||||
|
||||
/** @var int The kilobyte unit (number of bytes in a kilobyte) */
|
||||
const UNIT_KB = 1024;
|
||||
|
||||
/** @var int The megabyte unit (number of bytes in a megabyte) */
|
||||
const UNIT_MB = 1048576;
|
||||
|
||||
/** @var int The gigabyte unit (number of bytes in a gigabyte) */
|
||||
const UNIT_GB = 1073741824;
|
||||
|
||||
/** @var int default size unit */
|
||||
protected $defaultunit;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $name unique ascii name, either 'mysetting' for settings that in config,
|
||||
* or 'myplugin/mysetting' for ones in config_plugins.
|
||||
* @param string $visiblename localised name
|
||||
* @param string $description localised long description
|
||||
* @param int|null $defaultvalue Value of the settings in bytes
|
||||
* @param int|null $defaultunit GB, MB, etc. (in bytes)
|
||||
*/
|
||||
public function __construct(string $name, string $visiblename, string $description,
|
||||
int $defaultvalue = null, int $defaultunit = null) {
|
||||
|
||||
$defaultsetting = self::parse_bytes($defaultvalue);
|
||||
|
||||
if ($defaultunit && array_key_exists($defaultunit, self::get_units())) {
|
||||
$this->defaultunit = $defaultunit;
|
||||
} else {
|
||||
$this->defaultunit = self::UNIT_MB;
|
||||
}
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns selectable units.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function get_units(): array {
|
||||
return [
|
||||
self::UNIT_GB => get_string('sizegb'),
|
||||
self::UNIT_MB => get_string('sizemb'),
|
||||
self::UNIT_KB => get_string('sizekb'),
|
||||
self::UNIT_B => get_string('sizeb'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts bytes to some more user friendly string.
|
||||
*
|
||||
* @param int $bytes The number of bytes we want to convert from
|
||||
* @return string
|
||||
*/
|
||||
protected static function get_size_text(int $bytes): string {
|
||||
if (empty($bytes)) {
|
||||
return get_string('none');
|
||||
}
|
||||
return display_size($bytes, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds suitable units for given file size.
|
||||
*
|
||||
* @param int $bytes The number of bytes
|
||||
* @return array Parsed file size in the format of ['v' => value, 'u' => unit]
|
||||
*/
|
||||
protected static function parse_bytes(int $bytes): array {
|
||||
foreach (self::get_units() as $unit => $unused) {
|
||||
if ($bytes % $unit === 0) {
|
||||
return ['v' => (int)($bytes / $unit), 'u' => $unit];
|
||||
}
|
||||
}
|
||||
return ['v' => (int)$bytes, 'u' => self::UNIT_B];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected file size as array.
|
||||
*
|
||||
* @return array|null An array containing 'v' => xx, 'u' => xx, or null if not set
|
||||
*/
|
||||
public function get_setting(): ?array {
|
||||
$bytes = $this->config_read($this->name);
|
||||
if (is_null($bytes)) {
|
||||
return null;
|
||||
}
|
||||
$bytes = intval($bytes);
|
||||
|
||||
return self::parse_bytes($bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the file size as bytes.
|
||||
*
|
||||
* @param array $data Must be form 'h' => xx, 'm' => xx
|
||||
* @return string The error string if any
|
||||
*/
|
||||
public function write_setting($data): string {
|
||||
if (!is_array($data)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!is_numeric($data['v']) || $data['v'] < 0) {
|
||||
return get_string('errorsetting', 'admin');
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
return ($result ? '' : get_string('errorsetting', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns file size text+select fields.
|
||||
*
|
||||
* @param array $data The current setting value. Must be form 'v' => xx, 'u' => xx.
|
||||
* @param string $query Admin search query to be highlighted.
|
||||
* @return string File size text+select fields and wrapping div(s).
|
||||
*/
|
||||
public function output_html($data, $query = ''): string {
|
||||
global $OUTPUT;
|
||||
|
||||
$default = $this->get_defaultsetting();
|
||||
if (is_number($default)) {
|
||||
$defaultinfo = self::get_size_text($default);
|
||||
} else if (is_array($default)) {
|
||||
$defaultinfo = self::get_size_text($default['v'] * $default['u']);
|
||||
} else {
|
||||
$defaultinfo = null;
|
||||
}
|
||||
|
||||
$inputid = $this->get_id() . 'v';
|
||||
$units = self::get_units();
|
||||
$defaultunit = $this->defaultunit;
|
||||
|
||||
$context = (object) [
|
||||
'id' => $this->get_id(),
|
||||
'name' => $this->get_full_name(),
|
||||
'value' => $data['v'],
|
||||
'readonly' => $this->is_readonly(),
|
||||
'options' => array_map(function($unit, $title) use ($data, $defaultunit) {
|
||||
return [
|
||||
'value' => $unit,
|
||||
'name' => $title,
|
||||
'selected' => ($data['v'] == 0 && $unit == $defaultunit) || $unit == $data['u']
|
||||
];
|
||||
}, array_keys($units), $units)
|
||||
];
|
||||
|
||||
$element = $OUTPUT->render_from_template('core_admin/setting_configfilesize', $context);
|
||||
|
||||
return format_admin_setting($this, $this->visiblename, $element, $this->description, $inputid, '', $defaultinfo, $query);
|
||||
}
|
||||
}
|
||||
@@ -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,74 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Payment gateway admin setting.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2020 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
/**
|
||||
* Generic class for managing plugins in a table that allows re-ordering and enable/disable of each plugin.
|
||||
*/
|
||||
class manage_payment_gateway_plugins extends \admin_setting_manage_plugins {
|
||||
/**
|
||||
* Get the admin settings section title (use get_string).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_section_title() {
|
||||
return get_string('type_paygw_plural', 'plugin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of plugin to manage.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_type() {
|
||||
return 'paygw';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the second column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_info_column_name() {
|
||||
return get_string('supportedcurrencies', 'core_payment');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of plugin to manage.
|
||||
*
|
||||
* @param plugininfo The plugin info class.
|
||||
* @return string
|
||||
*/
|
||||
public function get_info_column($plugininfo) {
|
||||
$codes = $plugininfo->get_supported_currencies();
|
||||
|
||||
$currencies = [];
|
||||
foreach ($codes as $c) {
|
||||
$currencies[$c] = new \lang_string($c, 'core_currencies');
|
||||
}
|
||||
|
||||
return implode(get_string('listsep', 'langconfig') . ' ', $currencies);
|
||||
}
|
||||
}
|
||||
@@ -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,41 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/**
|
||||
* Privacy Subsystem implementation for core_admin.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_admin\privacy;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
/**
|
||||
* Privacy Subsystem for core_admin implementing null_provider.
|
||||
*
|
||||
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
||||
@@ -1,117 +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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_admin\reportbuilder\datasource;
|
||||
|
||||
use core_admin\reportbuilder\local\entities\task_log;
|
||||
use core_reportbuilder\datasource;
|
||||
use core_reportbuilder\local\entities\user;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
|
||||
/**
|
||||
* Task logs datasource
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2022 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class task_logs extends datasource {
|
||||
|
||||
/**
|
||||
* Return user friendly name of the report source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name(): string {
|
||||
return get_string('tasklogs', 'core_admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise report
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
$tasklogentity = new task_log();
|
||||
|
||||
$tasklogalias = $tasklogentity->get_table_alias('task_log');
|
||||
$this->set_main_table('task_log', $tasklogalias);
|
||||
|
||||
$this->add_entity($tasklogentity);
|
||||
|
||||
// Join the user entity to represent the associated user.
|
||||
$userentity = new user();
|
||||
$useralias = $userentity->get_table_alias('user');
|
||||
$this->add_entity($userentity->add_join("
|
||||
LEFT JOIN {user} {$useralias}
|
||||
ON {$useralias}.id = {$tasklogalias}.userid")
|
||||
);
|
||||
|
||||
// Add report elements from each of the entities we added to the report.
|
||||
$this->add_all_from_entities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the columns that will be added to the report upon creation
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_columns(): array {
|
||||
return [
|
||||
'task_log:name',
|
||||
'task_log:starttime',
|
||||
'task_log:duration',
|
||||
'task_log:result',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filters that will be added to the report upon creation
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_filters(): array {
|
||||
return [
|
||||
'task_log:timestart',
|
||||
'task_log:result',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the conditions that will be added to the report upon creation
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_conditions(): array {
|
||||
return [
|
||||
'task_log:type',
|
||||
'task_log:timestart',
|
||||
'task_log:result',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the condition values that will be set for the report upon creation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_condition_values(): array {
|
||||
return [
|
||||
'task_log:type_operator' => select::EQUAL_TO,
|
||||
'task_log:type_value' => \core\task\database_logger::TYPE_SCHEDULED,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,427 +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\reportbuilder\local\entities;
|
||||
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\duration;
|
||||
use core_reportbuilder\local\filters\number;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\filters\autocomplete;
|
||||
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;
|
||||
use core_collator;
|
||||
|
||||
/**
|
||||
* 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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the entity
|
||||
*
|
||||
* @return base
|
||||
*/
|
||||
public function initialise(): base {
|
||||
$columns = $this->get_all_columns();
|
||||
foreach ($columns as $column) {
|
||||
$this->add_column($column);
|
||||
}
|
||||
|
||||
// All the filters defined by the entity can also be used as conditions.
|
||||
$filters = $this->get_all_filters();
|
||||
foreach ($filters as $filter) {
|
||||
$this
|
||||
->add_filter($filter)
|
||||
->add_condition($filter);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all available columns
|
||||
*
|
||||
* @return column[]
|
||||
*/
|
||||
protected function get_all_columns(): array {
|
||||
global $DB;
|
||||
|
||||
$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 $classname): string {
|
||||
$output = '';
|
||||
if (class_exists($classname)) {
|
||||
$task = new $classname;
|
||||
if ($task instanceof \core\task\task_base) {
|
||||
$output = $task->get_name();
|
||||
}
|
||||
}
|
||||
$output .= \html_writer::tag('div', "\\{$classname}", [
|
||||
'class' => 'small text-muted',
|
||||
]);
|
||||
return $output;
|
||||
});
|
||||
|
||||
// Component column.
|
||||
$columns[] = (new column(
|
||||
'component',
|
||||
new lang_string('plugin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("{$tablealias}.component")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// Type column.
|
||||
$columns[] = (new column(
|
||||
'type',
|
||||
new lang_string('tasktype', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("{$tablealias}.type")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function($value): string {
|
||||
if (\core\task\database_logger::TYPE_SCHEDULED === (int) $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'));
|
||||
|
||||
// End time column.
|
||||
$columns[] = (new column(
|
||||
'endtime',
|
||||
new lang_string('task_endtime', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TIMESTAMP)
|
||||
->add_field("{$tablealias}.timeend")
|
||||
->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)
|
||||
// Although this is an integer column, it doesn't make sense to perform numeric aggregation on it.
|
||||
->set_disabled_aggregation(['avg', 'count', 'countdistinct', 'max', 'min', 'sum']);
|
||||
|
||||
// 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, ["{$tablealias}.dbreads", "{$tablealias}.dbwrites"])
|
||||
->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;
|
||||
})
|
||||
// Although this is an integer column, it doesn't make sense to perform numeric aggregation on it.
|
||||
->set_disabled_aggregation(['avg', 'count', 'countdistinct', 'max', 'min', 'sum']);
|
||||
|
||||
// Database reads column.
|
||||
$columns[] = (new column(
|
||||
'dbreads',
|
||||
new lang_string('task_dbreads', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_fields("{$tablealias}.dbreads")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// Database writes column.
|
||||
$columns[] = (new column(
|
||||
'dbwrites',
|
||||
new lang_string('task_dbwrites', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_fields("{$tablealias}.dbwrites")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// 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_BOOLEAN)
|
||||
// For accurate aggregation, we need to return boolean success = true by xor'ing the field value.
|
||||
->add_field($DB->sql_bitxor("{$tablealias}.result", 1), 'success')
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(bool $success): string {
|
||||
if (!$success) {
|
||||
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 {
|
||||
global $DB;
|
||||
|
||||
$tablealias = $this->get_table_alias('task_log');
|
||||
|
||||
// Name filter (Filter by classname).
|
||||
$filters[] = (new filter(
|
||||
autocomplete::class,
|
||||
'name',
|
||||
new lang_string('classname', 'tool_task'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.classname"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_options_callback(static function(): array {
|
||||
global $DB;
|
||||
$classnames = $DB->get_fieldset_sql('SELECT DISTINCT classname FROM {task_log} ORDER BY classname ASC');
|
||||
|
||||
$options = [];
|
||||
foreach ($classnames as $classname) {
|
||||
if (class_exists($classname)) {
|
||||
$task = new $classname;
|
||||
$options[$classname] = $task->get_name();
|
||||
}
|
||||
}
|
||||
|
||||
core_collator::asort($options);
|
||||
return $options;
|
||||
});
|
||||
|
||||
// Component filter.
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'component',
|
||||
new lang_string('plugin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.component"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Type filter.
|
||||
$filters[] = (new filter(
|
||||
select::class,
|
||||
'type',
|
||||
new lang_string('tasktype', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.type"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_options([
|
||||
\core\task\database_logger::TYPE_ADHOC => new lang_string('task_type:adhoc', 'admin'),
|
||||
\core\task\database_logger::TYPE_SCHEDULED => new lang_string('task_type:scheduled', 'admin'),
|
||||
]);
|
||||
|
||||
// Output filter (Filter by task output).
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'output',
|
||||
new lang_string('task_logoutput', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
$DB->sql_cast_to_char("{$tablealias}.output")
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// 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,
|
||||
]);
|
||||
|
||||
// End time.
|
||||
$filters[] = (new filter(
|
||||
date::class,
|
||||
'timeend',
|
||||
new lang_string('task_endtime', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.timeend"
|
||||
))
|
||||
->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());
|
||||
|
||||
// Database reads.
|
||||
$filters[] = (new filter(
|
||||
number::class,
|
||||
'dbreads',
|
||||
new lang_string('task_dbreads', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.dbreads"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Database writes.
|
||||
$filters[] = (new filter(
|
||||
number::class,
|
||||
'dbwrites',
|
||||
new lang_string('task_dbwrites', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.dbwrites"
|
||||
))
|
||||
->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'),
|
||||
]);
|
||||
|
||||
return $filters;
|
||||
}
|
||||
}
|
||||
@@ -1,159 +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\reportbuilder\local\systemreports;
|
||||
|
||||
use context_system;
|
||||
use core_admin\reportbuilder\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:type',
|
||||
'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'),
|
||||
)));
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Task executor for adhoc tasks.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once("{$CFG->libdir}/clilib.php");
|
||||
require_once("{$CFG->libdir}/cronlib.php");
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'execute' => false,
|
||||
'help' => false,
|
||||
'keep-alive' => 0,
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'ignorelimits' => false,
|
||||
'force' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'e' => 'execute',
|
||||
'k' => 'keep-alive',
|
||||
'i' => 'ignorelimits',
|
||||
'f' => 'force',
|
||||
]
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help'] or empty($options['execute'])) {
|
||||
$help = <<<EOT
|
||||
Ad hoc cron tasks.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
--showsql Show sql queries before they are executed
|
||||
--showdebugging Show developer level debugging information
|
||||
-e, --execute Run all queued adhoc tasks
|
||||
-k, --keep-alive=N Keep this script alive for N seconds and poll for new adhoc tasks
|
||||
-i --ignorelimits Ignore task_adhoc_concurrency_limit and task_adhoc_max_runtime limits
|
||||
-f, --force Run even if cron is disabled
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
|
||||
|
||||
EOT;
|
||||
|
||||
echo $help;
|
||||
die;
|
||||
}
|
||||
|
||||
if ($options['showdebugging']) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if ($options['showsql']) {
|
||||
$DB->set_debug(true);
|
||||
}
|
||||
|
||||
if (CLI_MAINTENANCE) {
|
||||
echo "CLI maintenance mode active, cron execution suspended.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (moodle_needs_upgrading()) {
|
||||
echo "Moodle upgrade pending, cron execution suspended.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (empty($options['execute'])) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (empty($options['keep-alive'])) {
|
||||
$options['keep-alive'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($CFG->showcronsql)) {
|
||||
$DB->set_debug(true);
|
||||
}
|
||||
if (!empty($CFG->showcrondebugging)) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
$checklimits = empty($options['ignorelimits']);
|
||||
|
||||
core_php_time_limit::raise();
|
||||
|
||||
// Increase memory limit.
|
||||
raise_memory_limit(MEMORY_EXTRA);
|
||||
|
||||
// Emulate normal session - we use admin account by default.
|
||||
cron_setup_user();
|
||||
|
||||
$humantimenow = date('r', time());
|
||||
$keepalive = (int)$options['keep-alive'];
|
||||
|
||||
\core\local\cli\shutdown::script_supports_graceful_exit();
|
||||
|
||||
mtrace("Server Time: {$humantimenow}\n");
|
||||
cron_run_adhoc_tasks(time(), $keepalive, $checklimits);
|
||||
@@ -1,119 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Build and store theme CSS.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once("$CFG->libdir/clilib.php");
|
||||
require_once("$CFG->libdir/csslib.php");
|
||||
require_once("$CFG->libdir/outputlib.php");
|
||||
|
||||
$longparams = [
|
||||
'themes' => null,
|
||||
'direction' => null,
|
||||
'help' => false,
|
||||
'verbose' => false
|
||||
];
|
||||
|
||||
$shortmappings = [
|
||||
't' => 'themes',
|
||||
'd' => 'direction',
|
||||
'h' => 'help',
|
||||
'v' => 'verbose'
|
||||
];
|
||||
|
||||
// Get CLI params.
|
||||
list($options, $unrecognized) = cli_get_params($longparams, $shortmappings);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
echo
|
||||
"Compile the CSS for one or more installed themes.
|
||||
Existing CSS caches will replaced.
|
||||
By default all themes will be recompiled unless otherwise specified.
|
||||
|
||||
Options:
|
||||
-t, --themes A comma separated list of themes to be compiled
|
||||
-d, --direction Only compile a single direction (either ltr or rtl)
|
||||
-v, --verbose Print info comments to stdout
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$ sudo -u www-data /usr/bin/php admin/cli/build_theme_css.php --themes=boost --direction=ltr
|
||||
";
|
||||
|
||||
die;
|
||||
}
|
||||
|
||||
if (empty($options['verbose'])) {
|
||||
$trace = new null_progress_trace();
|
||||
} else {
|
||||
$trace = new text_progress_trace();
|
||||
}
|
||||
|
||||
cli_heading('Build theme css');
|
||||
|
||||
// Determine which themes we need to build.
|
||||
$themenames = [];
|
||||
if (is_null($options['themes'])) {
|
||||
$trace->output('No themes specified. Finding all installed themes.');
|
||||
$themenames = array_keys(core_component::get_plugin_list('theme'));
|
||||
} else {
|
||||
if (is_string($options['themes'])) {
|
||||
$themenames = explode(',', $options['themes']);
|
||||
} else {
|
||||
cli_error('--themes must be a comma separated list of theme names');
|
||||
}
|
||||
}
|
||||
|
||||
$trace->output('Checking that each theme is correctly installed...');
|
||||
$themeconfigs = [];
|
||||
foreach ($themenames as $themename) {
|
||||
if (is_null(theme_get_config_file_path($themename))) {
|
||||
cli_error("Unable to find theme config for {$themename}");
|
||||
}
|
||||
|
||||
// Load the config for the theme.
|
||||
$themeconfigs[] = theme_config::load($themename);
|
||||
}
|
||||
|
||||
$directions = ['ltr', 'rtl'];
|
||||
|
||||
if (!is_null($options['direction'])) {
|
||||
if (!in_array($options['direction'], $directions)) {
|
||||
cli_error("--direction must be either ltr or rtl");
|
||||
}
|
||||
|
||||
$directions = [$options['direction']];
|
||||
}
|
||||
|
||||
$trace->output('Building CSS for themes: ' . implode(', ', $themenames));
|
||||
theme_build_css_for_themes($themeconfigs, $directions);
|
||||
|
||||
exit(0);
|
||||
@@ -1,185 +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 allowing to get and set config values.
|
||||
*
|
||||
* This is technically just a thin wrapper for {@link get_config()} and
|
||||
* {@link set_config()} functions.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2017 David Mudrák <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
|
||||
$usage = "Displays the current value of the given site setting. Allows to set it to the given value, too.
|
||||
|
||||
Usage:
|
||||
# php cfg.php [--component=<componentname>] [--json] [--shell-arg]
|
||||
# php cfg.php --name=<configname> [--component=<componentname>] [--shell-arg] [--no-eol]
|
||||
# php cfg.php --name=<configname> [--component=<componentname>] --set=<value>
|
||||
# php cfg.php --name=<configname> [--component=<componentname>] --unset
|
||||
# php cfg.php [--help|-h]
|
||||
|
||||
Options:
|
||||
-h --help Print this help.
|
||||
--component=<frankenstyle> Name of the component the variable is part of. Defaults to core.
|
||||
--name=<configname> Name of the configuration variable to get/set. If missing, print all
|
||||
configuration variables of the given component.
|
||||
--set=<value> Set the given variable to this value.
|
||||
--unset Unset the given variable.
|
||||
--shell-arg Escape output values so that they can be directly used as shell script arguments.
|
||||
--json Encode output list of values using JSON notation.
|
||||
--no-eol Do not include the trailing new line character when printing the value.
|
||||
|
||||
The list of all variables of the given component can be printed as
|
||||
tab-separated list (default) or JSON object (--json). Particular values are
|
||||
printed as raw text values, optionally escaped so that they can be directly
|
||||
used as shell script arguments (--shell-arg). Single values are displayed with
|
||||
trailing new line by default, unless explicitly disabled (--no-eol).
|
||||
|
||||
In the read mode, the script exits with success status 0 if the requested value
|
||||
is found. If the requested variable is not set, the script exits with status 3.
|
||||
When listing all variables of the component, the exit status is always 0 even
|
||||
if no variables for the given component are found. When setting/unsetting a
|
||||
value, the exit status is 0. When attempting to set/unset a value that has
|
||||
already been hard-set in config.php, the script exits with error status 4. In
|
||||
case of unexpected error, the script exits with error status 1.
|
||||
|
||||
Examples:
|
||||
|
||||
# php cfg.php
|
||||
Prints tab-separated list of all core configuration variables and their values.
|
||||
|
||||
# php cfg.php --json
|
||||
Prints list of all core configuration variables and their values as a JSON object.
|
||||
|
||||
# php cfg.php --name=release
|
||||
Prints the given configuration variable - e.g. \$CFG->release in this case.
|
||||
|
||||
# php cfg.php --component=tool_recyclebin
|
||||
# Prints tab-separated list of the plugin's configuration variables.
|
||||
|
||||
# export DATAROOT=\$(php cfg.php --name=dataroot --shell-arg --no-eol)
|
||||
Stores the given configuration variable in the shell variable, escaped
|
||||
so that it can be safely used as a shell argument.
|
||||
|
||||
# php cfg.php --name=theme --set=classic
|
||||
Sets the given configuration variable to the given value.
|
||||
|
||||
# php cfg.php --name=noemailever --unset
|
||||
Unsets the previously configured variable.
|
||||
";
|
||||
|
||||
list($options, $unrecognised) = cli_get_params([
|
||||
'help' => false,
|
||||
'component' => null,
|
||||
'name' => null,
|
||||
'set' => null,
|
||||
'unset' => false,
|
||||
'shell-arg' => false,
|
||||
'json' => false,
|
||||
'no-eol' => false,
|
||||
], [
|
||||
'h' => 'help'
|
||||
]);
|
||||
|
||||
if ($unrecognised) {
|
||||
$unrecognised = implode(PHP_EOL.' ', $unrecognised);
|
||||
cli_error(get_string('cliunknowoption', 'core_admin', $unrecognised));
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
cli_writeln($usage);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if ($options['unset'] || $options['set'] !== null) {
|
||||
// Unset the variable or set it to the given value.
|
||||
if (empty($options['name'])) {
|
||||
cli_error('Missing configuration variable name', 2);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
cli_error('The configuration variable is hard-set in the config.php, unable to change.', 4);
|
||||
}
|
||||
|
||||
$new = $options['set'];
|
||||
$old = get_config($options['component'], $options['name']);
|
||||
if ($new !== $old) {
|
||||
set_config($options['name'], $options['set'], $options['component']);
|
||||
add_to_config_log($options['name'], $old, $new, $options['component']);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['name'] === null) {
|
||||
// List all variables provided by the component (defaults to core).
|
||||
$got = get_config($options['component']);
|
||||
|
||||
if ($options['json']) {
|
||||
cli_writeln(json_encode($got));
|
||||
|
||||
} else {
|
||||
foreach ($got as $name => $value) {
|
||||
if ($options['shell-arg']) {
|
||||
$value = escapeshellarg($value);
|
||||
}
|
||||
cli_writeln($name."\t".$value);
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
||||
} else {
|
||||
// Display the value of a single variable.
|
||||
|
||||
$got = get_config($options['component'], $options['name']);
|
||||
|
||||
if ($got === false) {
|
||||
cli_error('No such configuration variable found.', 3);
|
||||
}
|
||||
|
||||
if ($options['shell-arg']) {
|
||||
$got = escapeshellarg($got);
|
||||
}
|
||||
|
||||
if ($options['json']) {
|
||||
$got = json_encode($got);
|
||||
}
|
||||
|
||||
if ($options['no-eol']) {
|
||||
cli_write($got);
|
||||
} else {
|
||||
cli_writeln($got);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -1,171 +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 tool for system checks
|
||||
*
|
||||
* @package core
|
||||
* @category check
|
||||
* @copyright 2020 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');
|
||||
|
||||
use core\check\result;
|
||||
|
||||
list($options, $unrecognized) = cli_get_params([
|
||||
'help' => false,
|
||||
'filter' => '',
|
||||
'type' => 'status',
|
||||
'verbose' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'f' => 'filter',
|
||||
'v' => 'verbose',
|
||||
't' => 'type',
|
||||
]);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
$checks = \core\check\manager::get_checks($options['type']);
|
||||
$types = join(', ', \core\check\manager::TYPES);
|
||||
|
||||
$help = "Run Moodle system checks
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
-f, --filter Filter to a subset of checks
|
||||
-t, --type Which set of checks? Defaults to 'status'
|
||||
One of $types
|
||||
-v, --verbose Show details of all checks, not just failed checks
|
||||
|
||||
Example:
|
||||
|
||||
sudo -u www-data php admin/cli/checks.php
|
||||
sudo -u www-data php admin/cli/checks.php -v
|
||||
sudo -u www-data php admin/cli/checks.php -v --filter=environment
|
||||
|
||||
";
|
||||
|
||||
if ($options['help']) {
|
||||
echo $help;
|
||||
die();
|
||||
}
|
||||
|
||||
$filter = $options['filter'];
|
||||
if ($filter) {
|
||||
$checks = array_filter($checks, function($check, $key) use ($filter) {
|
||||
$ref = $check->get_ref();
|
||||
return (strpos($ref, $filter) !== false);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
// These shell exit codes and labels align with the NRPE standard.
|
||||
$exitcodes = [
|
||||
result::NA => 0,
|
||||
result::OK => 0,
|
||||
result::INFO => 0,
|
||||
result::UNKNOWN => 3,
|
||||
result::WARNING => 1,
|
||||
result::ERROR => 2,
|
||||
result::CRITICAL => 2,
|
||||
];
|
||||
$exitlabel = [
|
||||
result::NA => 'OK',
|
||||
result::OK => 'OK',
|
||||
result::INFO => 'OK',
|
||||
result::UNKNOWN => 'UNKNOWN',
|
||||
result::WARNING => 'WARNING',
|
||||
result::ERROR => 'CRITICAL',
|
||||
result::CRITICAL => 'CRITICAL',
|
||||
];
|
||||
|
||||
$format = "% 10s| % -60s\n";
|
||||
$spacer = "----------+--------------------------------------------------------------------\n";
|
||||
$prefix = ' |';
|
||||
|
||||
$output = '';
|
||||
$header = $exitlabel[result::OK] . ': ' . get_string('checksok', '', $options['type']) . "\n";
|
||||
$exitcode = $exitcodes[result::OK];
|
||||
|
||||
foreach ($checks as $check) {
|
||||
$ref = $check->get_ref();
|
||||
$result = $check->get_result();
|
||||
|
||||
$status = $result->get_status();
|
||||
$checkexitcode = $exitcodes[$status];
|
||||
|
||||
// Summary is treated as html.
|
||||
$summary = $result->get_summary();
|
||||
$summary = html_to_text($summary, 60, false);
|
||||
|
||||
if ($checkexitcode > $exitcode) {
|
||||
$exitcode = $checkexitcode;
|
||||
$header = $exitlabel[$status] . ': ' . $check->get_name() . " (" . $check->get_ref() . ")\n";
|
||||
}
|
||||
|
||||
if (empty($messages[$status])) {
|
||||
$messages[$status] = $result;
|
||||
}
|
||||
|
||||
$len = strlen(get_string('status' . $status));
|
||||
|
||||
if ($options['verbose'] ||
|
||||
$status == result::WARNING ||
|
||||
$status == result::CRITICAL ||
|
||||
$status == result::ERROR) {
|
||||
|
||||
$output .= sprintf(
|
||||
$format,
|
||||
$OUTPUT->check_result($result),
|
||||
sprintf('%s (%s)', $check->get_name(), $ref)
|
||||
);
|
||||
|
||||
$summary = str_replace("\n", "\n" . $prefix . ' ', $summary);
|
||||
$output .= sprintf( $format, '', ' ' . $summary);
|
||||
|
||||
if ($options['verbose']) {
|
||||
$actionlink = $check->get_action_link();
|
||||
if ($actionlink) {
|
||||
$output .= sprintf( $format, '', ' ' . $actionlink->url);
|
||||
}
|
||||
$output .= sprintf( $format, '', '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print NRPE header.
|
||||
print $header;
|
||||
|
||||
// Only show the table header if there is anything to show.
|
||||
if ($output) {
|
||||
print sprintf($format,
|
||||
get_string('status'). ' ',
|
||||
get_string('check')
|
||||
) . $spacer;
|
||||
print $output;
|
||||
}
|
||||
|
||||
// NRPE shell exit code.
|
||||
exit($exitcode);
|
||||
|
||||
+3
-120
@@ -35,25 +35,8 @@ require_once($CFG->libdir.'/clilib.php'); // cli only functions
|
||||
require_once($CFG->libdir.'/cronlib.php');
|
||||
|
||||
// now get cli options
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'help' => false,
|
||||
'stop' => false,
|
||||
'list' => false,
|
||||
'force' => false,
|
||||
'enable' => false,
|
||||
'disable' => false,
|
||||
'disable-wait' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
's' => 'stop',
|
||||
'l' => 'list',
|
||||
'f' => 'force',
|
||||
'e' => 'enable',
|
||||
'd' => 'disable',
|
||||
'w' => 'disable-wait',
|
||||
]
|
||||
);
|
||||
list($options, $unrecognized) = cli_get_params(array('help'=>false),
|
||||
array('h'=>'help'));
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
@@ -65,13 +48,7 @@ if ($options['help']) {
|
||||
"Execute periodic cron actions.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
-s, --stop Notify all other running cron processes to stop after the current task
|
||||
-l, --list Show the list of currently running tasks and how long they have been running
|
||||
-f, --force Execute task even if cron is disabled
|
||||
-e, --enable Enable cron
|
||||
-d, --disable Disable cron
|
||||
-w, --disable-wait=600 Disable cron and wait until all tasks finished or fail after N seconds (optional param)
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/cron.php
|
||||
@@ -81,98 +58,4 @@ Example:
|
||||
die;
|
||||
}
|
||||
|
||||
if ($options['stop']) {
|
||||
// By clearing the caches this signals to other running processes
|
||||
// to exit after finishing the current task.
|
||||
\core\task\manager::clear_static_caches();
|
||||
die;
|
||||
}
|
||||
|
||||
if ($options['enable']) {
|
||||
set_config('cron_enabled', 1);
|
||||
mtrace('Cron has been enabled for the site.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['disable']) {
|
||||
set_config('cron_enabled', 0);
|
||||
\core\task\manager::clear_static_caches();
|
||||
mtrace('Cron has been disabled for the site.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['list']) {
|
||||
$tasks = \core\task\manager::get_running_tasks();
|
||||
mtrace('The list of currently running tasks:');
|
||||
$format = "%7s %-12s %-9s %-20s %-52s\n";
|
||||
printf ($format,
|
||||
'PID',
|
||||
'HOST',
|
||||
'TYPE',
|
||||
'TIME',
|
||||
'CLASSNAME'
|
||||
);
|
||||
foreach ($tasks as $task) {
|
||||
printf ($format,
|
||||
$task->pid,
|
||||
substr($task->hostname, 0, 12),
|
||||
$task->type,
|
||||
format_time(time() - $task->timestarted),
|
||||
substr($task->classname, 0, 52)
|
||||
);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($wait = $options['disable-wait']) {
|
||||
$started = time();
|
||||
if (true === $wait) {
|
||||
// Default waiting time.
|
||||
$waitsec = 600;
|
||||
} else {
|
||||
$waitsec = $wait;
|
||||
$wait = true;
|
||||
}
|
||||
|
||||
set_config('cron_enabled', 0);
|
||||
\core\task\manager::clear_static_caches();
|
||||
mtrace('Cron has been disabled for the site.');
|
||||
mtrace('Allocating '. format_time($waitsec) . ' for the tasks to finish.');
|
||||
|
||||
$lastcount = 0;
|
||||
while ($wait) {
|
||||
$tasks = \core\task\manager::get_running_tasks();
|
||||
|
||||
if (count($tasks) == 0) {
|
||||
mtrace('');
|
||||
mtrace('All scheduled and adhoc tasks finished.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (time() - $started >= $waitsec) {
|
||||
mtrace('');
|
||||
mtrace('Wait time ('. format_time($waitsec) . ') elapsed, but ' . count($tasks) . ' task(s) still running.');
|
||||
mtrace('Exiting with code 1.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (count($tasks) !== $lastcount) {
|
||||
mtrace('');
|
||||
mtrace(count($tasks) . " tasks currently running.", '');
|
||||
$lastcount = count($tasks);
|
||||
} else {
|
||||
mtrace('.', '');
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
\core\local\cli\shutdown::script_supports_graceful_exit();
|
||||
|
||||
cron_run();
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* CLI script to reset dashboards.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2021 Brendan Heywood (brendan@catalyst-au.net)
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
require_once($CFG->dirroot.'/my/lib.php');
|
||||
|
||||
list($options, $unrecognized) = cli_get_params([
|
||||
'help' => false,
|
||||
'execute' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'e' => 'execute',
|
||||
]);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2);
|
||||
}
|
||||
|
||||
if (!$options['execute']) {
|
||||
$help = <<<EOF
|
||||
Resets Moodle dashboards for all users
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
-e, --execute Actually run the reset
|
||||
|
||||
Example:
|
||||
\$ sudo -u www-data /usr/bin/php admin/cli/dashboard_reset.php -e
|
||||
|
||||
EOF;
|
||||
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$progressbar = new progress_bar();
|
||||
$progressbar->create();
|
||||
my_reset_page_for_all_users(MY_PAGE_PRIVATE, 'my-index', $progressbar);
|
||||
|
||||
@@ -1,124 +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 delete a course.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @author Mikhail Golenkov <mikhailgolenkov@catalyst-au.net>
|
||||
* @copyright 2022 Catalyst IT
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir . '/clilib.php');
|
||||
require_once($CFG->libdir . '/cronlib.php');
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'courseid' => false,
|
||||
'help' => false,
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'disablerecyclebin' => false,
|
||||
'non-interactive' => false,
|
||||
], [
|
||||
'c' => 'courseid',
|
||||
'h' => 'help',
|
||||
]
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help'] || empty($options['courseid'])) {
|
||||
$help = <<<EOT
|
||||
CLI script to delete a course.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
--showsql Show sql queries before they are executed
|
||||
--showdebugging Show developer level debugging information
|
||||
--disablerecyclebin Skip backing up the course
|
||||
--non-interactive No interactive questions or confirmations
|
||||
-c, --courseid Course id to be deleted
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/delete_course.php --courseid=123456
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/delete_course.php --courseid=123456 --showdebugging
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/delete_course.php --courseid=123456 --disablerecyclebin
|
||||
|
||||
EOT;
|
||||
|
||||
echo $help;
|
||||
die;
|
||||
}
|
||||
|
||||
$interactive = empty($options['non-interactive']);
|
||||
|
||||
if ($options['showdebugging']) {
|
||||
mtrace('Enabling debugging...');
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if ($options['showsql']) {
|
||||
mtrace('Enabling SQL debugging...');
|
||||
$DB->set_debug(true);
|
||||
}
|
||||
|
||||
if (CLI_MAINTENANCE) {
|
||||
cli_error('CLI maintenance mode active, CLI execution suspended');
|
||||
}
|
||||
|
||||
if (moodle_needs_upgrading()) {
|
||||
cli_error('Moodle upgrade pending, CLI execution suspended');
|
||||
}
|
||||
|
||||
$course = $DB->get_record('course', array('id' => $options['courseid']));
|
||||
if (empty($course)) {
|
||||
cli_error('Course not found');
|
||||
}
|
||||
|
||||
mtrace('Deleting course id ' . $course->id);
|
||||
mtrace('Course name: ' . $course->fullname);
|
||||
mtrace('Short name: ' . $course->shortname);
|
||||
|
||||
if ($interactive) {
|
||||
mtrace('');
|
||||
$input = cli_input('Are you sure you wish to delete this course? (y/N)', 'N', ['y', 'Y', 'n', 'N']);
|
||||
if (strtolower($input) != 'y') {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if ($options['disablerecyclebin']) {
|
||||
mtrace('Disabling recycle bin...');
|
||||
$overrideconfig = ['tool_recyclebin' => ['coursebinenable' => false, 'categorybinenable' => false]];
|
||||
$CFG->forced_plugin_settings = array_merge($CFG->forced_plugin_settings, $overrideconfig);
|
||||
}
|
||||
|
||||
core_php_time_limit::raise();
|
||||
delete_course($course);
|
||||
|
||||
mtrace('Updating course count in categories...');
|
||||
fix_course_sortorder();
|
||||
|
||||
mtrace('Done!');
|
||||
@@ -73,7 +73,6 @@ foreach ($rs as $user) {
|
||||
echo "Redeleting user $user->id: $user->username ($user->email)\n";
|
||||
delete_user($user);
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
cli_heading('Deleting all leftovers');
|
||||
|
||||
|
||||
@@ -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";
|
||||
+190
-233
@@ -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.
|
||||
@@ -148,9 +146,14 @@ define('PHPUNIT_TEST', false);
|
||||
|
||||
define('IGNORE_COMPONENT_CACHE', true);
|
||||
|
||||
// Check that PHP is of a sufficient version as soon as possible.
|
||||
require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
|
||||
moodle_require_minimum_php_version();
|
||||
// Check that PHP is of a sufficient version
|
||||
if (version_compare(phpversion(), "5.6.5") < 0) {
|
||||
$phpversion = phpversion();
|
||||
// do NOT localise - lang strings would not work here and we CAN NOT move it after installib
|
||||
fwrite(STDERR, "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).\n");
|
||||
fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// set up configuration
|
||||
global $CFG;
|
||||
@@ -217,11 +220,11 @@ define('SITEID', 1);
|
||||
|
||||
//Database types
|
||||
$databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'),
|
||||
'auroramysql' => moodle_database::get_driver_instance('auroramysql', 'native'),
|
||||
'mariadb'=> moodle_database::get_driver_instance('mariadb', 'native'),
|
||||
'pgsql' => moodle_database::get_driver_instance('pgsql', 'native'),
|
||||
'oci' => moodle_database::get_driver_instance('oci', 'native'),
|
||||
'sqlsrv' => moodle_database::get_driver_instance('sqlsrv', 'native'), // MS SQL*Server PHP driver
|
||||
'mssql' => moodle_database::get_driver_instance('mssql', 'native'), // FreeTDS driver
|
||||
);
|
||||
foreach ($databases as $type=>$database) {
|
||||
if ($database->driver_installed() !== true) {
|
||||
@@ -256,8 +259,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'adminuser' => 'admin',
|
||||
'adminpass' => '',
|
||||
'adminemail' => '',
|
||||
'sitepreset' => '',
|
||||
'supportemail' => '',
|
||||
'upgradekey' => '',
|
||||
'non-interactive' => false,
|
||||
'agree-license' => false,
|
||||
@@ -271,7 +272,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
);
|
||||
|
||||
$interactive = empty($options['non-interactive']);
|
||||
$skipdatabase = $options['skip-database'];
|
||||
|
||||
// set up language
|
||||
$lang = clean_param($options['lang'], PARAM_SAFEDIR);
|
||||
@@ -280,12 +280,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));
|
||||
@@ -403,6 +397,7 @@ if ($interactive) {
|
||||
$CFG->wwwroot = $wwwroot;
|
||||
$CFG->httpswwwroot = $CFG->wwwroot;
|
||||
|
||||
|
||||
//We need dataroot before lang download
|
||||
$CFG->dataroot = $options['dataroot'];
|
||||
if ($interactive) {
|
||||
@@ -453,7 +448,6 @@ if ($interactive) {
|
||||
}
|
||||
}
|
||||
$CFG->tempdir = $CFG->dataroot.'/temp';
|
||||
$CFG->backuptempdir = $CFG->tempdir.'/backup';
|
||||
$CFG->cachedir = $CFG->dataroot.'/cache';
|
||||
$CFG->localcachedir = $CFG->dataroot.'/localcache';
|
||||
|
||||
@@ -525,105 +519,100 @@ if ($interactive) {
|
||||
$database = $databases[$CFG->dbtype];
|
||||
|
||||
|
||||
// We cannot do any validation until all DB connection data is provided.
|
||||
$hintdatabase = '';
|
||||
do {
|
||||
echo $hintdatabase;
|
||||
|
||||
// Ask for db host.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasehost', 'install'));
|
||||
if ($options['dbhost'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbhost = cli_input($prompt, $options['dbhost']);
|
||||
|
||||
// ask for db host
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasehost', 'install'));
|
||||
if ($options['dbhost'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
|
||||
} else {
|
||||
$CFG->dbhost = $options['dbhost'];
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbhost = cli_input($prompt, $options['dbhost']);
|
||||
|
||||
// Ask for db name.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasename', 'install'));
|
||||
if ($options['dbname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbname = cli_input($prompt, $options['dbname']);
|
||||
} else {
|
||||
$CFG->dbhost = $options['dbhost'];
|
||||
}
|
||||
|
||||
// ask for db name
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasename', 'install'));
|
||||
if ($options['dbname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
|
||||
} else {
|
||||
$CFG->dbname = $options['dbname'];
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbname = cli_input($prompt, $options['dbname']);
|
||||
|
||||
// Ask for db prefix.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('dbprefix', 'install'));
|
||||
//TODO: solve somehow the prefix trouble for oci.
|
||||
if ($options['prefix'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->prefix = cli_input($prompt, $options['prefix']);
|
||||
} else {
|
||||
$CFG->dbname = $options['dbname'];
|
||||
}
|
||||
|
||||
// ask for db prefix
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('dbprefix', 'install'));
|
||||
//TODO: solve somehow the prefix trouble for oci
|
||||
if ($options['prefix'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
|
||||
} else {
|
||||
$CFG->prefix = $options['prefix'];
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->prefix = cli_input($prompt, $options['prefix']);
|
||||
|
||||
// Ask for db port.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databaseport', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
|
||||
$CFG->dboptions['dbport'] = (int) cli_input($prompt, $options['dbport']);
|
||||
} else {
|
||||
$CFG->prefix = $options['prefix'];
|
||||
}
|
||||
|
||||
// ask for db port
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databaseport', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
|
||||
$CFG->dboptions['dbport'] = (int)cli_input($prompt, $options['dbport']);
|
||||
|
||||
} else {
|
||||
$CFG->dboptions['dbport'] = (int)$options['dbport'];
|
||||
}
|
||||
if ($CFG->dboptions['dbport'] <= 0) {
|
||||
$CFG->dboptions['dbport'] = '';
|
||||
}
|
||||
|
||||
// ask for db socket
|
||||
if ($CFG->ostype === 'WINDOWS') {
|
||||
$CFG->dboptions['dbsocket'] = '';
|
||||
|
||||
} else if ($interactive and empty($CFG->dboptions['dbport'])) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasesocket', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
|
||||
$CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
|
||||
|
||||
} else {
|
||||
$CFG->dboptions['dbsocket'] = $options['dbsocket'];
|
||||
}
|
||||
|
||||
// ask for db user
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databaseuser', 'install'));
|
||||
if ($options['dbuser'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
|
||||
} else {
|
||||
$CFG->dboptions['dbport'] = (int) $options['dbport'];
|
||||
}
|
||||
if ($CFG->dboptions['dbport'] <= 0) {
|
||||
$CFG->dboptions['dbport'] = '';
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbuser = cli_input($prompt, $options['dbuser']);
|
||||
|
||||
// Ask for db socket.
|
||||
if ($CFG->ostype === 'WINDOWS') {
|
||||
$CFG->dboptions['dbsocket'] = '';
|
||||
|
||||
} else if ($interactive and empty($CFG->dboptions['dbport'])) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasesocket', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
|
||||
$CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
|
||||
|
||||
} else {
|
||||
$CFG->dboptions['dbsocket'] = $options['dbsocket'];
|
||||
}
|
||||
|
||||
// Ask for db user.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databaseuser', 'install'));
|
||||
if ($options['dbuser'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
$CFG->dbuser = cli_input($prompt, $options['dbuser']);
|
||||
|
||||
} else {
|
||||
$CFG->dbuser = $options['dbuser'];
|
||||
}
|
||||
|
||||
// Ask for db password.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasepass', 'install'));
|
||||
} else {
|
||||
$CFG->dbuser = $options['dbuser'];
|
||||
}
|
||||
|
||||
// ask for db password
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('databasepass', 'install'));
|
||||
do {
|
||||
if ($options['dbpass'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbpass']);
|
||||
} else {
|
||||
@@ -631,132 +620,110 @@ do {
|
||||
}
|
||||
|
||||
$CFG->dbpass = cli_input($prompt, $options['dbpass']);
|
||||
if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation.
|
||||
$distro = distro_pre_create_db($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
|
||||
array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']),
|
||||
$distro);
|
||||
if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation
|
||||
$distro = distro_pre_create_db($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersist'=>0, 'dbport'=>$CFG->dboptions['dbport'], 'dbsocket'=>$CFG->dboptions['dbsocket']), $distro);
|
||||
}
|
||||
$hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
|
||||
array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
|
||||
$hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersist'=>0, 'dbport'=>$CFG->dboptions['dbport'], 'dbsocket'=>$CFG->dboptions['dbsocket']));
|
||||
} while ($hint_database !== '');
|
||||
|
||||
} else {
|
||||
$CFG->dbpass = $options['dbpass'];
|
||||
$hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
|
||||
array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
|
||||
if ($hintdatabase !== '') {
|
||||
cli_error(get_string('dbconnectionerror', 'install'));
|
||||
}
|
||||
} else {
|
||||
$CFG->dbpass = $options['dbpass'];
|
||||
$hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersist'=>0, 'dbport'=>$CFG->dboptions['dbport'], 'dbsocket'=>$CFG->dboptions['dbsocket']));
|
||||
if ($hint_database !== '') {
|
||||
cli_error(get_string('dbconnectionerror', 'install'));
|
||||
}
|
||||
} while ($hintdatabase !== '');
|
||||
}
|
||||
|
||||
// If --skip-database option is provided, we do not need to ask for site fullname, shortname, adminuser, adminpass, adminemail.
|
||||
// These fields will be requested during the database install part.
|
||||
if (!$skipdatabase) {
|
||||
// Ask for fullname.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('fullsitename', 'moodle'));
|
||||
// ask for fullname
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('fullsitename', 'moodle'));
|
||||
|
||||
if ($options['fullname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
|
||||
do {
|
||||
$options['fullname'] = cli_input($prompt, $options['fullname']);
|
||||
} while (empty($options['fullname']));
|
||||
if ($options['fullname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
|
||||
} else {
|
||||
if (empty($options['fullname'])) {
|
||||
$a = (object)['option' => 'fullname', 'value' => $options['fullname']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for shortname.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('shortsitename', 'moodle'));
|
||||
|
||||
if ($options['shortname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
|
||||
do {
|
||||
$options['shortname'] = cli_input($prompt, $options['shortname']);
|
||||
} while (empty($options['shortname']));
|
||||
} else {
|
||||
if (empty($options['shortname'])) {
|
||||
$a = (object)['option' => 'shortname', 'value' => $options['shortname']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for admin user name.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminusername', 'install'));
|
||||
if (!empty($options['adminuser'])) {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
do {
|
||||
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
|
||||
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
|
||||
} else {
|
||||
if ((empty($options['adminuser']) || $options['adminuser'] === 'guest')) {
|
||||
$a = (object)['option' => 'adminuser', 'value' => $options['adminuser']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for admin user password.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminpassword', 'install'));
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
do {
|
||||
$options['adminpass'] = cli_input($prompt);
|
||||
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
|
||||
}
|
||||
|
||||
do {
|
||||
$options['fullname'] = cli_input($prompt, $options['fullname']);
|
||||
} while (empty($options['fullname']));
|
||||
} else {
|
||||
if (empty($options['fullname'])) {
|
||||
$a = (object)array('option'=>'fullname', 'value'=>$options['fullname']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// ask for shortname
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('shortsitename', 'moodle'));
|
||||
|
||||
if ($options['shortname'] !== '') {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
|
||||
} else {
|
||||
if ((empty($options['adminpass']) or $options['adminpass'] === 'admin')) {
|
||||
$a = (object)['option' => 'adminpass', 'value' => $options['adminpass']];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
|
||||
// Ask for the admin email address.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminemail', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
|
||||
$options['adminemail'] = cli_input($prompt, $options['adminemail']);
|
||||
}
|
||||
|
||||
// Validate that the address provided was an e-mail address.
|
||||
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
|
||||
$a = (object)['option' => 'adminemail', 'value' => $options['adminemail']];
|
||||
do {
|
||||
$options['shortname'] = cli_input($prompt, $options['shortname']);
|
||||
} while (empty($options['shortname']));
|
||||
} else {
|
||||
if (empty($options['shortname'])) {
|
||||
$a = (object)array('option'=>'shortname', 'value'=>$options['shortname']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for 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']);
|
||||
// ask for admin user name
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminusername', 'install'));
|
||||
if (!empty($options['adminuser'])) {
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
|
||||
} else {
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
}
|
||||
|
||||
// Validate that the support email address provided is valid.
|
||||
if (!empty($options['supportemail']) && !validate_email($options['supportemail'])) {
|
||||
$a = (object)['option' => 'supportemail', 'value' => $options['supportemail']];
|
||||
do {
|
||||
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
|
||||
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
|
||||
} else {
|
||||
if (empty($options['adminuser']) or $options['adminuser'] === 'guest') {
|
||||
$a = (object)array('option'=>'adminuser', 'value'=>$options['adminuser']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// ask for admin user password
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminpassword', 'install'));
|
||||
$prompt = get_string('clitypevalue', 'admin');
|
||||
do {
|
||||
$options['adminpass'] = cli_input($prompt);
|
||||
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
|
||||
} else {
|
||||
if (empty($options['adminpass']) or $options['adminpass'] === 'admin') {
|
||||
$a = (object)array('option'=>'adminpass', 'value'=>$options['adminpass']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
}
|
||||
|
||||
// Ask for the admin email address.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('cliadminemail', 'install'));
|
||||
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
|
||||
$options['adminemail'] = cli_input($prompt);
|
||||
}
|
||||
|
||||
// Validate that the address provided was an e-mail address.
|
||||
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
|
||||
$a = (object) array('option' => 'adminemail', 'value' => $options['adminemail']);
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
|
||||
// Ask for the upgrade key.
|
||||
if ($interactive) {
|
||||
cli_separator();
|
||||
@@ -775,27 +742,23 @@ if ($options['upgradekey'] !== '') {
|
||||
$CFG->upgradekey = $options['upgradekey'];
|
||||
}
|
||||
|
||||
// The user does not also need to pass agree-license when --skip-database is provided as the user will need to accept
|
||||
// the license again in the database install part.
|
||||
if (!$skipdatabase) {
|
||||
if ($interactive) {
|
||||
if (!$options['agree-license']) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('copyrightnotice'));
|
||||
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
|
||||
echo get_string('gpl3')."\n\n";
|
||||
echo get_string('doyouagree')."\n";
|
||||
$prompt = get_string('cliyesnoprompt', 'admin');
|
||||
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
|
||||
if ($input == get_string('clianswerno', 'admin')) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$options['agree-license'] && !$skipdatabase) {
|
||||
cli_error(get_string('climustagreelicense', 'install'));
|
||||
if ($interactive) {
|
||||
if (!$options['agree-license']) {
|
||||
cli_separator();
|
||||
cli_heading(get_string('copyrightnotice'));
|
||||
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
|
||||
echo get_string('gpl3')."\n\n";
|
||||
echo get_string('doyouagree')."\n";
|
||||
$prompt = get_string('cliyesnoprompt', 'admin');
|
||||
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
|
||||
if ($input == get_string('clianswerno', 'admin')) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$options['agree-license']) {
|
||||
cli_error(get_string('climustagreelicense', 'install'));
|
||||
}
|
||||
}
|
||||
|
||||
// Finally we have all info needed for config.php
|
||||
@@ -843,14 +806,8 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
cli_error(get_string('pluginschecktodo', 'admin'));
|
||||
}
|
||||
|
||||
if (!$skipdatabase) {
|
||||
if (!$options['skip-database']) {
|
||||
install_cli_database($options, $interactive);
|
||||
// This needs to happen at the end to ensure it occurs after all caches
|
||||
// have been purged for the last time.
|
||||
// This will build a cached version of the current theme for the user
|
||||
// to immediately start browsing the site.
|
||||
require_once($CFG->libdir.'/upgradelib.php');
|
||||
upgrade_themes();
|
||||
} else {
|
||||
echo get_string('cliskipdatabase', 'install')."\n";
|
||||
}
|
||||
|
||||
@@ -56,17 +56,20 @@ 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
|
||||
--supportemail=STRING Email address for support and help.
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/install_database.php --lang=cs --adminpass=soMePass123 --agree-license
|
||||
";
|
||||
|
||||
// Check that PHP is of a sufficient version as soon as possible.
|
||||
require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
|
||||
moodle_require_minimum_php_version();
|
||||
// Check that PHP is of a sufficient version
|
||||
if (version_compare(phpversion(), "5.6.5") < 0) {
|
||||
$phpversion = phpversion();
|
||||
// do NOT localise - lang strings would not work here and we CAN NOT move it after installib
|
||||
fwrite(STDERR, "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).\n");
|
||||
fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Nothing to do if config.php does not exist
|
||||
$configfile = __DIR__.'/../../config.php';
|
||||
@@ -84,6 +87,11 @@ require_once($CFG->libdir.'/installlib.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/componentlib.class.php');
|
||||
|
||||
// make sure no tables are installed yet
|
||||
if ($DB->get_tables() ) {
|
||||
cli_error(get_string('clitablesexist', 'install'));
|
||||
}
|
||||
|
||||
$CFG->early_install_lang = true;
|
||||
get_string_manager(true);
|
||||
|
||||
@@ -98,8 +106,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'adminemail' => '',
|
||||
'fullname' => '',
|
||||
'shortname' => '',
|
||||
'summary' => '',
|
||||
'supportemail' => '',
|
||||
'agree-license' => false,
|
||||
'help' => false
|
||||
),
|
||||
@@ -108,22 +114,12 @@ 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;
|
||||
die;
|
||||
}
|
||||
|
||||
// Make sure no tables are installed yet.
|
||||
if ($DB->get_tables() ) {
|
||||
cli_error(get_string('clitablesexist', 'install'));
|
||||
}
|
||||
|
||||
if (!$options['agree-license']) {
|
||||
cli_error('You have to agree to the license. --help prints out the help'); // TODO: localize
|
||||
}
|
||||
@@ -138,15 +134,6 @@ if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
|
||||
// Validate that the supportemail provided was an e-mail address.
|
||||
if (!empty($options['supportemail']) && !validate_email($options['supportemail'])) {
|
||||
$a = (object) [
|
||||
'option' => 'supportemail',
|
||||
'value' => $options['supportemail']
|
||||
];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
|
||||
$options['lang'] = clean_param($options['lang'], PARAM_SAFEDIR);
|
||||
if (!file_exists($CFG->dirroot.'/install/lang/'.$options['lang'])) {
|
||||
$options['lang'] = 'en';
|
||||
@@ -196,12 +183,5 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
|
||||
install_cli_database($options, true);
|
||||
|
||||
// This needs to happen at the end to ensure it occurs after all caches
|
||||
// have been purged for the last time.
|
||||
// This will build a cached version of the current theme for the user
|
||||
// to immediately start browsing the site.
|
||||
require_once($CFG->libdir.'/upgradelib.php');
|
||||
upgrade_themes();
|
||||
|
||||
echo get_string('cliinstallfinished', 'install')."\n";
|
||||
exit(0); // 0 means success
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* CLI script to kill all user sessions without asking for confirmation.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2017 Alexander Bias <alexander.bias@uni-ulm.de>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(array('help' => false), array('h' => 'help'));
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2);
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
$help =
|
||||
"Kill all Moodle sessions
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/kill_all_sessions.php
|
||||
";
|
||||
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
\core\session\manager::kill_all_sessions();
|
||||
|
||||
exit(0);
|
||||
@@ -53,7 +53,7 @@ Options:
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$ sudo -u www-data /usr/bin/php admin/cli/mysql_collation.php --collation=utf8mb4_unicode_ci
|
||||
\$ sudo -u www-data /usr/bin/php admin/cli/mysql_collation.php --collation=utf8_general_ci
|
||||
";
|
||||
|
||||
if (!empty($options['collation'])) {
|
||||
@@ -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) {
|
||||
@@ -145,25 +145,12 @@ if (!empty($options['collation'])) {
|
||||
$skipped++;
|
||||
|
||||
} else {
|
||||
try {
|
||||
$DB->change_database_structure("ALTER TABLE `$table->name` CONVERT TO CHARACTER SET $charset COLLATE $collation");
|
||||
echo "CONVERTED\n";
|
||||
$converted++;
|
||||
} catch (ddl_exception $e) {
|
||||
$result = mysql_set_row_format($table->name, $charset, $collation, $engine);
|
||||
if ($result) {
|
||||
echo "CONVERTED\n";
|
||||
$converted++;
|
||||
} else {
|
||||
// We don't know what the problem is. Stop the conversion.
|
||||
cli_error("Error: Tried to convert $table->name, but there was a problem. Please check the details of this
|
||||
table and try again.");
|
||||
die();
|
||||
}
|
||||
}
|
||||
$DB->change_database_structure("ALTER TABLE $table->name DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation");
|
||||
echo "CONVERTED\n";
|
||||
$converted++;
|
||||
}
|
||||
|
||||
$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 +168,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,18 +179,18 @@ 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";
|
||||
$DB->change_database_structure($sql);
|
||||
} else {
|
||||
echo "ERROR (unknown column type: $column->type)\n";
|
||||
$errors++;
|
||||
$error++;
|
||||
continue;
|
||||
}
|
||||
echo "CONVERTED\n";
|
||||
@@ -303,26 +290,3 @@ function mysql_get_column_collations($tablename) {
|
||||
$rs->close();
|
||||
return $collations;
|
||||
}
|
||||
|
||||
function mysql_set_row_format($tablename, $charset, $collation, $engine) {
|
||||
global $DB;
|
||||
|
||||
$sql = "SELECT row_format
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE table_schema = DATABASE() AND table_name = ?";
|
||||
$rs = $DB->get_record_sql($sql, array($tablename));
|
||||
if ($rs) {
|
||||
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");
|
||||
} else {
|
||||
// Row format may not be the problem. Can not diagnose problem. Send fail reply.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -15,8 +15,6 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* CLI script to purge caches without asking for confirmation.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2011 David Mudrak <david@moodle.com>
|
||||
@@ -28,16 +26,7 @@ define('CLI_SCRIPT', true);
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
|
||||
$longoptions = [
|
||||
'help' => false,
|
||||
'muc' => false,
|
||||
'theme' => false,
|
||||
'lang' => false,
|
||||
'js' => false,
|
||||
'filter' => false,
|
||||
'other' => false
|
||||
];
|
||||
list($options, $unrecognized) = cli_get_params($longoptions, ['h' => 'help']);
|
||||
list($options, $unrecognized) = cli_get_params(array('help' => false), array('h' => 'help'));
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
@@ -45,32 +34,20 @@ if ($unrecognized) {
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
// The indentation of this string is "wrong" but this is to avoid a extra whitespace in console output.
|
||||
$help = <<<EOF
|
||||
Invalidates Moodle internal caches
|
||||
|
||||
Specific caches can be defined (alone or in combination) using arguments. If none are specified,
|
||||
all caches will be purged.
|
||||
$help =
|
||||
"Invalidates all Moodle internal caches
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
--muc Purge all MUC caches (includes lang cache)
|
||||
--theme Purge theme cache
|
||||
--lang Purge language string cache
|
||||
--js Purge JavaScript cache
|
||||
--filter Purge text filter cache
|
||||
--other Purge all file caches and other miscellaneous caches (may include MUC
|
||||
if using cachestore_file).
|
||||
|
||||
Example:
|
||||
\$ sudo -u www-data /usr/bin/php admin/cli/purge_caches.php
|
||||
|
||||
EOF;
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/purge_caches.php
|
||||
";
|
||||
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
purge_caches(array_filter($options));
|
||||
purge_all_caches();
|
||||
|
||||
exit(0);
|
||||
exit(0);
|
||||
@@ -94,7 +94,7 @@ if ($options['password'] == '' ) {
|
||||
|
||||
$errmsg = '';//prevent eclipse warning
|
||||
if (!$options['ignore-password-policy'] ) {
|
||||
if (!check_password_policy($password, $errmsg, $user)) {
|
||||
if (!check_password_policy($password, $errmsg)) {
|
||||
cli_error(html_to_text($errmsg, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This script allows to restore a course from CLI.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2020 Catalyst IT
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', 1);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir . '/clilib.php');
|
||||
require_once($CFG->dirroot . "/backup/util/includes/restore_includes.php");
|
||||
|
||||
list($options, $unrecognized) = cli_get_params([
|
||||
'file' => '',
|
||||
'categoryid' => '',
|
||||
'showdebugging' => false,
|
||||
'help' => false,
|
||||
], [
|
||||
'f' => 'file',
|
||||
'c' => 'categoryid',
|
||||
's' => 'showdebugging',
|
||||
'h' => 'help',
|
||||
]);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help'] || !($options['file']) || !($options['categoryid'])) {
|
||||
$help = <<<EOL
|
||||
Restore backup into provided category.
|
||||
|
||||
Options:
|
||||
-f, --file=STRING Path to the backup file.
|
||||
-c, --categoryid=INT ID of the category to restore too.
|
||||
-s, --showdebugging Show developer level debugging information
|
||||
-h, --help Print out this help.
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/restore_backup.php --file=/path/to/backup/file.mbz --categoryid=1\n
|
||||
EOL;
|
||||
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['showdebugging']) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if (!$admin = get_admin()) {
|
||||
throw new \moodle_exception('noadmins');
|
||||
}
|
||||
|
||||
if (!file_exists($options['file'])) {
|
||||
throw new \moodle_exception('filenotfound');
|
||||
}
|
||||
|
||||
if (!$category = $DB->get_record('course_categories', ['id' => $options['categoryid']], 'id')) {
|
||||
throw new \moodle_exception('invalidcategoryid');
|
||||
}
|
||||
|
||||
$backupdir = "restore_" . uniqid();
|
||||
$path = $CFG->tempdir . DIRECTORY_SEPARATOR . "backup" . DIRECTORY_SEPARATOR . $backupdir;
|
||||
|
||||
cli_heading(get_string('extractingbackupfileto', 'backup', $path));
|
||||
$fp = get_file_packer('application/vnd.moodle.backup');
|
||||
$fp->extract_to_pathname($options['file'], $path);
|
||||
|
||||
cli_heading(get_string('preprocessingbackupfile'));
|
||||
try {
|
||||
list($fullname, $shortname) = restore_dbops::calculate_course_names(0, get_string('restoringcourse', 'backup'),
|
||||
get_string('restoringcourseshortname', 'backup'));
|
||||
|
||||
$courseid = restore_dbops::create_new_course($fullname, $shortname, $category->id);
|
||||
|
||||
$rc = new restore_controller($backupdir, $courseid, backup::INTERACTIVE_NO,
|
||||
backup::MODE_GENERAL, $admin->id, backup::TARGET_NEW_COURSE);
|
||||
$rc->execute_precheck();
|
||||
$rc->execute_plan();
|
||||
$rc->destroy();
|
||||
} catch (Exception $e) {
|
||||
cli_heading(get_string('cleaningtempdata'));
|
||||
fulldelete($path);
|
||||
throw new \moodle_exception('generalexceptionmessage', 'error', '', $e->getMessage());
|
||||
}
|
||||
|
||||
cli_heading(get_string('restoredcourseid', 'backup', $courseid));
|
||||
exit(0);
|
||||
@@ -1,168 +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 task execution.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2014 Petr Skoda
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once("$CFG->libdir/clilib.php");
|
||||
require_once("$CFG->libdir/cronlib.php");
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'help' => false,
|
||||
'list' => false,
|
||||
'execute' => false,
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'force' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'f' => 'force',
|
||||
]
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help'] or (!$options['list'] and !$options['execute'])) {
|
||||
$help =
|
||||
"Scheduled cron tasks.
|
||||
|
||||
Options:
|
||||
--execute=\\some\\task Execute scheduled task manually
|
||||
--list List all scheduled tasks
|
||||
--showsql Show sql queries before they are executed
|
||||
--showdebugging Show developer level debugging information
|
||||
-h, --help Print out this help
|
||||
-f, --force Execute task even if cron is disabled
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
|
||||
|
||||
";
|
||||
|
||||
echo $help;
|
||||
die;
|
||||
}
|
||||
|
||||
if ($options['showdebugging'] || !empty($CFG->showcrondebugging)) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if ($options['showsql'] || !empty($CFG->showcronsql)) {
|
||||
$DB->set_debug(true);
|
||||
}
|
||||
if ($options['list']) {
|
||||
cli_heading("List of scheduled tasks ($CFG->wwwroot)");
|
||||
|
||||
$shorttime = get_string('strftimedatetimeshort');
|
||||
|
||||
$tasks = \core\task\manager::get_all_scheduled_tasks();
|
||||
echo str_pad(get_string('scheduledtasks', 'tool_task'), 50, ' ') . ' ' . str_pad(get_string('runpattern', 'tool_task'), 17, ' ')
|
||||
. ' ' . str_pad(get_string('lastruntime', 'tool_task'), 40, ' ') . get_string('nextruntime', 'tool_task') . "\n";
|
||||
foreach ($tasks as $task) {
|
||||
$class = '\\' . get_class($task);
|
||||
$schedule = $task->get_minute() . ' '
|
||||
. $task->get_hour() . ' '
|
||||
. $task->get_day() . ' '
|
||||
. $task->get_day_of_week() . ' '
|
||||
. $task->get_month() . ' '
|
||||
. $task->get_day_of_week();
|
||||
$nextrun = $task->get_next_run_time();
|
||||
$lastrun = $task->get_last_run_time();
|
||||
|
||||
$plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
|
||||
$plugindisabled = $plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled();
|
||||
|
||||
if ($plugindisabled) {
|
||||
$nextrun = get_string('plugindisabled', 'tool_task');
|
||||
} else if ($task->get_disabled()) {
|
||||
$nextrun = get_string('taskdisabled', 'tool_task');
|
||||
} else if ($nextrun > time()) {
|
||||
$nextrun = userdate($nextrun);
|
||||
} else {
|
||||
$nextrun = get_string('asap', 'tool_task');
|
||||
}
|
||||
|
||||
if ($lastrun) {
|
||||
$lastrun = userdate($lastrun);
|
||||
} else {
|
||||
$lastrun = get_string('never');
|
||||
}
|
||||
|
||||
echo str_pad($class, 50, ' ') . ' ' . str_pad($schedule, 17, ' ') .
|
||||
' ' . str_pad($lastrun, 40, ' ') . ' ' . $nextrun . "\n";
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($execute = $options['execute']) {
|
||||
if (!$task = \core\task\manager::get_scheduled_task($execute)) {
|
||||
mtrace("Task '$execute' not found");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (moodle_needs_upgrading()) {
|
||||
mtrace("Moodle upgrade pending, cannot execute tasks.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
\core\task\manager::scheduled_task_starting($task);
|
||||
|
||||
// Increase memory limit.
|
||||
raise_memory_limit(MEMORY_EXTRA);
|
||||
|
||||
// Emulate normal session - we use admin account by default.
|
||||
cron_setup_user();
|
||||
|
||||
// Execute the task.
|
||||
\core\local\cli\shutdown::script_supports_graceful_exit();
|
||||
$cronlockfactory = \core\lock\lock_config::get_lock_factory('cron');
|
||||
if (!$cronlock = $cronlockfactory->get_lock('core_cron', 10)) {
|
||||
mtrace('Cannot obtain cron lock');
|
||||
exit(129);
|
||||
}
|
||||
if (!$lock = $cronlockfactory->get_lock('\\' . get_class($task), 10)) {
|
||||
$cronlock->release();
|
||||
mtrace('Cannot obtain task lock');
|
||||
exit(130);
|
||||
}
|
||||
|
||||
$task->set_lock($lock);
|
||||
if (!$task->is_blocking()) {
|
||||
$cronlock->release();
|
||||
} else {
|
||||
$task->set_cron_lock($cronlock);
|
||||
}
|
||||
|
||||
cron_run_inner_scheduled_task($task);
|
||||
}
|
||||
@@ -38,17 +38,17 @@ if ($unrecognized) {
|
||||
}
|
||||
|
||||
// If necessary add files that should be ignored - such as in 3rd party plugins.
|
||||
$ignorelist = array();
|
||||
$blacklist = array();
|
||||
$path = $options['path'];
|
||||
if (!file_exists($path)) {
|
||||
cli_error("Invalid path $path");
|
||||
}
|
||||
|
||||
if ($options['ie9fix']) {
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $ignorelist);
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $blacklist);
|
||||
|
||||
} else if ($options['noaspectratio']) {
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $ignorelist);
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $blacklist);
|
||||
|
||||
} else {
|
||||
$help =
|
||||
@@ -153,9 +153,9 @@ function core_admin_svgtool_noaspectratio($file) {
|
||||
* @param string $base
|
||||
* @param string $sub
|
||||
* @param string $filecallback
|
||||
* @param array $ignorelist List of files to be ignored and skipped.
|
||||
* @param array $blacklist
|
||||
*/
|
||||
function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
|
||||
function core_admin_recurse_svgs($base, $sub, $filecallback, $blacklist) {
|
||||
if (is_dir("$base/$sub")) {
|
||||
$items = new DirectoryIterator("$base/$sub");
|
||||
foreach ($items as $item) {
|
||||
@@ -163,7 +163,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
|
||||
continue;
|
||||
}
|
||||
$file = $item->getFilename();
|
||||
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $ignorelist);
|
||||
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $blacklist);
|
||||
}
|
||||
unset($item);
|
||||
unset($items);
|
||||
@@ -174,7 +174,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
|
||||
return;
|
||||
}
|
||||
$file = realpath("$base/$sub");
|
||||
if (in_array($file, $ignorelist)) {
|
||||
if (in_array($file, $blacklist)) {
|
||||
return;
|
||||
}
|
||||
$filecallback($file);
|
||||
|
||||
@@ -1,183 +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 uninstall plugins.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@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->libdir . '/adminlib.php');
|
||||
|
||||
$help = "Command line tool to uninstall plugins.
|
||||
|
||||
Options:
|
||||
-h --help Print this help.
|
||||
--show-all Displays a list of all installed plugins.
|
||||
--show-contrib Displays a list of all third-party installed plugins.
|
||||
--show-missing Displays a list of plugins missing from disk.
|
||||
--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:
|
||||
|
||||
# php uninstall_plugins.php --show-all
|
||||
Prints tab-separated list of all installed plugins.
|
||||
|
||||
# php uninstall_plugins.php --show-contrib
|
||||
Prints tab-separated list of all third-party installed plugins.
|
||||
|
||||
# php uninstall_plugins.php --show-missing
|
||||
Prints tab-separated list of all missing from disk plugins.
|
||||
|
||||
# php uninstall_plugins.php --purge-missing
|
||||
A dry run of uninstalling all missing plugins.
|
||||
|
||||
# php uninstall_plugins.php --purge-missing --run
|
||||
Run uninstall of all missing plugins.
|
||||
|
||||
# php uninstall_plugins.php --plugins=mod_assign,mod_forum
|
||||
A dry run of uninstalling mod_assign and mod_forum plugins.
|
||||
|
||||
# php uninstall_plugins.php --plugins=mod_assign,mod_forum --run
|
||||
Run uninstall for mod_assign and mod_forum plugins.
|
||||
";
|
||||
|
||||
list($options, $unrecognised) = cli_get_params([
|
||||
'help' => false,
|
||||
'show-all' => false,
|
||||
'show-contrib' => false,
|
||||
'show-missing' => false,
|
||||
'purge-missing' => false,
|
||||
'plugins' => false,
|
||||
'run' => false,
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
], [
|
||||
'h' => 'help'
|
||||
]);
|
||||
|
||||
if ($unrecognised) {
|
||||
$unrecognised = implode(PHP_EOL.' ', $unrecognised);
|
||||
cli_error(get_string('cliunknowoption', 'core_admin', $unrecognised));
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
cli_writeln($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();
|
||||
|
||||
if ($options['show-all'] || $options['show-missing'] || $options['show-contrib']) {
|
||||
foreach ($plugininfo as $type => $plugins) {
|
||||
foreach ($plugins as $name => $plugin) {
|
||||
if ($options['show-contrib'] && $plugin->is_standard()) {
|
||||
continue;
|
||||
}
|
||||
$pluginstring = $plugin->component . "\t" . $plugin->displayname;
|
||||
|
||||
if ($options['show-all'] || $options['show-contrib']) {
|
||||
cli_writeln($pluginstring);
|
||||
} else {
|
||||
if ($plugin->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
cli_writeln($pluginstring);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['purge-missing']) {
|
||||
foreach ($plugininfo as $type => $plugins) {
|
||||
foreach ($plugins as $name => $plugin) {
|
||||
if ($plugin->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
|
||||
$pluginstring = $plugin->component . "\t" . $plugin->displayname;
|
||||
|
||||
if ($pluginman->can_uninstall_plugin($plugin->component)) {
|
||||
if ($options['run']) {
|
||||
cli_writeln('Uninstalling: ' . $pluginstring);
|
||||
|
||||
$progress = new progress_trace_buffer(new text_progress_trace(), true);
|
||||
$pluginman->uninstall_plugin($plugin->component, $progress);
|
||||
$progress->finished();
|
||||
cli_write($progress->get_buffer());
|
||||
} else {
|
||||
cli_writeln('Will be uninstalled: ' . $pluginstring);
|
||||
}
|
||||
} else {
|
||||
cli_writeln('Can not be uninstalled: ' . $pluginstring);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['plugins']) {
|
||||
$components = explode(',', $options['plugins']);
|
||||
foreach ($components as $component) {
|
||||
$plugin = $pluginman->get_plugin_info($component);
|
||||
|
||||
if (is_null($plugin)) {
|
||||
cli_writeln('Unknown plugin: ' . $component);
|
||||
} else {
|
||||
$pluginstring = $plugin->component . "\t" . $plugin->displayname;
|
||||
|
||||
if ($pluginman->can_uninstall_plugin($plugin->component)) {
|
||||
if ($options['run']) {
|
||||
cli_writeln('Uninstalling: ' . $pluginstring);
|
||||
$progress = new progress_trace_buffer(new text_progress_trace(), true);
|
||||
$pluginman->uninstall_plugin($plugin->component, $progress);
|
||||
$progress->finished();
|
||||
cli_write($progress->get_buffer());
|
||||
} else {
|
||||
cli_writeln('Will be uninstalled: ' . $pluginstring);
|
||||
}
|
||||
} else {
|
||||
cli_writeln('Can not be uninstalled: ' . $pluginstring);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
cli_writeln($help);
|
||||
exit(0);
|
||||
+9
-51
@@ -51,9 +51,7 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'non-interactive' => false,
|
||||
'allow-unstable' => false,
|
||||
'help' => false,
|
||||
'lang' => $lang,
|
||||
'verbose-settings' => false,
|
||||
'is-pending' => false,
|
||||
'lang' => $lang
|
||||
),
|
||||
array(
|
||||
'h' => 'help'
|
||||
@@ -86,11 +84,6 @@ Options:
|
||||
site language if not set. Defaults to 'en' if the lang
|
||||
parameter is invalid or if the language pack is not
|
||||
installed.
|
||||
--verbose-settings Show new settings values. By default only the name of
|
||||
new core or plugin settings are displayed. This option
|
||||
outputs the new values as well as the setting name.
|
||||
--is-pending If an upgrade is needed it exits with an error code of
|
||||
2 so it distinct from other types of errors.
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
@@ -119,10 +112,6 @@ if (!moodle_needs_upgrading()) {
|
||||
cli_error(get_string('cliupgradenoneed', 'core_admin', $newversion), 0);
|
||||
}
|
||||
|
||||
if ($options['is-pending']) {
|
||||
cli_error(get_string('cliupgradepending', 'core_admin'), 2);
|
||||
}
|
||||
|
||||
// Test environment first.
|
||||
list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
|
||||
if (!$envstatus) {
|
||||
@@ -135,27 +124,17 @@ 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)) {
|
||||
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
|
||||
cli_error(get_string('pluginschecktodo', 'admin'));
|
||||
}
|
||||
|
||||
$a = new stdClass();
|
||||
$a->oldversion = $oldversion;
|
||||
$a->newversion = $newversion;
|
||||
|
||||
if ($interactive) {
|
||||
$a = new stdClass();
|
||||
$a->oldversion = $oldversion;
|
||||
$a->newversion = $newversion;
|
||||
echo cli_heading(get_string('databasechecking', '', $a)) . PHP_EOL;
|
||||
}
|
||||
|
||||
@@ -204,30 +183,9 @@ upgrade_noncore(true);
|
||||
// log in as admin - we need doanything permission when applying defaults
|
||||
\core\session\manager::set_user(get_admin());
|
||||
|
||||
// Apply default settings and output those that have changed.
|
||||
cli_heading(get_string('cliupgradedefaultheading', 'admin'));
|
||||
$settingsoutput = admin_apply_default_settings(null, false);
|
||||
// apply all default settings, just in case do it twice to fill all defaults
|
||||
admin_apply_default_settings(NULL, false);
|
||||
admin_apply_default_settings(NULL, false);
|
||||
|
||||
foreach ($settingsoutput as $setting => $value) {
|
||||
|
||||
if ($options['verbose-settings']) {
|
||||
$stringvlaues = array(
|
||||
'name' => $setting,
|
||||
'defaultsetting' => var_export($value, true) // Expand objects.
|
||||
);
|
||||
echo get_string('cliupgradedefaultverbose', 'admin', $stringvlaues) . PHP_EOL;
|
||||
|
||||
} else {
|
||||
echo get_string('cliupgradedefault', 'admin', $setting) . PHP_EOL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// This needs to happen at the end to ensure it occurs after all caches
|
||||
// have been purged for the last time.
|
||||
// This will build a cached version of the current theme for the user
|
||||
// to immediately start browsing the site.
|
||||
upgrade_themes();
|
||||
|
||||
echo get_string('cliupgradefinished', 'admin', $a)."\n";
|
||||
echo get_string('cliupgradefinished', 'admin')."\n";
|
||||
exit(0); // 0 means success
|
||||
|
||||
@@ -1,87 +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/>.
|
||||
|
||||
/**
|
||||
* Content bank and its plugins settings.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage contentbank
|
||||
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$name = required_param('name', PARAM_PLUGIN);
|
||||
|
||||
$syscontext = context_system::instance();
|
||||
$PAGE->set_url('/admin/contentbank.php');
|
||||
$PAGE->set_context($syscontext);
|
||||
|
||||
require_admin();
|
||||
require_sesskey();
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section' => 'managecontentbanktypes'));
|
||||
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('contenttype');
|
||||
$sortorder = array_flip(array_keys($plugins));
|
||||
|
||||
if (!isset($plugins[$name])) {
|
||||
throw new \moodle_exception('contenttypenotfound', 'error', $return, $name);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
if ($plugins[$name]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('contenttype');
|
||||
$class::enable_plugin($name, false);
|
||||
}
|
||||
break;
|
||||
case 'enable':
|
||||
if (!$plugins[$name]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('contenttype');
|
||||
$class::enable_plugin($name, true);
|
||||
}
|
||||
break;
|
||||
case 'up':
|
||||
if ($sortorder[$name]) {
|
||||
$currentindex = $sortorder[$name];
|
||||
$seq = array_keys($plugins);
|
||||
$seq[$currentindex] = $seq[$currentindex - 1];
|
||||
$seq[$currentindex - 1] = $name;
|
||||
set_config('contentbank_plugins_sortorder', implode(',', $seq));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
case 'down':
|
||||
if ($sortorder[$name] < count($sortorder) - 1) {
|
||||
$currentindex = $sortorder[$name];
|
||||
$seq = array_keys($plugins);
|
||||
$seq[$currentindex] = $seq[$currentindex + 1];
|
||||
$seq[$currentindex + 1] = $name;
|
||||
set_config('contentbank_plugins_sortorder', implode(',', $seq));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
break;
|
||||
}
|
||||
$cache = cache::make('core', 'contentbank_enabled_extensions');
|
||||
$cache->purge();
|
||||
$cache = cache::make('core', 'contentbank_context_extensions');
|
||||
$cache->purge();
|
||||
|
||||
redirect($return);
|
||||
@@ -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();
|
||||
+10
-6
@@ -32,7 +32,8 @@ $syscontext = context_system::instance();
|
||||
$PAGE->set_url('/admin/courseformats.php');
|
||||
$PAGE->set_context($syscontext);
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', $syscontext);
|
||||
require_sesskey();
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section' => 'manageformats'));
|
||||
@@ -41,20 +42,23 @@ $formatplugins = core_plugin_manager::instance()->get_plugins_of_type('format');
|
||||
$sortorder = array_flip(array_keys($formatplugins));
|
||||
|
||||
if (!isset($formatplugins[$formatname])) {
|
||||
throw new \moodle_exception('courseformatnotfound', 'error', $return, $formatname);
|
||||
print_error('courseformatnotfound', 'error', $return, $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':
|
||||
|
||||
+2
-2
@@ -58,7 +58,7 @@ require_once($CFG->libdir.'/cronlib.php');
|
||||
// check if execution allowed
|
||||
if (!empty($CFG->cronclionly)) {
|
||||
// This script can only be run via the cli.
|
||||
throw new \moodle_exception('cronerrorclionly', 'admin');
|
||||
print_error('cronerrorclionly', 'admin');
|
||||
exit;
|
||||
}
|
||||
// This script is being called via the web, so check the password if there is one.
|
||||
@@ -66,7 +66,7 @@ if (!empty($CFG->cronremotepassword)) {
|
||||
$pass = optional_param('password', '', PARAM_RAW);
|
||||
if ($pass != $CFG->cronremotepassword) {
|
||||
// wrong password.
|
||||
throw new \moodle_exception('cronerrorpassword', 'admin');
|
||||
print_error('cronerrorpassword', 'admin');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Allows the admin to enable, disable and uninstall custom fields
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2018 Daniel Neis Araujo
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$customfieldname = required_param('field', PARAM_PLUGIN);
|
||||
|
||||
$syscontext = context_system::instance();
|
||||
$PAGE->set_url('/admin/customfields.php');
|
||||
$PAGE->set_context($syscontext);
|
||||
|
||||
require_admin();
|
||||
require_sesskey();
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section' => 'managecustomfields'));
|
||||
|
||||
$customfieldplugins = core_plugin_manager::instance()->get_plugins_of_type('customfield');
|
||||
$sortorder = array_flip(array_keys($customfieldplugins));
|
||||
|
||||
if (!isset($customfieldplugins[$customfieldname])) {
|
||||
throw new \moodle_exception('customfieldnotfound', 'error', $return, $customfieldname);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
if ($customfieldplugins[$customfieldname]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('customfield');
|
||||
$class::enable_plugin($customfieldname, false);
|
||||
}
|
||||
break;
|
||||
case 'enable':
|
||||
if (!$customfieldplugins[$customfieldname]->is_enabled()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('customfield');
|
||||
$class::enable_plugin($customfieldname, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
redirect($return);
|
||||
@@ -33,7 +33,8 @@ $syscontext = context_system::instance();
|
||||
$PAGE->set_url('/admin/dataformats.php');
|
||||
$PAGE->set_context($syscontext);
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', $syscontext);
|
||||
require_sesskey();
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section' => 'managedataformats'));
|
||||
@@ -42,20 +43,20 @@ $plugins = core_plugin_manager::instance()->get_plugins_of_type('dataformat');
|
||||
$sortorder = array_flip(array_keys($plugins));
|
||||
|
||||
if (!isset($plugins[$name])) {
|
||||
throw new \moodle_exception('courseformatnotfound', 'error', $return, $name);
|
||||
print_error('courseformatnotfound', 'error', $return, $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 +79,4 @@ switch ($action) {
|
||||
break;
|
||||
}
|
||||
redirect($return);
|
||||
|
||||
|
||||
+19
-11
@@ -15,7 +15,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$PAGE->set_url('/admin/editors.php', array('action'=>$action, 'editor'=>$editor));
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageeditors";
|
||||
|
||||
@@ -39,19 +40,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 +69,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 +83,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 +91,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);
|
||||
}
|
||||
|
||||
+14
-6
@@ -35,7 +35,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$PAGE->set_url('/admin/enrol.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
require_sesskey();
|
||||
|
||||
$enabled = enrol_get_plugins(true);
|
||||
@@ -43,18 +44,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 +130,4 @@ switch ($action) {
|
||||
}
|
||||
|
||||
|
||||
redirect($return);
|
||||
redirect($return);
|
||||
@@ -55,11 +55,11 @@ if ($action == 'updatecomponent' && confirm_sesskey()) {
|
||||
$a = new stdClass();
|
||||
$a->url = 'https://download.moodle.org/environment/environment.zip';
|
||||
$a->dest = $CFG->dataroot . '/';
|
||||
throw new \moodle_exception($cd->get_error(), 'error', $PAGE->url, $a);
|
||||
print_error($cd->get_error(), 'error', $PAGE->url, $a);
|
||||
die();
|
||||
|
||||
} else {
|
||||
throw new \moodle_exception($cd->get_error(), 'error', $PAGE->url);
|
||||
print_error($cd->get_error(), 'error', $PAGE->url);
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+38
-44
@@ -28,18 +28,21 @@ require_once($CFG->libdir . '/adminlib.php');
|
||||
$action = optional_param('action', '', PARAM_ALPHA);
|
||||
$filterpath = optional_param('filterpath', '', PARAM_PLUGIN);
|
||||
|
||||
require_login();
|
||||
$systemcontext = context_system::instance();
|
||||
require_capability('moodle/site:config', $systemcontext);
|
||||
|
||||
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 +54,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 +76,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 +87,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 +100,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 +119,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 +161,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 +182,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,22 +213,20 @@ 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.
|
||||
$updown = '';
|
||||
$spacer = $OUTPUT->spacer();
|
||||
$spacer = '<img src="' . $OUTPUT->pix_url('spacer') . '" class="iconsmall" alt="" />';
|
||||
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 +234,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;
|
||||
}
|
||||
|
||||
+36
-107
@@ -29,9 +29,14 @@ if (!file_exists('../config.php')) {
|
||||
die();
|
||||
}
|
||||
|
||||
// Check that PHP is of a sufficient version as soon as possible.
|
||||
require_once(__DIR__.'/../lib/phpminimumversionlib.php');
|
||||
moodle_require_minimum_php_version();
|
||||
// Check that PHP is of a sufficient version as soon as possible
|
||||
if (version_compare(phpversion(), '5.6.5') < 0) {
|
||||
$phpversion = phpversion();
|
||||
// do NOT localise - lang strings would not work here and we CAN NOT move it to later place
|
||||
echo "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).<br />";
|
||||
echo "Please upgrade your server software or install older Moodle version.";
|
||||
die();
|
||||
}
|
||||
|
||||
// make sure iconv is available and actually works
|
||||
if (!function_exists('iconv')) {
|
||||
@@ -53,12 +58,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'])) {
|
||||
@@ -102,12 +101,6 @@ if (function_exists('opcache_invalidate')) {
|
||||
// indirectly calls the protected init() method is good here.
|
||||
core_component::get_core_subsystems();
|
||||
|
||||
if (is_major_upgrade_required() && isloggedin()) {
|
||||
// A major upgrade is required.
|
||||
// Terminate the session and redirect back here before anything DB-related happens.
|
||||
redirect_if_major_upgrade_required();
|
||||
}
|
||||
|
||||
require_once($CFG->libdir.'/adminlib.php'); // various admin-only functions
|
||||
require_once($CFG->libdir.'/upgradelib.php'); // general upgrade/install related functions
|
||||
|
||||
@@ -174,17 +167,15 @@ $documentationlink = '<a href="http://docs.moodle.org/en/Installation">Installat
|
||||
// Check some PHP server settings
|
||||
|
||||
if (ini_get_bool('session.auto_start')) {
|
||||
throw new \moodle_exception('phpvaroff', 'debug', '',
|
||||
(object)array('name' => 'session.auto_start', 'link' => $documentationlink));
|
||||
print_error('phpvaroff', 'debug', '', (object)array('name'=>'session.auto_start', 'link'=>$documentationlink));
|
||||
}
|
||||
|
||||
if (!ini_get_bool('file_uploads')) {
|
||||
throw new \moodle_exception('phpvaron', 'debug', '',
|
||||
(object)array('name' => 'file_uploads', 'link' => $documentationlink));
|
||||
print_error('phpvaron', 'debug', '', (object)array('name'=>'file_uploads', 'link'=>$documentationlink));
|
||||
}
|
||||
|
||||
if (is_float_problem()) {
|
||||
throw new \moodle_exception('phpfloatproblem', 'admin', '', $documentationlink);
|
||||
print_error('phpfloatproblem', 'admin', '', $documentationlink);
|
||||
}
|
||||
|
||||
// Set some necessary variables during set-up to avoid PHP warnings later on this page
|
||||
@@ -205,7 +196,7 @@ require("$CFG->dirroot/version.php"); // defines $version, $release, $bran
|
||||
$CFG->target_release = $release; // used during installation and upgrades
|
||||
|
||||
if (!$version or !$release) {
|
||||
throw new \moodle_exception('withoutversion', 'debug'); // Without version, stop.
|
||||
print_error('withoutversion', 'debug'); // without version, stop
|
||||
}
|
||||
|
||||
if (!core_tables_exist()) {
|
||||
@@ -224,7 +215,7 @@ if (!core_tables_exist()) {
|
||||
$strlicense = get_string('license');
|
||||
|
||||
$PAGE->navbar->add($strlicense);
|
||||
$PAGE->set_title($strinstallation . moodle_page::TITLE_SEPARATOR . 'Moodle ' . $CFG->target_release, false);
|
||||
$PAGE->set_title($strinstallation.' - Moodle '.$CFG->target_release);
|
||||
$PAGE->set_heading($strinstallation);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
@@ -234,7 +225,7 @@ if (!core_tables_exist()) {
|
||||
}
|
||||
if (empty($confirmrelease)) {
|
||||
require_once($CFG->libdir.'/environmentlib.php');
|
||||
list($envstatus, $environmentresults) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
|
||||
list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
|
||||
$strcurrentrelease = get_string('currentrelease');
|
||||
|
||||
$PAGE->navbar->add($strcurrentrelease);
|
||||
@@ -243,13 +234,13 @@ if (!core_tables_exist()) {
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
echo $output->install_environment_page($maturity, $envstatus, $environmentresults, $release);
|
||||
echo $output->install_environment_page($maturity, $envstatus, $environment_results, $release);
|
||||
die();
|
||||
}
|
||||
|
||||
// check plugin dependencies
|
||||
$failed = array();
|
||||
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
|
||||
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
$PAGE->navbar->add(get_string('pluginscheck', 'admin'));
|
||||
$PAGE->set_title($strinstallation);
|
||||
$PAGE->set_heading($strinstallation . ' - Moodle ' . $CFG->target_release);
|
||||
@@ -267,7 +258,7 @@ if (!core_tables_exist()) {
|
||||
upgrade_init_javascript();
|
||||
|
||||
$PAGE->navbar->add($strdatabasesetup);
|
||||
$PAGE->set_title($strinstallation . moodle_page::TITLE_SEPARATOR . $CFG->target_release, false);
|
||||
$PAGE->set_title($strinstallation.' - Moodle '.$CFG->target_release);
|
||||
$PAGE->set_heading($strinstallation);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
@@ -277,7 +268,7 @@ if (!core_tables_exist()) {
|
||||
if (!$DB->setup_is_unicodedb()) {
|
||||
if (!$DB->change_db_encoding()) {
|
||||
// If could not convert successfully, throw error, and prevent installation
|
||||
throw new \moodle_exception('unicoderequired', 'admin');
|
||||
print_error('unicoderequired', 'admin');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +290,7 @@ $stradministration = get_string('administration');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
if (empty($CFG->version)) {
|
||||
throw new \moodle_exception('missingconfigversion', 'debug');
|
||||
print_error('missingconfigversion', 'debug');
|
||||
}
|
||||
|
||||
// Detect config cache inconsistency, this happens when you switch branches on dev servers.
|
||||
@@ -366,9 +357,9 @@ if (!$cache and $version > $CFG->version) { // upgrade
|
||||
echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite);
|
||||
die();
|
||||
|
||||
} else if (empty($confirmrelease)) {
|
||||
} else if (empty($confirmrelease)){
|
||||
require_once($CFG->libdir.'/environmentlib.php');
|
||||
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
|
||||
list($envstatus, $environment_results) = check_moodle_environment($release, ENV_SELECT_RELEASE);
|
||||
$strcurrentrelease = get_string('currentrelease');
|
||||
|
||||
$PAGE->navbar->add($strcurrentrelease);
|
||||
@@ -376,7 +367,7 @@ if (!$cache and $version > $CFG->version) { // upgrade
|
||||
$PAGE->set_heading($strcurrentrelease);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
|
||||
echo $output->upgrade_environment_page($release, $envstatus, $environment_results);
|
||||
die();
|
||||
|
||||
} else if (empty($confirmplugins)) {
|
||||
@@ -516,9 +507,8 @@ if (!$cache and $version > $CFG->version) { // upgrade
|
||||
} else {
|
||||
// Always verify plugin dependencies!
|
||||
$failed = array();
|
||||
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
|
||||
array('confirmplugincheck' => 0)));
|
||||
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
|
||||
die();
|
||||
}
|
||||
unset($failed);
|
||||
@@ -542,10 +532,7 @@ if (!$cache and $branch <> $CFG->branch) { // Update the branch
|
||||
|
||||
if (!$cache and moodle_needs_upgrading()) {
|
||||
|
||||
$PAGE->set_url(new moodle_url($PAGE->url, array(
|
||||
'confirmrelease' => $confirmrelease,
|
||||
'confirmplugincheck' => $confirmplugins,
|
||||
)));
|
||||
$PAGE->set_url(new moodle_url($PAGE->url, array('confirmplugincheck' => $confirmplugins)));
|
||||
|
||||
check_upgrade_key($upgradekeyhash);
|
||||
|
||||
@@ -555,21 +542,7 @@ if (!$cache and moodle_needs_upgrading()) {
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
|
||||
if (empty($confirmrelease)) {
|
||||
require_once($CFG->libdir . '/environmentlib.php');
|
||||
|
||||
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
|
||||
$strcurrentrelease = get_string('currentrelease');
|
||||
|
||||
$PAGE->navbar->add($strcurrentrelease);
|
||||
$PAGE->set_title($strcurrentrelease);
|
||||
$PAGE->set_heading($strcurrentrelease);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
|
||||
die();
|
||||
|
||||
} else if (!$confirmplugins) {
|
||||
if (!$confirmplugins) {
|
||||
$strplugincheck = get_string('plugincheck');
|
||||
|
||||
$PAGE->navbar->add($strplugincheck);
|
||||
@@ -708,10 +681,9 @@ if (!$cache and moodle_needs_upgrading()) {
|
||||
|
||||
// Make sure plugin dependencies are always checked.
|
||||
$failed = array();
|
||||
if (!$pluginman->all_plugins_ok($version, $failed, $CFG->branch)) {
|
||||
if (!$pluginman->all_plugins_ok($version, $failed)) {
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
|
||||
array('confirmplugincheck' => 0)));
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
|
||||
die();
|
||||
}
|
||||
unset($failed);
|
||||
@@ -726,13 +698,6 @@ if (!$cache and moodle_needs_upgrading()) {
|
||||
if (during_initial_install()) {
|
||||
set_config('rolesactive', 1); // after this, during_initial_install will return false.
|
||||
set_config('adminsetuppending', 1);
|
||||
set_config('registrationpending', 1); // Remind to register site after all other setup is finished.
|
||||
|
||||
// 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");
|
||||
}
|
||||
@@ -750,7 +715,7 @@ if (during_initial_install()) {
|
||||
redirect("index.php?sessionstarted=1&sessionverify=1&lang=$CFG->lang");
|
||||
} else {
|
||||
if (empty($SESSION->sessionverify)) {
|
||||
throw new \moodle_exception('installsessionerror', 'admin', "index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
print_error('installsessionerror', 'admin', "index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
}
|
||||
unset($SESSION->sessionverify);
|
||||
}
|
||||
@@ -767,7 +732,7 @@ if (during_initial_install()) {
|
||||
if ($adminuser->password === 'adminsetuppending') {
|
||||
// prevent installation hijacking
|
||||
if ($adminuser->lastip !== getremoteaddr()) {
|
||||
throw new \moodle_exception('installhijacked', 'admin');
|
||||
print_error('installhijacked', 'admin');
|
||||
}
|
||||
// login user and let him set password and admin details
|
||||
$adminuser->newadminuser = 1;
|
||||
@@ -811,7 +776,7 @@ $context = context_system::instance();
|
||||
|
||||
if (!has_capability('moodle/site:config', $context)) {
|
||||
// Do not throw exception display an empty page with administration menu if visible for current user.
|
||||
$PAGE->set_title(get_string('home'));
|
||||
$PAGE->set_title($SITE->fullname);
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->footer();
|
||||
@@ -833,10 +798,9 @@ $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)) {
|
||||
if (any_new_admin_settings($adminroot)){
|
||||
redirect('upgradesettings.php');
|
||||
}
|
||||
|
||||
@@ -849,20 +813,14 @@ if (isset($SESSION->pluginuninstallreturn)) {
|
||||
}
|
||||
}
|
||||
|
||||
// If site registration needs updating, redirect.
|
||||
\core\hub\registration::registration_reminder('/admin/index.php');
|
||||
|
||||
// Everything should now be set up, and the user is an admin
|
||||
|
||||
// Print default admin page with notifications.
|
||||
$errorsdisplayed = defined('WARN_DISPLAY_ERRORS_ENABLED');
|
||||
|
||||
$lastcron = get_config('tool_task', 'lastcronstart');
|
||||
// We make the assumption that at least one schedule task should run once per day.
|
||||
$lastcron = $DB->get_field_sql('SELECT MAX(lastruntime) FROM {task_scheduled}');
|
||||
$cronoverdue = ($lastcron < time() - 3600 * 24);
|
||||
$lastcroninterval = get_config('tool_task', 'lastcroninterval');
|
||||
|
||||
$expectedfrequency = $CFG->expectedcronfrequency ?? MINSECS;
|
||||
$croninfrequent = !$cronoverdue && ($lastcroninterval > ($expectedfrequency + MINSECS) || $lastcron < time() - $expectedfrequency);
|
||||
$dbproblems = $DB->diagnose();
|
||||
$maintenancemode = !empty($CFG->maintenance_enabled);
|
||||
|
||||
@@ -898,38 +856,12 @@ if ($updateschecker->enabled()) {
|
||||
|
||||
$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
|
||||
//check if the site is registered on Moodle.org
|
||||
$registered = \core\hub\registration::is_registered();
|
||||
$registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
|
||||
// Check if there are any cache warnings.
|
||||
$cachewarnings = cache_helper::warnings();
|
||||
// Check if there are events 1 API handlers.
|
||||
$eventshandlers = $DB->get_records_sql('SELECT DISTINCT component FROM {events_handlers}');
|
||||
$themedesignermode = !empty($CFG->themedesignermode);
|
||||
$mobileconfigured = !empty($CFG->enablemobilewebservice);
|
||||
$invalidforgottenpasswordurl = !empty($CFG->forgottenpasswordurl) && empty(clean_param($CFG->forgottenpasswordurl, PARAM_URL));
|
||||
|
||||
// Check if a directory with development libraries exists.
|
||||
if (empty($CFG->disabledevlibdirscheck) && (is_dir($CFG->dirroot.'/vendor') || is_dir($CFG->dirroot.'/node_modules'))) {
|
||||
$devlibdir = true;
|
||||
} else {
|
||||
$devlibdir = false;
|
||||
}
|
||||
// Check if the site is being foced onto ssl.
|
||||
$overridetossl = !empty($CFG->overridetossl);
|
||||
|
||||
// Check if moodle campaign content setting is enabled or not.
|
||||
$showcampaigncontent = !isset($CFG->showcampaigncontent) || $CFG->showcampaigncontent;
|
||||
|
||||
// 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');
|
||||
|
||||
@@ -937,7 +869,4 @@ $output = $PAGE->get_renderer('core', 'admin');
|
||||
|
||||
echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed, $cronoverdue, $dbproblems,
|
||||
$maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
|
||||
$registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir,
|
||||
$mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent,
|
||||
$showcampaigncontent, $showfeedbackencouragement, $servicesandsupportcontent,
|
||||
$xmlrpcwarning);
|
||||
$registered, $cachewarnings, $eventshandlers, $themedesignermode);
|
||||
|
||||
+9
-5
@@ -55,7 +55,7 @@ function admin_page_type_list($pagetype, $parentcontext, $currentcontext) {
|
||||
function core_admin_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
|
||||
global $CFG;
|
||||
|
||||
if (in_array($filearea, ['logo', 'logocompact', 'favicon'])) {
|
||||
if (in_array($filearea, ['logo', 'logocompact'])) {
|
||||
$size = array_shift($args); // The path hides the size.
|
||||
$itemid = clean_param(array_shift($args), PARAM_INT);
|
||||
$filename = clean_param(array_shift($args), PARAM_FILE);
|
||||
@@ -96,16 +96,20 @@ function core_admin_pluginfile($course, $cm, $context, $filearea, $args, $forced
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
// Check whether width/height are specified, and we can resize the image (some types such as ICO cannot be resized).
|
||||
if (($maxwidth === 0 && $maxheight === 0) ||
|
||||
!$filedata = $file->resize_image($maxwidth, $maxheight)) {
|
||||
|
||||
// No need for resizing, but if the file should be cached we save it so we can serve it fast next time.
|
||||
if (empty($maxwidth) && empty($maxheight)) {
|
||||
if ($lifetime) {
|
||||
file_safe_save_content($file->get_content(), $candidate);
|
||||
}
|
||||
send_stored_file($file, $lifetime, 0, false, $options);
|
||||
}
|
||||
|
||||
// Proceed with the resizing.
|
||||
$filedata = $file->resize_image($maxwidth, $maxheight);
|
||||
if (!$filedata) {
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
// If we don't want to cached the file, serve now and quit.
|
||||
if (!$lifetime) {
|
||||
send_content_uncached($filedata, $filename);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Allows admin to configure licenses.
|
||||
*/
|
||||
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/licenselib.php');
|
||||
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=managelicenses";
|
||||
|
||||
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
|
||||
$license = optional_param('license', '', PARAM_SAFEDIR);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// process actions
|
||||
|
||||
if (!confirm_sesskey()) {
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
$return = true;
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
license_manager::disable($license);
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
license_manager::enable($license);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ($return) {
|
||||
redirect ($returnurl);
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
* Displays the list of found local plugins, their version (if found) and
|
||||
* a link to delete the local plugin.
|
||||
*
|
||||
* @see https://moodledev.io/docs/apis/plugintypes/local
|
||||
* @see http://docs.moodle.org/dev/Local_customisation
|
||||
* @package admin
|
||||
* @copyright 2010 David Mudrak <david.mudrak@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file is used to display a categories sub categories, external pages, and settings.
|
||||
*
|
||||
* @package admin
|
||||
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../config.php');
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
|
||||
$contextid = required_param('id', PARAM_INT);
|
||||
$confirm = optional_param('confirm', null, PARAM_INT);
|
||||
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
|
||||
|
||||
$PAGE->set_url('/admin/lock.php', ['id' => $contextid]);
|
||||
|
||||
list($context, $course, $cm) = get_context_info_array($contextid);
|
||||
|
||||
$parentcontext = $context->get_parent_context();
|
||||
if ($parentcontext && !empty($parentcontext->locked)) {
|
||||
// Can't make changes to a context whose parent is locked.
|
||||
throw new \coding_exception('Not sure how you got here');
|
||||
}
|
||||
|
||||
if ($course) {
|
||||
$isfrontpage = ($course->id == SITEID);
|
||||
} else {
|
||||
$isfrontpage = false;
|
||||
$course = $SITE;
|
||||
}
|
||||
|
||||
require_login($course, false, $cm);
|
||||
require_capability('moodle/site:managecontextlocks', $context);
|
||||
|
||||
$PAGE->set_pagelayout('admin');
|
||||
$PAGE->navigation->clear_cache();
|
||||
|
||||
$a = (object) [
|
||||
'contextname' => $context->get_context_name(),
|
||||
];
|
||||
|
||||
if (null !== $confirm && confirm_sesskey()) {
|
||||
$context->set_locked(!empty($confirm));
|
||||
|
||||
if ($context->locked) {
|
||||
$lockmessage = get_string('managecontextlocklocked', 'admin', $a);
|
||||
} else {
|
||||
$lockmessage = get_string('managecontextlockunlocked', 'admin', $a);
|
||||
}
|
||||
|
||||
if (empty($returnurl)) {
|
||||
$returnurl = $context->get_url();
|
||||
} else {
|
||||
$returnurl = new moodle_url($returnurl);
|
||||
}
|
||||
redirect($returnurl, $lockmessage);
|
||||
}
|
||||
|
||||
$heading = get_string('managecontextlock', 'admin');
|
||||
$PAGE->set_title($heading);
|
||||
$PAGE->set_heading($heading);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
if ($context->locked) {
|
||||
$confirmstring = get_string('confirmcontextunlock', 'admin', $a);
|
||||
$target = 0;
|
||||
} else {
|
||||
$confirmstring = get_string('confirmcontextlock', 'admin', $a);
|
||||
$target = 1;
|
||||
}
|
||||
|
||||
$confirmurl = new \moodle_url($PAGE->url, ['confirm' => $target]);
|
||||
if (!empty($returnurl)) {
|
||||
$confirmurl->param('returnurl', $returnurl);
|
||||
}
|
||||
|
||||
echo $OUTPUT->confirm($confirmstring, $confirmurl, $context->get_url());
|
||||
echo $OUTPUT->footer();
|
||||
@@ -45,7 +45,7 @@ if (isset($_ENV['TMPDIR']) && is_dir($_ENV['TMPDIR'])) {
|
||||
$tmpfile = $tmpdir . '/moodle-mailout.log';
|
||||
$fh = fopen($tmpfile, 'a+', false)
|
||||
or mdie("Error openning $tmpfile on append\n");
|
||||
fwrite($fh, "==== ".date("D M d H:i:s Y", time())." ====\n");
|
||||
fwrite($fh, "==== ".strftime("%a %b %e %H:%M:%S %Y", time())." ====\n");
|
||||
fwrite($fh, "==== Commandline: " . implode(' ',$argv) . "\n");
|
||||
|
||||
$stdin = fopen('php://stdin', 'r');
|
||||
|
||||
+4
-5
@@ -35,7 +35,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$PAGE->set_url('/admin/media.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
require_sesskey();
|
||||
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('media');
|
||||
@@ -49,13 +50,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':
|
||||
|
||||
+30
-89
@@ -25,109 +25,50 @@ require_once(__DIR__ . '/../config.php');
|
||||
require_once($CFG->dirroot . '/message/lib.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
// This is an admin page.
|
||||
// This is an admin page
|
||||
admin_externalpage_setup('managemessageoutputs');
|
||||
|
||||
// Fetch processors.
|
||||
$allprocessors = get_message_processors();
|
||||
$processors = array_filter($allprocessors, function($processor) {
|
||||
return $processor->enabled;
|
||||
});
|
||||
$disabledprocessors = array_filter($allprocessors, function($processor) {
|
||||
return !$processor->enabled;
|
||||
});
|
||||
// Require site configuration capability
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
|
||||
// Fetch message providers.
|
||||
$providers = get_message_providers();
|
||||
// Fetch the manage message outputs interface.
|
||||
$preferences = get_message_output_default_preferences();
|
||||
// Get the submitted params
|
||||
$disable = optional_param('disable', 0, PARAM_INT);
|
||||
$enable = optional_param('enable', 0, PARAM_INT);
|
||||
|
||||
if (($form = data_submitted()) && confirm_sesskey()) {
|
||||
$newpreferences = array();
|
||||
// Prepare default message outputs settings.
|
||||
foreach ($providers as $provider) {
|
||||
$componentproviderbase = $provider->component.'_'.$provider->name;
|
||||
$disableprovidersetting = $componentproviderbase.'_disable';
|
||||
if (!isset($form->$disableprovidersetting)) {
|
||||
$newpreferences[$disableprovidersetting] = 1;
|
||||
} else {
|
||||
$newpreferences[$disableprovidersetting] = 0;
|
||||
}
|
||||
$headingtitle = get_string('managemessageoutputs', 'message');
|
||||
|
||||
$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)) {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
// Record the site preference.
|
||||
$newpreferences['message_provider_'.$componentprovidersetting] = $value;
|
||||
if (!empty($disable) && confirm_sesskey()) {
|
||||
if (!$processor = $DB->get_record('message_processors', array('id'=>$disable))) {
|
||||
print_error('outputdoesnotexist', 'message');
|
||||
}
|
||||
|
||||
// Update database.
|
||||
$transaction = $DB->start_delegated_transaction();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
\core_message\api::update_processor_status($processor, 0); // Disable output.
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
|
||||
if (!empty($enable) && confirm_sesskey()) {
|
||||
if (!$processor = $DB->get_record('message_processors', array('id'=>$enable))) {
|
||||
print_error('outputdoesnotexist', 'message');
|
||||
}
|
||||
\core_message\api::update_processor_status($processor, 1); // Enable output.
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
|
||||
if ($disable || $enable) {
|
||||
$url = new moodle_url('message.php');
|
||||
redirect($url);
|
||||
}
|
||||
|
||||
// Page settings
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
// Grab the renderer
|
||||
$renderer = $PAGE->get_renderer('core', 'message');
|
||||
|
||||
// Display the page.
|
||||
// Display the manage message outputs interface
|
||||
$processors = get_message_processors();
|
||||
$messageoutputs = $renderer->manage_messageoutputs($processors);
|
||||
|
||||
// Display the page
|
||||
echo $OUTPUT->header();
|
||||
echo $renderer->manage_messageoutput_settings($allprocessors, $processors, $providers, $preferences);
|
||||
echo $OUTPUT->heading($headingtitle);
|
||||
echo $messageoutputs;
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -6,16 +6,18 @@ 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);
|
||||
$action = trim(strtolower(optional_param('action', '', PARAM_ALPHA)));
|
||||
|
||||
require_login();
|
||||
|
||||
admin_externalpage_setup('ssoaccesscontrol');
|
||||
|
||||
if (!extension_loaded('openssl')) {
|
||||
throw new \moodle_exception('requiresopenssl', 'mnet');
|
||||
print_error('requiresopenssl', 'mnet');
|
||||
}
|
||||
|
||||
$sitecontext = context_system::instance();
|
||||
@@ -35,13 +37,13 @@ if (!empty($action) and confirm_sesskey()) {
|
||||
|
||||
// boot if insufficient permission
|
||||
if (!has_capability('moodle/user:delete', $sitecontext)) {
|
||||
throw new \moodle_exception('nomodifyacl', 'mnet');
|
||||
print_error('nomodifyacl','mnet');
|
||||
}
|
||||
|
||||
// fetch the record in question
|
||||
$id = required_param('id', PARAM_INT);
|
||||
if (!$idrec = $DB->get_record('mnet_sso_access_control', array('id'=>$id))) {
|
||||
throw new \moodle_exception('recordnoexists', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
print_error('recordnoexists','mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
@@ -56,7 +58,7 @@ if (!empty($action) and confirm_sesskey()) {
|
||||
// require the access parameter, and it must be 'allow' or 'deny'
|
||||
$accessctrl = trim(strtolower(required_param('accessctrl', PARAM_ALPHA)));
|
||||
if ($accessctrl != 'allow' and $accessctrl != 'deny') {
|
||||
throw new \moodle_exception('invalidaccessparam', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
print_error('invalidaccessparam', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
}
|
||||
|
||||
if (mnet_update_sso_access_control($idrec->username, $idrec->mnet_host_id, $accessctrl)) {
|
||||
@@ -71,7 +73,7 @@ if (!empty($action) and confirm_sesskey()) {
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \moodle_exception('invalidactionparam', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
print_error('invalidactionparam', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +84,7 @@ if ($form = data_submitted() and confirm_sesskey()) {
|
||||
|
||||
// check permissions and verify form input
|
||||
if (!has_capability('moodle/user:delete', $sitecontext)) {
|
||||
throw new \moodle_exception('nomodifyacl', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
print_error('nomodifyacl','mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
}
|
||||
if (empty($form->username)) {
|
||||
$formerror['username'] = get_string('enterausername','mnet');
|
||||
@@ -148,20 +150,12 @@ foreach ($columns as $column) {
|
||||
} else {
|
||||
$columndir = $dir == "ASC" ? "DESC" : "ASC";
|
||||
$columnicon = $dir == "ASC" ? "down" : "up";
|
||||
$columnicon = " " . $OUTPUT->pix_icon('t/' . $columnicon, get_string('sort'));
|
||||
$columnicon = " <img src=\"" . $OUTPUT->pix_url('t/' . $columnicon) . "\" alt=\"\" />";
|
||||
}
|
||||
$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) {
|
||||
|
||||
@@ -34,6 +34,11 @@ $step = optional_param('step', 'verify', PARAM_ALPHA);
|
||||
$hostid = required_param('hostid', PARAM_INT);
|
||||
|
||||
|
||||
require_login();
|
||||
|
||||
$context = context_system::instance();
|
||||
require_capability('moodle/site:config', $context, $USER->id, true, "nopermissions");
|
||||
|
||||
$mnet = get_mnet_environment();
|
||||
|
||||
$PAGE->set_url('/admin/mnet/delete.php');
|
||||
|
||||
+9
-22
@@ -6,10 +6,12 @@
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
include_once($CFG->dirroot.'/mnet/lib.php');
|
||||
|
||||
require_login();
|
||||
admin_externalpage_setup('net');
|
||||
|
||||
$context = context_system::instance();
|
||||
|
||||
require_capability('moodle/site:config', $context, $USER->id, true, "nopermissions");
|
||||
|
||||
$site = get_site();
|
||||
$mnet = get_mnet_environment();
|
||||
@@ -17,13 +19,13 @@
|
||||
if (!extension_loaded('openssl')) {
|
||||
echo $OUTPUT->header();
|
||||
set_config('mnet_dispatcher_mode', 'off');
|
||||
throw new \moodle_exception('requiresopenssl', 'mnet');
|
||||
print_error('requiresopenssl', 'mnet');
|
||||
}
|
||||
|
||||
if (!function_exists('curl_init') ) {
|
||||
echo $OUTPUT->header();
|
||||
set_config('mnet_dispatcher_mode', 'off');
|
||||
throw new \moodle_exception('nocurl', 'mnet');
|
||||
print_error('nocurl', 'mnet');
|
||||
}
|
||||
|
||||
if (!isset($CFG->mnet_dispatcher_mode)) {
|
||||
@@ -37,7 +39,7 @@
|
||||
if (set_config('mnet_dispatcher_mode', $form->mode)) {
|
||||
redirect('index.php', get_string('changessaved'));
|
||||
} else {
|
||||
throw new \moodle_exception('invalidaction', '', 'index.php');
|
||||
print_error('invalidaction', '', 'index.php');
|
||||
}
|
||||
}
|
||||
} elseif (!empty($form->submit) && $form->submit == get_string('delete')) {
|
||||
@@ -46,23 +48,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,22 +65,19 @@
|
||||
|
||||
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']))) {
|
||||
// fail - you're being attacked?
|
||||
throw new \moodle_exception ('deletewrongkeyvalue', 'mnet', 'index.php');
|
||||
print_error ('deletewrongkeyvalue', 'mnet', 'index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$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');
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -155,7 +156,7 @@ class mnet_review_host_form extends moodleform {
|
||||
if ($mnet_peer && !empty($mnet_peer->deleted)) {
|
||||
$radioarray = array();
|
||||
$radioarray[] = $mform->createElement('static', 'deletedinfo', '',
|
||||
$OUTPUT->container(get_string('deletedhostinfo', 'mnet'), 'alert alert-warning'));
|
||||
$OUTPUT->container(get_string('deletedhostinfo', 'mnet'), 'deletedhostinfo'));
|
||||
$radioarray[] = $mform->createElement('radio', 'deleted', '', get_string('yes'), 1);
|
||||
$radioarray[] = $mform->createElement('radio', 'deleted', '', get_string('no'), 0);
|
||||
$mform->addGroup($radioarray, 'radioar', get_string('deleted'), array(' ', ' '), false);
|
||||
|
||||
+11
-3
@@ -32,6 +32,10 @@ require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->dirroot.'/mnet/lib.php');
|
||||
require_once($CFG->dirroot.'/'.$CFG->admin.'/mnet/peer_forms.php');
|
||||
|
||||
require_login();
|
||||
|
||||
$context = context_system::instance();
|
||||
require_capability('moodle/site:config', $context, $USER->id, true, 'nopermissions');
|
||||
|
||||
/// Initialize variables.
|
||||
$hostid = optional_param('hostid', 0, PARAM_INT);
|
||||
@@ -52,11 +56,15 @@ $PAGE->set_url('/admin/mnet/peers.php');
|
||||
admin_externalpage_setup($adminsection);
|
||||
|
||||
if (!extension_loaded('openssl')) {
|
||||
throw new \moodle_exception('requiresopenssl', 'mnet');
|
||||
print_error('requiresopenssl', 'mnet');
|
||||
}
|
||||
|
||||
if (!function_exists('curl_init') ) {
|
||||
throw new \moodle_exception('nocurl', 'mnet');
|
||||
print_error('nocurl', 'mnet');
|
||||
}
|
||||
|
||||
if (!function_exists('xmlrpc_encode_request')) {
|
||||
print_error('xmlrpc-missing', 'mnet');
|
||||
}
|
||||
|
||||
if (!isset($CFG->mnet_dispatcher_mode)) {
|
||||
@@ -169,7 +177,7 @@ if ($formdata = $reviewform->get_data()) {
|
||||
if ($mnet_peer->commit()) {
|
||||
redirect(new moodle_url('/admin/mnet/peers.php', array('hostid' => $mnet_peer->id)), get_string('changessaved'));
|
||||
} else {
|
||||
throw new \moodle_exception('invalidaction', 'error', 'index.php');
|
||||
print_error('invalidaction', 'error', 'index.php');
|
||||
}
|
||||
} else if ($reviewform->is_submitted()) { // submitted, but errors
|
||||
echo $OUTPUT->header();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user