Compare commits
967 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de301d4237 | |||
| e2c8f4ad1b | |||
| 8c1455d220 | |||
| 7b85e141da | |||
| cd744ba504 | |||
| 974c63505b | |||
| 724210c4f7 | |||
| ae9d510288 | |||
| 981f750b81 | |||
| 721d57228f | |||
| 3c25c373d9 | |||
| 17eb41c270 | |||
| af6e65f221 | |||
| 8bbc064e29 | |||
| 78b18c00bf | |||
| 4b3b4b7d78 | |||
| 557d1c8820 | |||
| 698e1f7823 | |||
| 5b4702a6b6 | |||
| 77c0b16613 | |||
| 9adef8af21 | |||
| cc45df637f | |||
| 13655cd5ea | |||
| ea3f1d19b9 | |||
| 8256ebd431 | |||
| 8ba97d0104 | |||
| 71ee378a69 | |||
| 8208453a14 | |||
| 7c6e9b37b3 | |||
| 19dc872bca | |||
| 0a51214fb3 | |||
| 6910afa56f | |||
| 5e5e82621c | |||
| 2edff57e63 | |||
| 3b8bb4d4c1 | |||
| 920763ad00 | |||
| 1acd3cac07 | |||
| 7de4119fe2 | |||
| 6fb2fa9859 | |||
| 1d54d21ec0 | |||
| c87ed01b17 | |||
| 23541c936a | |||
| b7490a205f | |||
| 8415e0461b | |||
| 9ee41118b0 | |||
| 137b10b378 | |||
| bb9e3ec1ff | |||
| 7152b05700 | |||
| 087ccaff4f | |||
| 3fb245f481 | |||
| 8de31cf961 | |||
| 88e7da61cd | |||
| 3648b629ed | |||
| 0d833e248a | |||
| 783fba428f | |||
| 514c7ee639 | |||
| fa35b9506f | |||
| 29f7630b75 | |||
| 7a2a47d9e8 | |||
| 17211224a1 | |||
| 2394a675dd | |||
| 449c835fe2 | |||
| 322afa9f4f | |||
| 1d0777dbe4 | |||
| cd94f2bc2e | |||
| e899fd5c02 | |||
| 438b2ac8c2 | |||
| f6ae03bf41 | |||
| fc52aaf319 | |||
| ef8eb8ef1a | |||
| f1c6cf8b26 | |||
| e68cea5747 | |||
| 3f797704ea | |||
| aae57db8d2 | |||
| 8c3091e5f3 | |||
| b52ad05038 | |||
| ec5d807139 | |||
| 1f00b5d9bb | |||
| 0f53bd6b8e | |||
| bf29fea4bb | |||
| 8a733bc85f | |||
| 1b87f634a8 | |||
| 9260dad3b3 | |||
| 6002a1454f | |||
| cef3216f2a | |||
| bed6bfe7d4 | |||
| 1c39517553 | |||
| e92846ce18 | |||
| 31d0ccb078 | |||
| fc7fa7f72c | |||
| 6994f63eef | |||
| c28c0ed466 | |||
| 479b0f0eaa | |||
| 7b96e8a413 | |||
| 2321fe4da9 | |||
| 3aa05048cf | |||
| 17d6ecd26d | |||
| 7d5c5fad77 | |||
| c1296560bf | |||
| 93e25f8657 | |||
| f43de821c6 | |||
| 1b0690a7f1 | |||
| e003e8a6ff | |||
| 1e8f432437 | |||
| 51d7849f08 | |||
| ede7d22dc7 | |||
| 4355451e2f | |||
| 5e102fa8c3 | |||
| 1925b641e2 | |||
| 377da86151 | |||
| 9a2db9e2ec | |||
| 844637b880 | |||
| 9e597d3658 | |||
| 0e25936c0d | |||
| 627e14727e | |||
| ffe84e977f | |||
| 7bc67e92e2 | |||
| dd96341354 | |||
| 1714cb74b3 | |||
| c94c579aa6 | |||
| 16bcd8f057 | |||
| 5e65d02eab | |||
| 1b8bfedaa9 | |||
| 7b920d2d7b | |||
| 63b0a865dd | |||
| 7766af18a5 | |||
| 14d68d98b5 | |||
| 8676a67888 | |||
| 8af16c5709 | |||
| 7f74dc1c16 | |||
| 5bdc07a3b6 | |||
| bccfc48b94 | |||
| 95c3de0877 | |||
| d833fc2131 | |||
| 6e04f9f294 | |||
| 7f45f9ab3e | |||
| 547a6dcdde | |||
| 28fff43d2b | |||
| 7565cda9c6 | |||
| 90fa490de7 | |||
| 5f9ddb348e | |||
| ff8da7e008 | |||
| a6ab91786f | |||
| 0a43bdcc6c | |||
| b1a4bd579a | |||
| 4825c139ef | |||
| d207a2ad02 | |||
| ccc6b4d00b | |||
| cc3a909810 | |||
| c93de36436 | |||
| da3ebf216e | |||
| 7c8fd0d417 | |||
| 558ace5997 | |||
| 98254ccd1a | |||
| 5be02868af | |||
| a36b3ec48f | |||
| ea4e0ae3cb | |||
| 68c3eb8aa9 | |||
| 331b9947a3 | |||
| 4e8d58374e | |||
| 86669b0564 | |||
| e80e613f65 | |||
| 81410615ed | |||
| 1d0bd0cfdf | |||
| b4f40ae78e | |||
| 556611a864 | |||
| 7ce8e4cde2 | |||
| bde7f5d734 | |||
| e08f640061 | |||
| 4f01d454a7 | |||
| 35cc7cad05 | |||
| 7b5fa603dd | |||
| 4e72b72720 | |||
| eaf24d71f2 | |||
| ed46bff4ae | |||
| 87bcff8c6e | |||
| 81c2fe97a3 | |||
| 8b53812c8f | |||
| 78aeaf17e7 | |||
| 662d20869a | |||
| f66c4fa42d | |||
| 76a830b058 | |||
| 2f9582d754 | |||
| 12d4c82f98 | |||
| 3648ffdc8e | |||
| 1194dde152 | |||
| f727dad657 | |||
| 985d5a5824 | |||
| 0210ab0005 | |||
| 99cf35e681 | |||
| 61d0134488 | |||
| 2369ad7737 | |||
| 71dcd85182 | |||
| f5d19447e0 | |||
| b276f33850 | |||
| b932b798f1 | |||
| 14cecfa4c0 | |||
| 9582b85c16 | |||
| f920fdced0 | |||
| 53836d2035 | |||
| ff2b655928 | |||
| 706f6c93ae | |||
| 6028dc3924 | |||
| fd34a36514 | |||
| 27da8851f6 | |||
| 248ab7a4b3 | |||
| fcf07d64c8 | |||
| 897cfd7c81 | |||
| 193aa32b88 | |||
| 78908d7757 | |||
| 896c962160 | |||
| 1178406516 | |||
| 409f92b75d | |||
| 6ea0b003d7 | |||
| 918b60d700 | |||
| b997786180 | |||
| 3e8447fe9a | |||
| 28a1f0943d | |||
| 7a2d0fb5dc | |||
| 28de3d7db9 | |||
| 9fa04e3f2e | |||
| 1d41237ae8 | |||
| b0a9faf1c6 | |||
| e9961085eb | |||
| 766376261a | |||
| 8e2e459daa | |||
| fedd703ce1 | |||
| a1216eb05b | |||
| e49e58a924 | |||
| 97a03ba74d | |||
| ba43374d96 | |||
| 09d078c3b8 | |||
| a8e089a8c8 | |||
| 3e8043f3f4 | |||
| 70f695d068 | |||
| e83cad80b1 | |||
| d727c1eafd | |||
| 463b232453 | |||
| 02a8be1f80 | |||
| 7bc714ac09 | |||
| 3accc543ec | |||
| 481c57cabe | |||
| c0256a7351 | |||
| f8287cb170 | |||
| 621cd70b4c | |||
| 7e2acbfb55 | |||
| c87ccd3111 | |||
| 06be826b2e | |||
| 06a4390060 | |||
| 126cbbff7c | |||
| f252b08433 | |||
| fae048b402 | |||
| 0408008fbe | |||
| 0ff5242a3c | |||
| 2488fe37ca | |||
| 4edad07619 | |||
| 6cdcee7a65 | |||
| 28fbba8b3c | |||
| 90fde2b40d | |||
| d8bfd5b747 | |||
| 0d9c49d8d6 | |||
| 4d9ffaae34 | |||
| 21cfc35074 | |||
| 5d0b569ba1 | |||
| fd7db38d8b | |||
| 2f9f0b0fcc | |||
| 14aaba1b72 | |||
| 629657363d | |||
| 498c54d1de | |||
| a3f72b3972 | |||
| 098f09b638 | |||
| 99732c4c3b | |||
| 905d3939f5 | |||
| 051cad238b | |||
| 6a4bf785cc | |||
| 223f7cc0b4 | |||
| 287ed73429 | |||
| db1368926a | |||
| ec19837b79 | |||
| 3b0d958065 | |||
| 6722a6b105 | |||
| 920b4dd6ab | |||
| 898bdfdd67 | |||
| ed7485277e | |||
| eb238722da | |||
| da1f204a0a | |||
| 5dd385d522 | |||
| dca6513b8a | |||
| 6484e89188 | |||
| 9312e7389a | |||
| 0218859c3e | |||
| 18702b5869 | |||
| d0ab1d1540 | |||
| 7d25143979 | |||
| a067cc5ada | |||
| ea68407895 | |||
| 03f5e32712 | |||
| c0b0649582 | |||
| 72cd24d3c9 | |||
| d16aa74359 | |||
| 7e52e95d8d | |||
| 42f3862b91 | |||
| 556648db0b | |||
| 6026aa7b3c | |||
| 8e5782b848 | |||
| f38e17f16f | |||
| 465cc9e91a | |||
| faa76ee29a | |||
| d6491a67c8 | |||
| 27db5c5024 | |||
| e6b274a542 | |||
| 6f317a983e | |||
| a5293c4ed8 | |||
| 66e77f8173 | |||
| 4ba58ac02f | |||
| 21f5c148fc | |||
| 2e026689c6 | |||
| 3a718d620e | |||
| beff06190a | |||
| 975081c367 | |||
| 9417cedd78 | |||
| 19343c7bd1 | |||
| 64dd473559 | |||
| 9e4a19af6c | |||
| eeba9c1dc5 | |||
| 55a465c445 | |||
| d1d52a3399 | |||
| ad7b38f3ff | |||
| a22b74872c | |||
| 1af998d32c | |||
| 4d9ab4ca48 | |||
| 55189f02ee | |||
| 115f703440 | |||
| 5cd7b5cad0 | |||
| fb81664dc3 | |||
| 8cbc470f2a | |||
| 1bc92d37f2 | |||
| 348e338a21 | |||
| bf854f5f24 | |||
| b861165753 | |||
| 3c2208cc24 | |||
| 2d1fcf6cce | |||
| 2f502066cb | |||
| 41cd0c4d3a | |||
| 0efc7095e3 | |||
| 6178388d94 | |||
| f0e9fa2a7b | |||
| c651779095 | |||
| ce5efbc1da | |||
| e9506c638b | |||
| bb3f9ee492 | |||
| 14017f40b9 | |||
| 413736095b | |||
| f78101f638 | |||
| 105e40d377 | |||
| ce2f6179cd | |||
| 47ff67ec29 | |||
| 3fb1660734 | |||
| 6e7c392d84 | |||
| 806e6bec59 | |||
| 8d7fe960a0 | |||
| 8d1cbe3a35 | |||
| 197ec7e822 | |||
| fbab65f86b | |||
| cd054d77f1 | |||
| 6168569323 | |||
| 5da2fa002e | |||
| 4b137eb20c | |||
| 34ffdc2c81 | |||
| 83d478ce93 | |||
| 565bc965b1 | |||
| e2cdcc563d | |||
| ae61985191 | |||
| 2b169e9b31 | |||
| ccbd35915c | |||
| 114d1a051e | |||
| 856c31cc32 | |||
| 25049f4f19 | |||
| 00a46671fa | |||
| d008aa7c99 | |||
| 2d462ee8bd | |||
| 3f50f83dc1 | |||
| 41121d705f | |||
| cc2faa2c90 | |||
| ae4f9b31f7 | |||
| 01f3495a46 | |||
| c4c328565d | |||
| 7961a36b76 | |||
| eda7eb44b3 | |||
| 6589c3cdd6 | |||
| eeb76ddd3f | |||
| 14ea69c07c | |||
| 9f0400b74d | |||
| f68a64d50b | |||
| d82acd309b | |||
| 22f34e807d | |||
| 31d3a656d6 | |||
| 3d41104fab | |||
| 523f308a9a | |||
| e4d03a9257 | |||
| cedf141cc3 | |||
| b4d51d67a9 | |||
| 9763c99f87 | |||
| 56be61d4f6 | |||
| 6de6fe9590 | |||
| 754440d796 | |||
| 1ddaad70ad | |||
| c954e18a99 | |||
| e0a366fa0a | |||
| 2e5daf9108 | |||
| 5281e10e77 | |||
| aae7a2b206 | |||
| 419ff44b78 | |||
| c4a8787574 | |||
| 834a1d64c5 | |||
| 496e6ac804 | |||
| 7eb0f97113 | |||
| 9f1df0f2e4 | |||
| 8fc60dd25d | |||
| 558a30dc7d | |||
| 9773b4b079 | |||
| d686ee8faa | |||
| 5cb1cf7695 | |||
| 465f3b477b | |||
| ad00d91851 | |||
| 1eed96dec7 | |||
| 2e21c78006 | |||
| aba9644393 | |||
| 4aa6b89ead | |||
| f8bce36ef2 | |||
| fce2b0008c | |||
| c2bd0a7d31 | |||
| 2d7a59d060 | |||
| 57e0a20dec | |||
| 3fe455fab4 | |||
| ca743b6a95 | |||
| 5ea37637b7 | |||
| 75bae1a55b | |||
| f3db3d30e0 | |||
| 7714ea42ec | |||
| 12c103b21a | |||
| ec157a3052 | |||
| 57bb2fdaac | |||
| e437183098 | |||
| 3af8f89e58 | |||
| 52b1184468 | |||
| 99d0308e4b | |||
| 3ae46b2a93 | |||
| 5fce0b3f5d | |||
| b3ebbb61f4 | |||
| 16689245e8 | |||
| 98280a4c8c | |||
| 171e55f304 | |||
| f1fed72bda | |||
| 07674eb12f | |||
| 2308a02324 | |||
| 1da6703d6d | |||
| 27a62292ad | |||
| 271b94ff4f | |||
| 315ec3bad6 | |||
| 4cb342ef34 | |||
| e7bb7aa9a2 | |||
| 7aca3ebb3c | |||
| 61bb2c70c2 | |||
| d84da184c5 | |||
| f612465b53 | |||
| 4727970abd | |||
| 88c700bd2c | |||
| b354694012 | |||
| a9bccc9dbc | |||
| 7c52a27375 | |||
| 300d9ca23d | |||
| 00b2219fd4 | |||
| 8b9d73dad8 | |||
| 9029eb0e71 | |||
| d54b3447e6 | |||
| 39d542eeb4 | |||
| 2cf6b7cc41 | |||
| 5651e88dc9 | |||
| 5a90580646 | |||
| c98428aab3 | |||
| dc780e3eb1 | |||
| d75844ea12 | |||
| 11e5003bd6 | |||
| a348c5f420 | |||
| 4b651226d5 | |||
| e33c554aaa | |||
| 31937c4b0e | |||
| 141216f94c | |||
| fba96f096b | |||
| 7148c9d35e | |||
| 8193ba9da9 | |||
| 6bf314500a | |||
| ee034c39e5 | |||
| 46aea33b69 | |||
| e0f9ca6787 | |||
| 976f8f0c52 | |||
| 767be5d8c1 | |||
| 94140b11e8 | |||
| a45e6838ef | |||
| ae17678a1c | |||
| 3ae39301b9 | |||
| 422fcb70ca | |||
| 29a396fe4e | |||
| af777f92a0 | |||
| 6f35d6536d | |||
| 36cde1e295 | |||
| 05a1532e88 | |||
| 91ae4ab5db | |||
| 2cc3588b77 | |||
| 222aefb456 | |||
| 94160c9ad0 | |||
| 9c7ab777d9 | |||
| 7818990010 | |||
| 17a035ac59 | |||
| abe11a9ace | |||
| bfab0d603c | |||
| 070454489f | |||
| e32a114998 | |||
| 3db28cdebd | |||
| ccd4ef8ddd | |||
| 51b0a67bd2 | |||
| b9371d7bf6 | |||
| 1ec406cbd7 | |||
| b1c1119743 | |||
| 3d45f2c083 | |||
| 1f5da975e2 | |||
| 7156a01a0c | |||
| db22846df6 | |||
| ef6e3bfd77 | |||
| ee0106f70b | |||
| 36ee886a12 | |||
| 97e0452344 | |||
| 874bdf2035 | |||
| ab43412ae9 | |||
| 3d01fc77de | |||
| 08d7552f4d | |||
| 8983d50bd1 | |||
| 9fb8221fb3 | |||
| 4b60cede1e | |||
| 4514918c33 | |||
| 86d6bdf079 | |||
| f5d75c8e24 | |||
| bfeb6f3bac | |||
| ec52cca8b1 | |||
| 6bbb402129 | |||
| 7375466f51 | |||
| 8635e2cefa | |||
| 52bad33356 | |||
| 5c155ba8f7 | |||
| ffa17ad17d | |||
| 5d6fcc67cf | |||
| a37dc94598 | |||
| 1e08e046e2 | |||
| 4ff5d5ef17 | |||
| 84ef6eb8d9 | |||
| 3b45e0db41 | |||
| 535523f21f | |||
| 9c50ccbf7e | |||
| 6c39b7890e | |||
| b676817a64 | |||
| 8eca15c5f1 | |||
| 1bb4c59adc | |||
| 2332ac5f87 | |||
| 0700b8510f | |||
| 7bc82ad672 | |||
| 92b9900d6e | |||
| 312ca07bb7 | |||
| bea621d6c6 | |||
| 28a8eb3856 | |||
| fb39317a64 | |||
| 6e7f80363b | |||
| 82bd2ff5a9 | |||
| e657192d31 | |||
| 85782cffd7 | |||
| fac004cfe9 | |||
| 221c293ac7 | |||
| 5ad20a0633 | |||
| d63bdf9bb9 | |||
| bc29f1c98a | |||
| 4830f55122 | |||
| 48508e4ecc | |||
| fbb2d6592d | |||
| 581a497189 | |||
| 3d3314d433 | |||
| a1f21bad0d | |||
| 189810269a | |||
| e592c6dd9d | |||
| 563cfa0e1e | |||
| 863fb96ffa | |||
| 10f03d2a99 | |||
| b3b04e083b | |||
| 9262b490ee | |||
| f37d0629ea | |||
| 6d9518cf56 | |||
| 0d8bf37407 | |||
| 159115b7c7 | |||
| 930dba73c3 | |||
| 22217ac42f | |||
| d46ee17722 | |||
| 5f1d9df828 | |||
| 95cc0d562b | |||
| 3584cd786a | |||
| fa92e6a809 | |||
| 1257e39d92 | |||
| 65c7339199 | |||
| 2cb720a3d2 | |||
| 138ed9c1fa | |||
| 3c7a4833e5 | |||
| 0400b5ef3f | |||
| 122ed3beaf | |||
| b58a45df37 | |||
| 2d450e9a3b | |||
| 3513964883 | |||
| fde9d44286 | |||
| ba8185cb2a | |||
| 362c598d1b | |||
| 185fc93ed5 | |||
| 8b254440d6 | |||
| 5989a94787 | |||
| e290345cd6 | |||
| 4c48bccbad | |||
| ef1bb2b193 | |||
| 9e103451e2 | |||
| 832f5f7019 | |||
| 40f92ac55d | |||
| 887efbd939 | |||
| 6305c7b83c | |||
| 6bbb4e4df2 | |||
| 79e98f6ac4 | |||
| 1c1a96981d | |||
| 6e9d203e52 | |||
| c02fc98d06 | |||
| 895e5748e1 | |||
| 96805ec18e | |||
| 010f1eff60 | |||
| a713a68af8 | |||
| 1547225e52 | |||
| cc52ff7703 | |||
| 3f51798192 | |||
| 8578e19aff | |||
| e4ffa5f3f6 | |||
| 8cc9ebea1e | |||
| 2cb5248ac3 | |||
| 43a9717a33 | |||
| 4fd5a7bfcb | |||
| 3c2c15d4dc | |||
| 7969cfb39f | |||
| f2fe8b1664 | |||
| 23dc056578 | |||
| 3e9dadc85e | |||
| 6e37e120fc | |||
| 091a6ca62e | |||
| a8cdc38272 | |||
| 2296b4b16e | |||
| 4e873c2ab6 | |||
| 130d29bb5f | |||
| 3ae4d6e824 | |||
| be1847d075 | |||
| 68810e04c6 | |||
| b8b894dd36 | |||
| a12b0aff07 | |||
| 3523edfd90 | |||
| fbaab99733 | |||
| 6408db6427 | |||
| 2cd36e8ea0 | |||
| 6a930e2c88 | |||
| 78079c3f2b | |||
| a88c706d98 | |||
| b9d20f8481 | |||
| 545b24fa52 | |||
| 2f6437ec5c | |||
| 806042d58a | |||
| 58e66823a2 | |||
| 119010b16d | |||
| c6895d7dd4 | |||
| 1f7f5e368d | |||
| b80006b600 | |||
| 9e42721660 | |||
| 0f13aee6fb | |||
| 8cc4708c2a | |||
| 507d51eebf | |||
| 89d8f73703 | |||
| f0f37cb2e7 | |||
| 62cd827dc5 | |||
| 1b682b3b6a | |||
| 5e372ecd61 | |||
| 4401c891e8 | |||
| 61a17c94be | |||
| 75911e67bd | |||
| 3a2eb35800 | |||
| 5ae88aba9d | |||
| dbd0a1dbf7 | |||
| d1e4c0fecc | |||
| 522dd18e62 | |||
| 563bfb4582 | |||
| f03d9e1aab | |||
| 454a93cbbf | |||
| a64f376595 | |||
| f620bbf2f5 | |||
| 4ddbc1ee38 | |||
| f9bd169b6e | |||
| 332fdda507 | |||
| 77f46da53a | |||
| ebacd8353f | |||
| a97c45a15d | |||
| f307dc23d7 | |||
| b21f182106 | |||
| 0991b0a091 | |||
| 54eb1f8f23 | |||
| 97df1db020 | |||
| 8c1eb6cfd3 | |||
| 4eeb1bbd8f | |||
| 5778aa1fa1 | |||
| a0c582342c | |||
| cf13f285e4 | |||
| 08d7dd1db4 | |||
| a6908c3ee8 | |||
| cc91fe0988 | |||
| f66e6749ae | |||
| f3fd372584 | |||
| e29a887814 | |||
| f1743d9179 | |||
| 73827e8eda | |||
| abb81c79d7 | |||
| 8b55712485 | |||
| f967acc533 | |||
| 61d4bf3f88 | |||
| 94dc00614c | |||
| 976ec609bc | |||
| 7cc4f8883a | |||
| 9b48e7420e | |||
| eae4f24877 | |||
| 72e24ec057 | |||
| da2cb39c15 | |||
| 695b470305 | |||
| 076bbff5a7 | |||
| 023064558f | |||
| a934784741 | |||
| 13a31a6b83 | |||
| f29c1bee74 | |||
| 3c5ba23f7f | |||
| 777c810671 | |||
| 9a642c49e1 | |||
| a5708767a0 | |||
| 1117eb6579 | |||
| f131e22bc4 | |||
| 76fd40f2f9 | |||
| 52925cb9df | |||
| 3d68237956 | |||
| b79b33c664 | |||
| 8a6b5024a1 | |||
| f51dcd3c96 | |||
| 7a4f10ddda | |||
| 2d7f517b5b | |||
| 3161583d89 | |||
| 9e3b1f2d7e | |||
| ff2d425711 | |||
| 95c4f624c8 | |||
| 7882fff01a | |||
| d68848383e | |||
| f395c5b238 | |||
| a9782addfc | |||
| d093887447 | |||
| f0be299db3 | |||
| 6a3edc34bd | |||
| 135dfe2144 | |||
| 13de4b94dc | |||
| c6ec3c048e | |||
| 6d1680998d | |||
| bbfcb91b1f | |||
| 7d1f5e81ea | |||
| 5f9d183b46 | |||
| 646ebff5dd | |||
| 8f6f312d65 | |||
| 5762e5ec3e | |||
| 52dbe51339 | |||
| dfaad3e8ca | |||
| 7da6f2675d | |||
| 9ae2623d89 | |||
| e64f37c3c5 | |||
| b39ed13500 | |||
| 532a81f846 | |||
| 2b96f7b343 | |||
| 6a07b3c08c | |||
| 744726275d | |||
| 07afdeedac | |||
| b8c3fefd02 | |||
| ac7cb0921b | |||
| 6b6a083916 | |||
| 6acd719f0f | |||
| 455e7f50d8 | |||
| f49fe84488 | |||
| 5ce4bd05df | |||
| b9f2e3d99b | |||
| 42bcf62000 | |||
| 86f5acdc88 | |||
| 45aa8db99d | |||
| d35fc78761 | |||
| d8b0be3eb3 | |||
| 12e884c5b3 | |||
| 115d6033fc | |||
| 9ffeab1ad1 | |||
| 7bad9a9f15 | |||
| 5a003a1da9 | |||
| 9e96129104 | |||
| 5068d59b13 | |||
| bf9c4ab68a | |||
| 44022305cc | |||
| 0595cfb07d | |||
| c8098c7a80 | |||
| 2e71c132fe | |||
| 7c3522f902 | |||
| 4dcb3165e7 | |||
| 4fbe8bec4a | |||
| 4a723a329e | |||
| 592b8980aa | |||
| 1e63a97698 | |||
| 9d41810bed | |||
| 8cdebcf4e0 | |||
| 9744e6e8cb | |||
| f4d6bd1188 | |||
| d8c8c75ec4 | |||
| 9eaaa8997b | |||
| ef2a7d7302 | |||
| b660b92b3f | |||
| 87ae4833c4 | |||
| 4f9d34da81 | |||
| 13ad9d1f5b | |||
| 8cf328dc54 | |||
| af1f371aa7 | |||
| 3e78b603a5 | |||
| 50da793d5b | |||
| 4affbe94be | |||
| d18eacbd35 | |||
| 3de3755281 | |||
| 04a1611139 | |||
| 0b5889d299 | |||
| aa6bf0f367 | |||
| 7164e1626e | |||
| a869415180 | |||
| b39f2de8ad | |||
| b02b1f3ea9 | |||
| 72ad5d94ea | |||
| 1c2358de43 | |||
| ba56dfb574 | |||
| da48e72353 | |||
| 3c5757b0e2 | |||
| e1a310bde7 | |||
| a040f29f03 | |||
| 3f3262c76e | |||
| 5018c4e4db | |||
| 6e5ae126af | |||
| a0b8d8c0ff | |||
| 1636ee5980 | |||
| a092131b73 | |||
| b4a73ff47f | |||
| 73c4f6c2a5 | |||
| d8a886d75a | |||
| 480f26720d | |||
| 333d17b8e1 | |||
| f78caa59d2 | |||
| 1f09dea479 | |||
| 8e619076cb | |||
| d80e9d463d | |||
| 6a17f29147 | |||
| cafc042bf6 | |||
| d2e303436b | |||
| fb0d5acf4c | |||
| 376d34142f | |||
| 8eb7f7e366 | |||
| 762e8afa6f | |||
| c3018e9ee7 | |||
| 996c94fd08 | |||
| fd7c3c4834 | |||
| c3b7f2f974 | |||
| 8589fbda8c | |||
| f1a681c983 | |||
| a17188f51c | |||
| 8a66849a57 | |||
| 20318b8b7d | |||
| d84d6f57a3 | |||
| 619e11c07a | |||
| 01ec0ee85b | |||
| 91b23a2caa | |||
| 053a433d74 | |||
| 3725a41b39 | |||
| fe5ca8e768 | |||
| b1a2e67326 | |||
| 40553ed459 | |||
| ae9e1f1888 | |||
| 9127c17778 | |||
| 8f28fbee11 | |||
| be7bda671e | |||
| c58101cde3 | |||
| 4a16804df7 | |||
| ff92024ec2 | |||
| 6e5b0b5c20 | |||
| c201456f20 | |||
| 02b3d5aacf | |||
| dde1ead9fe | |||
| 3915147b9b | |||
| 55c7fe15a0 | |||
| 82dba4d510 | |||
| 9ecff3766a | |||
| 4fb85c9c9f | |||
| 6ea5922916 | |||
| 287e8f16e6 | |||
| 846422a90f | |||
| ea6621e00e | |||
| 44ffa8a801 | |||
| a1d5911159 | |||
| c38e38d6b4 | |||
| f5b5f97f56 | |||
| 5528302282 | |||
| 995f0a3a58 | |||
| 894ebe38a2 | |||
| 0609febf16 | |||
| 1d6c1cc0ae | |||
| 50b076c4af | |||
| d783f12861 | |||
| f324c2d16c | |||
| 5486975097 | |||
| d4b6b26f4f | |||
| 996dd0b0b9 | |||
| b44588aaba | |||
| 95fbf4d8e5 | |||
| 6f78024717 | |||
| 7b2e257157 | |||
| bb344d07e7 | |||
| 959c2cb84e | |||
| ee7b438f61 | |||
| dc0241306b | |||
| 89ce4db476 | |||
| 55a1405a84 | |||
| fb21fc9274 | |||
| 57b920b8b7 | |||
| bae07c1bfb | |||
| 4f7016f2da | |||
| 7af8441403 | |||
| 7ba95339a6 | |||
| b6c37f2926 | |||
| b8408c3582 | |||
| fb625069cf | |||
| d4297993a4 | |||
| 2104324ded | |||
| 153b2cb484 | |||
| c72adaa749 | |||
| 3c2ed1533c | |||
| b9518bf811 | |||
| 4f0f1bd84f | |||
| e2ef786003 | |||
| 5b134b5de5 | |||
| 62c4da281a | |||
| 4c27f858b9 | |||
| 6ced5c26d0 | |||
| ccd504115d | |||
| 647e5d8021 | |||
| 6a7042d980 | |||
| 7532b032bb | |||
| b5c1d17da5 | |||
| 56a7d91066 | |||
| 93d636a95b | |||
| 7ca771e4ac | |||
| 6e7e7e1241 | |||
| 8b43f32f8c | |||
| a30eb7d16c |
@@ -0,0 +1,92 @@
|
||||
# Generated by "grunt ignorefiles"
|
||||
*/**/yui/src/*/meta/
|
||||
*/**/build/
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
auth/cas/CAS/
|
||||
cache/stores/mongodb/MongoDB/
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
filter/tex/mimetex.*
|
||||
h5p/h5plib/v124/joubel/core/
|
||||
h5p/h5plib/v124/joubel/editor/
|
||||
lib/editor/atto/plugins/html/yui/src/codemirror/
|
||||
lib/editor/atto/plugins/html/yui/src/beautify/
|
||||
lib/editor/atto/yui/src/rangy/js/*.*
|
||||
lib/editor/tinymce/plugins/pdw/tinymce/
|
||||
lib/editor/tinymce/plugins/spellchecker/rpc.php
|
||||
lib/editor/tinymce/tiny_mce/
|
||||
lib/mlbackend/php/phpml/
|
||||
lib/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
lib/phpspreadsheet/
|
||||
lib/google/
|
||||
lib/htmlpurifier/
|
||||
lib/jabber/
|
||||
lib/minify/matthiasmullie-minify/
|
||||
lib/minify/matthiasmullie-pathconverter/
|
||||
lib/pear/HTML/Common.php
|
||||
lib/pear/HTML/QuickForm.php
|
||||
lib/pear/HTML/QuickForm/
|
||||
lib/pear/PEAR.php
|
||||
lib/phpmailer/
|
||||
lib/simplepie/
|
||||
lib/tcpdf/
|
||||
lib/typo3/
|
||||
lib/yuilib/
|
||||
lib/yuilib/gallery/
|
||||
lib/jquery/
|
||||
lib/html2text/
|
||||
lib/markdown/
|
||||
lib/xhprof/
|
||||
lib/horde/
|
||||
lib/requirejs/
|
||||
lib/amd/src/loglevel.js
|
||||
lib/mustache/
|
||||
lib/amd/src/mustache.js
|
||||
lib/graphlib.php
|
||||
lib/php-css-parser/
|
||||
lib/rtlcss/
|
||||
lib/scssphp/
|
||||
lib/spout/
|
||||
lib/amd/src/chartjs-lazy.js
|
||||
lib/maxmind/GeoIp2/
|
||||
lib/maxmind/MaxMind/
|
||||
lib/ltiprovider/
|
||||
lib/amd/src/truncate.js
|
||||
lib/fonts/
|
||||
lib/amd/src/adapter.js
|
||||
lib/validateurlsyntax.php
|
||||
lib/amd/src/popper.js
|
||||
lib/geopattern-php/
|
||||
lib/php-jwt/
|
||||
lib/babel-polyfill/
|
||||
lib/polyfills/
|
||||
lib/emoji-data/
|
||||
lib/plist/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
media/player/videojs/amd/src/videojs-flash-lazy.js
|
||||
media/player/videojs/videojs/video-js.swf
|
||||
mod/assign/feedback/editpdf/fpdi/
|
||||
repository/s3/S3.php
|
||||
theme/boost/scss/bootstrap/
|
||||
theme/boost/amd/src/bootstrap/alert.js
|
||||
theme/boost/amd/src/bootstrap/button.js
|
||||
theme/boost/amd/src/bootstrap/carousel.js
|
||||
theme/boost/amd/src/bootstrap/collapse.js
|
||||
theme/boost/amd/src/bootstrap/dropdown.js
|
||||
theme/boost/amd/src/bootstrap/index.js
|
||||
theme/boost/amd/src/bootstrap/modal.js
|
||||
theme/boost/amd/src/bootstrap/popover.js
|
||||
theme/boost/amd/src/bootstrap/tools/sanitizer.js
|
||||
theme/boost/amd/src/bootstrap/scrollspy.js
|
||||
theme/boost/amd/src/bootstrap/tab.js
|
||||
theme/boost/amd/src/bootstrap/toast.js
|
||||
theme/boost/amd/src/bootstrap/tooltip.js
|
||||
theme/boost/amd/src/bootstrap/util.js
|
||||
theme/boost/amd/src/tether.js
|
||||
theme/boost/scss/fontawesome/
|
||||
@@ -2,7 +2,6 @@
|
||||
'plugins': [
|
||||
'babel',
|
||||
'promise',
|
||||
'jsdoc',
|
||||
],
|
||||
'env': {
|
||||
'browser': true,
|
||||
@@ -192,6 +191,7 @@
|
||||
'property': 'str',
|
||||
'message': 'Use AMD module "core/str" or M.util.get_string()'
|
||||
}],
|
||||
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
@@ -200,34 +200,18 @@
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'no-unused-expressions': 'off',
|
||||
|
||||
// === JSDocs ===
|
||||
"jsdoc/check-access": 'off',
|
||||
"jsdoc/check-alignment": 'off',
|
||||
"jsdoc/check-param-names": 'off',
|
||||
"jsdoc/check-property-names": 'off',
|
||||
"jsdoc/empty-tags": 'off',
|
||||
"jsdoc/implements-on-classes": 'off',
|
||||
"jsdoc/multiline-blocks": 'off',
|
||||
"jsdoc/require-jsdoc": 'off',
|
||||
"jsdoc/require-param": 'off',
|
||||
"jsdoc/require-param-name": 'off',
|
||||
"jsdoc/require-param-type": 'off',
|
||||
"jsdoc/require-property": 'off',
|
||||
"jsdoc/require-property-name": 'off',
|
||||
"jsdoc/require-property-type": 'off',
|
||||
'no-unused-expressions': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile*.js", "babel-plugin-add-module-to-define.js", "jsdoc.conf.js"],
|
||||
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile*.js", "babel-plugin-add-module-to-define.js"],
|
||||
// We support es6 now. Woot!
|
||||
env: {
|
||||
es6: true
|
||||
},
|
||||
// We're using babel transpiling so use their parser
|
||||
// for linting.
|
||||
parser: '@babel/eslint-parser',
|
||||
parser: 'babel-eslint',
|
||||
// Check AMD with some slightly stricter rules.
|
||||
rules: {
|
||||
'no-unused-vars': 'error',
|
||||
@@ -254,54 +238,11 @@
|
||||
// === Promises ===
|
||||
// We have Promise now that we're using ES6.
|
||||
'promise/no-native': 'off',
|
||||
'promise/avoid-new': 'off',
|
||||
|
||||
// === JSDocs ===
|
||||
"jsdoc/check-access": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/check-alignment": 1, // Recommended.
|
||||
"jsdoc/check-param-names": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/check-property-names": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/empty-tags": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/implements-on-classes": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/multiline-blocks": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-jsdoc": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-param": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-param-name": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-param-type": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-property": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-property-name": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-property-type": [
|
||||
'error',
|
||||
],
|
||||
'promise/avoid-new': 'off'
|
||||
},
|
||||
parserOptions: {
|
||||
'ecmaVersion': 9,
|
||||
'sourceType': 'module',
|
||||
'requireConfigFile': false,
|
||||
'sourceType': 'module'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
name: Core
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- master
|
||||
- MOODLE_[0-9]+_STABLE
|
||||
tags-ignore:
|
||||
- v[0-9]+.[0-9]+.[0-9]+*
|
||||
on: [push]
|
||||
|
||||
env:
|
||||
php: 7.4
|
||||
@@ -20,9 +14,8 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Configuring node & npm
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
shell: bash -l {0}
|
||||
run: nvm install
|
||||
|
||||
- name: Installing node stuff
|
||||
run: npm install
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
/cscope.*
|
||||
/.patches/
|
||||
/.idea/
|
||||
.phpstorm.*
|
||||
/nbproject/
|
||||
CVS
|
||||
.DS_Store
|
||||
@@ -34,7 +33,6 @@ CVS
|
||||
/.project
|
||||
/.buildpath
|
||||
/.cache
|
||||
.phpunit.result.cache
|
||||
phpunit.xml
|
||||
# Composer support. Do not ignore composer.json, or composer.lock. These should be shipped by us.
|
||||
composer.phar
|
||||
@@ -46,8 +44,3 @@ composer.phar
|
||||
/lib/yuilib/*/*/*-coverage.js
|
||||
atlassian-ide-plugin.xml
|
||||
/node_modules/
|
||||
/.vscode/
|
||||
moodle-plugin-ci.phar
|
||||
.eslintignore
|
||||
.stylelintignore
|
||||
/jsdoc
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Moodle JavaScript Documentation
|
||||
|
||||
```
|
||||
.-..-.
|
||||
_____ | || |
|
||||
/____/-.---_ .---. .---. .-.| || | .---.
|
||||
| | _ _ |/ _ \/ _ \/ _ || |/ __ \
|
||||
* | | | | | || |_| || |_| || |_| || || |___/
|
||||
|_| |_| |_|\_____/\_____/\_____||_|\_____)
|
||||
|
||||
Moodle - the world's open source learning platform
|
||||
|
||||
```
|
||||
|
||||
## About
|
||||
This generated documentation includes API documentation for JavaScript written in the AMD and ES2015 module formats within Moodle.
|
||||
|
||||
## Related information
|
||||
See [https://docs.moodle.org/dev](https://docs.moodle.org/dev) for other related Developer Documentation.
|
||||
@@ -1,131 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Helper functions for working with Moodle component names, directories, and sources.
|
||||
*
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
/* eslint-env node */
|
||||
|
||||
// Do not include any plugins as stanard.
|
||||
const plugins = [];
|
||||
|
||||
plugins.push('plugins/markdown');
|
||||
|
||||
/**
|
||||
* Get the source configuration.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
const getSource = () => {
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
const ComponentList = require(path.resolve('GruntfileComponents.js'));
|
||||
const thirdPartyPaths = ComponentList.getThirdPartyPaths();
|
||||
|
||||
const source = {
|
||||
include: [],
|
||||
includePattern: ".+\\.js$",
|
||||
};
|
||||
|
||||
let includeList = [];
|
||||
|
||||
ComponentList.getAmdSrcGlobList().forEach(async pattern => {
|
||||
includeList.push(...glob.sync(pattern));
|
||||
});
|
||||
|
||||
const cwdLength = process.cwd().length + 1;
|
||||
includeList.forEach(path => {
|
||||
if (source.include.indexOf(path) !== -1) {
|
||||
// Ensure no duplicates.
|
||||
return;
|
||||
}
|
||||
|
||||
const relPath = path.substring(cwdLength);
|
||||
if (thirdPartyPaths.indexOf(relPath) !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
source.include.push(path);
|
||||
});
|
||||
|
||||
source.include.push('.grunt/jsdoc/README.md');
|
||||
return source;
|
||||
};
|
||||
|
||||
const tags = {
|
||||
// Allow the use of unknown tags.
|
||||
// We have a lot of legacy uses of these.
|
||||
allowUnknownTags: true,
|
||||
|
||||
// We make use of jsdoc and closure dictionaries as standard.
|
||||
dictionaries: [
|
||||
'jsdoc',
|
||||
'closure',
|
||||
],
|
||||
};
|
||||
|
||||
// Template configuraiton.
|
||||
const templates = {
|
||||
cleverLinks: false,
|
||||
monospaceLinks: false,
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
opts: {
|
||||
destination: "./jsdoc/",
|
||||
template: "node_modules/docdash",
|
||||
},
|
||||
plugins,
|
||||
recurseDepth: 10,
|
||||
source: getSource(),
|
||||
sourceType: 'module',
|
||||
tags,
|
||||
templates,
|
||||
docdash: {
|
||||
collapse: true,
|
||||
search: true,
|
||||
sort: true,
|
||||
sectionOrder: [
|
||||
"Namespaces",
|
||||
"Modules",
|
||||
"Events",
|
||||
"Classes",
|
||||
"Externals",
|
||||
"Mixins",
|
||||
"Tutorials",
|
||||
"Interfaces"
|
||||
],
|
||||
"menu": {
|
||||
"Developer Docs": {
|
||||
href: "https://docs.moodle.org/dev",
|
||||
target: "_blank",
|
||||
"class": "menu-item",
|
||||
id: "devdocs"
|
||||
},
|
||||
"MDN Docs": {
|
||||
href: "https://developer.mozilla.org/en-US/docs/Web/JavaScript",
|
||||
target: "_blank",
|
||||
"class": "menu-item",
|
||||
id: "mdndocs",
|
||||
},
|
||||
},
|
||||
typedefs: true,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
# Generated by "grunt ignorefiles"
|
||||
**/yui/build/*
|
||||
theme/boost/style/moodle.css
|
||||
theme/classic/style/moodle.css
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
|
||||
auth/cas/CAS/
|
||||
cache/stores/mongodb/MongoDB/
|
||||
enrol/lti/ims-blti/
|
||||
filter/algebra/AlgParser.pm
|
||||
filter/tex/mimetex.*
|
||||
h5p/h5plib/v124/joubel/core/
|
||||
h5p/h5plib/v124/joubel/editor/
|
||||
lib/editor/atto/plugins/html/yui/src/codemirror/
|
||||
lib/editor/atto/plugins/html/yui/src/beautify/
|
||||
lib/editor/atto/yui/src/rangy/js/*.*
|
||||
lib/editor/tinymce/plugins/pdw/tinymce/
|
||||
lib/editor/tinymce/plugins/spellchecker/rpc.php
|
||||
lib/editor/tinymce/tiny_mce/
|
||||
lib/mlbackend/php/phpml/
|
||||
lib/adodb/
|
||||
lib/bennu/
|
||||
lib/evalmath/
|
||||
lib/phpspreadsheet/
|
||||
lib/google/
|
||||
lib/htmlpurifier/
|
||||
lib/jabber/
|
||||
lib/minify/matthiasmullie-minify/
|
||||
lib/minify/matthiasmullie-pathconverter/
|
||||
lib/pear/HTML/Common.php
|
||||
lib/pear/HTML/QuickForm.php
|
||||
lib/pear/HTML/QuickForm/
|
||||
lib/pear/PEAR.php
|
||||
lib/phpmailer/
|
||||
lib/simplepie/
|
||||
lib/tcpdf/
|
||||
lib/typo3/
|
||||
lib/yuilib/
|
||||
lib/yuilib/gallery/
|
||||
lib/jquery/
|
||||
lib/html2text/
|
||||
lib/markdown/
|
||||
lib/xhprof/
|
||||
lib/horde/
|
||||
lib/requirejs/
|
||||
lib/amd/src/loglevel.js
|
||||
lib/mustache/
|
||||
lib/amd/src/mustache.js
|
||||
lib/graphlib.php
|
||||
lib/php-css-parser/
|
||||
lib/rtlcss/
|
||||
lib/scssphp/
|
||||
lib/spout/
|
||||
lib/amd/src/chartjs-lazy.js
|
||||
lib/maxmind/GeoIp2/
|
||||
lib/maxmind/MaxMind/
|
||||
lib/ltiprovider/
|
||||
lib/amd/src/truncate.js
|
||||
lib/fonts/
|
||||
lib/amd/src/adapter.js
|
||||
lib/validateurlsyntax.php
|
||||
lib/amd/src/popper.js
|
||||
lib/geopattern-php/
|
||||
lib/php-jwt/
|
||||
lib/babel-polyfill/
|
||||
lib/polyfills/
|
||||
lib/emoji-data/
|
||||
lib/plist/
|
||||
media/player/videojs/amd/src/video-lazy.js
|
||||
media/player/videojs/amd/src/Youtube-lazy.js
|
||||
media/player/videojs/videojs/
|
||||
media/player/videojs/amd/src/videojs-flash-lazy.js
|
||||
media/player/videojs/videojs/video-js.swf
|
||||
mod/assign/feedback/editpdf/fpdi/
|
||||
repository/s3/S3.php
|
||||
theme/boost/scss/bootstrap/
|
||||
theme/boost/amd/src/bootstrap/alert.js
|
||||
theme/boost/amd/src/bootstrap/button.js
|
||||
theme/boost/amd/src/bootstrap/carousel.js
|
||||
theme/boost/amd/src/bootstrap/collapse.js
|
||||
theme/boost/amd/src/bootstrap/dropdown.js
|
||||
theme/boost/amd/src/bootstrap/index.js
|
||||
theme/boost/amd/src/bootstrap/modal.js
|
||||
theme/boost/amd/src/bootstrap/popover.js
|
||||
theme/boost/amd/src/bootstrap/tools/sanitizer.js
|
||||
theme/boost/amd/src/bootstrap/scrollspy.js
|
||||
theme/boost/amd/src/bootstrap/tab.js
|
||||
theme/boost/amd/src/bootstrap/toast.js
|
||||
theme/boost/amd/src/bootstrap/tooltip.js
|
||||
theme/boost/amd/src/bootstrap/util.js
|
||||
theme/boost/amd/src/tether.js
|
||||
theme/boost/scss/fontawesome/
|
||||
+2
-8
@@ -10,7 +10,7 @@ language: php
|
||||
|
||||
os: linux
|
||||
|
||||
dist: bionic
|
||||
dist: xenial
|
||||
|
||||
services:
|
||||
- mysql
|
||||
@@ -19,12 +19,6 @@ services:
|
||||
addons:
|
||||
postgresql: "9.6"
|
||||
|
||||
branches:
|
||||
except:
|
||||
- master
|
||||
- /MOODLE_[0-9]+_STABLE/
|
||||
- /^v[0-9]+\.[0-9]+\.[0-9]+.*/
|
||||
|
||||
jobs:
|
||||
# Enable fast finish.
|
||||
# This will fail the build if a single job fails (except those in allow_failures).
|
||||
@@ -220,7 +214,7 @@ before_script:
|
||||
# We need the official upstream for comparison
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
git fetch upstream MOODLE_310_STABLE;
|
||||
git fetch upstream MOODLE_39_STABLE;
|
||||
export GIT_PREVIOUS_COMMIT="`git merge-base FETCH_HEAD $TRAVIS_COMMIT`";
|
||||
export GIT_COMMIT="$TRAVIS_COMMIT";
|
||||
export UPSTREAM_FETCH_HEAD=`git rev-parse FETCH_HEAD`
|
||||
|
||||
+49
-135
@@ -122,10 +122,9 @@ const registerStyleLintTasks = (grunt, files, fullRunDir) => {
|
||||
if (hasScss) {
|
||||
scssTasks.unshift('stylelint:scss');
|
||||
}
|
||||
scssTasks.unshift('ignorefiles');
|
||||
grunt.registerTask('scss', scssTasks);
|
||||
|
||||
const cssTasks = ['ignorefiles'];
|
||||
const cssTasks = [];
|
||||
if (hasCss) {
|
||||
cssTasks.push('stylelint:css');
|
||||
}
|
||||
@@ -286,71 +285,6 @@ module.exports = function(grunt) {
|
||||
return ['**/tests/behat/*.feature'];
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
eslint: {
|
||||
@@ -367,73 +301,55 @@ module.exports = function(grunt) {
|
||||
// Check YUI module source files.
|
||||
yui: {src: files ? files : yuiSrc},
|
||||
},
|
||||
rollup: {
|
||||
dist: {
|
||||
options: {
|
||||
format: 'esm',
|
||||
dir: 'output',
|
||||
sourcemap: true,
|
||||
treeshake: false,
|
||||
context: 'window',
|
||||
plugins: [
|
||||
rateLimit({initialDelay: 0}),
|
||||
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('babel-plugin-add-module-to-define.js'),
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-syntax-import-meta',
|
||||
['@babel/plugin-proposal-class-properties', {'loose': false}],
|
||||
'@babel/plugin-proposal-json-strings'
|
||||
],
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: [
|
||||
">0.25%",
|
||||
"last 2 versions",
|
||||
"not ie <= 10",
|
||||
"not op_mini all",
|
||||
"not Opera > 0",
|
||||
"not dead"
|
||||
]
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: false
|
||||
}]
|
||||
babel: {
|
||||
options: {
|
||||
sourceMaps: true,
|
||||
comments: false,
|
||||
plugins: [
|
||||
'transform-es2015-modules-amd-lazy',
|
||||
'system-import-transformer',
|
||||
// This plugin modifies the Babel transpiling for "export default"
|
||||
// so that if it's used then only the exported value is returned
|
||||
// by the generated AMD module.
|
||||
//
|
||||
// It also adds the Moodle plugin name to the AMD module definition
|
||||
// so that it can be imported as expected in other modules.
|
||||
path.resolve('babel-plugin-add-module-to-define.js'),
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-syntax-import-meta',
|
||||
['@babel/plugin-proposal-class-properties', {'loose': false}],
|
||||
'@babel/plugin-proposal-json-strings'
|
||||
],
|
||||
presets: [
|
||||
['minify', {
|
||||
// This minification plugin needs to be disabled because it breaks the
|
||||
// source map generation and causes invalid source maps to be output.
|
||||
simplify: false,
|
||||
builtIns: false
|
||||
}],
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: [
|
||||
">0.25%",
|
||||
"last 2 versions",
|
||||
"not ie <= 10",
|
||||
"not op_mini all",
|
||||
"not Opera > 0",
|
||||
"not dead"
|
||||
]
|
||||
}),
|
||||
|
||||
terser({
|
||||
// Do not mangle variables.
|
||||
// Makes debugging easier.
|
||||
mangle: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: false
|
||||
}]
|
||||
]
|
||||
},
|
||||
dist: {
|
||||
files: [{
|
||||
expand: true,
|
||||
src: files ? files : amdSrc,
|
||||
rename: babelRename
|
||||
}],
|
||||
},
|
||||
},
|
||||
jsdoc: {
|
||||
dist: {
|
||||
options: {
|
||||
configure: ".grunt/jsdoc/jsdoc.conf.js",
|
||||
},
|
||||
},
|
||||
}]
|
||||
}
|
||||
},
|
||||
sass: {
|
||||
dist: {
|
||||
@@ -508,7 +424,7 @@ module.exports = function(grunt) {
|
||||
'*/**/yui/src/*/meta/',
|
||||
'*/**/build/',
|
||||
].concat(thirdPartyPaths);
|
||||
grunt.file.write('.eslintignore', eslintIgnores.join('\n') + '\n');
|
||||
grunt.file.write('.eslintignore', eslintIgnores.join('\n'));
|
||||
|
||||
// Generate .stylelintignore.
|
||||
const stylelintIgnores = [
|
||||
@@ -517,7 +433,7 @@ module.exports = function(grunt) {
|
||||
'theme/boost/style/moodle.css',
|
||||
'theme/classic/style/moodle.css',
|
||||
].concat(thirdPartyPaths);
|
||||
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n') + '\n');
|
||||
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -918,9 +834,7 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-sass');
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
grunt.loadNpmTasks('grunt-stylelint');
|
||||
grunt.loadNpmTasks('grunt-rollup');
|
||||
|
||||
grunt.loadNpmTasks('grunt-jsdoc');
|
||||
grunt.loadNpmTasks('grunt-babel');
|
||||
|
||||
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
|
||||
grunt.renameTask('watch', 'watch-grunt');
|
||||
@@ -931,7 +845,7 @@ module.exports = function(grunt) {
|
||||
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles);
|
||||
grunt.registerTask('watch', 'Run tasks on file changes', tasks.watch);
|
||||
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
|
||||
grunt.registerTask('amd', ['ignorefiles', 'eslint:amd', 'rollup']);
|
||||
grunt.registerTask('amd', ['eslint:amd', 'babel']);
|
||||
grunt.registerTask('js', ['amd', 'yui']);
|
||||
|
||||
// Register CSS tasks.
|
||||
|
||||
@@ -140,50 +140,6 @@ const getThirdPartyLibsList = relativeTo => {
|
||||
.sort();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of thirdparty library paths.
|
||||
*
|
||||
* @returns {array}
|
||||
*/
|
||||
const getThirdPartyPaths = () => {
|
||||
const DOMParser = require('xmldom').DOMParser;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const xpath = require('xpath');
|
||||
|
||||
const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./'));
|
||||
const libs = ['node_modules/', 'vendor/'];
|
||||
|
||||
const addLibToList = lib => {
|
||||
if (!lib.match('\\*') && fs.statSync(lib).isDirectory()) {
|
||||
// Ensure trailing slash on dirs.
|
||||
lib = lib.replace(/\/?$/, '/');
|
||||
}
|
||||
|
||||
// Look for duplicate paths before adding to array.
|
||||
if (libs.indexOf(lib) === -1) {
|
||||
libs.push(lib);
|
||||
}
|
||||
};
|
||||
|
||||
thirdpartyfiles.forEach(function(file) {
|
||||
const dirname = path.dirname(file);
|
||||
|
||||
const xmlContent = fs.readFileSync(file, 'utf8');
|
||||
const doc = new DOMParser().parseFromString(xmlContent);
|
||||
const nodes = xpath.select("/libraries/library/location/text()", doc);
|
||||
|
||||
nodes.forEach(function(node) {
|
||||
let lib = path.posix.join(dirname, node.toString());
|
||||
addLibToList(lib);
|
||||
});
|
||||
});
|
||||
|
||||
return libs;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Find the name of the component matching the specified path.
|
||||
*
|
||||
@@ -229,5 +185,4 @@ module.exports = {
|
||||
getOwningComponentDirectory,
|
||||
getYuiSrcGlobList,
|
||||
getThirdPartyLibsList,
|
||||
getThirdPartyPaths,
|
||||
};
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ MOODLE TRADEMARKS POLICY
|
||||
========================
|
||||
|
||||
The word "Moodle" is trademarked in many countries around the world. The word
|
||||
was originally coined as an acronym: Modular Object-Oriented Dynamic Learning
|
||||
was originally an acronym: Modular Object-Oriented Dynamic Learning
|
||||
Environment. The trademark is owned by Martin Dougiamas, Founder and Director
|
||||
of Moodle.
|
||||
|
||||
|
||||
+18
-25
@@ -15,41 +15,34 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Clientside filter base.
|
||||
* Admin settings search form
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2020 The Open University
|
||||
* @package admin
|
||||
* @copyright 2016 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\clientside_filter;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use stdClass;
|
||||
use tool_usertours\local\filter\base;
|
||||
use tool_usertours\tour;
|
||||
require_once $CFG->libdir.'/formslib.php';
|
||||
|
||||
/**
|
||||
* Clientside filter base.
|
||||
* Admin settings search form
|
||||
*
|
||||
* @copyright 2020 The Open University
|
||||
* @package admin
|
||||
* @copyright 2016 Damyon Wiese
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class clientside_filter extends base {
|
||||
/**
|
||||
* Returns the filter values needed for client side filtering.
|
||||
*
|
||||
* @param tour $tour The tour to find the filter values for
|
||||
* @return stdClass
|
||||
*/
|
||||
public static function get_client_side_values(tour $tour): stdClass {
|
||||
$data = (object) [];
|
||||
class admin_settings_search_form extends moodleform {
|
||||
function definition () {
|
||||
$mform = $this->_form;
|
||||
|
||||
if (is_a(static::class, clientside_filter::class, true)) {
|
||||
$data->filterdata = $tour->get_filter_values(static::get_filter_name());
|
||||
}
|
||||
|
||||
return $data;
|
||||
//$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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,9 +158,4 @@ echo $outputhtml;
|
||||
echo html_writer::end_tag('fieldset');
|
||||
echo html_writer::end_tag('form');
|
||||
|
||||
$PAGE->requires->yui_module('moodle-core-formchangechecker', 'M.core_formchangechecker.init', [[
|
||||
'formid' => 'adminsettings'
|
||||
]]);
|
||||
$PAGE->requires->string_for_js('changesmadereallygoaway', 'moodle');
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -43,7 +43,7 @@ class testoutgoingmailconf_form extends \moodleform {
|
||||
$mform = $this->_form;
|
||||
|
||||
// Recipient.
|
||||
$options = ['maxlength' => '100', 'size' => '25', 'autocomplete' => 'email'];
|
||||
$options = ['maxlength' => '100', 'size' => '25'];
|
||||
$mform->addElement('text', 'recipient', get_string('testoutgoingmailconf_toemail', 'admin'), $options);
|
||||
$mform->setType('recipient', PARAM_EMAIL);
|
||||
$mform->addRule('recipient', get_string('required'), 'required');
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* External admin page class that allows a callback to be provided to determine whether page can be accessed
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2019 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\externalpage;
|
||||
|
||||
use admin_externalpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
|
||||
/**
|
||||
* Admin externalpage class
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2019 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class accesscallback extends admin_externalpage {
|
||||
|
||||
/** @var callable $accesscheckcallback */
|
||||
protected $accesscheckcallback;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $visiblename
|
||||
* @param string $url
|
||||
* @param callable $accesscheckcallback The callback method that will be executed to check whether user has access to
|
||||
* this page. The setting instance ($this) is passed as an argument to the callback. Should return boolean value
|
||||
* @param bool $hidden
|
||||
*/
|
||||
public function __construct(string $name, string $visiblename, string $url, callable $accesscheckcallback,
|
||||
bool $hidden = false) {
|
||||
|
||||
$this->accesscheckcallback = $accesscheckcallback;
|
||||
|
||||
parent::__construct($name, $visiblename, $url, [], $hidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the current user has access to this external page based on access callback
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function check_access() {
|
||||
return ($this->accesscheckcallback)($this);
|
||||
}
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Auto complete admin setting.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2020 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
/**
|
||||
* Auto complete setting class.
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @copyright 2020 The Open University
|
||||
*/
|
||||
class autocomplete extends \admin_setting_configmultiselect {
|
||||
/** @var boolean Should we allow typing new entries to the field? */
|
||||
protected $tags = false;
|
||||
/** @var string Name of an AMD module to send/process ajax requests. */
|
||||
protected $ajax = '';
|
||||
/** @var string Placeholder text for an empty list. */
|
||||
protected $placeholder = '';
|
||||
/** @var bool Whether the search has to be case-sensitive. */
|
||||
protected $casesensitive = false;
|
||||
/** @var bool Show suggestions by default - but this can be turned off. */
|
||||
protected $showsuggestions = true;
|
||||
/** @var string String that is shown when there are no selections. */
|
||||
protected $noselectionstring = '';
|
||||
/** @var string Delimiter to store values in database. */
|
||||
protected $delimiter = ',';
|
||||
/** @var string Should be multiple choices? */
|
||||
protected $multiple = true;
|
||||
/** @var string The link to manage choices. */
|
||||
protected $manageurl = true;
|
||||
/** @var string The text to display in manage link. */
|
||||
protected $managetext = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting'
|
||||
* for ones in config_plugins.
|
||||
* @param string $visiblename localised
|
||||
* @param string $description long localised info
|
||||
* @param array $defaultsetting array of selected items
|
||||
* @param array $choices options for autocomplete field
|
||||
* @param array $attributes settings for autocomplete field
|
||||
*/
|
||||
public function __construct($name, $visiblename, $description, $defaultsetting, $choices, $attributes = null) {
|
||||
|
||||
if ($attributes === null) {
|
||||
$attributes = [];
|
||||
}
|
||||
|
||||
$this->placeholder = get_string('search');
|
||||
$this->noselectionstring = get_string('noselection', 'form');
|
||||
$defaultattributes = [
|
||||
'tags',
|
||||
'showsuggestions',
|
||||
'placeholder',
|
||||
'noselectionstring',
|
||||
'ajax',
|
||||
'casesensitive',
|
||||
'delimiter',
|
||||
'multiple',
|
||||
'manageurl',
|
||||
'managetext'
|
||||
];
|
||||
|
||||
foreach ($defaultattributes as $attributename) {
|
||||
if (isset($attributes[$attributename])) {
|
||||
$this->$attributename = $attributes[$attributename];
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting, $choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the select setting(s)
|
||||
*
|
||||
* @return mixed null or array. Null if no settings else array of setting(s)
|
||||
*/
|
||||
public function get_setting() {
|
||||
$result = $this->config_read($this->name);
|
||||
if (is_null($result)) {
|
||||
return null;
|
||||
}
|
||||
if ($result === '') {
|
||||
return [];
|
||||
}
|
||||
return explode($this->delimiter, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves setting(s) provided through $data
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function write_setting($data) {
|
||||
if (!is_array($data)) {
|
||||
return ''; // Ignore it.
|
||||
}
|
||||
if (!$this->load_choices() || empty($this->choices)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
unset($data['xxxxx']);
|
||||
|
||||
$save = [];
|
||||
foreach ($data as $value) {
|
||||
if (!array_key_exists($value, $this->choices)) {
|
||||
continue; // Ignore it.
|
||||
}
|
||||
$save[] = $value;
|
||||
}
|
||||
|
||||
return ($this->config_write($this->name, implode($this->delimiter, $save)) ? '' : get_string('errorsetting', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns XHTML autocomplete field
|
||||
*
|
||||
* @param array $data Array of values to select by default
|
||||
* @param string $query
|
||||
* @return string XHTML autocomplete field
|
||||
*/
|
||||
public function output_html($data, $query = '') {
|
||||
global $OUTPUT;
|
||||
|
||||
if (!$this->load_choices() or empty($this->choices)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$default = $this->get_defaultsetting();
|
||||
if (empty($default)) {
|
||||
$default = [];
|
||||
}
|
||||
|
||||
if (is_null($data)) {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
$context = [
|
||||
'id' => $this->get_id(),
|
||||
'name' => $this->get_full_name()
|
||||
];
|
||||
|
||||
$defaults = [];
|
||||
$options = [];
|
||||
$template = 'core_admin/local/settings/autocomplete';
|
||||
|
||||
foreach ($this->choices as $value => $name) {
|
||||
if (in_array($value, $default)) {
|
||||
$defaults[] = $name;
|
||||
}
|
||||
$options[] = [
|
||||
'value' => $value,
|
||||
'text' => $name,
|
||||
'selected' => in_array($value, $data),
|
||||
'disabled' => false
|
||||
];
|
||||
}
|
||||
|
||||
$context['options'] = $options;
|
||||
$context['tags'] = $this->tags;
|
||||
$context['placeholder'] = $this->placeholder;
|
||||
$context['casesensitive'] = $this->casesensitive;
|
||||
$context['multiple'] = $this->multiple;
|
||||
$context['showsuggestions'] = $this->showsuggestions;
|
||||
$context['manageurl'] = $this->manageurl;
|
||||
$context['managetext'] = $this->managetext;
|
||||
|
||||
if (is_null($default)) {
|
||||
$defaultinfo = null;
|
||||
} if (!empty($defaults)) {
|
||||
$defaultinfo = implode(', ', $defaults);
|
||||
} else {
|
||||
$defaultinfo = get_string('none');
|
||||
}
|
||||
|
||||
$element = $OUTPUT->render_from_template($template, $context);
|
||||
|
||||
return format_admin_setting($this, $this->visiblename, $element, $this->description, true, '', $defaultinfo, $query);
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,6 @@ class filesize extends \admin_setting {
|
||||
if (is_null($bytes)) {
|
||||
return null;
|
||||
}
|
||||
$bytes = intval($bytes);
|
||||
|
||||
return self::parse_bytes($bytes);
|
||||
}
|
||||
@@ -146,10 +145,9 @@ class filesize extends \admin_setting {
|
||||
return get_string('errorsetting', 'admin');
|
||||
}
|
||||
|
||||
// Calculate size in bytes, ensuring we don't overflow PHP_INT_MAX.
|
||||
$bytes = $data['v'] * $data['u'];
|
||||
$result = (is_int($bytes) && $this->config_write($this->name, $bytes));
|
||||
|
||||
$result = $this->config_write($this->name, $bytes);
|
||||
return ($result ? '' : get_string('errorsetting', 'admin'));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Payment gateway admin setting.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2020 Shamim Rezaie <shamim@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_admin\local\settings;
|
||||
|
||||
/**
|
||||
* Generic class for managing plugins in a table that allows re-ordering and enable/disable of each plugin.
|
||||
*/
|
||||
class manage_payment_gateway_plugins extends \admin_setting_manage_plugins {
|
||||
/**
|
||||
* Get the admin settings section title (use get_string).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_section_title() {
|
||||
return get_string('type_paygw_plural', 'plugin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of plugin to manage.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_plugin_type() {
|
||||
return 'paygw';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the second column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_info_column_name() {
|
||||
return get_string('supportedcurrencies', 'core_payment');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of plugin to manage.
|
||||
*
|
||||
* @param plugininfo The plugin info class.
|
||||
* @return string
|
||||
*/
|
||||
public function get_info_column($plugininfo) {
|
||||
$codes = $plugininfo->get_supported_currencies();
|
||||
|
||||
$currencies = [];
|
||||
foreach ($codes as $c) {
|
||||
$currencies[$c] = new \lang_string($c, 'core_currencies');
|
||||
}
|
||||
|
||||
return implode(get_string('listsep', 'langconfig') . ' ', $currencies);
|
||||
}
|
||||
}
|
||||
@@ -57,8 +57,6 @@ class task_log_table extends \table_sql {
|
||||
'userid' => get_string('user', 'admin'),
|
||||
'timestart' => get_string('task_starttime', 'admin'),
|
||||
'duration' => get_string('task_duration', 'admin'),
|
||||
'hostname' => get_string('hostname', 'tool_task'),
|
||||
'pid' => get_string('pid', 'tool_task'),
|
||||
'db' => get_string('task_dbstats', 'admin'),
|
||||
'result' => get_string('task_result', 'admin'),
|
||||
'actions' => '',
|
||||
@@ -134,7 +132,6 @@ class task_log_table extends \table_sql {
|
||||
|
||||
$sql = "SELECT
|
||||
tl.id, tl.type, tl.component, tl.classname, tl.userid, tl.timestart, tl.timeend,
|
||||
tl.hostname, tl.pid,
|
||||
tl.dbreads, tl.dbwrites, tl.result,
|
||||
tl.dbreads + tl.dbwrites AS db,
|
||||
tl.timeend - tl.timestart AS duration,
|
||||
|
||||
@@ -37,13 +37,11 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'ignorelimits' => false,
|
||||
'force' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'e' => 'execute',
|
||||
'k' => 'keep-alive',
|
||||
'i' => 'ignorelimits',
|
||||
'f' => 'force',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -63,7 +61,6 @@ Options:
|
||||
-e, --execute Run all queued adhoc tasks
|
||||
-k, --keep-alive=N Keep this script alive for N seconds and poll for new adhoc tasks
|
||||
-i --ignorelimits Ignore task_adhoc_concurrency_limit and task_adhoc_max_runtime limits
|
||||
-f, --force Run even if cron is disabled
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
|
||||
@@ -95,12 +92,6 @@ if (moodle_needs_upgrading()) {
|
||||
if (empty($options['execute'])) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (empty($options['keep-alive'])) {
|
||||
$options['keep-alive'] = 0;
|
||||
}
|
||||
|
||||
+1
-8
@@ -120,14 +120,7 @@ if ($options['unset'] || $options['set'] !== null) {
|
||||
}
|
||||
|
||||
// Check that the variable is not hard-set in the main config.php already.
|
||||
$component = $options['component'];
|
||||
if (!empty($component)) {
|
||||
$componentsettings = $CFG->forced_plugin_settings[$component] ?? [];
|
||||
$settinginconfig = array_key_exists($options['name'], $componentsettings);
|
||||
} else {
|
||||
$settinginconfig = array_key_exists($options['name'], $CFG->config_php_settings);
|
||||
}
|
||||
if ($settinginconfig) {
|
||||
if (array_key_exists($options['name'], $CFG->config_php_settings)) {
|
||||
cli_error('The configuration variable is hard-set in the config.php, unable to change.', 4);
|
||||
}
|
||||
|
||||
|
||||
+6
-105
@@ -36,23 +36,14 @@ require_once($CFG->libdir.'/cronlib.php');
|
||||
|
||||
// now get cli options
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
array(
|
||||
'help' => false,
|
||||
'stop' => false,
|
||||
'list' => false,
|
||||
'force' => false,
|
||||
'enable' => false,
|
||||
'disable' => false,
|
||||
'disable-wait' => false,
|
||||
], [
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
's' => 'stop',
|
||||
'l' => 'list',
|
||||
'f' => 'force',
|
||||
'e' => 'enable',
|
||||
'd' => 'disable',
|
||||
'w' => 'disable-wait',
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
@@ -65,13 +56,8 @@ if ($options['help']) {
|
||||
"Execute periodic cron actions.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
-s, --stop Notify all other running cron processes to stop after the current task
|
||||
-l, --list Show the list of currently running tasks and how long they have been running
|
||||
-f, --force Execute task even if cron is disabled
|
||||
-e, --enable Enable cron
|
||||
-d, --disable Disable cron
|
||||
-w, --disable-wait=600 Disable cron and wait until all tasks finished or fail after N seconds (optional param)
|
||||
-h, --help Print out this help
|
||||
-s, --stop Notify all other running cron processes to stop after the current task
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/cron.php
|
||||
@@ -88,91 +74,6 @@ if ($options['stop']) {
|
||||
die;
|
||||
}
|
||||
|
||||
if ($options['enable']) {
|
||||
set_config('cron_enabled', 1);
|
||||
mtrace('Cron has been enabled for the site.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['disable']) {
|
||||
set_config('cron_enabled', 0);
|
||||
\core\task\manager::clear_static_caches();
|
||||
mtrace('Cron has been disabled for the site.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['list']) {
|
||||
$tasks = \core\task\manager::get_running_tasks();
|
||||
mtrace('The list of currently running tasks:');
|
||||
$format = "%7s %-12s %-9s %-20s %-52s\n";
|
||||
printf ($format,
|
||||
'PID',
|
||||
'HOST',
|
||||
'TYPE',
|
||||
'TIME',
|
||||
'CLASSNAME'
|
||||
);
|
||||
foreach ($tasks as $task) {
|
||||
printf ($format,
|
||||
$task->pid,
|
||||
substr($task->hostname, 0, 12),
|
||||
$task->type,
|
||||
format_time(time() - $task->timestarted),
|
||||
substr($task->classname, 0, 52)
|
||||
);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($wait = $options['disable-wait']) {
|
||||
$started = time();
|
||||
if (true === $wait) {
|
||||
// Default waiting time.
|
||||
$waitsec = 600;
|
||||
} else {
|
||||
$waitsec = $wait;
|
||||
$wait = true;
|
||||
}
|
||||
|
||||
set_config('cron_enabled', 0);
|
||||
\core\task\manager::clear_static_caches();
|
||||
mtrace('Cron has been disabled for the site.');
|
||||
mtrace('Allocating '. format_time($waitsec) . ' for the tasks to finish.');
|
||||
|
||||
$lastcount = 0;
|
||||
while ($wait) {
|
||||
$tasks = \core\task\manager::get_running_tasks();
|
||||
|
||||
if (count($tasks) == 0) {
|
||||
mtrace('');
|
||||
mtrace('All scheduled and adhoc tasks finished.');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (time() - $started >= $waitsec) {
|
||||
mtrace('');
|
||||
mtrace('Wait time ('. format_time($waitsec) . ') elapsed, but ' . count($tasks) . ' task(s) still running.');
|
||||
mtrace('Exiting with code 1.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (count($tasks) !== $lastcount) {
|
||||
mtrace('');
|
||||
mtrace(count($tasks) . " tasks currently running.", '');
|
||||
$lastcount = count($tasks);
|
||||
} else {
|
||||
mtrace('.', '');
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
\core\local\cli\shutdown::script_supports_graceful_exit();
|
||||
|
||||
cron_run();
|
||||
|
||||
@@ -1,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.");
|
||||
}
|
||||
@@ -119,7 +119,7 @@ if (!empty($options['collation'])) {
|
||||
if ($dbcollation->value !== $collation || $dbcharset->value !== $charset) {
|
||||
// Try to convert the DB.
|
||||
echo "Converting database to '$collation' for $CFG->wwwroot:\n";
|
||||
$sql = "ALTER DATABASE `$CFG->dbname` DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
|
||||
$sql = "ALTER DATABASE $CFG->dbname DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
|
||||
try {
|
||||
$DB->change_database_structure($sql);
|
||||
} catch (exception $e) {
|
||||
@@ -146,7 +146,7 @@ if (!empty($options['collation'])) {
|
||||
|
||||
} else {
|
||||
try {
|
||||
$DB->change_database_structure("ALTER TABLE `$table->name` CONVERT TO CHARACTER SET $charset COLLATE $collation");
|
||||
$DB->change_database_structure("ALTER TABLE $table->name CONVERT TO CHARACTER SET $charset COLLATE $collation");
|
||||
echo "CONVERTED\n";
|
||||
$converted++;
|
||||
} catch (ddl_exception $e) {
|
||||
@@ -163,7 +163,7 @@ if (!empty($options['collation'])) {
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "SHOW FULL COLUMNS FROM `$table->name` WHERE collation IS NOT NULL";
|
||||
$sql = "SHOW FULL COLUMNS FROM $table->name WHERE collation IS NOT NULL";
|
||||
$rs2 = $DB->get_recordset_sql($sql);
|
||||
foreach ($rs2 as $column) {
|
||||
$column = (object)array_change_key_case((array)$column, CASE_LOWER);
|
||||
@@ -181,7 +181,7 @@ if (!empty($options['collation'])) {
|
||||
$notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
|
||||
$default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
|
||||
// primary, unique and inc are not supported for texts
|
||||
$sql = "ALTER TABLE `$table->name`
|
||||
$sql = "ALTER TABLE $table->name
|
||||
MODIFY COLUMN $column->field $column->type
|
||||
CHARACTER SET $charset
|
||||
COLLATE $collation $notnull $default";
|
||||
@@ -192,11 +192,11 @@ if (!empty($options['collation'])) {
|
||||
$default = !is_null($column->default) ? "DEFAULT '$column->default'" : '';
|
||||
|
||||
if ($rowformat != '') {
|
||||
$sql = "ALTER TABLE `$table->name` $rowformat";
|
||||
$sql = "ALTER TABLE $table->name $rowformat";
|
||||
$DB->change_database_structure($sql);
|
||||
}
|
||||
|
||||
$sql = "ALTER TABLE `$table->name`
|
||||
$sql = "ALTER TABLE $table->name
|
||||
MODIFY COLUMN $column->field $column->type
|
||||
CHARACTER SET $charset
|
||||
COLLATE $collation $notnull $default";
|
||||
@@ -315,8 +315,8 @@ function mysql_set_row_format($tablename, $charset, $collation, $engine) {
|
||||
if ($rs->row_format == 'Compact' || $rs->row_format == 'Redundant') {
|
||||
$rowformat = $DB->get_row_format_sql($engine, $collation);
|
||||
// Try to convert to compressed format and then try updating the collation again.
|
||||
$DB->change_database_structure("ALTER TABLE `$tablename` $rowformat");
|
||||
$DB->change_database_structure("ALTER TABLE `$tablename` CONVERT TO CHARACTER SET $charset COLLATE $collation");
|
||||
$DB->change_database_structure("ALTER TABLE $tablename $rowformat");
|
||||
$DB->change_database_structure("ALTER TABLE $tablename CONVERT TO CHARACTER SET $charset COLLATE $collation");
|
||||
} else {
|
||||
// Row format may not be the problem. Can not diagnose problem. Send fail reply.
|
||||
return false;
|
||||
|
||||
@@ -158,7 +158,7 @@ if (!empty($options['info'])) {
|
||||
}
|
||||
|
||||
foreach ($fixtables as $table) {
|
||||
$DB->change_database_structure("ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed");
|
||||
$DB->change_database_structure("ALTER TABLE {$prefix}$table ROW_FORMAT=Compressed");
|
||||
echo str_pad($prefix . $table, 32, ' ', STR_PAD_RIGHT) . " ... Compressed\n";
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ if (!empty($options['info'])) {
|
||||
echo "SET GLOBAL innodb_file_per_table=1;\n";
|
||||
echo "SET GLOBAL innodb_file_format=Barracuda;\n";
|
||||
foreach ($fixtables as $table) {
|
||||
echo "ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed;\n";
|
||||
echo "ALTER TABLE {$prefix}$table ROW_FORMAT=Compressed;\n";
|
||||
}
|
||||
echo "\n";
|
||||
exit(0);
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This script allows to restore a course from CLI.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2020 Catalyst IT
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', 1);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir . '/clilib.php');
|
||||
require_once($CFG->dirroot . "/backup/util/includes/restore_includes.php");
|
||||
|
||||
list($options, $unrecognized) = cli_get_params([
|
||||
'file' => '',
|
||||
'categoryid' => '',
|
||||
'showdebugging' => false,
|
||||
'help' => false,
|
||||
], [
|
||||
'f' => 'file',
|
||||
'c' => 'categoryid',
|
||||
's' => 'showdebugging',
|
||||
'h' => 'help',
|
||||
]);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help'] || !($options['file']) || !($options['categoryid'])) {
|
||||
$help = <<<EOL
|
||||
Restore backup into provided category.
|
||||
|
||||
Options:
|
||||
-f, --file=STRING Path to the backup file.
|
||||
-c, --categoryid=INT ID of the category to restore too.
|
||||
-s, --showdebugging Show developer level debugging information
|
||||
-h, --help Print out this help.
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/restore_backup.php --file=/path/to/backup/file.mbz --categoryid=1\n
|
||||
EOL;
|
||||
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($options['showdebugging']) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if (!$admin = get_admin()) {
|
||||
print_error('noadmins');
|
||||
}
|
||||
|
||||
if (!file_exists($options['file'])) {
|
||||
print_error('filenotfound');
|
||||
}
|
||||
|
||||
if (!$category = $DB->get_record('course_categories', ['id' => $options['categoryid']], 'id')) {
|
||||
print_error('invalidcategoryid');
|
||||
}
|
||||
|
||||
$backupdir = "restore_" . uniqid();
|
||||
$path = $CFG->tempdir . DIRECTORY_SEPARATOR . "backup" . DIRECTORY_SEPARATOR . $backupdir;
|
||||
|
||||
cli_heading(get_string('extractingbackupfileto', 'backup', $path));
|
||||
$fp = get_file_packer('application/vnd.moodle.backup');
|
||||
$fp->extract_to_pathname($options['file'], $path);
|
||||
|
||||
cli_heading(get_string('preprocessingbackupfile'));
|
||||
try {
|
||||
list($fullname, $shortname) = restore_dbops::calculate_course_names(0, get_string('restoringcourse', 'backup'),
|
||||
get_string('restoringcourseshortname', 'backup'));
|
||||
|
||||
$courseid = restore_dbops::create_new_course($fullname, $shortname, $category->id);
|
||||
|
||||
$rc = new restore_controller($backupdir, $courseid, backup::INTERACTIVE_NO,
|
||||
backup::MODE_GENERAL, $admin->id, backup::TARGET_NEW_COURSE);
|
||||
$rc->execute_precheck();
|
||||
$rc->execute_plan();
|
||||
$rc->destroy();
|
||||
} catch (Exception $e) {
|
||||
cli_heading(get_string('cleaningtempdata'));
|
||||
fulldelete($path);
|
||||
print_error('generalexceptionmessage', 'error', '', $e->getMessage());
|
||||
}
|
||||
|
||||
cli_heading(get_string('restoredcourseid', 'backup', $courseid));
|
||||
exit(0);
|
||||
@@ -30,17 +30,8 @@ require_once("$CFG->libdir/clilib.php");
|
||||
require_once("$CFG->libdir/cronlib.php");
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'help' => false,
|
||||
'list' => false,
|
||||
'execute' => false,
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'force' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'f' => 'force',
|
||||
]
|
||||
array('help' => false, 'list' => false, 'execute' => false, 'showsql' => false, 'showdebugging' => false),
|
||||
array('h' => 'help')
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
@@ -58,7 +49,6 @@ if ($options['help'] or (!$options['list'] and !$options['execute'])) {
|
||||
--showsql Show sql queries before they are executed
|
||||
--showdebugging Show developer level debugging information
|
||||
-h, --help Print out this help
|
||||
-f, --force Execute task even if cron is disabled
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
|
||||
@@ -131,13 +121,6 @@ if ($execute = $options['execute']) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
\core\task\manager::scheduled_task_starting($task);
|
||||
|
||||
// Increase memory limit.
|
||||
raise_memory_limit(MEMORY_EXTRA);
|
||||
|
||||
|
||||
@@ -38,17 +38,17 @@ if ($unrecognized) {
|
||||
}
|
||||
|
||||
// If necessary add files that should be ignored - such as in 3rd party plugins.
|
||||
$ignorelist = array();
|
||||
$blacklist = array();
|
||||
$path = $options['path'];
|
||||
if (!file_exists($path)) {
|
||||
cli_error("Invalid path $path");
|
||||
}
|
||||
|
||||
if ($options['ie9fix']) {
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $ignorelist);
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $blacklist);
|
||||
|
||||
} else if ($options['noaspectratio']) {
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $ignorelist);
|
||||
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $blacklist);
|
||||
|
||||
} else {
|
||||
$help =
|
||||
@@ -153,9 +153,9 @@ function core_admin_svgtool_noaspectratio($file) {
|
||||
* @param string $base
|
||||
* @param string $sub
|
||||
* @param string $filecallback
|
||||
* @param array $ignorelist List of files to be ignored and skipped.
|
||||
* @param array $blacklist
|
||||
*/
|
||||
function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
|
||||
function core_admin_recurse_svgs($base, $sub, $filecallback, $blacklist) {
|
||||
if (is_dir("$base/$sub")) {
|
||||
$items = new DirectoryIterator("$base/$sub");
|
||||
foreach ($items as $item) {
|
||||
@@ -163,7 +163,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
|
||||
continue;
|
||||
}
|
||||
$file = $item->getFilename();
|
||||
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $ignorelist);
|
||||
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $blacklist);
|
||||
}
|
||||
unset($item);
|
||||
unset($items);
|
||||
@@ -174,7 +174,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
|
||||
return;
|
||||
}
|
||||
$file = realpath("$base/$sub");
|
||||
if (in_array($file, $ignorelist)) {
|
||||
if (in_array($file, $blacklist)) {
|
||||
return;
|
||||
}
|
||||
$filecallback($file);
|
||||
|
||||
+1
-206
@@ -2815,7 +2815,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.1.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -2997,7 +2996,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.2.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -3163,11 +3161,6 @@
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_igbinary322_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="igbinary322buggyversion" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.10" requires="3.5">
|
||||
@@ -3184,7 +3177,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.2.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -3350,11 +3342,6 @@
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_igbinary322_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="igbinary322buggyversion" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.11" requires="3.6">
|
||||
@@ -3457,7 +3444,7 @@
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="optional"/>
|
||||
<PHP_EXTENSION name="sodium" level="required"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
@@ -3537,198 +3524,6 @@
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.0" requires="3.6">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.2.29" />
|
||||
<VENDOR name="mysql" version="5.7" />
|
||||
<VENDOR name="postgres" version="10" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.3.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlrpc" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="xmlrpcrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="optional"/>
|
||||
<PHP_EXTENSION name="exif" level="optional"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="iscustomadminwarnings" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
+16
-27
@@ -220,7 +220,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$output .= $this->container_end();
|
||||
}
|
||||
|
||||
$button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get', true);
|
||||
$button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get');
|
||||
$button->class = 'continuebutton';
|
||||
$output .= $this->render($button);
|
||||
$output .= $this->footer();
|
||||
@@ -1616,18 +1616,12 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
|
||||
$plugininfo = $pluginman->get_plugins();
|
||||
|
||||
$numtotal = $numextension = $numupdatable = $numinstallable = 0;
|
||||
$numtotal = $numextension = $numupdatable = 0;
|
||||
|
||||
foreach ($plugininfo as $type => $plugins) {
|
||||
foreach ($plugins as $name => $plugin) {
|
||||
if ($res = $plugin->available_updates()) {
|
||||
if ($plugin->available_updates()) {
|
||||
$numupdatable++;
|
||||
foreach ($res as $updateinfo) {
|
||||
if ($pluginman->is_remote_plugin_installable($updateinfo->component, $updateinfo->version, $reason, false)) {
|
||||
$numinstallable++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($plugin->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
continue;
|
||||
@@ -1670,13 +1664,16 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$out .= $this->output->heading(get_string('overviewext', 'core_plugin'), 3);
|
||||
}
|
||||
|
||||
if ($numinstallable) {
|
||||
$out .= $this->output->single_button(
|
||||
new moodle_url($this->page->url, array('installupdatex' => 1)),
|
||||
get_string('updateavailableinstallall', 'core_admin', $numinstallable),
|
||||
'post',
|
||||
array('class' => 'singlebutton updateavailableinstallall')
|
||||
);
|
||||
if ($numupdatable) {
|
||||
$installableupdates = $pluginman->filter_installable($pluginman->available_updates());
|
||||
if ($installableupdates) {
|
||||
$out .= $this->output->single_button(
|
||||
new moodle_url($this->page->url, array('installupdatex' => 1)),
|
||||
get_string('updateavailableinstallall', 'core_admin', count($installableupdates)),
|
||||
'post',
|
||||
array('class' => 'singlebutton updateavailableinstallall')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$out .= html_writer::div($infoall, 'info info-all').
|
||||
@@ -1910,7 +1907,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
'infos'
|
||||
);
|
||||
|
||||
if ($pluginman->is_remote_plugin_installable($updateinfo->component, $updateinfo->version, $reason, false)) {
|
||||
if ($pluginman->is_remote_plugin_installable($updateinfo->component, $updateinfo->version, $reason)) {
|
||||
$box .= $this->output->single_button(
|
||||
new moodle_url($this->page->url, array('installupdate' => $updateinfo->component,
|
||||
'installupdateversion' => $updateinfo->version)),
|
||||
@@ -2130,16 +2127,8 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$output .= $this->container_start('upgradekeyreq');
|
||||
$output .= $this->heading(get_string('upgradekeyreq', 'core_admin'));
|
||||
$output .= html_writer::start_tag('form', array('method' => 'POST', 'action' => $url));
|
||||
$output .= html_writer::empty_tag('input', [
|
||||
'name' => 'upgradekey',
|
||||
'type' => 'password',
|
||||
'class' => 'form-control w-auto',
|
||||
]);
|
||||
$output .= html_writer::empty_tag('input', [
|
||||
'type' => 'submit',
|
||||
'value' => get_string('submit'),
|
||||
'class' => 'btn btn-primary mt-3',
|
||||
]);
|
||||
$output .= html_writer::empty_tag('input', array('name' => 'upgradekey', 'type' => 'password'));
|
||||
$output .= html_writer::empty_tag('input', array('value' => get_string('submit'), 'type' => 'submit'));
|
||||
$output .= html_writer::end_tag('form');
|
||||
$output .= $this->container_end();
|
||||
$output .= $this->footer();
|
||||
|
||||
@@ -536,7 +536,7 @@ class core_role_privacy_testcase extends provider_testcase {
|
||||
$user1->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist2->get_userids());
|
||||
$this->assertEquals($expected, $userlist2->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for coursecontext1 should user1, user2 and admin (role creator).
|
||||
$userlist3 = new \core_privacy\local\request\userlist($coursecontext1, $component);
|
||||
@@ -547,7 +547,7 @@ class core_role_privacy_testcase extends provider_testcase {
|
||||
$user2->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist3->get_userids());
|
||||
$this->assertEquals($expected, $userlist3->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for coursecatcontext should user2 and admin (role creator).
|
||||
$userlist4 = new \core_privacy\local\request\userlist($coursecatcontext, $component);
|
||||
@@ -557,7 +557,7 @@ class core_role_privacy_testcase extends provider_testcase {
|
||||
$user2->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist4->get_userids());
|
||||
$this->assertEquals($expected, $userlist4->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for systemcontext should user1 and admin (role creator).
|
||||
$userlist6 = new \core_privacy\local\request\userlist($systemcontext, $component);
|
||||
@@ -567,7 +567,7 @@ class core_role_privacy_testcase extends provider_testcase {
|
||||
$user1->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist6->get_userids());
|
||||
$this->assertEquals($expected, $userlist6->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for cmcontext should user1, user2 and admin (role creator).
|
||||
$userlist7 = new \core_privacy\local\request\userlist($cmcontext, $component);
|
||||
@@ -578,7 +578,7 @@ class core_role_privacy_testcase extends provider_testcase {
|
||||
$user2->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist7->get_userids());
|
||||
$this->assertEquals($expected, $userlist7->get_userids(), '', 0.0, 10, true);
|
||||
|
||||
// The user list for blockcontext should user1 and admin (role creator).
|
||||
$userlist8 = new \core_privacy\local\request\userlist($blockcontext, $component);
|
||||
@@ -588,7 +588,7 @@ class core_role_privacy_testcase extends provider_testcase {
|
||||
$user1->id,
|
||||
$admin->id
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $userlist8->get_userids());
|
||||
$this->assertEquals($expected, $userlist8->get_userids(), '', 0.0, 10, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -744,4 +744,4 @@ class core_role_privacy_testcase extends provider_testcase {
|
||||
}
|
||||
return $rolesnames;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-10
@@ -68,16 +68,9 @@ if ($errormsg !== '') {
|
||||
$showsettingslinks = true;
|
||||
|
||||
if ($hassiteconfig) {
|
||||
$data = [
|
||||
'action' => new moodle_url('/admin/search.php'),
|
||||
'btnclass' => 'btn-primary',
|
||||
'inputname' => 'query',
|
||||
'searchstring' => get_string('search'),
|
||||
'query' => $query,
|
||||
'extraclasses' => 'd-flex justify-content-center'
|
||||
];
|
||||
echo $OUTPUT->render_from_template('core/search_input', $data);
|
||||
|
||||
require_once("admin_settings_search_form.php");
|
||||
$form = new admin_settings_search_form();
|
||||
$form->display();
|
||||
echo '<hr>';
|
||||
if ($query) {
|
||||
echo admin_search_settings_html($query);
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core_admin\local\settings\filesize;
|
||||
|
||||
$capabilities = array(
|
||||
'moodle/backup:backupcourse',
|
||||
'moodle/category:manage',
|
||||
@@ -77,17 +75,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configselect('moodlecourse/visible', new lang_string('visible'), new lang_string('visible_help'),
|
||||
1, $choices));
|
||||
|
||||
// Enable/disable download course content.
|
||||
$choices = [
|
||||
DOWNLOAD_COURSE_CONTENT_DISABLED => new lang_string('no'),
|
||||
DOWNLOAD_COURSE_CONTENT_ENABLED => new lang_string('yes'),
|
||||
];
|
||||
$downloadcontentsitedefault = new admin_setting_configselect('moodlecourse/downloadcontentsitedefault',
|
||||
new lang_string('enabledownloadcoursecontent', 'course'),
|
||||
new lang_string('downloadcoursecontent_help', 'course'), 0, $choices);
|
||||
$downloadcontentsitedefault->add_dependent_on('downloadcoursecontentallowed');
|
||||
$temp->add($downloadcontentsitedefault);
|
||||
|
||||
// Course format.
|
||||
$temp->add(new admin_setting_heading('courseformathdr', new lang_string('type_format', 'plugin'), ''));
|
||||
|
||||
@@ -174,21 +161,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
|
||||
$ADMIN->add('courses', $temp);
|
||||
|
||||
// Download course content.
|
||||
$downloadcoursedefaulturl = new moodle_url('/admin/settings.php', ['section' => 'coursesettings']);
|
||||
$temp = new admin_settingpage('downloadcoursecontent', new lang_string('downloadcoursecontent', 'course'));
|
||||
$temp->add(new admin_setting_configcheckbox('downloadcoursecontentallowed',
|
||||
new lang_string('downloadcoursecontentallowed', 'admin'),
|
||||
new lang_string('downloadcoursecontentallowed_desc', 'admin', $downloadcoursedefaulturl->out()), 0));
|
||||
|
||||
// 50MB default maximum size per file when downloading course content.
|
||||
$defaultmaxdownloadsize = 50 * filesize::UNIT_MB;
|
||||
$temp->add(new filesize('maxsizeperdownloadcoursefile', new lang_string('maxsizeperdownloadcoursefile', 'admin'),
|
||||
new lang_string('maxsizeperdownloadcoursefile_desc', 'admin'), $defaultmaxdownloadsize, filesize::UNIT_MB));
|
||||
$temp->hide_if('maxsizeperdownloadcoursefile', 'downloadcoursecontentallowed');
|
||||
|
||||
$ADMIN->add('courses', $temp);
|
||||
|
||||
// "courserequests" settingpage.
|
||||
$temp = new admin_settingpage('courserequest', new lang_string('courserequest'));
|
||||
$temp->add(new admin_setting_configcheckbox('enablecourserequests',
|
||||
@@ -212,7 +184,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
// Add a category for the Activity Chooser.
|
||||
$ADMIN->add('courses', new admin_category('activitychooser', new lang_string('activitychoosercategory', 'course')));
|
||||
$temp = new admin_settingpage('activitychoosersettings', new lang_string('activitychoosersettings', 'course'));
|
||||
// Tab mode for the activity chooser.
|
||||
$temp->add(
|
||||
new admin_setting_configselect(
|
||||
'activitychoosertabmode',
|
||||
@@ -226,31 +197,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
// Build a list of plugins that use the footer callback.
|
||||
$pluginswithfunction = get_plugins_with_function('custom_chooser_footer', 'lib.php');
|
||||
$pluginsoptions = [];
|
||||
$pluginsoptions[COURSE_CHOOSER_FOOTER_NONE] = get_string('activitychooserhidefooter', 'course');
|
||||
if ($pluginswithfunction) {
|
||||
foreach ($pluginswithfunction as $plugintype => $plugins) {
|
||||
foreach ($plugins as $pluginname => $pluginfunction) {
|
||||
$plugin = $plugintype.'_'.$pluginname;
|
||||
$pluginsoptions[$plugin] = get_string('pluginname', $plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Select what plugin to show in the footer.
|
||||
$temp->add(
|
||||
new admin_setting_configselect(
|
||||
'activitychooseractivefooter',
|
||||
new lang_string('activitychooseractivefooter', 'course'),
|
||||
new lang_string('activitychooseractivefooter_desc', 'course'),
|
||||
COURSE_CHOOSER_FOOTER_NONE,
|
||||
$pluginsoptions
|
||||
)
|
||||
);
|
||||
|
||||
$ADMIN->add('activitychooser', $temp);
|
||||
$ADMIN->add('activitychooser',
|
||||
new admin_externalpage('activitychooserrecommended', new lang_string('activitychooserrecommendations', 'course'),
|
||||
@@ -313,9 +259,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
['value' => 1, 'locked' => 0])
|
||||
);
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_legacyfiles',
|
||||
new lang_string('generallegacyfiles', 'backup'),
|
||||
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
$ADMIN->add('backups', $temp);
|
||||
|
||||
// Create a page for general import configuration and defaults.
|
||||
@@ -342,9 +285,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
new lang_string('configgeneralcontentbankcontent', 'backup'),
|
||||
['value' => 1, 'locked' => 0])
|
||||
);
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_legacyfiles',
|
||||
new lang_string('generallegacyfiles', 'backup'),
|
||||
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
|
||||
$ADMIN->add('backups', $temp);
|
||||
|
||||
@@ -471,10 +411,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
1)
|
||||
);
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_legacyfiles',
|
||||
new lang_string('generallegacyfiles', 'backup'),
|
||||
new lang_string('configlegacyfiles', 'backup'), 1));
|
||||
|
||||
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_messages', new lang_string('messages', 'message'), new lang_string('backupmessageshelp','message'), 0));
|
||||
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_blogs', new lang_string('blogs', 'blog'), new lang_string('backupblogshelp','blog'), 0));
|
||||
|
||||
@@ -537,9 +473,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_contentbankcontent',
|
||||
new lang_string('generalcontentbankcontent', 'backup'),
|
||||
new lang_string('configrestorecontentbankcontent', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_legacyfiles',
|
||||
new lang_string('generallegacyfiles', 'backup'),
|
||||
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
|
||||
|
||||
// Restore defaults when merging into another course.
|
||||
$temp->add(new admin_setting_heading('mergerestoredefaults', new lang_string('mergerestoredefaults', 'backup'), ''));
|
||||
|
||||
@@ -38,17 +38,9 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
// "debugging" settingpage
|
||||
$temp = new admin_settingpage('debugging', new lang_string('debugging', 'admin'));
|
||||
$temp->add(new admin_setting_special_debug());
|
||||
$temp->add(new admin_setting_configcheckbox('debugdisplay', new lang_string('debugdisplay', 'admin'),
|
||||
new lang_string('configdebugdisplay', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('debugdisplay', new lang_string('debugdisplay', 'admin'), new lang_string('configdebugdisplay', 'admin'), ini_get_bool('display_errors')));
|
||||
$temp->add(new admin_setting_configcheckbox('perfdebug', new lang_string('perfdebug', 'admin'), new lang_string('configperfdebug', 'admin'), '7', '15', '7'));
|
||||
$temp->add(new admin_setting_configcheckbox('debugstringids', new lang_string('debugstringids', 'admin'), new lang_string('debugstringids_desc', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configselect('debugsqltrace',
|
||||
new lang_string('debugsqltrace', 'admin'),
|
||||
new lang_string('debugsqltrace_desc', 'admin'), 0, array(
|
||||
0 => new lang_string('disabled', 'admin'),
|
||||
1 => new lang_string('debugsqltrace1', 'admin'),
|
||||
2 => new lang_string('debugsqltrace2', 'admin'),
|
||||
100 => new lang_string('debugsqltrace100', 'admin'))));
|
||||
$temp->add(new admin_setting_configcheckbox('debugvalidators', new lang_string('debugvalidators', 'admin'), new lang_string('configdebugvalidators', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('debugpageinfo', new lang_string('debugpageinfo', 'admin'), new lang_string('configdebugpageinfo', 'admin'), 0));
|
||||
$ADMIN->add('development', $temp);
|
||||
|
||||
@@ -8,8 +8,6 @@ if ($hassiteconfig) {
|
||||
$temp = new admin_settingpage('langsettings', new lang_string('languagesettings', 'admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('autolang', new lang_string('autolang', 'admin'), new lang_string('configautolang', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configselect('lang', new lang_string('lang', 'admin'), new lang_string('configlang', 'admin'), current_language(), get_string_manager()->get_list_of_translations())); // $CFG->lang might be set in installer already, default en is in setup.php
|
||||
$temp->add(new admin_setting_configcheckbox('autolangusercreation', new lang_string('autolangusercreation', 'admin'),
|
||||
new lang_string('configautolangusercreation', 'admin'), 1));
|
||||
$temp->add(new admin_setting_configcheckbox('langmenu', new lang_string('langmenu', 'admin'), new lang_string('configlangmenu', 'admin'), 1));
|
||||
$temp->add(new admin_setting_langlist());
|
||||
$temp->add(new admin_setting_configcheckbox('langcache', new lang_string('langcache', 'admin'), new lang_string('langcache_desc', 'admin'), 1));
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Adds payments links to the admin tree
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2020 Marina Glancy
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$ADMIN->add('payment', new admin_externalpage(
|
||||
'paymentaccounts',
|
||||
new lang_string('paymentaccounts', 'payment'),
|
||||
new moodle_url("/payment/accounts.php"),
|
||||
['moodle/payment:manageaccounts', 'moodle/payment:viewpayments']));
|
||||
+2
-105
@@ -167,42 +167,6 @@ if ($hassiteconfig) {
|
||||
$ADMIN->add('modules', new admin_category('antivirussettings', new lang_string('antiviruses', 'antivirus')));
|
||||
$temp = new admin_settingpage('manageantiviruses', new lang_string('antivirussettings', 'antivirus'));
|
||||
$temp->add(new admin_setting_manageantiviruses());
|
||||
|
||||
// Common settings.
|
||||
$temp->add(new admin_setting_heading('antiviruscommonsettings', new lang_string('antiviruscommonsettings', 'antivirus'), ''));
|
||||
|
||||
// Alert email.
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'antivirus/notifyemail',
|
||||
new lang_string('notifyemail', 'antivirus'),
|
||||
new lang_string('notifyemail_help', 'antivirus'),
|
||||
'',
|
||||
PARAM_EMAIL
|
||||
)
|
||||
);
|
||||
|
||||
// Enable quarantine.
|
||||
$temp->add(
|
||||
new admin_setting_configcheckbox(
|
||||
'antivirus/enablequarantine',
|
||||
new lang_string('enablequarantine', 'antivirus'),
|
||||
new lang_string('enablequarantine_help', 'antivirus',
|
||||
\core\antivirus\quarantine::DEFAULT_QUARANTINE_FOLDER),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
// Quarantine time.
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'antivirus/quarantinetime',
|
||||
new lang_string('quarantinetime', 'antivirus'),
|
||||
new lang_string('quarantinetime_desc', 'antivirus'),
|
||||
\core\antivirus\quarantine::DEFAULT_QUARANTINE_TIME
|
||||
)
|
||||
);
|
||||
|
||||
$ADMIN->add('antivirussettings', $temp);
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('antivirus');
|
||||
core_collator::asort_objects_by_property($plugins, 'displayname');
|
||||
@@ -280,25 +244,6 @@ if ($hassiteconfig) {
|
||||
$plugin->load_settings($ADMIN, 'mediaplayers', $hassiteconfig);
|
||||
}
|
||||
|
||||
// Payment gateway plugins.
|
||||
$ADMIN->add('modules', new admin_category('paymentgateways', new lang_string('type_paygw_plural', 'plugin')));
|
||||
$temp = new admin_settingpage('managepaymentgateways', new lang_string('type_paygwmanage', 'plugin'));
|
||||
$temp->add(new \core_admin\local\settings\manage_payment_gateway_plugins());
|
||||
$temp->add(new admin_setting_description(
|
||||
'managepaymentgatewayspostfix',
|
||||
'',
|
||||
new lang_string('gotopaymentaccounts', 'payment',
|
||||
html_writer::link(new moodle_url('/payment/accounts.php'), get_string('paymentaccounts', 'payment')))
|
||||
));
|
||||
$ADMIN->add('paymentgateways', $temp);
|
||||
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('paygw');
|
||||
core_collator::asort_objects_by_property($plugins, 'displayname');
|
||||
foreach ($plugins as $plugin) {
|
||||
/** @var \core\plugininfo\paygw $plugin */
|
||||
$plugin->load_settings($ADMIN, 'paymentgateways', $hassiteconfig);
|
||||
}
|
||||
|
||||
// Data format settings.
|
||||
$ADMIN->add('modules', new admin_category('dataformatsettings', new lang_string('dataformats')));
|
||||
$temp = new admin_settingpage('managedataformats', new lang_string('managedataformats'));
|
||||
@@ -604,19 +549,8 @@ if ($hassiteconfig) {
|
||||
|
||||
// Search engine selection.
|
||||
$temp->add(new admin_setting_heading('searchengineheading', new lang_string('searchengine', 'admin'), ''));
|
||||
$searchengineselect = new admin_setting_configselect('searchengine',
|
||||
new lang_string('selectsearchengine', 'admin'), '', 'simpledb', $engines);
|
||||
$searchengineselect->set_validate_function(function(string $value): string {
|
||||
global $CFG;
|
||||
|
||||
// Check nobody's setting the indexing and query-only server to the same one.
|
||||
if (isset($CFG->searchenginequeryonly) && $CFG->searchenginequeryonly === $value) {
|
||||
return get_string('searchenginequeryonlysame', 'admin');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
$temp->add($searchengineselect);
|
||||
$temp->add(new admin_setting_configselect('searchengine',
|
||||
new lang_string('selectsearchengine', 'admin'), '', 'simpledb', $engines));
|
||||
$temp->add(new admin_setting_heading('searchoptionsheading', new lang_string('searchoptions', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configcheckbox('searchindexwhendisabled',
|
||||
new lang_string('searchindexwhendisabled', 'admin'), new lang_string('searchindexwhendisabled_desc', 'admin'),
|
||||
@@ -656,43 +590,6 @@ if ($hassiteconfig) {
|
||||
new lang_string('searchhideallcategory_desc', 'admin'),
|
||||
0));
|
||||
|
||||
$temp->add(new admin_setting_heading('searchmanagement', new lang_string('searchmanagement', 'admin'),
|
||||
new lang_string('searchmanagement_desc', 'admin')));
|
||||
|
||||
// Get list of search engines including those with alternate settings.
|
||||
$searchenginequeryonlyselect = new admin_setting_configselect('searchenginequeryonly',
|
||||
new lang_string('searchenginequeryonly', 'admin'),
|
||||
new lang_string('searchenginequeryonly_desc', 'admin'), '', function() use($engines) {
|
||||
$options = ['' => new lang_string('searchenginequeryonly_none', 'admin')];
|
||||
foreach ($engines as $name => $display) {
|
||||
$options[$name] = $display;
|
||||
|
||||
$classname = '\search_' . $name . '\engine';
|
||||
$engine = new $classname;
|
||||
if ($engine->has_alternate_configuration()) {
|
||||
$options[$name . '-alternate'] =
|
||||
new lang_string('searchenginealternatesettings', 'admin', $display);
|
||||
}
|
||||
}
|
||||
return $options;
|
||||
});
|
||||
$searchenginequeryonlyselect->set_validate_function(function(string $value): string {
|
||||
global $CFG;
|
||||
|
||||
// Check nobody's setting the indexing and query-only server to the same one.
|
||||
if (isset($CFG->searchengine) && $CFG->searchengine === $value) {
|
||||
return get_string('searchenginequeryonlysame', 'admin');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
$temp->add($searchenginequeryonlyselect);
|
||||
$temp->add(new admin_setting_configcheckbox('searchbannerenable',
|
||||
new lang_string('searchbannerenable', 'admin'), new lang_string('searchbannerenable_desc', 'admin'),
|
||||
0));
|
||||
$temp->add(new admin_setting_confightmleditor('searchbanner',
|
||||
new lang_string('searchbanner', 'admin'), '', ''));
|
||||
|
||||
$ADMIN->add('searchplugins', $temp);
|
||||
$ADMIN->add('searchplugins', new admin_externalpage('searchareas', new lang_string('searchareas', 'admin'),
|
||||
new moodle_url('/admin/searchareas.php')));
|
||||
|
||||
@@ -160,23 +160,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
$temp->add(new admin_setting_configportlist('curlsecurityallowedport',
|
||||
new lang_string('curlsecurityallowedport', 'admin'),
|
||||
new lang_string('curlsecurityallowedportsyntax', 'admin'), ""));
|
||||
|
||||
// HTTP Header referrer policy settings.
|
||||
$referreroptions = [
|
||||
'default' => get_string('referrernone', 'admin'),
|
||||
'no-referrer' => 'no-referrer',
|
||||
'no-referrer-when-downgrade' => 'no-referrer-when-downgrade',
|
||||
'origin' => 'origin',
|
||||
'origin-when-cross-origin' => 'origin-when-cross-origin',
|
||||
'same-origin' => 'same-origin',
|
||||
'strict-origin' => 'strict-origin',
|
||||
'strict-origin-when-cross-origin' => 'strict-origin-when-cross-origin',
|
||||
'unsafe-url' => 'unsafe-url',
|
||||
];
|
||||
$temp->add(new admin_setting_configselect('referrerpolicy',
|
||||
new lang_string('referrerpolicy', 'admin'),
|
||||
new lang_string('referrerpolicydesc', 'admin'), 'default', $referreroptions));
|
||||
|
||||
$ADMIN->add('security', $temp);
|
||||
|
||||
// "notifications" settingpage
|
||||
|
||||
+316
-458
@@ -1,225 +1,162 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Defines settingpages and externalpages under the "server" category.
|
||||
*
|
||||
* @package core
|
||||
* @category admin
|
||||
* @copyright 2006 Martin Dougiamas
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
// This file defines settingpages and externalpages under the "server" category
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
|
||||
if ($hassiteconfig) {
|
||||
// System paths.
|
||||
$temp = new admin_settingpage('systempaths', new lang_string('systempaths', 'admin'));
|
||||
$temp->add(new admin_setting_configexecutable('pathtophp', new lang_string('pathtophp', 'admin'),
|
||||
new lang_string('configpathtophp', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'),
|
||||
new lang_string('configpathtodu', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'),
|
||||
new lang_string('edhelpaspellpath'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'),
|
||||
new lang_string('pathtodot_help', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtogs', new lang_string('pathtogs', 'admin'),
|
||||
new lang_string('pathtogs_help', 'admin'), '/usr/bin/gs'));
|
||||
$temp->add(new admin_setting_configexecutable('pathtopython', new lang_string('pathtopython', 'admin'),
|
||||
new lang_string('pathtopythondesc', 'admin'), ''));
|
||||
$ADMIN->add('server', $temp);
|
||||
// "systempaths" settingpage
|
||||
$temp = new admin_settingpage('systempaths', new lang_string('systempaths','admin'));
|
||||
$temp->add(new admin_setting_configexecutable('pathtophp', new lang_string('pathtophp', 'admin'),
|
||||
new lang_string('configpathtophp', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'), new lang_string('configpathtodu', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'), new lang_string('edhelpaspellpath'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'), new lang_string('pathtodot_help', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configexecutable('pathtogs', new lang_string('pathtogs', 'admin'), new lang_string('pathtogs_help', 'admin'), '/usr/bin/gs'));
|
||||
$temp->add(new admin_setting_configexecutable('pathtopython', new lang_string('pathtopython', 'admin'),
|
||||
new lang_string('pathtopythondesc', 'admin'), ''));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// Support contact.
|
||||
$temp = new admin_settingpage('supportcontact', new lang_string('supportcontact', 'admin'));
|
||||
$primaryadmin = get_admin();
|
||||
if ($primaryadmin) {
|
||||
$primaryadminemail = $primaryadmin->email;
|
||||
$primaryadminname = fullname($primaryadmin, true);
|
||||
} else {
|
||||
// No defaults during installation - admin user must be created first.
|
||||
$primaryadminemail = null;
|
||||
$primaryadminname = null;
|
||||
}
|
||||
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'),
|
||||
new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
|
||||
$setting = new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'),
|
||||
new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_EMAIL);
|
||||
$setting->set_force_ltr(true);
|
||||
$temp->add($setting);
|
||||
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'),
|
||||
new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// Session handling.
|
||||
$temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandling', 'admin'));
|
||||
if (empty($CFG->session_handler_class) and $DB->session_lock_supported()) {
|
||||
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'),
|
||||
new lang_string('configdbsessions', 'admin'), 0));
|
||||
}
|
||||
|
||||
$temp->add(new admin_setting_configduration('sessiontimeout', new lang_string('sessiontimeout', 'admin'),
|
||||
new lang_string('configsessiontimeout', 'admin'), 8 * 60 * 60));
|
||||
// "supportcontact" settingpage
|
||||
$temp = new admin_settingpage('supportcontact', new lang_string('supportcontact','admin'));
|
||||
$primaryadmin = get_admin();
|
||||
if ($primaryadmin) {
|
||||
$primaryadminemail = $primaryadmin->email;
|
||||
$primaryadminname = fullname($primaryadmin, true);
|
||||
} else {
|
||||
// no defaults during installation - admin user must be created first
|
||||
$primaryadminemail = NULL;
|
||||
$primaryadminname = NULL;
|
||||
}
|
||||
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'),
|
||||
new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
|
||||
$setting = new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'),
|
||||
new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_EMAIL);
|
||||
$setting->set_force_ltr(true);
|
||||
$temp->add($setting);
|
||||
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'), new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp->add(new admin_setting_configtext('sessioncookie', new lang_string('sessioncookie', 'admin'),
|
||||
new lang_string('configsessioncookie', 'admin'), '', PARAM_ALPHANUM));
|
||||
$temp->add(new admin_setting_configtext('sessioncookiepath', new lang_string('sessioncookiepath', 'admin'),
|
||||
new lang_string('configsessioncookiepath', 'admin'), '', PARAM_RAW));
|
||||
$temp->add(new admin_setting_configtext('sessioncookiedomain', new lang_string('sessioncookiedomain', 'admin'),
|
||||
new lang_string('configsessioncookiedomain', 'admin'), '', PARAM_RAW, 50));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// Statistics.
|
||||
$temp = new admin_settingpage('stats', new lang_string('stats'), 'moodle/site:config', empty($CFG->enablestats));
|
||||
$temp->add(new admin_setting_configselect('statsfirstrun', new lang_string('statsfirstrun', 'admin'),
|
||||
new lang_string('configstatsfirstrun', 'admin'), 'none',
|
||||
[
|
||||
'none' => new lang_string('none'),
|
||||
60 * 60 * 24 * 7 => new lang_string('numweeks', 'moodle', 1),
|
||||
60 * 60 * 24 * 14 => new lang_string('numweeks', 'moodle', 2),
|
||||
60 * 60 * 24 * 21 => new lang_string('numweeks', 'moodle', 3),
|
||||
60 * 60 * 24 * 28 => new lang_string('nummonths', 'moodle', 1),
|
||||
60 * 60 * 24 * 56 => new lang_string('nummonths', 'moodle', 2),
|
||||
60 * 60 * 24 * 84 => new lang_string('nummonths', 'moodle', 3),
|
||||
60 * 60 * 24 * 112 => new lang_string('nummonths', 'moodle', 4),
|
||||
60 * 60 * 24 * 140 => new lang_string('nummonths', 'moodle', 5),
|
||||
60 * 60 * 24 * 168 => new lang_string('nummonths', 'moodle', 6),
|
||||
'all' => new lang_string('all')
|
||||
]
|
||||
));
|
||||
$temp->add(new admin_setting_configselect('statsmaxruntime', new lang_string('statsmaxruntime', 'admin'),
|
||||
new lang_string('configstatsmaxruntime3', 'admin'), 0,
|
||||
[
|
||||
0 => new lang_string('untilcomplete'),
|
||||
60 * 30 => '10 ' . new lang_string('minutes'),
|
||||
60 * 30 => '30 ' . new lang_string('minutes'),
|
||||
60 * 60 => '1 ' . new lang_string('hour'),
|
||||
60 * 60 * 2 => '2 ' . new lang_string('hours'),
|
||||
60 * 60 * 3 => '3 ' . new lang_string('hours'),
|
||||
60 * 60 * 4 => '4 ' . new lang_string('hours'),
|
||||
60 * 60 * 5 => '5 ' . new lang_string('hours'),
|
||||
60 * 60 * 6 => '6 ' . new lang_string('hours'),
|
||||
60 * 60 * 7 => '7 ' . new lang_string('hours'),
|
||||
60 * 60 * 8 => '8 ' . new lang_string('hours'),
|
||||
]
|
||||
));
|
||||
$temp->add(new admin_setting_configtext('statsruntimedays', new lang_string('statsruntimedays', 'admin'),
|
||||
new lang_string('configstatsruntimedays', 'admin'), 31, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('statsuserthreshold', new lang_string('statsuserthreshold', 'admin'),
|
||||
new lang_string('configstatsuserthreshold', 'admin'), 0, PARAM_INT));
|
||||
$ADMIN->add('server', $temp);
|
||||
// "sessionhandling" settingpage
|
||||
$temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandling', 'admin'));
|
||||
if (empty($CFG->session_handler_class) and $DB->session_lock_supported()) {
|
||||
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'), new lang_string('configdbsessions', 'admin'), 0));
|
||||
}
|
||||
|
||||
// HTTP.
|
||||
$temp = new admin_settingpage('http', new lang_string('http', 'admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('slasharguments', new lang_string('slasharguments', 'admin'),
|
||||
new lang_string('configslasharguments', 'admin'), 1));
|
||||
$temp->add(new admin_setting_heading('reverseproxy', new lang_string('reverseproxy', 'admin'), '', ''));
|
||||
$options = [
|
||||
0 => 'HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR => 'HTTP_CLIENT, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR | GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'REMOTE_ADDR'
|
||||
];
|
||||
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'),
|
||||
new lang_string('configgetremoteaddrconf', 'admin'),
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR | GETREMOTEADDR_SKIP_HTTP_CLIENT_IP, $options));
|
||||
$temp->add(new admin_setting_configtext('reverseproxyignore', new lang_string('reverseproxyignore', 'admin'),
|
||||
new lang_string('configreverseproxyignore', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configduration('sessiontimeout', new lang_string('sessiontimeout', 'admin'),
|
||||
new lang_string('configsessiontimeout', 'admin'), 8 * 60 * 60));
|
||||
|
||||
$temp->add(new admin_setting_heading('webproxy', new lang_string('webproxy', 'admin'),
|
||||
new lang_string('webproxyinfo', 'admin')));
|
||||
$temp->add(new admin_setting_configtext('proxyhost', new lang_string('proxyhost', 'admin'),
|
||||
new lang_string('configproxyhost', 'admin'), '', PARAM_HOST));
|
||||
$temp->add(new admin_setting_configtext('proxyport', new lang_string('proxyport', 'admin'),
|
||||
new lang_string('configproxyport', 'admin'), 0, PARAM_INT));
|
||||
$options = ['HTTP' => 'HTTP'];
|
||||
if (defined('CURLPROXY_SOCKS5')) {
|
||||
$options['SOCKS5'] = 'SOCKS5';
|
||||
}
|
||||
$temp->add(new admin_setting_configselect('proxytype', new lang_string('proxytype', 'admin'),
|
||||
new lang_string('configproxytype', 'admin'), 'HTTP', $options));
|
||||
$temp->add(new admin_setting_configtext('proxyuser', new lang_string('proxyuser', 'admin'),
|
||||
new lang_string('configproxyuser', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configpasswordunmask('proxypassword', new lang_string('proxypassword', 'admin'),
|
||||
new lang_string('configproxypassword', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'),
|
||||
new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
|
||||
$ADMIN->add('server', $temp);
|
||||
$temp->add(new admin_setting_configtext('sessioncookie', new lang_string('sessioncookie', 'admin'), new lang_string('configsessioncookie', 'admin'), '', PARAM_ALPHANUM));
|
||||
$temp->add(new admin_setting_configtext('sessioncookiepath', new lang_string('sessioncookiepath', 'admin'), new lang_string('configsessioncookiepath', 'admin'), '', PARAM_RAW));
|
||||
$temp->add(new admin_setting_configtext('sessioncookiedomain', new lang_string('sessioncookiedomain', 'admin'), new lang_string('configsessioncookiedomain', 'admin'), '', PARAM_RAW, 50));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp = new admin_settingpage('maintenancemode', new lang_string('sitemaintenancemode', 'admin'));
|
||||
$options = [0 => new lang_string('disable'), 1 => new lang_string('enable')];
|
||||
$temp->add(new admin_setting_configselect('maintenance_enabled', new lang_string('sitemaintenancemode', 'admin'),
|
||||
new lang_string('helpsitemaintenance', 'admin'), 0, $options));
|
||||
$temp->add(new admin_setting_confightmleditor('maintenance_message', new lang_string('optionalmaintenancemessage', 'admin'),
|
||||
'', ''));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// Cleanup.
|
||||
$temp = new admin_settingpage('cleanup', new lang_string('cleanup', 'admin'));
|
||||
$temp->add(new admin_setting_configselect('deleteunconfirmed', new lang_string('deleteunconfirmed', 'admin'),
|
||||
new lang_string('configdeleteunconfirmed', 'admin'), 168,
|
||||
[
|
||||
0 => new lang_string('never'),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
144 => new lang_string('numdays', '', 6),
|
||||
120 => new lang_string('numdays', '', 5),
|
||||
96 => new lang_string('numdays', '', 4),
|
||||
72 => new lang_string('numdays', '', 3),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
24 => new lang_string('numdays', '', 1),
|
||||
12 => new lang_string('numhours', '', 12),
|
||||
6 => new lang_string('numhours', '', 6),
|
||||
1 => new lang_string('numhours', '', 1),
|
||||
]
|
||||
));
|
||||
// "stats" settingpage
|
||||
$temp = new admin_settingpage('stats', new lang_string('stats'), 'moodle/site:config', empty($CFG->enablestats));
|
||||
$temp->add(new admin_setting_configselect('statsfirstrun', new lang_string('statsfirstrun', 'admin'), new lang_string('configstatsfirstrun', 'admin'), 'none', array('none' => new lang_string('none'),
|
||||
60*60*24*7 => new lang_string('numweeks','moodle',1),
|
||||
60*60*24*14 => new lang_string('numweeks','moodle',2),
|
||||
60*60*24*21 => new lang_string('numweeks','moodle',3),
|
||||
60*60*24*28 => new lang_string('nummonths','moodle',1),
|
||||
60*60*24*56 => new lang_string('nummonths','moodle',2),
|
||||
60*60*24*84 => new lang_string('nummonths','moodle',3),
|
||||
60*60*24*112 => new lang_string('nummonths','moodle',4),
|
||||
60*60*24*140 => new lang_string('nummonths','moodle',5),
|
||||
60*60*24*168 => new lang_string('nummonths','moodle',6),
|
||||
'all' => new lang_string('all') )));
|
||||
$temp->add(new admin_setting_configselect('statsmaxruntime', new lang_string('statsmaxruntime', 'admin'), new lang_string('configstatsmaxruntime3', 'admin'), 0, array(0 => new lang_string('untilcomplete'),
|
||||
60*30 => '10 '.new lang_string('minutes'),
|
||||
60*30 => '30 '.new lang_string('minutes'),
|
||||
60*60 => '1 '.new lang_string('hour'),
|
||||
60*60*2 => '2 '.new lang_string('hours'),
|
||||
60*60*3 => '3 '.new lang_string('hours'),
|
||||
60*60*4 => '4 '.new lang_string('hours'),
|
||||
60*60*5 => '5 '.new lang_string('hours'),
|
||||
60*60*6 => '6 '.new lang_string('hours'),
|
||||
60*60*7 => '7 '.new lang_string('hours'),
|
||||
60*60*8 => '8 '.new lang_string('hours') )));
|
||||
$temp->add(new admin_setting_configtext('statsruntimedays', new lang_string('statsruntimedays', 'admin'), new lang_string('configstatsruntimedays', 'admin'), 31, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('statsuserthreshold', new lang_string('statsuserthreshold', 'admin'), new lang_string('configstatsuserthreshold', 'admin'), 0, PARAM_INT));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp->add(new admin_setting_configselect('deleteincompleteusers', new lang_string('deleteincompleteusers', 'admin'),
|
||||
new lang_string('configdeleteincompleteusers', 'admin'), 0,
|
||||
[
|
||||
0 => new lang_string('never'),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
144 => new lang_string('numdays', '', 6),
|
||||
120 => new lang_string('numdays', '', 5),
|
||||
96 => new lang_string('numdays', '', 4),
|
||||
72 => new lang_string('numdays', '', 3),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
24 => new lang_string('numdays', '', 1),
|
||||
]
|
||||
));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('disablegradehistory', new lang_string('disablegradehistory', 'grades'),
|
||||
new lang_string('disablegradehistory_help', 'grades'), 0));
|
||||
// "http" settingpage
|
||||
$temp = new admin_settingpage('http', new lang_string('http', 'admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('slasharguments', new lang_string('slasharguments', 'admin'), new lang_string('configslasharguments', 'admin'), 1));
|
||||
$temp->add(new admin_setting_heading('reverseproxy', new lang_string('reverseproxy', 'admin'), '', ''));
|
||||
$options = array(
|
||||
0 => 'HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR => 'HTTP_CLIENT, REMOTE_ADDR',
|
||||
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR|GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'REMOTE_ADDR');
|
||||
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'),
|
||||
new lang_string('configgetremoteaddrconf', 'admin'),
|
||||
GETREMOTEADDR_SKIP_DEFAULT, $options));
|
||||
$temp->add(new admin_setting_configtext('reverseproxyignore', new lang_string('reverseproxyignore', 'admin'), new lang_string('configreverseproxyignore', 'admin'), ''));
|
||||
|
||||
$temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_string('gradehistorylifetime', 'grades'),
|
||||
new lang_string('gradehistorylifetime_help', 'grades'), 0,
|
||||
[
|
||||
0 => new lang_string('neverdeletehistory', 'grades'),
|
||||
1000 => new lang_string('numdays', '', 1000),
|
||||
365 => new lang_string('numdays', '', 365),
|
||||
180 => new lang_string('numdays', '', 180),
|
||||
150 => new lang_string('numdays', '', 150),
|
||||
120 => new lang_string('numdays', '', 120),
|
||||
90 => new lang_string('numdays', '', 90),
|
||||
60 => new lang_string('numdays', '', 60),
|
||||
30 => new lang_string('numdays', '', 30),
|
||||
]
|
||||
));
|
||||
$temp->add(new admin_setting_heading('webproxy', new lang_string('webproxy', 'admin'), new lang_string('webproxyinfo', 'admin')));
|
||||
$temp->add(new admin_setting_configtext('proxyhost', new lang_string('proxyhost', 'admin'), new lang_string('configproxyhost', 'admin'), '', PARAM_HOST));
|
||||
$temp->add(new admin_setting_configtext('proxyport', new lang_string('proxyport', 'admin'), new lang_string('configproxyport', 'admin'), 0, PARAM_INT));
|
||||
$options = array('HTTP'=>'HTTP');
|
||||
if (defined('CURLPROXY_SOCKS5')) {
|
||||
$options['SOCKS5'] = 'SOCKS5';
|
||||
}
|
||||
$temp->add(new admin_setting_configselect('proxytype', new lang_string('proxytype', 'admin'), new lang_string('configproxytype','admin'), 'HTTP', $options));
|
||||
$temp->add(new admin_setting_configtext('proxyuser', new lang_string('proxyuser', 'admin'), new lang_string('configproxyuser', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configpasswordunmask('proxypassword', new lang_string('proxypassword', 'admin'), new lang_string('configproxypassword', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'), new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'),
|
||||
new lang_string('configtempdatafoldercleanup', 'admin'), 168,
|
||||
[
|
||||
$temp = new admin_settingpage('maintenancemode', new lang_string('sitemaintenancemode', 'admin'));
|
||||
$options = array(0=>new lang_string('disable'), 1=>new lang_string('enable'));
|
||||
$temp->add(new admin_setting_configselect('maintenance_enabled', new lang_string('sitemaintenancemode', 'admin'),
|
||||
new lang_string('helpsitemaintenance', 'admin'), 0, $options));
|
||||
$temp->add(new admin_setting_confightmleditor('maintenance_message', new lang_string('optionalmaintenancemessage', 'admin'),
|
||||
'', ''));
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp = new admin_settingpage('cleanup', new lang_string('cleanup', 'admin'));
|
||||
$temp->add(new admin_setting_configselect('deleteunconfirmed', new lang_string('deleteunconfirmed', 'admin'), new lang_string('configdeleteunconfirmed', 'admin'), 168, array(0 => new lang_string('never'),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
144 => new lang_string('numdays', '', 6),
|
||||
120 => new lang_string('numdays', '', 5),
|
||||
96 => new lang_string('numdays', '', 4),
|
||||
72 => new lang_string('numdays', '', 3),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
24 => new lang_string('numdays', '', 1),
|
||||
12 => new lang_string('numhours', '', 12),
|
||||
6 => new lang_string('numhours', '', 6),
|
||||
1 => new lang_string('numhours', '', 1))));
|
||||
|
||||
$temp->add(new admin_setting_configselect('deleteincompleteusers', new lang_string('deleteincompleteusers', 'admin'), new lang_string('configdeleteincompleteusers', 'admin'), 0, array(0 => new lang_string('never'),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
144 => new lang_string('numdays', '', 6),
|
||||
120 => new lang_string('numdays', '', 5),
|
||||
96 => new lang_string('numdays', '', 4),
|
||||
72 => new lang_string('numdays', '', 3),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
24 => new lang_string('numdays', '', 1))));
|
||||
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('disablegradehistory', new lang_string('disablegradehistory', 'grades'),
|
||||
new lang_string('disablegradehistory_help', 'grades'), 0));
|
||||
|
||||
$temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_string('gradehistorylifetime', 'grades'),
|
||||
new lang_string('gradehistorylifetime_help', 'grades'), 0, array(0 => new lang_string('neverdeletehistory', 'grades'),
|
||||
1000 => new lang_string('numdays', '', 1000),
|
||||
365 => new lang_string('numdays', '', 365),
|
||||
180 => new lang_string('numdays', '', 180),
|
||||
150 => new lang_string('numdays', '', 150),
|
||||
120 => new lang_string('numdays', '', 120),
|
||||
90 => new lang_string('numdays', '', 90),
|
||||
60 => new lang_string('numdays', '', 60),
|
||||
30 => new lang_string('numdays', '', 30))));
|
||||
|
||||
$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'),
|
||||
new lang_string('configtempdatafoldercleanup', 'admin'), 168, array(
|
||||
1 => new lang_string('numhours', '', 1),
|
||||
3 => new lang_string('numhours', '', 3),
|
||||
6 => new lang_string('numhours', '', 6),
|
||||
@@ -229,303 +166,224 @@ if ($hassiteconfig) {
|
||||
24 => new lang_string('numhours', '', 24),
|
||||
48 => new lang_string('numdays', '', 2),
|
||||
168 => new lang_string('numdays', '', 7),
|
||||
]
|
||||
));
|
||||
)));
|
||||
|
||||
$ADMIN->add('server', $temp);
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
$temp->add(new admin_setting_configduration('filescleanupperiod',
|
||||
new lang_string('filescleanupperiod', 'admin'),
|
||||
new lang_string('filescleanupperiod_help', 'admin'),
|
||||
86400));
|
||||
|
||||
// Environment.
|
||||
$ADMIN->add('server', new admin_externalpage('environment', new lang_string('environment', 'admin'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/environment.php"));
|
||||
$ADMIN->add('server', new admin_externalpage('environment', new lang_string('environment','admin'), "$CFG->wwwroot/$CFG->admin/environment.php"));
|
||||
$ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo'), "$CFG->wwwroot/$CFG->admin/phpinfo.php"));
|
||||
$ADMIN->add('server', new admin_externalpage('testoutgoingmailconf', new lang_string('testoutgoingmailconf', 'admin'),
|
||||
new moodle_url("$CFG->wwwroot/$CFG->admin/testoutgoingmailconf.php"), 'moodle/site:config', true));
|
||||
|
||||
// PHP info.
|
||||
$ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/phpinfo.php"));
|
||||
|
||||
// Test outgoing mail configuration (hidden, accessed via direct link from the settings page).
|
||||
$ADMIN->add('server', new admin_externalpage('testoutgoingmailconf', new lang_string('testoutgoingmailconf', 'admin'),
|
||||
new moodle_url('/admin/testoutgoingmailconf.php'), 'moodle/site:config', true));
|
||||
// "performance" settingpage
|
||||
$temp = new admin_settingpage('performance', new lang_string('performance', 'admin'));
|
||||
|
||||
// Performance.
|
||||
$temp = new admin_settingpage('performance', new lang_string('performance', 'admin'));
|
||||
// Memory limit options for large administration tasks.
|
||||
$memoryoptions = array(
|
||||
'64M' => '64M',
|
||||
'128M' => '128M',
|
||||
'256M' => '256M',
|
||||
'512M' => '512M',
|
||||
'1024M' => '1024M',
|
||||
'2048M' => '2048M');
|
||||
|
||||
// Memory limit options for large administration tasks.
|
||||
$memoryoptions = [
|
||||
'64M' => '64M',
|
||||
'128M' => '128M',
|
||||
'256M' => '256M',
|
||||
'512M' => '512M',
|
||||
'1024M' => '1024M',
|
||||
'2048M' => '2048M',
|
||||
];
|
||||
// Allow larger memory usage for 64-bit sites only.
|
||||
if (PHP_INT_SIZE === 8) {
|
||||
$memoryoptions['3072M'] = '3072M';
|
||||
$memoryoptions['4096M'] = '4096M';
|
||||
}
|
||||
|
||||
// Allow larger memory usage for 64-bit sites only.
|
||||
if (PHP_INT_SIZE === 8) {
|
||||
$memoryoptions['3072M'] = '3072M';
|
||||
$memoryoptions['4096M'] = '4096M';
|
||||
}
|
||||
|
||||
$temp->add(new admin_setting_configselect('extramemorylimit', new lang_string('extramemorylimit', 'admin'),
|
||||
new lang_string('configextramemorylimit', 'admin'), '512M', $memoryoptions));
|
||||
|
||||
$temp->add(new admin_setting_configtext('maxtimelimit', new lang_string('maxtimelimit', 'admin'),
|
||||
$temp->add(new admin_setting_configselect('extramemorylimit', new lang_string('extramemorylimit', 'admin'),
|
||||
new lang_string('configextramemorylimit', 'admin'), '512M',
|
||||
$memoryoptions));
|
||||
$temp->add(new admin_setting_configtext('maxtimelimit', new lang_string('maxtimelimit', 'admin'),
|
||||
new lang_string('maxtimelimit_desc', 'admin'), 0, PARAM_INT));
|
||||
|
||||
$temp->add(new admin_setting_configtext('curlcache', new lang_string('curlcache', 'admin'),
|
||||
new lang_string('configcurlcache', 'admin'), 120, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('curlcache', new lang_string('curlcache', 'admin'),
|
||||
new lang_string('configcurlcache', 'admin'), 120, PARAM_INT));
|
||||
|
||||
$temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('curltimeoutkbitrate', 'admin'),
|
||||
new lang_string('curltimeoutkbitrate_help', 'admin'), 56, PARAM_INT));
|
||||
$temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('curltimeoutkbitrate', 'admin'),
|
||||
new lang_string('curltimeoutkbitrate_help', 'admin'), 56, PARAM_INT));
|
||||
|
||||
$ADMIN->add('server', $temp);
|
||||
$ADMIN->add('server', $temp);
|
||||
|
||||
// Tasks.
|
||||
$ADMIN->add('server', new admin_category('taskconfig', new lang_string('taskadmintitle', 'admin')));
|
||||
|
||||
// Task processing.
|
||||
$temp = new admin_settingpage('taskprocessing', new lang_string('taskprocessing', 'admin'));
|
||||
$ADMIN->add('server', new admin_category('taskconfig', new lang_string('taskadmintitle', 'admin')));
|
||||
$temp = new admin_settingpage('taskprocessing', new lang_string('taskprocessing','admin'));
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_scheduled_concurrency_limit',
|
||||
new lang_string('task_scheduled_concurrency_limit', 'admin'),
|
||||
new lang_string('task_scheduled_concurrency_limit_desc', 'admin'),
|
||||
3,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
|
||||
$setting = new admin_setting_configcheckbox(
|
||||
'cron_enabled',
|
||||
new lang_string('cron_enabled', 'admin'),
|
||||
new lang_string('cron_enabled_desc', 'admin'),
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_scheduled_max_runtime',
|
||||
new lang_string('task_scheduled_max_runtime', 'admin'),
|
||||
new lang_string('task_scheduled_max_runtime_desc', 'admin'),
|
||||
30 * MINSECS
|
||||
)
|
||||
);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_adhoc_concurrency_limit',
|
||||
new lang_string('task_adhoc_concurrency_limit', 'admin'),
|
||||
new lang_string('task_adhoc_concurrency_limit_desc', 'admin'),
|
||||
3,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_adhoc_max_runtime',
|
||||
new lang_string('task_adhoc_max_runtime', 'admin'),
|
||||
new lang_string('task_adhoc_max_runtime_desc', 'admin'),
|
||||
30 * MINSECS
|
||||
)
|
||||
);
|
||||
$ADMIN->add('taskconfig', $temp);
|
||||
|
||||
$temp = new admin_settingpage('tasklogging', new lang_string('tasklogging','admin'));
|
||||
$temp->add(
|
||||
new admin_setting_configselect(
|
||||
'task_logmode',
|
||||
new lang_string('task_logmode', 'admin'),
|
||||
new lang_string('task_logmode_desc', 'admin'),
|
||||
\core\task\logmanager::MODE_ALL,
|
||||
[
|
||||
\core\task\logmanager::MODE_ALL => new lang_string('task_logmode_all', 'admin'),
|
||||
\core\task\logmanager::MODE_FAILONLY => new lang_string('task_logmode_failonly', 'admin'),
|
||||
\core\task\logmanager::MODE_NONE => new lang_string('task_logmode_none', 'admin'),
|
||||
]
|
||||
)
|
||||
);
|
||||
$temp->add(
|
||||
new admin_setting_configcheckbox(
|
||||
'task_logtostdout',
|
||||
new lang_string('task_logtostdout', 'admin'),
|
||||
new lang_string('task_logtostdout_desc', 'admin'),
|
||||
1
|
||||
);
|
||||
$setting->set_updatedcallback('theme_reset_static_caches');
|
||||
$temp->add($setting);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_scheduled_concurrency_limit',
|
||||
new lang_string('task_scheduled_concurrency_limit', 'admin'),
|
||||
new lang_string('task_scheduled_concurrency_limit_desc', 'admin'),
|
||||
3,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
|
||||
if (\core\task\logmanager::uses_standard_settings()) {
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_scheduled_max_runtime',
|
||||
new lang_string('task_scheduled_max_runtime', 'admin'),
|
||||
new lang_string('task_scheduled_max_runtime_desc', 'admin'),
|
||||
30 * MINSECS
|
||||
'task_logretention',
|
||||
new \lang_string('task_logretention', 'admin'),
|
||||
new \lang_string('task_logretention_desc', 'admin'),
|
||||
28 * DAYSECS
|
||||
)
|
||||
);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_adhoc_concurrency_limit',
|
||||
new lang_string('task_adhoc_concurrency_limit', 'admin'),
|
||||
new lang_string('task_adhoc_concurrency_limit_desc', 'admin'),
|
||||
3,
|
||||
'task_logretainruns',
|
||||
new \lang_string('task_logretainruns', 'admin'),
|
||||
new \lang_string('task_logretainruns_desc', 'admin'),
|
||||
20,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
}
|
||||
$ADMIN->add('taskconfig', $temp);
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_adhoc_max_runtime',
|
||||
new lang_string('task_adhoc_max_runtime', 'admin'),
|
||||
new lang_string('task_adhoc_max_runtime_desc', 'admin'),
|
||||
30 * MINSECS
|
||||
)
|
||||
);
|
||||
$ADMIN->add('taskconfig', $temp);
|
||||
if (\core\task\logmanager::uses_standard_settings()) {
|
||||
$ADMIN->add('taskconfig', new admin_externalpage(
|
||||
'tasklogs',
|
||||
new lang_string('tasklogs','admin'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/tasklogs.php"
|
||||
));
|
||||
}
|
||||
|
||||
// Task log configuration.
|
||||
$temp = new admin_settingpage('tasklogging', new lang_string('tasklogging', 'admin'));
|
||||
$temp->add(
|
||||
new admin_setting_configselect(
|
||||
'task_logmode',
|
||||
new lang_string('task_logmode', 'admin'),
|
||||
new lang_string('task_logmode_desc', 'admin'),
|
||||
\core\task\logmanager::MODE_ALL,
|
||||
[
|
||||
\core\task\logmanager::MODE_ALL => new lang_string('task_logmode_all', 'admin'),
|
||||
\core\task\logmanager::MODE_FAILONLY => new lang_string('task_logmode_failonly', 'admin'),
|
||||
\core\task\logmanager::MODE_NONE => new lang_string('task_logmode_none', 'admin'),
|
||||
]
|
||||
)
|
||||
);
|
||||
$temp->add(
|
||||
new admin_setting_configcheckbox(
|
||||
'task_logtostdout',
|
||||
new lang_string('task_logtostdout', 'admin'),
|
||||
new lang_string('task_logtostdout_desc', 'admin'),
|
||||
1
|
||||
)
|
||||
);
|
||||
// E-mail settings.
|
||||
$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
|
||||
|
||||
if (\core\task\logmanager::uses_standard_settings()) {
|
||||
$temp->add(
|
||||
new admin_setting_configduration(
|
||||
'task_logretention',
|
||||
new \lang_string('task_logretention', 'admin'),
|
||||
new \lang_string('task_logretention_desc', 'admin'),
|
||||
28 * DAYSECS
|
||||
)
|
||||
);
|
||||
$temp = new admin_settingpage('outgoingmailconfig', new lang_string('outgoingmailconfig', 'admin'));
|
||||
|
||||
$temp->add(
|
||||
new admin_setting_configtext(
|
||||
'task_logretainruns',
|
||||
new \lang_string('task_logretainruns', 'admin'),
|
||||
new \lang_string('task_logretainruns_desc', 'admin'),
|
||||
20,
|
||||
PARAM_INT
|
||||
)
|
||||
);
|
||||
}
|
||||
$ADMIN->add('taskconfig', $temp);
|
||||
|
||||
// Task logs.
|
||||
if (\core\task\logmanager::uses_standard_settings()) {
|
||||
$ADMIN->add('taskconfig', new admin_externalpage(
|
||||
'tasklogs',
|
||||
new lang_string('tasklogs', 'admin'),
|
||||
"{$CFG->wwwroot}/{$CFG->admin}/tasklogs.php"
|
||||
));
|
||||
}
|
||||
|
||||
// Email.
|
||||
$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
|
||||
|
||||
// Outgoing mail configuration.
|
||||
$temp = new admin_settingpage('outgoingmailconfig', new lang_string('outgoingmailconfig', 'admin'));
|
||||
|
||||
$temp->add(new admin_setting_heading('smtpheading', new lang_string('smtp', 'admin'),
|
||||
new lang_string('smtpdetail', 'admin')));
|
||||
|
||||
$temp->add(new admin_setting_configtext('smtphosts', new lang_string('smtphosts', 'admin'),
|
||||
new lang_string('configsmtphosts', 'admin'), '', PARAM_RAW));
|
||||
|
||||
$options = [
|
||||
'' => new lang_string('none', 'admin'),
|
||||
'ssl' => 'SSL',
|
||||
'tls' => 'TLS',
|
||||
];
|
||||
|
||||
$temp->add(new admin_setting_configselect('smtpsecure', new lang_string('smtpsecure', 'admin'),
|
||||
new lang_string('configsmtpsecure', 'admin'), '', $options));
|
||||
|
||||
$authtypeoptions = [
|
||||
'LOGIN' => 'LOGIN',
|
||||
'PLAIN' => 'PLAIN',
|
||||
'NTLM' => 'NTLM',
|
||||
'CRAM-MD5' => 'CRAM-MD5',
|
||||
];
|
||||
|
||||
$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
|
||||
new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));
|
||||
|
||||
$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
|
||||
new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));
|
||||
|
||||
$temp->add(new admin_setting_configpasswordunmask('smtppass', new lang_string('smtppass', 'admin'),
|
||||
new lang_string('configsmtpuser', 'admin'), ''));
|
||||
|
||||
$temp->add(new admin_setting_configtext('smtpmaxbulk', new lang_string('smtpmaxbulk', 'admin'),
|
||||
new lang_string('configsmtpmaxbulk', 'admin'), 1, PARAM_INT));
|
||||
|
||||
$temp->add(new admin_setting_heading('noreplydomainheading', new lang_string('noreplydomain', 'admin'),
|
||||
$temp->add(new admin_setting_heading('smtpheading', new lang_string('smtp', 'admin'),
|
||||
new lang_string('smtpdetail', 'admin')));
|
||||
$temp->add(new admin_setting_configtext('smtphosts', new lang_string('smtphosts', 'admin'),
|
||||
new lang_string('configsmtphosts', 'admin'), '', PARAM_RAW));
|
||||
$options = array('' => new lang_string('none', 'admin'), 'ssl' => 'SSL', 'tls' => 'TLS');
|
||||
$temp->add(new admin_setting_configselect('smtpsecure', new lang_string('smtpsecure', 'admin'),
|
||||
new lang_string('configsmtpsecure', 'admin'), '', $options));
|
||||
$authtypeoptions = array('LOGIN' => 'LOGIN', 'PLAIN' => 'PLAIN', 'NTLM' => 'NTLM', 'CRAM-MD5' => 'CRAM-MD5');
|
||||
$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
|
||||
new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));
|
||||
$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
|
||||
new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));
|
||||
$temp->add(new admin_setting_configpasswordunmask('smtppass', new lang_string('smtppass', 'admin'),
|
||||
new lang_string('configsmtpuser', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configtext('smtpmaxbulk', new lang_string('smtpmaxbulk', 'admin'),
|
||||
new lang_string('configsmtpmaxbulk', 'admin'), 1, PARAM_INT));
|
||||
$temp->add(new admin_setting_heading('noreplydomainheading', new lang_string('noreplydomain', 'admin'),
|
||||
new lang_string('noreplydomaindetail', 'admin')));
|
||||
|
||||
$temp->add(new admin_setting_configtext('noreplyaddress', new lang_string('noreplyaddress', 'admin'),
|
||||
new lang_string('confignoreplyaddress', 'admin'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_EMAIL));
|
||||
|
||||
$temp->add(new admin_setting_configtextarea('allowedemaildomains',
|
||||
$temp->add(new admin_setting_configtext('noreplyaddress', new lang_string('noreplyaddress', 'admin'),
|
||||
new lang_string('confignoreplyaddress', 'admin'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_EMAIL));
|
||||
$temp->add(new admin_setting_configtextarea('allowedemaildomains',
|
||||
new lang_string('allowedemaildomains', 'admin'),
|
||||
new lang_string('configallowedemaildomains', 'admin'),
|
||||
''));
|
||||
|
||||
$temp->add(new admin_setting_heading('divertallemailsheading', new lang_string('divertallemails', 'admin'),
|
||||
new lang_string('divertallemailsdetail', 'admin')));
|
||||
$temp->add(new admin_setting_configtext('divertallemailsto',
|
||||
new lang_string('divertallemailsto', 'admin'),
|
||||
new lang_string('divertallemailsto_desc', 'admin'),
|
||||
''));
|
||||
$temp->add(new admin_setting_configtextarea('divertallemailsexcept',
|
||||
new lang_string('divertallemailsexcept', 'admin'),
|
||||
new lang_string('divertallemailsexcept_desc', 'admin'),
|
||||
'', PARAM_RAW, '50', '4'));
|
||||
|
||||
$noreplyaddress = isset($CFG->noreplyaddress) ? $CFG->noreplyaddress : 'noreply@example.com';
|
||||
$dkimdomain = substr(strrchr($noreplyaddress, "@"), 1);
|
||||
$dkimselector = empty($CFG->emaildkimselector) ? '[selector]' : $CFG->emaildkimselector;
|
||||
$pempath = "\$CFG->dataroot/dkim/{$dkimdomain}/{$dkimselector}.private";
|
||||
$temp->add(new admin_setting_heading('emaildkim', new lang_string('emaildkim', 'admin'),
|
||||
new lang_string('emaildkiminfo', 'admin', ['path' => $pempath, 'docs' => \get_docs_url('Mail_configuration#DKIM')])));
|
||||
$temp->add(new admin_setting_configtext('emaildkimselector', new lang_string('emaildkimselector', 'admin'),
|
||||
new lang_string('configemaildkimselector', 'admin'), '', PARAM_FILE));
|
||||
|
||||
$url = new moodle_url('/admin/testoutgoingmailconf.php');
|
||||
$link = html_writer::link($url, get_string('testoutgoingmailconf', 'admin'));
|
||||
$temp->add(new admin_setting_heading('testoutgoinmailc', new lang_string('testoutgoingmailconf', 'admin'),
|
||||
$url = new moodle_url('/admin/testoutgoingmailconf.php');
|
||||
$link = html_writer::link($url, get_string('testoutgoingmailconf', 'admin'));
|
||||
$temp->add(new admin_setting_heading('testoutgoinmailc', new lang_string('testoutgoingmailconf', 'admin'),
|
||||
new lang_string('testoutgoingmaildetail', 'admin', $link)));
|
||||
|
||||
$temp->add(new admin_setting_heading('emaildoesnotfit', new lang_string('doesnotfit', 'admin'),
|
||||
$temp->add(new admin_setting_heading('emaildoesnotfit', new lang_string('doesnotfit', 'admin'),
|
||||
new lang_string('doesnotfitdetail', 'admin')));
|
||||
$charsets = get_list_of_charsets();
|
||||
unset($charsets['UTF-8']); // Not needed here.
|
||||
$options = array();
|
||||
$options['0'] = 'UTF-8';
|
||||
$options = array_merge($options, $charsets);
|
||||
$temp->add(new admin_setting_configselect('sitemailcharset', new lang_string('sitemailcharset', 'admin'),
|
||||
new lang_string('configsitemailcharset','admin'), '0', $options));
|
||||
$temp->add(new admin_setting_configcheckbox('allowusermailcharset', new lang_string('allowusermailcharset', 'admin'),
|
||||
new lang_string('configallowusermailcharset', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('allowattachments', new lang_string('allowattachments', 'admin'),
|
||||
new lang_string('configallowattachments', 'admin'), 1));
|
||||
$options = array('LF' => 'LF', 'CRLF' => 'CRLF');
|
||||
$temp->add(new admin_setting_configselect('mailnewline', new lang_string('mailnewline', 'admin'),
|
||||
new lang_string('configmailnewline', 'admin'), 'LF', $options));
|
||||
|
||||
$charsets = get_list_of_charsets();
|
||||
unset($charsets['UTF-8']);
|
||||
$options = [
|
||||
'0' => 'UTF-8',
|
||||
];
|
||||
$options = array_merge($options, $charsets);
|
||||
$temp->add(new admin_setting_configselect('sitemailcharset', new lang_string('sitemailcharset', 'admin'),
|
||||
new lang_string('configsitemailcharset', 'admin'), '0', $options));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('allowusermailcharset', new lang_string('allowusermailcharset', 'admin'),
|
||||
new lang_string('configallowusermailcharset', 'admin'), 0));
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('allowattachments', new lang_string('allowattachments', 'admin'),
|
||||
new lang_string('configallowattachments', 'admin'), 1));
|
||||
|
||||
$options = [
|
||||
'LF' => 'LF',
|
||||
'CRLF' => 'CRLF',
|
||||
];
|
||||
$temp->add(new admin_setting_configselect('mailnewline', new lang_string('mailnewline', 'admin'),
|
||||
new lang_string('configmailnewline', 'admin'), 'LF', $options));
|
||||
|
||||
$choices = [
|
||||
new lang_string('never', 'admin'),
|
||||
new lang_string('always', 'admin'),
|
||||
new lang_string('onlynoreply', 'admin'),
|
||||
];
|
||||
$temp->add(new admin_setting_configselect('emailfromvia', new lang_string('emailfromvia', 'admin'),
|
||||
new lang_string('configemailfromvia', 'admin'), 1, $choices));
|
||||
|
||||
$choices = array(new lang_string('never', 'admin'),
|
||||
new lang_string('always', 'admin'),
|
||||
new lang_string('onlynoreply', 'admin'));
|
||||
$temp->add(new admin_setting_configselect('emailfromvia', new lang_string('emailfromvia', 'admin'),
|
||||
new lang_string('configemailfromvia', 'admin'), 1, $choices));
|
||||
$temp->add(new admin_setting_configtext('emailsubjectprefix', new lang_string('emailsubjectprefix', 'admin'),
|
||||
new lang_string('configemailsubjectprefix', 'admin'), '', PARAM_RAW));
|
||||
|
||||
$temp->add(new admin_setting_configtextarea('emailheaders', new lang_string('emailheaders', 'admin'),
|
||||
new lang_string('configemailheaders', 'admin'), '', PARAM_RAW, '50', '3'));
|
||||
$ADMIN->add('email', $temp);
|
||||
|
||||
$ADMIN->add('email', $temp);
|
||||
|
||||
// Update notifications.
|
||||
if (empty($CFG->disableupdatenotifications)) {
|
||||
$temp = new admin_settingpage('updatenotifications', new lang_string('updatenotifications', 'core_admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('updateautocheck', new lang_string('updateautocheck', 'core_admin'),
|
||||
new lang_string('updateautocheck_desc', 'core_admin'), 1));
|
||||
$temp->add(new admin_setting_configselect('updateminmaturity', new lang_string('updateminmaturity', 'core_admin'),
|
||||
new lang_string('updateminmaturity_desc', 'core_admin'), MATURITY_STABLE,
|
||||
[
|
||||
MATURITY_ALPHA => new lang_string('maturity'.MATURITY_ALPHA, 'core_admin'),
|
||||
MATURITY_BETA => new lang_string('maturity'.MATURITY_BETA, 'core_admin'),
|
||||
MATURITY_RC => new lang_string('maturity'.MATURITY_RC, 'core_admin'),
|
||||
MATURITY_STABLE => new lang_string('maturity'.MATURITY_STABLE, 'core_admin'),
|
||||
]
|
||||
));
|
||||
$temp->add(new admin_setting_configcheckbox('updatenotifybuilds', new lang_string('updatenotifybuilds', 'core_admin'),
|
||||
new lang_string('updatenotifybuilds_desc', 'core_admin'), 0));
|
||||
$ADMIN->add('server', $temp);
|
||||
}
|
||||
// "update notifications" settingpage
|
||||
if (empty($CFG->disableupdatenotifications)) {
|
||||
$temp = new admin_settingpage('updatenotifications', new lang_string('updatenotifications', 'core_admin'));
|
||||
$temp->add(new admin_setting_configcheckbox('updateautocheck', new lang_string('updateautocheck', 'core_admin'),
|
||||
new lang_string('updateautocheck_desc', 'core_admin'), 1));
|
||||
$temp->add(new admin_setting_configselect('updateminmaturity', new lang_string('updateminmaturity', 'core_admin'),
|
||||
new lang_string('updateminmaturity_desc', 'core_admin'), MATURITY_STABLE,
|
||||
array(
|
||||
MATURITY_ALPHA => new lang_string('maturity'.MATURITY_ALPHA, 'core_admin'),
|
||||
MATURITY_BETA => new lang_string('maturity'.MATURITY_BETA, 'core_admin'),
|
||||
MATURITY_RC => new lang_string('maturity'.MATURITY_RC, 'core_admin'),
|
||||
MATURITY_STABLE => new lang_string('maturity'.MATURITY_STABLE, 'core_admin'),
|
||||
)));
|
||||
$temp->add(new admin_setting_configcheckbox('updatenotifybuilds', new lang_string('updatenotifybuilds', 'core_admin'),
|
||||
new lang_string('updatenotifybuilds_desc', 'core_admin'), 0));
|
||||
$ADMIN->add('server', $temp);
|
||||
}
|
||||
|
||||
} // end of speedup
|
||||
|
||||
@@ -39,7 +39,6 @@ $ADMIN->add('root', new admin_category('license', new lang_string('license')));
|
||||
$ADMIN->add('root', new admin_category('location', new lang_string('location','admin')));
|
||||
$ADMIN->add('root', new admin_category('language', new lang_string('language')));
|
||||
$ADMIN->add('root', new admin_category('messaging', new lang_string('messagingcategory', 'admin')));
|
||||
$ADMIN->add('root', new admin_category('payment', new lang_string('payments', 'payment')));
|
||||
$ADMIN->add('root', new admin_category('modules', new lang_string('plugins', 'admin')));
|
||||
$ADMIN->add('root', new admin_category('security', new lang_string('security','admin')));
|
||||
$ADMIN->add('root', new admin_category('appearance', new lang_string('appearance','admin')));
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_admin\local\settings\autocomplete
|
||||
|
||||
Admin setting auto complete.
|
||||
|
||||
Context variables required for this template:
|
||||
* name - element name
|
||||
* id - element id
|
||||
* options - choices
|
||||
* multiple - is multiple choices?
|
||||
* manageurl - url to manage choices
|
||||
* managetext - string to display manage url
|
||||
* tags - Should we allow typing new entries to the field?
|
||||
* ajax - Name of an AMD module to send/process ajax requests
|
||||
* placeholder - Placeholder text for an empty list
|
||||
* casesensitive - Whether the search has to be case-sensitive
|
||||
* showsuggestions - Show suggestions by default - but this can be turned off
|
||||
* noselectionstring - String that is shown when there are no selections
|
||||
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"name": "name0",
|
||||
"id": "id0",
|
||||
"options": [{
|
||||
"value": "1",
|
||||
"text": "option 1",
|
||||
"selected": true,
|
||||
"disabled": false
|
||||
}],
|
||||
"multiple": true,
|
||||
"manageurl": "",
|
||||
"managetext": "",
|
||||
"tags": false,
|
||||
"ajax": "",
|
||||
"placeholder": "",
|
||||
"casesensitive": false,
|
||||
"showsuggestions": true,
|
||||
"noselectionstring": ""
|
||||
}
|
||||
}}
|
||||
{{!
|
||||
Setting autocomplete.
|
||||
}}
|
||||
|
||||
<div class="form-select defaultsnext">
|
||||
<input type="hidden" name="{{name}}[xxxxx]" value="_qf__force_multiselect_submission">
|
||||
<select class="custom-select" name="{{name}}[]"
|
||||
id="{{id}}"
|
||||
{{#multiple}}multiple{{/multiple}}>
|
||||
{{#options}}
|
||||
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{{text}}}</option>
|
||||
{{/options}}
|
||||
</select>
|
||||
{{#manageurl}}
|
||||
<a href="{{manageurl}}">{{managetext}}</a>
|
||||
{{/manageurl}}
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
{{#js}}
|
||||
require(['core/form-autocomplete'], function(module) {
|
||||
module.enhance({{#quote}}#{{id}}{{/quote}},
|
||||
{{tags}},
|
||||
{{#quote}}{{ajax}}{{/quote}},
|
||||
{{#quote}}{{placeholder}}{{/quote}},
|
||||
{{casesensitive}},
|
||||
{{showsuggestions}},
|
||||
{{#quote}}{{noselectionstring}}{{/quote}});
|
||||
});
|
||||
{{/js}}
|
||||
@@ -53,8 +53,11 @@ class behat_admin extends behat_base {
|
||||
}
|
||||
|
||||
foreach ($data as $label => $value) {
|
||||
// Navigate straight to the search results fo rthis label.
|
||||
$this->execute('behat_general::i_visit', ["/admin/search.php?query=" . urlencode($label)]);
|
||||
$this->execute('behat_navigation::i_select_from_flat_navigation_drawer', [get_string('administrationsite')]);
|
||||
|
||||
// Search by label.
|
||||
$this->execute('behat_forms::i_set_the_field_to', [get_string('query', 'admin'), $label]);
|
||||
$this->execute("behat_forms::press_button", get_string('search', 'admin'));
|
||||
|
||||
// Admin settings does not use the same DOM structure than other moodle forms
|
||||
// but we also need to use lib/behat/form_field/* to deal with the different moodle form elements.
|
||||
|
||||
+2
-10
@@ -1,10 +1,2 @@
|
||||
/**
|
||||
* Shows a dialogue with info about this logs.
|
||||
*
|
||||
* @module tool_analytics/log_info
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define("tool_analytics/log_info",["jquery","core/str","core/modal_factory","core/notification"],(function($,str,ModalFactory,Notification){return{loadInfo:function(id,info){var link=$('[data-model-log-id="'+id+'"]');str.get_string("loginfo","tool_analytics").then((function(langString){var bodyInfo=$("<ul>");return info.forEach((function(item){bodyInfo.append("<li>"+item+"</li>")})),bodyInfo.append("</ul>"),ModalFactory.create({title:langString,body:bodyInfo.html(),large:!0},link)})).catch(Notification.exception)}}}));
|
||||
|
||||
//# sourceMappingURL=log_info.min.js.map
|
||||
define ("tool_analytics/log_info",["jquery","core/str","core/modal_factory","core/notification"],function(a,b,c,d){return{loadInfo:function loadInfo(e,f){var g=a("[data-model-log-id=\""+e+"\"]");b.get_string("loginfo","tool_analytics").then(function(b){var d=a("<ul>");f.forEach(function(a){d.append("<li>"+a+"</li>")});d.append("</ul>");return c.create({title:b,body:d.html(),large:!0},g)}).catch(d.exception)}}});
|
||||
//# sourceMappingURL=log_info.min.js.map
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"log_info.min.js","sources":["../src/log_info.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Shows a dialogue with info about this logs.\n *\n * @module tool_analytics/log_info\n * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/modal_factory', 'core/notification'], function($, str, ModalFactory, Notification) {\n\n return /** @alias module:tool_analytics/log_info */ {\n\n /**\n * Prepares a modal info for a log's results.\n *\n * @method loadInfo\n * @param {int} id\n * @param {string[]} info\n */\n loadInfo: function(id, info) {\n\n var link = $('[data-model-log-id=\"' + id + '\"]');\n str.get_string('loginfo', 'tool_analytics').then(function(langString) {\n\n var bodyInfo = $(\"<ul>\");\n info.forEach(function(item) {\n bodyInfo.append('<li>' + item + '</li>');\n });\n bodyInfo.append(\"</ul>\");\n\n return ModalFactory.create({\n title: langString,\n body: bodyInfo.html(),\n large: true,\n }, link);\n\n }).catch(Notification.exception);\n }\n };\n});\n"],"names":["define","$","str","ModalFactory","Notification","loadInfo","id","info","link","get_string","then","langString","bodyInfo","forEach","item","append","create","title","body","html","large","catch","exception"],"mappings":";;;;;;;AAsBAA,iCAAO,CAAC,SAAU,WAAY,qBAAsB,sBAAsB,SAASC,EAAGC,IAAKC,aAAcC,oBAEjD,CAShDC,SAAU,SAASC,GAAIC,UAEfC,KAAOP,EAAE,uBAAyBK,GAAK,MAC3CJ,IAAIO,WAAW,UAAW,kBAAkBC,MAAK,SAASC,gBAElDC,SAAWX,EAAE,eACjBM,KAAKM,SAAQ,SAASC,MAClBF,SAASG,OAAO,OAASD,KAAO,YAEpCF,SAASG,OAAO,SAETZ,aAAaa,OAAO,CACvBC,MAAON,WACPO,KAAMN,SAASO,OACfC,OAAO,GACRZ,SAEJa,MAAMjB,aAAakB"}
|
||||
{"version":3,"sources":["../src/log_info.js"],"names":["define","$","str","ModalFactory","Notification","loadInfo","id","info","link","get_string","then","langString","bodyInfo","forEach","item","append","create","title","body","html","large","catch","exception"],"mappings":"AAwBAA,OAAM,2BAAC,CAAC,QAAD,CAAW,UAAX,CAAuB,oBAAvB,CAA6C,mBAA7C,CAAD,CAAoE,SAASC,CAAT,CAAYC,CAAZ,CAAiBC,CAAjB,CAA+BC,CAA/B,CAA6C,CAEnH,MAAoD,CAShDC,QAAQ,CAAE,kBAASC,CAAT,CAAaC,CAAb,CAAmB,CAEzB,GAAIC,CAAAA,CAAI,CAAGP,CAAC,CAAC,wBAAyBK,CAAzB,CAA8B,KAA/B,CAAZ,CACAJ,CAAG,CAACO,UAAJ,CAAe,SAAf,CAA0B,gBAA1B,EAA4CC,IAA5C,CAAiD,SAASC,CAAT,CAAqB,CAElE,GAAIC,CAAAA,CAAQ,CAAGX,CAAC,CAAC,MAAD,CAAhB,CACAM,CAAI,CAACM,OAAL,CAAa,SAASC,CAAT,CAAe,CACxBF,CAAQ,CAACG,MAAT,CAAgB,OAASD,CAAT,CAAgB,OAAhC,CACH,CAFD,EAGAF,CAAQ,CAACG,MAAT,CAAgB,OAAhB,EAEA,MAAOZ,CAAAA,CAAY,CAACa,MAAb,CAAoB,CACvBC,KAAK,CAAEN,CADgB,CAEvBO,IAAI,CAAEN,CAAQ,CAACO,IAAT,EAFiB,CAGvBC,KAAK,GAHkB,CAApB,CAIJZ,CAJI,CAMV,CAdD,EAcGa,KAdH,CAcSjB,CAAY,CAACkB,SAdtB,CAeH,CA3B+C,CA6BvD,CA/BK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Shows a dialogue with info about this logs.\n *\n * @module tool_analytics/log_info\n * @class log_info\n * @package tool_analytics\n * @copyright 2017 David Monllao {@link http://www.davidmonllao.com}\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/str', 'core/modal_factory', 'core/notification'], function($, str, ModalFactory, Notification) {\n\n return /** @alias module:tool_analytics/log_info */ {\n\n /**\n * Prepares a modal info for a log's results.\n *\n * @method loadInfo\n * @param {int} id\n * @param {string[]} info\n */\n loadInfo: function(id, info) {\n\n var link = $('[data-model-log-id=\"' + id + '\"]');\n str.get_string('loginfo', 'tool_analytics').then(function(langString) {\n\n var bodyInfo = $(\"<ul>\");\n info.forEach(function(item) {\n bodyInfo.append('<li>' + item + '</li>');\n });\n bodyInfo.append(\"</ul>\");\n\n return ModalFactory.create({\n title: langString,\n body: bodyInfo.html(),\n large: true,\n }, link);\n\n }).catch(Notification.exception);\n }\n };\n});\n"],"file":"log_info.min.js"}
|
||||
+2
-10
@@ -1,10 +1,2 @@
|
||||
/**
|
||||
* AMD module for model actions confirmation.
|
||||
*
|
||||
* @module tool_analytics/model
|
||||
* @copyright 2017 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define("tool_analytics/model",["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],(function($,Str,log,Notification,ModalFactory,ModalEvents,Templates){var actionsList={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},delete:{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}};return{confirmAction:function(actionId,actionType){$('[data-action-id="'+actionId+'"]').on("click",(function(ev){ev.preventDefault();var a=$(ev.currentTarget);if(void 0!==actionsList[actionType]){var wrap,reqStrings=[actionsList[actionType].title,actionsList[actionType].body];reqStrings[1].param=(wrap=$(a).closest("[data-model-name]")).length?wrap.attr("data-model-name"):(log.error("Unexpected DOM error - unable to obtain the model name"),"");var stringsPromise=Str.get_strings(reqStrings),modalPromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL});$.when(stringsPromise,modalPromise).then((function(strings,modal){return modal.setTitle(strings[0]),modal.setBody(strings[1]),modal.setSaveButtonText(strings[0]),modal.getRoot().on(ModalEvents.save,(function(){window.location.href=a.attr("href")})),modal.show(),modal})).fail(Notification.exception)}else log.error('Action "'+actionType+'" is not allowed.')}))},selectEvaluationOptions:function(actionId,trainedOnlyExternally){$('[data-action-id="'+actionId+'"]').on("click",(function(ev){ev.preventDefault();var a=$(ev.currentTarget),timeSplittingMethods=$(this).attr("data-timesplitting-methods"),stringsPromise=Str.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluate",component:"tool_analytics"}]),modalPromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL}),bodyPromise=Templates.render("tool_analytics/evaluation_options",{trainedexternally:trainedOnlyExternally,timesplittingmethods:JSON.parse(timeSplittingMethods)});$.when(stringsPromise,modalPromise).then((function(strings,modal){return modal.getRoot().on(ModalEvents.hidden,modal.destroy.bind(modal)),modal.setTitle(strings[0]),modal.setSaveButtonText(strings[1]),modal.setBody(bodyPromise),modal.getRoot().on(ModalEvents.save,(function(){"trainedmodel"==$("input[name='evaluationmode']:checked").val()&&a.attr("href",a.attr("href")+"&mode=trainedmodel");var timeSplittingMethod=$("#id-evaluation-timesplitting").val();a.attr("href",a.attr("href")+"×plitting="+timeSplittingMethod),window.location.href=a.attr("href")})),modal.show(),modal})).fail(Notification.exception)}))},selectExportOptions:function(actionId,isTrained){$('[data-action-id="'+actionId+'"]').on("click",(function(ev){ev.preventDefault();var a=$(ev.currentTarget);if(!isTrained)return a.attr("href",a.attr("href")+"&action=exportmodel&includeweights=0"),void(window.location.href=a.attr("href"));var stringsPromise=Str.get_strings([{key:"export",component:"tool_analytics"}]),modalPromise=ModalFactory.create({type:ModalFactory.types.SAVE_CANCEL}),bodyPromise=Templates.render("tool_analytics/export_options",{});$.when(stringsPromise,modalPromise).then((function(strings,modal){return modal.getRoot().on(ModalEvents.hidden,modal.destroy.bind(modal)),modal.setTitle(strings[0]),modal.setSaveButtonText(strings[0]),modal.setBody(bodyPromise),modal.getRoot().on(ModalEvents.save,(function(){"exportdata"==$("input[name='exportoption']:checked").val()?a.attr("href",a.attr("href")+"&action=exportdata"):(a.attr("href",a.attr("href")+"&action=exportmodel"),$("#id-includeweights").is(":checked")?a.attr("href",a.attr("href")+"&includeweights=1"):a.attr("href",a.attr("href")+"&includeweights=0")),window.location.href=a.attr("href")})),modal.show(),modal})).fail(Notification.exception)}))}}}));
|
||||
|
||||
//# sourceMappingURL=model.min.js.map
|
||||
define ("tool_analytics/model",["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],function(b,c,d,e,f,g,h){var i={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},delete:{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}},j=function(a){var c=b(a).closest("[data-model-name]");if(c.length){return c.attr("data-model-name")}else{d.error("Unexpected DOM error - unable to obtain the model name");return""}};return{confirmAction:function confirmAction(a,h){b("[data-action-id=\""+a+"\"]").on("click",function(k){k.preventDefault();var l=b(k.currentTarget);if("undefined"==typeof i[h]){d.error("Action \""+h+"\" is not allowed.");return}var a=[i[h].title,i[h].body];a[1].param=j(l);var m=c.get_strings(a),n=f.create({type:f.types.SAVE_CANCEL});b.when(m,n).then(function(a,b){b.setTitle(a[0]);b.setBody(a[1]);b.setSaveButtonText(a[0]);b.getRoot().on(g.save,function(){window.location.href=l.attr("href")});b.show();return b}).fail(e.exception)})},selectEvaluationOptions:function selectEvaluationOptions(a,d){b("[data-action-id=\""+a+"\"]").on("click",function(i){i.preventDefault();var j=b(i.currentTarget),a=b(this).attr("data-timesplitting-methods"),k=c.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluate",component:"tool_analytics"}]),l=f.create({type:f.types.SAVE_CANCEL}),m=h.render("tool_analytics/evaluation_options",{trainedexternally:d,timesplittingmethods:JSON.parse(a)});b.when(k,l).then(function(a,c){c.getRoot().on(g.hidden,c.destroy.bind(c));c.setTitle(a[0]);c.setSaveButtonText(a[1]);c.setBody(m);c.getRoot().on(g.save,function(){var a=b("input[name='evaluationmode']:checked").val();if("trainedmodel"==a){j.attr("href",j.attr("href")+"&mode=trainedmodel")}var c=b("#id-evaluation-timesplitting").val();j.attr("href",j.attr("href")+"×plitting="+c);window.location.href=j.attr("href")});c.show();return c}).fail(e.exception)})},selectExportOptions:function selectExportOptions(a,d){b("[data-action-id=\""+a+"\"]").on("click",function(i){i.preventDefault();var j=b(i.currentTarget);if(!d){j.attr("href",j.attr("href")+"&action=exportmodel&includeweights=0");window.location.href=j.attr("href");return}var a=c.get_strings([{key:"export",component:"tool_analytics"}]),k=f.create({type:f.types.SAVE_CANCEL}),l=h.render("tool_analytics/export_options",{});b.when(a,k).then(function(a,c){c.getRoot().on(g.hidden,c.destroy.bind(c));c.setTitle(a[0]);c.setSaveButtonText(a[0]);c.setBody(l);c.getRoot().on(g.save,function(){var a=b("input[name='exportoption']:checked").val();if("exportdata"==a){j.attr("href",j.attr("href")+"&action=exportdata")}else{j.attr("href",j.attr("href")+"&action=exportmodel");if(b("#id-includeweights").is(":checked")){j.attr("href",j.attr("href")+"&includeweights=1")}else{j.attr("href",j.attr("href")+"&includeweights=0")}}window.location.href=j.attr("href")});c.show();return c}).fail(e.exception)})}}});
|
||||
//# sourceMappingURL=model.min.js.map
|
||||
|
||||
File diff suppressed because one or more lines are too long
+2
-10
@@ -1,10 +1,2 @@
|
||||
/**
|
||||
* Potential contexts selector module.
|
||||
*
|
||||
* @module tool_analytics/potential-contexts
|
||||
* @copyright 2019 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define("tool_analytics/potential-contexts",["jquery","core/ajax"],(function($,Ajax){return{processResults:function(selector,results){var contexts=[];return $.isArray(results)?($.each(results,(function(index,context){contexts.push({value:context.id,label:context.name})})),contexts):results},transport:function(selector,query,success,failure){var modelid=$(selector).attr("modelid")||null;Ajax.call([{methodname:"tool_analytics_potential_contexts",args:{query:query,modelid:modelid}}])[0].then(success).fail(failure)}}}));
|
||||
|
||||
//# sourceMappingURL=potential-contexts.min.js.map
|
||||
define ("tool_analytics/potential-contexts",["jquery","core/ajax"],function(a,b){return{processResults:function processResults(b,c){var d=[];if(a.isArray(c)){a.each(c,function(a,b){d.push({value:b.id,label:b.name})});return d}else{return c}},transport:function transport(c,d,e,f){var g,h=a(c).attr("modelid")||null;g=b.call([{methodname:"tool_analytics_potential_contexts",args:{query:d,modelid:h}}]);g[0].then(e).fail(f)}}});
|
||||
//# sourceMappingURL=potential-contexts.min.js.map
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"potential-contexts.min.js","sources":["../src/potential-contexts.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Potential contexts selector module.\n *\n * @module tool_analytics/potential-contexts\n * @copyright 2019 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n return /** @alias module:tool_analytics/potential-contexts */ {\n\n processResults: function(selector, results) {\n var contexts = [];\n if ($.isArray(results)) {\n $.each(results, function(index, context) {\n contexts.push({\n value: context.id,\n label: context.name\n });\n });\n return contexts;\n\n } else {\n return results;\n }\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n let modelid = $(selector).attr('modelid') || null;\n promise = Ajax.call([{\n methodname: 'tool_analytics_potential_contexts',\n args: {\n query: query,\n modelid: modelid\n }\n }]);\n\n promise[0].then(success).fail(failure);\n }\n\n };\n\n});\n"],"names":["define","$","Ajax","processResults","selector","results","contexts","isArray","each","index","context","push","value","id","label","name","transport","query","success","failure","modelid","attr","call","methodname","args","then","fail"],"mappings":";;;;;;;AAuBAA,2CAAO,CAAC,SAAU,cAAc,SAASC,EAAGC,YAEsB,CAE1DC,eAAgB,SAASC,SAAUC,aAC3BC,SAAW,UACXL,EAAEM,QAAQF,UACVJ,EAAEO,KAAKH,SAAS,SAASI,MAAOC,SAC5BJ,SAASK,KAAK,CACVC,MAAOF,QAAQG,GACfC,MAAOJ,QAAQK,UAGhBT,UAGAD,SAIfW,UAAW,SAASZ,SAAUa,MAAOC,QAASC,aAGtCC,QAAUnB,EAAEG,UAAUiB,KAAK,YAAc,KACnCnB,KAAKoB,KAAK,CAAC,CACjBC,WAAY,oCACZC,KAAM,CACFP,MAAOA,MACPG,QAASA,YAIT,GAAGK,KAAKP,SAASQ,KAAKP"}
|
||||
{"version":3,"sources":["../src/potential-contexts.js"],"names":["define","$","Ajax","processResults","selector","results","contexts","isArray","each","index","context","push","value","id","label","name","transport","query","success","failure","promise","modelid","attr","call","methodname","args","then","fail"],"mappings":"AAyBAA,OAAM,qCAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAE9C,MAA8D,CAE1DC,cAAc,CAAE,wBAASC,CAAT,CAAmBC,CAAnB,CAA4B,CACxC,GAAIC,CAAAA,CAAQ,CAAG,EAAf,CACA,GAAIL,CAAC,CAACM,OAAF,CAAUF,CAAV,CAAJ,CAAwB,CACpBJ,CAAC,CAACO,IAAF,CAAOH,CAAP,CAAgB,SAASI,CAAT,CAAgBC,CAAhB,CAAyB,CACrCJ,CAAQ,CAACK,IAAT,CAAc,CACVC,KAAK,CAAEF,CAAO,CAACG,EADL,CAEVC,KAAK,CAAEJ,CAAO,CAACK,IAFL,CAAd,CAIH,CALD,EAMA,MAAOT,CAAAA,CAEV,CATD,IASO,CACH,MAAOD,CAAAA,CACV,CACJ,CAhByD,CAkB1DW,SAAS,CAAE,mBAASZ,CAAT,CAAmBa,CAAnB,CAA0BC,CAA1B,CAAmCC,CAAnC,CAA4C,IAC/CC,CAAAA,CAD+C,CAG/CC,CAAO,CAAGpB,CAAC,CAACG,CAAD,CAAD,CAAYkB,IAAZ,CAAiB,SAAjB,GAA+B,IAHM,CAInDF,CAAO,CAAGlB,CAAI,CAACqB,IAAL,CAAU,CAAC,CACjBC,UAAU,CAAE,mCADK,CAEjBC,IAAI,CAAE,CACFR,KAAK,CAAEA,CADL,CAEFI,OAAO,CAAEA,CAFP,CAFW,CAAD,CAAV,CAAV,CAQAD,CAAO,CAAC,CAAD,CAAP,CAAWM,IAAX,CAAgBR,CAAhB,EAAyBS,IAAzB,CAA8BR,CAA9B,CACH,CA/ByD,CAmCjE,CArCK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Potential contexts selector module.\n *\n * @module tool_analytics/potential-contexts\n * @class potential-contexts\n * @package tool_analytics\n * @copyright 2019 David Monllao\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax'], function($, Ajax) {\n\n return /** @alias module:tool_analytics/potential-contexts */ {\n\n processResults: function(selector, results) {\n var contexts = [];\n if ($.isArray(results)) {\n $.each(results, function(index, context) {\n contexts.push({\n value: context.id,\n label: context.name\n });\n });\n return contexts;\n\n } else {\n return results;\n }\n },\n\n transport: function(selector, query, success, failure) {\n var promise;\n\n let modelid = $(selector).attr('modelid') || null;\n promise = Ajax.call([{\n methodname: 'tool_analytics_potential_contexts',\n args: {\n query: query,\n modelid: modelid\n }\n }]);\n\n promise[0].then(success).fail(failure);\n }\n\n };\n\n});\n"],"file":"potential-contexts.min.js"}
|
||||
@@ -17,6 +17,8 @@
|
||||
* Shows a dialogue with info about this logs.
|
||||
*
|
||||
* @module tool_analytics/log_info
|
||||
* @class log_info
|
||||
* @package tool_analytics
|
||||
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
* Potential contexts selector module.
|
||||
*
|
||||
* @module tool_analytics/potential-contexts
|
||||
* @class potential-contexts
|
||||
* @package tool_analytics
|
||||
* @copyright 2019 David Monllao
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
@@ -64,7 +64,7 @@ class models_list implements \renderable, \templatable {
|
||||
$data = new \stdClass();
|
||||
|
||||
$newmodelmenu = new \action_menu();
|
||||
$newmodelmenu->set_menu_trigger(get_string('newmodel', 'tool_analytics'), 'btn btn-secondary');
|
||||
$newmodelmenu->set_menu_trigger(get_string('newmodel', 'tool_analytics'), 'btn btn-default');
|
||||
$newmodelmenu->set_alignment(\action_menu::TL, \action_menu::BL);
|
||||
|
||||
$newmodelmenu->add(new \action_menu_link(
|
||||
|
||||
@@ -137,7 +137,7 @@ if (!empty($validdatasets) && !$model->is_enabled() && $options['non-interactive
|
||||
}
|
||||
|
||||
// Refresh the instance to prevent unexpected issues.
|
||||
$model = new \core_analytics\model($options['modelid']);
|
||||
$model = new \core_analytics\model($modelobj);
|
||||
|
||||
// Set the time splitting method file and enable it.
|
||||
$model->enable($input);
|
||||
|
||||
@@ -57,10 +57,10 @@
|
||||
{{/trainedexternally}}
|
||||
|
||||
{{! Hidden by default if #trainedexternally as the default option is trainedmodel in this case.}}
|
||||
<div id="id-evaluation-timesplitting-container" class="mt-3 {{#trainedexternally}}hidden{{/trainedexternally}}">
|
||||
<div id="id-evaluation-timesplitting-container" class="m-t-1 {{#trainedexternally}}hidden{{/trainedexternally}}">
|
||||
{{#str}} selecttimesplittingforevaluation, tool_analytics {{/str}}
|
||||
<div>
|
||||
<select id="id-evaluation-timesplitting" name="timesplitting" class="custom-select mt-3">
|
||||
<select id="id-evaluation-timesplitting" name="timesplitting" class="custom-select m-t-1">
|
||||
{{#timesplittingmethods}}
|
||||
<option value="{{id}}">{{text}}</option>
|
||||
{{/timesplittingmethods}}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<input class="custom-control-input" type="radio" name="exportoption" id="id-mode-exportmodel" value="exportmodel" checked>
|
||||
<label class="custom-control-label" for="id-mode-exportmodel">{{#str}} exportmodel, tool_analytics {{/str}}</label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox ml-5" id="id-includeweights-container">
|
||||
<div class="custom-control custom-checkbox m-l-2" id="id-includeweights-container">
|
||||
<input class="custom-control-input" type="checkbox" id="id-includeweights" value="1" checked>
|
||||
<label class="custom-control-label" for="id-includeweights">{{#str}} exportincludeweights, tool_analytics {{/str}}</label>
|
||||
</div>
|
||||
|
||||
@@ -66,6 +66,8 @@ class tool_analytics_external_testcase extends externallib_advanced_testcase {
|
||||
|
||||
/**
|
||||
* test_potential_contexts description
|
||||
*
|
||||
* @expectedException required_capability_exception
|
||||
*/
|
||||
public function test_potential_contexts_no_manager() {
|
||||
$this->resetAfterTest();
|
||||
@@ -73,7 +75,6 @@ class tool_analytics_external_testcase extends externallib_advanced_testcase {
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
$this->expectException(required_capability_exception::class);
|
||||
$this->assertCount(2, \tool_analytics\external::potential_contexts());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2020110300; // Requires this Moodle version.
|
||||
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2020060900; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_analytics'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2020110900;
|
||||
$plugin->requires = 2020110300;
|
||||
$plugin->version = 2020061500;
|
||||
$plugin->requires = 2020060900;
|
||||
$plugin->component = 'tool_availabilityconditions';
|
||||
|
||||
@@ -49,10 +49,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'torun' => 0,
|
||||
'optimize-runs' => '',
|
||||
'add-core-features-to-theme' => false,
|
||||
'axe' => false,
|
||||
'disable-composer' => false,
|
||||
'composer-upgrade' => true,
|
||||
'composer-self-update' => true,
|
||||
),
|
||||
array(
|
||||
'j' => 'parallel',
|
||||
@@ -68,36 +64,18 @@ $help = "
|
||||
Behat utilities to initialise behat tests
|
||||
|
||||
Usage:
|
||||
php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]]
|
||||
[--axe] [-o | --optimize-runs] [-a | --add-core-features-to-theme]
|
||||
[--no-composer-self-update] [--no-composer-upgrade]
|
||||
[--disable-composer]
|
||||
[--help]
|
||||
php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]] [--help]
|
||||
|
||||
Options:
|
||||
-j, --parallel Number of parallel behat run to initialise
|
||||
-m, --maxruns Max parallel processes to be executed at one time
|
||||
--fromrun Execute run starting from (Used for parallel runs on different vms)
|
||||
--torun Execute run till (Used for parallel runs on different vms)
|
||||
--axe Include axe accessibility tests
|
||||
-j, --parallel Number of parallel behat run to initialise
|
||||
-m, --maxruns Max parallel processes to be executed at one time.
|
||||
--fromrun Execute run starting from (Used for parallel runs on different vms)
|
||||
--torun Execute run till (Used for parallel runs on different vms)
|
||||
|
||||
-o, --optimize-runs
|
||||
Split features with specified tags in all parallel runs.
|
||||
-o, --optimize-runs Split features with specified tags in all parallel runs.
|
||||
-a, --add-core-features-to-theme Add all core features to specified theme's
|
||||
|
||||
-a, --add-core-features-to-theme
|
||||
Add all core features to specified theme's
|
||||
|
||||
--no-composer-self-update
|
||||
Prevent upgrade of the composer utility using its self-update command
|
||||
|
||||
--no-composer-upgrade
|
||||
Prevent update development dependencies using composer
|
||||
|
||||
--disable-composer
|
||||
A shortcut to disable composer self-update and dependency update
|
||||
Note: Installation of composer and/or dependencies will still happen as required
|
||||
|
||||
-h, --help Print out this help
|
||||
-h, --help Print out this help
|
||||
|
||||
Example from Moodle root directory:
|
||||
\$ php admin/tool/behat/cli/init.php --parallel=2
|
||||
@@ -124,10 +102,7 @@ if ($options['parallel'] && $options['parallel'] > 1) {
|
||||
}
|
||||
} else {
|
||||
// Only sanitize options for single run.
|
||||
$cmdoptionsforsinglerun = [
|
||||
'add-core-features-to-theme',
|
||||
'axe',
|
||||
];
|
||||
$cmdoptionsforsinglerun = array('add-core-features-to-theme');
|
||||
|
||||
foreach ($cmdoptionsforsinglerun as $option) {
|
||||
if (!empty($options[$option])) {
|
||||
@@ -140,15 +115,8 @@ if ($options['parallel'] && $options['parallel'] > 1) {
|
||||
$cwd = getcwd();
|
||||
$output = null;
|
||||
|
||||
if ($options['disable-composer']) {
|
||||
// Disable self-update and upgrade easily.
|
||||
// Note: Installation will still occur regardless of this setting.
|
||||
$options['composer-self-update'] = false;
|
||||
$options['composer-upgrade'] = false;
|
||||
}
|
||||
|
||||
// Install and update composer and dependencies as required.
|
||||
testing_update_composer_dependencies($options['composer-self-update'], $options['composer-upgrade']);
|
||||
// If behat dependencies not downloaded then do it first, else symfony/process can't be used.
|
||||
testing_update_composer_dependencies();
|
||||
|
||||
// Check whether the behat test environment needs to be updated.
|
||||
chdir(__DIR__);
|
||||
|
||||
@@ -45,7 +45,7 @@ list($options, $unrecognised) = cli_get_params(
|
||||
array(
|
||||
'stop-on-failure' => 0,
|
||||
'verbose' => false,
|
||||
'replace' => '',
|
||||
'replace' => false,
|
||||
'help' => false,
|
||||
'tags' => '',
|
||||
'profile' => '',
|
||||
@@ -70,7 +70,7 @@ $help = "
|
||||
Behat utilities to run behat tests in parallel
|
||||
|
||||
Usage:
|
||||
php run.php [--BEHAT_OPTION=\"value\"] [--feature=\"value\"] [--replace=\"{run}\"] [--fromrun=value --torun=value] [--help]
|
||||
php run.php [--BEHAT_OPTION=\"value\"] [--feature=\"value\"] [--replace] [--fromrun=value --torun=value] [--help]
|
||||
|
||||
Options:
|
||||
--BEHAT_OPTION Any combination of behat option specified in http://behat.readthedocs.org/en/v2.5/guides/6.cli.html
|
||||
@@ -144,10 +144,9 @@ $extraopts = $unrecognised;
|
||||
if ($options['profile']) {
|
||||
$profile = $options['profile'];
|
||||
|
||||
// If profile passed is not set, then exit (note we skip if the 'replace' option is found within the 'profile' value).
|
||||
// If profile passed is not set, then exit.
|
||||
if (!isset($CFG->behat_config[$profile]) && !isset($CFG->behat_profiles[$profile]) &&
|
||||
!($options['replace'] && (strpos($profile, (string) $options['replace']) !== false))) {
|
||||
|
||||
!(isset($options['replace']) && (strpos($options['profile'], $options['replace']) >= 0 ))) {
|
||||
echo "Invalid profile passed: " . $profile . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'torun' => 0,
|
||||
'optimize-runs' => '',
|
||||
'add-core-features-to-theme' => false,
|
||||
'axe' => false,
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
@@ -70,7 +69,7 @@ $help = "
|
||||
Behat utilities to manage the test environment
|
||||
|
||||
Usage:
|
||||
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--axe|--help] [--parallel=value [--maxruns=value]]
|
||||
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--help] [--parallel=value [--maxruns=value]]
|
||||
|
||||
Options:
|
||||
--install Installs the test environment for acceptance tests
|
||||
@@ -79,7 +78,6 @@ Options:
|
||||
--disable Disables test environment
|
||||
--diag Get behat test environment status code
|
||||
--updatesteps Update feature step file.
|
||||
--axe Include axe accessibility tests
|
||||
|
||||
-j, --parallel Number of parallel behat run operation
|
||||
-m, --maxruns Max parallel processes to be executed at one time.
|
||||
|
||||
@@ -49,7 +49,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'updatesteps' => false,
|
||||
'optimize-runs' => '',
|
||||
'add-core-features-to-theme' => false,
|
||||
'axe' => false,
|
||||
),
|
||||
array(
|
||||
'h' => 'help',
|
||||
@@ -76,7 +75,6 @@ Options:
|
||||
--disable Disables test environment
|
||||
--diag Get behat test environment status code
|
||||
--updatesteps Update feature step file.
|
||||
--axe Include axe accessibility tests
|
||||
|
||||
-o, --optimize-runs Split features with specified tags in all parallel runs.
|
||||
-a, --add-core-features-to-theme Add all core features to specified theme's
|
||||
@@ -183,17 +181,11 @@ if ($options['install']) {
|
||||
behat_config_manager::set_behat_run_config_value('behatsiteenabled', 1);
|
||||
}
|
||||
|
||||
// Define whether to run Behat with axe tests.
|
||||
behat_config_manager::set_behat_run_config_value('axe', $options['axe']);
|
||||
|
||||
// Enable test mode.
|
||||
$timestart = microtime(true);
|
||||
mtrace('Creating Behat configuration ...', '');
|
||||
behat_util::start_test_mode($options['add-core-features-to-theme'], $options['optimize-runs'], $parallel, $run);
|
||||
mtrace(' done in ' . round(microtime(true) - $timestart, 2) . ' seconds.');
|
||||
|
||||
// Themes are only built in the 'enable' command.
|
||||
behat_util::build_themes(true);
|
||||
behat_util::build_themes();
|
||||
mtrace("Testing environment themes built");
|
||||
|
||||
// This is only displayed once for parallel install.
|
||||
|
||||
@@ -46,7 +46,6 @@ $string['stepsdefinitionstype'] = 'Type';
|
||||
$string['theninfo'] = 'Then. Checkings to ensure the outcomes are the expected ones';
|
||||
$string['unknownexceptioninfo'] = 'There was a problem with Selenium or your browser. Please ensure you are using the latest version of Selenium. Error:';
|
||||
$string['viewsteps'] = 'Filter';
|
||||
$string['warndirrootconfigfound'] = 'A configuration file was found at {$a}. This file is not automatically updated and may become stale. We recommend removing this file.';
|
||||
$string['wheninfo'] = 'When. Action that provokes an event';
|
||||
$string['wrongbehatsetup'] = 'Something is wrong with the behat setup and so step definitions cannot be listed: <b>{$a->errormsg}</b><br/><br/>Please check:<ul>
|
||||
<li>$CFG->behat_dataroot, $CFG->behat_prefix and $CFG->behat_wwwroot are set in config.php with different values from $CFG->dataroot, $CFG->prefix and $CFG->wwwroot.</li>
|
||||
|
||||
@@ -156,7 +156,7 @@ Feature: Set up contextual data for tests
|
||||
And I log in as "user5"
|
||||
And I should see "You are logged in as"
|
||||
And I am on "Course 1" course homepage
|
||||
And I should see "You cannot enrol yourself in this course."
|
||||
And I should see "You can not enrol yourself in this course."
|
||||
|
||||
Scenario: Add modules
|
||||
Given the following "courses" exist:
|
||||
|
||||
@@ -21,5 +21,5 @@ Feature: Transform date time string arguments
|
||||
And I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test assignment name"
|
||||
And I should see "##yesterday##%A, %d %B %Y##"
|
||||
And I should see "##yesterday##l, j F Y##"
|
||||
And I log out
|
||||
|
||||
@@ -75,9 +75,9 @@ Feature: Edit capabilities
|
||||
| Your word for 'Student' | Studier & 'learner' |
|
||||
And I press "Save and display"
|
||||
And I navigate to course participants
|
||||
Then I should see "Teacher >= editing (Teacher)" in the "Teacher 1" "table_row"
|
||||
And I should see "Teacher < \"editing\" (Non-editing teacher)" in the "Teaching Assistant" "table_row"
|
||||
And I should see "Studier & 'learner' (Student)" in the "Student One" "table_row"
|
||||
Then I should see "Teacher >= editing" in the "Teacher 1" "table_row"
|
||||
And I should see "Teacher < \"editing\"" in the "Teaching Assistant" "table_row"
|
||||
And I should see "Studier & 'learner'" in the "Student One" "table_row"
|
||||
And I navigate to "Users > Permissions" in current page administration
|
||||
And I should see "Teacher >= editing" in the "mod/forum:replypost" "table_row"
|
||||
And I should see "Teacher < \"editing\"" in the "mod/forum:replypost" "table_row"
|
||||
|
||||
@@ -48,7 +48,7 @@ Feature: Verify that all form fields values can be get and set
|
||||
And the "Unenrol users" select box should not contain "Baker"
|
||||
And the "Unenrol users" select box should not contain "President, Baker"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I follow "Test this one"
|
||||
And I press "Create page"
|
||||
# Text (textarea & editor) & Select (multi-select) - Checking "I set the following fields to these values".
|
||||
When I set the following fields to these values:
|
||||
@@ -61,7 +61,8 @@ Feature: Verify that all form fields values can be get and set
|
||||
# Checkbox - Checking "I set the field" and "The field matches value" ticked.
|
||||
And I set the field "Force format" to "1"
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I expand all fieldsets
|
||||
And the field "Force format" matches value "1"
|
||||
@@ -69,7 +70,8 @@ Feature: Verify that all form fields values can be get and set
|
||||
# Checkbox - Checking "I set the field" and "The field matches value" unticked.
|
||||
And I set the field "Force format" to ""
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I expand all fieldsets
|
||||
And the field "Force format" matches value ""
|
||||
@@ -78,7 +80,8 @@ Feature: Verify that all form fields values can be get and set
|
||||
And I set the following fields to these values:
|
||||
| Force format | 1 |
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I expand all fieldsets
|
||||
And the following fields match these values:
|
||||
@@ -89,7 +92,8 @@ Feature: Verify that all form fields values can be get and set
|
||||
And I set the following fields to these values:
|
||||
| Force format | |
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test this one" "wiki activity" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I expand all fieldsets
|
||||
And the following fields match these values:
|
||||
@@ -111,21 +115,20 @@ Feature: Verify that all form fields values can be get and set
|
||||
| Wiki name | Test this one baby |
|
||||
| Default format | HTML |
|
||||
And I press "Cancel"
|
||||
And I am on "Course 1" course homepage
|
||||
# Radio - Checking "I set the field" and "the field matches value".
|
||||
And the following "activity" exists:
|
||||
| activity | choice |
|
||||
| course | C1 |
|
||||
| idnumber | choice1 |
|
||||
| intro | Test choice description |
|
||||
| name | Test choice name |
|
||||
| option | Option 1, Option 2, Option 3 |
|
||||
| section | 1 |
|
||||
| allowupdate | 1 |
|
||||
And I am on the "Test choice name" "choice activity" page
|
||||
And I set the field "Option 1" to "1"
|
||||
And I add a "Choice" to section "1" and I fill the form with:
|
||||
| Choice name | Test choice name |
|
||||
| Description | Test choice description |
|
||||
| Allow choice to be updated | Yes |
|
||||
| Option 1 | one |
|
||||
| Option 2 | two |
|
||||
| Option 3 | three |
|
||||
And I follow "Test choice name"
|
||||
And I set the field "one" to "1"
|
||||
And I press "Save my choice"
|
||||
And the field "Option 1" matches value "1"
|
||||
And the field "Option 2" matches value ""
|
||||
And the field "one" matches value "1"
|
||||
And the field "two" matches value ""
|
||||
# Check if field xpath set/match works.
|
||||
And I am on "Course 1" course homepage
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
@@ -171,23 +174,31 @@ Feature: Verify that all form fields values can be get and set
|
||||
And I press "Cancel"
|
||||
# Advanced checkbox requires real browser to allow uncheck to work. MDL-58681. MDL-55386.
|
||||
# Advanced checkbox - Checking "I set the field" and "The field matches value" ticked.
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I am on "Course 1" course homepage
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I set the field "Display description on course page" to "1"
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And the field "Display description on course page" matches value "1"
|
||||
And the field "Display description on course page" does not match value ""
|
||||
# Advanced checkbox - Checking "I set the field" and "The field matches value" unticked.
|
||||
And I set the field "Display description on course page" to ""
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And the field "Display description on course page" matches value ""
|
||||
And the field "Display description on course page" does not match value "1"
|
||||
# Advanced checkbox - Checking "I set the following fields to these values:" and "The following fields match these values" ticked.
|
||||
And I set the following fields to these values:
|
||||
| Display description on course page | 1 |
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And the following fields match these values:
|
||||
| Display description on course page | 1 |
|
||||
And the following fields do not match these values:
|
||||
@@ -196,7 +207,9 @@ Feature: Verify that all form fields values can be get and set
|
||||
And I set the following fields to these values:
|
||||
| Display description on course page | |
|
||||
And I press "Save and return to course"
|
||||
And I am on the "Test choice name" "choice activity editing" page
|
||||
And I should see "Test this one"
|
||||
And I follow "Test this one"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And the following fields match these values:
|
||||
| Display description on course page | |
|
||||
And the following fields do not match these values:
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
@tool @tool_behat
|
||||
Feature: Use core page resolvers for the I am on the page steps
|
||||
In order to write tests correctly
|
||||
As a developer
|
||||
I need to have steps which take me straight to a page
|
||||
|
||||
Scenario Outline: When I am on an instance
|
||||
Given the following "categories" exist:
|
||||
| name | category | idnumber |
|
||||
| Cat 1 | 0 | CAT1 |
|
||||
And the following "course" exists:
|
||||
| fullname | Economics 101 |
|
||||
| shortname | ECON101 |
|
||||
| idnumber | 2021-econ101 |
|
||||
And the following "activity" exists:
|
||||
| course | ECON101 |
|
||||
| activity | forum |
|
||||
| name | Fundamentals of Economics |
|
||||
| idnumber | fundamentalsofeconomics |
|
||||
And I log in as "admin"
|
||||
When I am on the <identifier> <type> page
|
||||
Then I should see "<shouldsee>"
|
||||
|
||||
Examples:
|
||||
| description | identifier | type | shouldsee |
|
||||
| Course Category idnumber | CAT1 | category | Add a new course |
|
||||
| Course Category name | "Cat 1" | Category | Add a new course |
|
||||
| Course Full name | "Economics 101" | course | Fundamentals of Economics |
|
||||
| Course Short name | ECON101 | COURSE | Fundamentals of Economics |
|
||||
| Course idnumber | "2021-econ101" | Course | Fundamentals of Economics |
|
||||
| Forum idnumber | fundamentalsofeconomics | Activity | Add a new discussion |
|
||||
| Generic activity editing | fundamentalsofeconomics | "Activity editing" | Updating: Forum |
|
||||
| Forum name | "Fundamentals of Economics" | "Forum activity" | Add a new discussion |
|
||||
| Forum name editing | "Fundamentals of Economics" | "Forum activity editing" | Updating: Forum |
|
||||
| Forum name permissions | "Fundamentals of Economics" | "Forum activity permissions" | Permissions in Forum: Fun |
|
||||
| Forum name roles | "Fundamentals of Economics" | "Forum activity roles" | Assign roles in Forum: Fun |
|
||||
|
||||
Scenario Outline: When I am on an instance logged in as
|
||||
Given the following "categories" exist:
|
||||
| name | category | idnumber |
|
||||
| Cat 1 | 0 | CAT1 |
|
||||
And the following "course" exists:
|
||||
| fullname | Economics 101 |
|
||||
| shortname | ECON101 |
|
||||
| idnumber | 2021-econ101 |
|
||||
And the following "activity" exists:
|
||||
| course | ECON101 |
|
||||
| activity | forum |
|
||||
| name | Fundamentals of Economics |
|
||||
| idnumber | fundamentalsofeconomics |
|
||||
When I am on the <identifier> <type> page logged in as admin
|
||||
Then I should see "<shouldsee>"
|
||||
|
||||
Examples:
|
||||
| description | identifier | type | shouldsee |
|
||||
| Course Category idnumber | CAT1 | category | Add a new course |
|
||||
| Course Category name | "Cat 1" | Category | Add a new course |
|
||||
| Course Full name | "Economics 101" | course | Fundamentals of Economics |
|
||||
| Course Short name | ECON101 | COURSE | Fundamentals of Economics |
|
||||
| Course idnumber | "2021-econ101" | Course | Fundamentals of Economics |
|
||||
| Forum idnumber | fundamentalsofeconomics | Activity | Add a new discussion |
|
||||
| Generic activity editing | fundamentalsofeconomics | "Activity editing" | Updating: Forum |
|
||||
| Forum name | "Fundamentals of Economics" | "Forum activity" | Add a new discussion |
|
||||
| Forum name editing | "Fundamentals of Economics" | "Forum activity editing" | Updating: Forum |
|
||||
| Forum name permissions | "Fundamentals of Economics" | "Forum activity permissions" | Permissions in Forum: Fun |
|
||||
| Forum name roles | "Fundamentals of Economics" | "Forum activity roles" | Assign roles in Forum: Fun |
|
||||
|
||||
Scenario Outline: When I am on a named page
|
||||
Given I log in as "admin"
|
||||
When I am on the <identifier> page
|
||||
Then I should see "<shouldsee>"
|
||||
|
||||
Examples:
|
||||
| description | identifier | shouldsee |
|
||||
| Admin page | "Admin notifications" | Check for available updates |
|
||||
| Home page | Homepage | Recently accessed courses |
|
||||
|
||||
Scenario Outline: When I am on a named page logged in as
|
||||
When I am on the <identifier> page logged in as admin
|
||||
Then I should see "<shouldsee>"
|
||||
|
||||
Examples:
|
||||
| description | identifier | shouldsee |
|
||||
| Admin page | "Admin notifications" | Check for available updates |
|
||||
| Home page | Homepage | Recently accessed courses |
|
||||
@@ -1,110 +0,0 @@
|
||||
@tool_behat
|
||||
Feature: Verify that the behat login and logout steps work as expected
|
||||
In order to use behat login and log out steps
|
||||
As a test writer
|
||||
I need to verify that login and logout happen when the steps are used
|
||||
|
||||
Scenario: Log in as a user using the step
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
When I log in as "traverst1"
|
||||
Then I should see "Thomas Travers"
|
||||
|
||||
@javascript
|
||||
Scenario: Log in as a user using the step (javascript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
When I log in as "traverst1"
|
||||
Then I should see "Thomas Travers"
|
||||
|
||||
Scenario: Log out using the log out step
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
And I am logged in as traverst1
|
||||
When I log out
|
||||
Then I should not see "Thomas Travers"
|
||||
And I should see "You are not logged in"
|
||||
|
||||
@javascript
|
||||
Scenario: Log out using the log out step (javascript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
And I am logged in as traverst1
|
||||
When I log out
|
||||
Then I should not see "Thomas Travers"
|
||||
And I should see "You are not logged in"
|
||||
|
||||
Scenario: Log in step should automatically log user out if already logged in
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
| emeryj | Jane | Emery |
|
||||
And I am logged in as traverst1
|
||||
When I log in as "emeryj"
|
||||
Then I should not see "Thomas Travers"
|
||||
And I should see "Jane Emery"
|
||||
|
||||
@javascript
|
||||
Scenario: Log in step should automatically log user out if already logged in (javascript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
| emeryj | Jane | Emery |
|
||||
And I am logged in as traverst1
|
||||
When I log in as "emeryj"
|
||||
Then I should not see "Thomas Travers"
|
||||
And I should see "Jane Emery"
|
||||
|
||||
Scenario: I am on page logged in as should redirect to correct page
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
And the following "course" exists:
|
||||
| fullname | Life, the Universe, and Everything |
|
||||
| shortname | hhgttg |
|
||||
When I am on the hhgttg Course page logged in as traverst1
|
||||
Then I should see "Thomas Travers"
|
||||
And I should see "Life, the Universe, and Everything"
|
||||
|
||||
@javascript
|
||||
Scenario: I am on page logged in as should redirect to correct page (javascript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
And the following "course" exists:
|
||||
| fullname | Life, the Universe, and Everything |
|
||||
| shortname | hhgttg |
|
||||
When I am on the hhgttg Course page logged in as traverst1
|
||||
Then I should see "Thomas Travers"
|
||||
And I should see "Life, the Universe, and Everything"
|
||||
|
||||
Scenario: I am on page logged in as should redirect to correct page when automatically logging a user out
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
| emeryj | Jane | Emery |
|
||||
And the following "course" exists:
|
||||
| fullname | Life, the Universe, and Everything |
|
||||
| shortname | hhgttg |
|
||||
And I am logged in as emeryj
|
||||
When I am on the hhgttg Course page logged in as traverst1
|
||||
Then I should see "Thomas Travers"
|
||||
And I should see "Life, the Universe, and Everything"
|
||||
|
||||
@javascript
|
||||
Scenario: I am on page logged in as should redirect to correct page when automatically logging a user out (javacript)
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname |
|
||||
| traverst1 | Thomas | Travers |
|
||||
| emeryj | Jane | Emery |
|
||||
And the following "course" exists:
|
||||
| fullname | Life, the Universe, and Everything |
|
||||
| shortname | hhgttg |
|
||||
And I am logged in as emeryj
|
||||
When I am on the hhgttg Course page logged in as traverst1
|
||||
Then I should see "Thomas Travers"
|
||||
And I should see "Life, the Universe, and Everything"
|
||||
@@ -14,6 +14,8 @@ Feature: Forms manipulation
|
||||
Then the field "First name" matches value "Field value"
|
||||
And the "Select a country" select box should contain "Japan"
|
||||
And the field "New password" matches value "TestPass"
|
||||
And I take focus off "Update profile" "button"
|
||||
And I press "Update profile"
|
||||
|
||||
@javascript
|
||||
Scenario: Expand all fieldsets and advanced elements
|
||||
|
||||
@@ -87,7 +87,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
/**
|
||||
* Setup test.
|
||||
*/
|
||||
public function setUp(): void {
|
||||
public function setup() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
@@ -165,7 +165,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
// Check contexts.
|
||||
@@ -324,7 +324,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
// Check contexts.
|
||||
@@ -368,7 +368,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
// Check contexts.
|
||||
@@ -399,7 +399,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
// Check contexts.
|
||||
@@ -428,7 +428,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
// Check contexts.
|
||||
@@ -532,7 +532,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
// Check contexts.
|
||||
@@ -611,7 +611,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
// Check contexts.
|
||||
@@ -646,7 +646,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,7 +662,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,7 +678,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,7 +693,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
|
||||
$this->assertCount(count($paths), $suites[$themename]['paths']);
|
||||
|
||||
foreach ($paths as $key => $feature) {
|
||||
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
|
||||
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2020110300; // Requires this Moodle version
|
||||
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2020060900; // Requires this Moodle version
|
||||
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -60,12 +60,12 @@ class tool_capability_settings_form extends moodleform {
|
||||
$form->addElement('select', 'roles', get_string('roleslabel', 'tool_capability'), $roles, $attributes);
|
||||
$form->setType('roles', PARAM_TEXT);
|
||||
|
||||
$filters = [];
|
||||
$filters[] = $form->createElement('checkbox', 'onlydiff', get_string('onlydiff', 'tool_capability'));
|
||||
$form->addElement('checkbox', 'onlydiff',
|
||||
get_string('filters', 'tool_capability'),
|
||||
get_string('onlydiff', 'tool_capability'));
|
||||
$form->setType('onlydiff', PARAM_BOOL);
|
||||
$form->addGroup($filters, 'filters', get_string('filters', 'tool_capability'), array('<br>'), false);
|
||||
|
||||
$form->addElement('submit', 'submitbutton', get_string('getreport', 'tool_capability'));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -53,12 +53,7 @@ function tool_capability_calculate_role_data($capability, array $roles) {
|
||||
$sql = 'SELECT DISTINCT con.path, 1
|
||||
FROM {context} con
|
||||
JOIN {role_capabilities} rc ON rc.contextid = con.id
|
||||
WHERE capability = ? ' .
|
||||
$sqlroletest .
|
||||
// Context path should never be null, but can happen in old database with
|
||||
// bad data (e.g. a course_module where the corresponding course no longer exists).
|
||||
// We need to leave these out of the report to prevent errors.
|
||||
' AND con.path IS NOT NULL';
|
||||
WHERE capability = ? '.$sqlroletest;
|
||||
$relevantpaths = $DB->get_records_sql_menu($sql, $params);
|
||||
$requiredcontexts = array($systemcontext->id);
|
||||
foreach ($relevantpaths as $path => $notused) {
|
||||
@@ -93,10 +88,6 @@ function tool_capability_calculate_role_data($capability, array $roles) {
|
||||
|
||||
// Put the role capabilities into the context tree.
|
||||
foreach ($rolecaps as $rolecap) {
|
||||
if (!isset($contexts[$rolecap->contextid])) {
|
||||
// Skip capabilities in orphaned contexts that are not in the tree.
|
||||
continue;
|
||||
}
|
||||
$contexts[$rolecap->contextid]->rolecapabilities[$rolecap->roleid] = $rolecap->permission;
|
||||
}
|
||||
|
||||
@@ -108,4 +99,4 @@ function tool_capability_calculate_role_data($capability, array $roles) {
|
||||
}
|
||||
|
||||
return $contexts;
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class tool_capability_events_testcase extends advanced_testcase {
|
||||
/**
|
||||
* Setup testcase.
|
||||
*/
|
||||
public function setUp(): void {
|
||||
public function setUp() {
|
||||
$this->setAdminUser();
|
||||
$this->resetAfterTest();
|
||||
}
|
||||
|
||||
@@ -1,88 +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/>.
|
||||
|
||||
/**
|
||||
* Tests for the capability overview helper functions.
|
||||
*
|
||||
* @package tool_capability
|
||||
* @copyright 2021 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/capability/locallib.php');
|
||||
|
||||
|
||||
/**
|
||||
* Tests for the capability overview helper functions.
|
||||
*/
|
||||
class tool_capability_locallib_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test the function that gets the data - simple case.
|
||||
*/
|
||||
public function test_tool_capability_calculate_role_data() {
|
||||
global $DB;
|
||||
|
||||
$data = tool_capability_calculate_role_data('mod/quiz:attempt', get_all_roles());
|
||||
|
||||
$systcontext = context_system::instance();
|
||||
$studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student']);
|
||||
|
||||
$this->assertArrayHasKey($systcontext->id, $data);
|
||||
$this->assertCount(1, $data);
|
||||
foreach ($data[$systcontext->id]->rolecapabilities as $roleid => $permission) {
|
||||
if ($roleid == $studentroleid) {
|
||||
$this->assertEquals(CAP_ALLOW, $permission);
|
||||
} else {
|
||||
$this->assertEquals(CAP_INHERIT, $permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the function that gets the data - simple case.
|
||||
*/
|
||||
public function test_tool_capability_calculate_role_data_orphan_contexts() {
|
||||
global $DB;
|
||||
$this->resetAfterTest();
|
||||
|
||||
// This simulates a situation that seems to happen sometimes, where
|
||||
// we end up with contexts with path = NULL in the database.
|
||||
$systcontext = context_system::instance();
|
||||
$generator = $this->getDataGenerator();
|
||||
$course = $generator->create_course();
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
$studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student']);
|
||||
role_change_permission($studentroleid, $coursecontext, 'mod/quiz:attempt', CAP_PREVENT);
|
||||
// This is where we simulate the breakage.
|
||||
$DB->set_field('context', 'path', null, ['id' => $coursecontext->id]);
|
||||
|
||||
// Now call the function. We mainly just want to know there is no exception.
|
||||
$data = tool_capability_calculate_role_data('mod/quiz:attempt', get_all_roles());
|
||||
|
||||
$this->assertArrayHasKey($systcontext->id, $data);
|
||||
$this->assertCount(1, $data);
|
||||
foreach ($data[$systcontext->id]->rolecapabilities as $roleid => $permission) {
|
||||
if ($roleid == $studentroleid) {
|
||||
$this->assertEquals(CAP_ALLOW, $permission);
|
||||
} else {
|
||||
$this->assertEquals(CAP_INHERIT, $permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2020110300; // Requires this Moodle version.
|
||||
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2020060900; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
admin/tool/capability/yui/build/moodle-tool_capability-search/moodle-tool_capability-search-debug.js
Vendored
+4
-27
@@ -53,13 +53,6 @@ SEARCH.prototype = {
|
||||
* @protected
|
||||
*/
|
||||
button: null,
|
||||
/**
|
||||
* The cancel button for the form.
|
||||
* @property button
|
||||
* @type Node
|
||||
* @protected
|
||||
*/
|
||||
cancel: null,
|
||||
/**
|
||||
* The last search node if there is one.
|
||||
* If there is a last search node then the last search term will be persisted between requests.
|
||||
@@ -83,28 +76,17 @@ SEARCH.prototype = {
|
||||
this.button = this.form.all('input[type=submit]');
|
||||
this.lastsearch = this.form.one('input[name=search]');
|
||||
|
||||
var div = Y.Node.create('<div id="capabilitysearchui" class="input-group simplesearchform mb-2"' +
|
||||
'data-fieldtype="text"></div>'),
|
||||
label = Y.Node.create('<label for="capabilitysearch"><span class="sr-only"' +
|
||||
this.get('strsearch') + '</span></label>');
|
||||
this.cancel = Y.Node.create('<a class="btn btn-clear d-none icon-no-margin">' +
|
||||
'<i class="icon fa fa-times fa-fw " aria-hidden="true"></i>' +
|
||||
'</a>');
|
||||
this.input = Y.Node.create('<input type="text" class="form-control withclear" placeholder="' +
|
||||
this.get('strsearch') + '"id="capabilitysearch" />');
|
||||
var div = Y.Node.create('<div id="capabilitysearchui" data-fieldtype="text"></div>'),
|
||||
label = Y.Node.create('<label for="capabilitysearch">' + this.get('strsearch') + '</label>');
|
||||
this.input = Y.Node.create('<input type="text" id="capabilitysearch" />');
|
||||
|
||||
div.append(label).append(this.input).append(this.cancel);
|
||||
div.append(label).append(this.input);
|
||||
|
||||
this.select.insert(div, 'before');
|
||||
|
||||
this.input.on('keyup', this.typed, this);
|
||||
this.select.on('change', this.validate, this);
|
||||
|
||||
this.cancel.on('click', function() {
|
||||
this.input.set('value', '');
|
||||
this.typed();
|
||||
}, this);
|
||||
|
||||
if (this.lastsearch) {
|
||||
this.input.set('value', this.lastsearch.get('value'));
|
||||
this.typed();
|
||||
@@ -151,11 +133,6 @@ SEARCH.prototype = {
|
||||
last.set('selected', true);
|
||||
}
|
||||
}
|
||||
if (search !== '') {
|
||||
this.cancel.removeClass("d-none");
|
||||
} else {
|
||||
this.cancel.addClass("d-none");
|
||||
}
|
||||
this.validate();
|
||||
}
|
||||
};
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
YUI.add("moodle-tool_capability-search",function(s,t){var e=function(){e.superclass.constructor.apply(this,arguments)};s.extend(e,s.Base,e.prototype={form:null,select:null,selectoptions:{},input:null,button:null,cancel:null,lastsearch:null,initializer:function(){this.form=s.one("#capability-overview-form"),this.select=this.form.one("select[data-search=capability]"),this.select.setStyle("minWidth",this.select.get("offsetWidth")),this.select.get("options").each(function(t){var e=t.get("value");this.selectoptions[e]=t},this),this.button=this.form.all("input[type=submit]"),this.lastsearch=this.form.one("input[name=search]");var t=s.Node.create('<div id="capabilitysearchui" class="input-group simplesearchform mb-2"data-fieldtype="text"></div>'),e=s.Node.create('<label for="capabilitysearch"><span class="sr-only"'+this.get("strsearch")+"</span></label>");this.cancel=s.Node.create('<a class="btn btn-clear d-none icon-no-margin"><i class="icon fa fa-times fa-fw " aria-hidden="true"></i></a>'),this.input=s.Node.create('<input type="text" class="form-control withclear" placeholder="'+this.get("strsearch")+'"id="capabilitysearch" />'),t.append(e).append(this.input).append(this.cancel),this.select.insert(t,"before"),this.input.on("keyup",this.typed,this),this.select.on("change",this.validate,this),this.cancel.on("click",function(){this.input.set("value",""),this.typed()},this),this.lastsearch&&(this.input.set("value",this.lastsearch.get("value")),this.typed(),this.select.one("option[selected]")&&this.select.set("scrollTop",this.select.one("option[selected]").get("getX"))),this.validate()},validate:function(){this.button.set("disabled",""===this.select.get("value"))},typed:function(){var t,e=this.input.get("value"),s=0,i=null;for(t in this.lastsearch&&this.lastsearch.set("value",e),this.select.all("option").remove(),this.selectoptions)0<=t.indexOf(e)&&(s++,i=this.selectoptions[t],this.select.append(this.selectoptions[t]));0===s?this.input.addClass("error"):(this.input.removeClass("error"),1===s&&i.set("selected",!0)),""!==e?this.cancel.removeClass("d-none"):this.cancel.addClass("d-none"),this.validate()}},{NAME:"tool_capability-search",ATTRS:{strsearch:{}}}),M.tool_capability=M.tool_capability||{},M.tool_capability.init_capability_search=function(t){new e(t)}},"@VERSION@",{requires:["base","node"]});
|
||||
YUI.add("moodle-tool_capability-search",function(i,t){var e=function(){e.superclass.constructor.apply(this,arguments)};e.prototype={form:null,select:null,selectoptions:{},input:null,button:null,lastsearch:null,initializer:function(){this.form=i.one("#capability-overview-form"),this.select=this.form.one("select[data-search=capability]"),this.select.setStyle("minWidth",this.select.get("offsetWidth")),this.select.get("options").each(function(t){var e=t.get("value");this.selectoptions[e]=t},this),this.button=this.form.all("input[type=submit]"),this.lastsearch=this.form.one("input[name=search]");var t=i.Node.create('<div id="capabilitysearchui" data-fieldtype="text"></div>'),e=i.Node.create('<label for="capabilitysearch">'+this.get("strsearch")+"</label>");this.input=i.Node.create('<input type="text" id="capabilitysearch" />'),t.append(e).append(this.input),this.select.insert(t,"before"),this.input.on("keyup",this.typed,this),this.select.on("change",this.validate,this),this.lastsearch&&(this.input.set("value",this.lastsearch.get("value")),this.typed(),this.select.one("option[selected]")&&this.select.set("scrollTop",this.select.one("option[selected]").get("getX"))),this.validate()},validate:function(){this.button.set("disabled",""===this.select.get("value"))},typed:function(){var t,e=this.input.get("value"),i=0,s=null;for(t in this.lastsearch&&this.lastsearch.set("value",e),this.select.all("option").remove(),this.selectoptions)0<=t.indexOf(e)&&(i++,s=this.selectoptions[t],this.select.append(this.selectoptions[t]));0===i?this.input.addClass("error"):(this.input.removeClass("error"),1===i&&s.set("selected",!0)),this.validate()}},i.extend(e,i.Base,e.prototype,{NAME:"tool_capability-search",ATTRS:{strsearch:{}}}),M.tool_capability=M.tool_capability||{},M.tool_capability.init_capability_search=function(t){new e(t)}},"@VERSION@",{requires:["base","node"]});
|
||||
Vendored
+4
-27
@@ -53,13 +53,6 @@ SEARCH.prototype = {
|
||||
* @protected
|
||||
*/
|
||||
button: null,
|
||||
/**
|
||||
* The cancel button for the form.
|
||||
* @property button
|
||||
* @type Node
|
||||
* @protected
|
||||
*/
|
||||
cancel: null,
|
||||
/**
|
||||
* The last search node if there is one.
|
||||
* If there is a last search node then the last search term will be persisted between requests.
|
||||
@@ -83,28 +76,17 @@ SEARCH.prototype = {
|
||||
this.button = this.form.all('input[type=submit]');
|
||||
this.lastsearch = this.form.one('input[name=search]');
|
||||
|
||||
var div = Y.Node.create('<div id="capabilitysearchui" class="input-group simplesearchform mb-2"' +
|
||||
'data-fieldtype="text"></div>'),
|
||||
label = Y.Node.create('<label for="capabilitysearch"><span class="sr-only"' +
|
||||
this.get('strsearch') + '</span></label>');
|
||||
this.cancel = Y.Node.create('<a class="btn btn-clear d-none icon-no-margin">' +
|
||||
'<i class="icon fa fa-times fa-fw " aria-hidden="true"></i>' +
|
||||
'</a>');
|
||||
this.input = Y.Node.create('<input type="text" class="form-control withclear" placeholder="' +
|
||||
this.get('strsearch') + '"id="capabilitysearch" />');
|
||||
var div = Y.Node.create('<div id="capabilitysearchui" data-fieldtype="text"></div>'),
|
||||
label = Y.Node.create('<label for="capabilitysearch">' + this.get('strsearch') + '</label>');
|
||||
this.input = Y.Node.create('<input type="text" id="capabilitysearch" />');
|
||||
|
||||
div.append(label).append(this.input).append(this.cancel);
|
||||
div.append(label).append(this.input);
|
||||
|
||||
this.select.insert(div, 'before');
|
||||
|
||||
this.input.on('keyup', this.typed, this);
|
||||
this.select.on('change', this.validate, this);
|
||||
|
||||
this.cancel.on('click', function() {
|
||||
this.input.set('value', '');
|
||||
this.typed();
|
||||
}, this);
|
||||
|
||||
if (this.lastsearch) {
|
||||
this.input.set('value', this.lastsearch.get('value'));
|
||||
this.typed();
|
||||
@@ -151,11 +133,6 @@ SEARCH.prototype = {
|
||||
last.set('selected', true);
|
||||
}
|
||||
}
|
||||
if (search !== '') {
|
||||
this.cancel.removeClass("d-none");
|
||||
} else {
|
||||
this.cancel.addClass("d-none");
|
||||
}
|
||||
this.validate();
|
||||
}
|
||||
};
|
||||
|
||||
+4
-27
@@ -51,13 +51,6 @@ SEARCH.prototype = {
|
||||
* @protected
|
||||
*/
|
||||
button: null,
|
||||
/**
|
||||
* The cancel button for the form.
|
||||
* @property button
|
||||
* @type Node
|
||||
* @protected
|
||||
*/
|
||||
cancel: null,
|
||||
/**
|
||||
* The last search node if there is one.
|
||||
* If there is a last search node then the last search term will be persisted between requests.
|
||||
@@ -81,28 +74,17 @@ SEARCH.prototype = {
|
||||
this.button = this.form.all('input[type=submit]');
|
||||
this.lastsearch = this.form.one('input[name=search]');
|
||||
|
||||
var div = Y.Node.create('<div id="capabilitysearchui" class="input-group simplesearchform mb-2"' +
|
||||
'data-fieldtype="text"></div>'),
|
||||
label = Y.Node.create('<label for="capabilitysearch"><span class="sr-only"' +
|
||||
this.get('strsearch') + '</span></label>');
|
||||
this.cancel = Y.Node.create('<a class="btn btn-clear d-none icon-no-margin">' +
|
||||
'<i class="icon fa fa-times fa-fw " aria-hidden="true"></i>' +
|
||||
'</a>');
|
||||
this.input = Y.Node.create('<input type="text" class="form-control withclear" placeholder="' +
|
||||
this.get('strsearch') + '"id="capabilitysearch" />');
|
||||
var div = Y.Node.create('<div id="capabilitysearchui" data-fieldtype="text"></div>'),
|
||||
label = Y.Node.create('<label for="capabilitysearch">' + this.get('strsearch') + '</label>');
|
||||
this.input = Y.Node.create('<input type="text" id="capabilitysearch" />');
|
||||
|
||||
div.append(label).append(this.input).append(this.cancel);
|
||||
div.append(label).append(this.input);
|
||||
|
||||
this.select.insert(div, 'before');
|
||||
|
||||
this.input.on('keyup', this.typed, this);
|
||||
this.select.on('change', this.validate, this);
|
||||
|
||||
this.cancel.on('click', function() {
|
||||
this.input.set('value', '');
|
||||
this.typed();
|
||||
}, this);
|
||||
|
||||
if (this.lastsearch) {
|
||||
this.input.set('value', this.lastsearch.get('value'));
|
||||
this.typed();
|
||||
@@ -149,11 +131,6 @@ SEARCH.prototype = {
|
||||
last.set('selected', true);
|
||||
}
|
||||
}
|
||||
if (search !== '') {
|
||||
this.cancel.removeClass("d-none");
|
||||
} else {
|
||||
this.cancel.addClass("d-none");
|
||||
}
|
||||
this.validate();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -189,12 +189,7 @@ class cohort_role_assignments_table extends table_sql {
|
||||
FROM {tool_cohortroles} uca
|
||||
JOIN {user} u ON u.id = uca.userid
|
||||
JOIN {cohort} c ON c.id = uca.cohortid";
|
||||
|
||||
// Check if any additional filtering is required.
|
||||
[$sqlwhere, $params] = $this->get_sql_where();
|
||||
if ($sqlwhere) {
|
||||
$sql .= " WHERE {$sqlwhere}";
|
||||
}
|
||||
$params = array();
|
||||
|
||||
// Add order by if needed.
|
||||
if (!$count && $sqlsort = $this->get_sql_sort()) {
|
||||
|
||||
@@ -44,8 +44,5 @@ function xmldb_tool_cohortroles_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -86,8 +86,8 @@ if ($removeid) {
|
||||
|
||||
$title = get_string('existingcohortroles', 'tool_cohortroles');
|
||||
echo $output->heading($title);
|
||||
|
||||
$table = new tool_cohortroles\output\cohort_role_assignments_table('cohort-role-assignments', $pageurl);
|
||||
$url = new moodle_url('/admin/tool/cohortroles/index.php');
|
||||
$table = new tool_cohortroles\output\cohort_role_assignments_table(uniqid(), $url);
|
||||
echo $table->out(50, true);
|
||||
|
||||
echo $output->spacer();
|
||||
|
||||
@@ -49,7 +49,7 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
|
||||
/**
|
||||
* Setup function- we will create a course and add an assign instance to it.
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
protected function setUp() {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
// Create some users.
|
||||
@@ -60,6 +60,9 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
|
||||
cohort_add_member($this->cohort->id, $this->userassignover->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException required_capability_exception
|
||||
*/
|
||||
public function test_create_cohort_role_assignment_without_permission() {
|
||||
$this->setUser($this->userassignto);
|
||||
$params = (object) array(
|
||||
@@ -67,10 +70,12 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
|
||||
'roleid' => $this->roleid,
|
||||
'cohortid' => $this->cohort->id
|
||||
);
|
||||
$this->expectException(required_capability_exception::class);
|
||||
api::create_cohort_role_assignment($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException core_competency\invalid_persistent_exception
|
||||
*/
|
||||
public function test_create_cohort_role_assignment_with_invalid_data() {
|
||||
$this->setAdminUser();
|
||||
$params = (object) array(
|
||||
@@ -78,7 +83,6 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
|
||||
'roleid' => -8,
|
||||
'cohortid' => $this->cohort->id
|
||||
);
|
||||
$this->expectException(\core_competency\invalid_persistent_exception::class);
|
||||
api::create_cohort_role_assignment($params);
|
||||
}
|
||||
|
||||
@@ -96,6 +100,9 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
|
||||
$this->assertEquals($result->get('cohortid'), $this->cohort->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException required_capability_exception
|
||||
*/
|
||||
public function test_delete_cohort_role_assignment_without_permission() {
|
||||
$this->setAdminUser();
|
||||
$params = (object) array(
|
||||
@@ -105,10 +112,12 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
|
||||
);
|
||||
$result = api::create_cohort_role_assignment($params);
|
||||
$this->setUser($this->userassignto);
|
||||
$this->expectException(required_capability_exception::class);
|
||||
api::delete_cohort_role_assignment($result->get('id'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException dml_missing_record_exception
|
||||
*/
|
||||
public function test_delete_cohort_role_assignment_with_invalid_data() {
|
||||
$this->setAdminUser();
|
||||
$params = (object) array(
|
||||
@@ -117,7 +126,6 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
|
||||
'cohortid' => $this->cohort->id
|
||||
);
|
||||
$result = api::create_cohort_role_assignment($params);
|
||||
$this->expectException(dml_missing_record_exception::class);
|
||||
api::delete_cohort_role_assignment($result->get('id') + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class tool_cohortroles_privacy_testcase extends \core_privacy\tests\provider_tes
|
||||
/**
|
||||
* Overriding setUp() function to always reset after tests.
|
||||
*/
|
||||
public function setUp(): void {
|
||||
public function setUp() {
|
||||
$this->resetAfterTest(true);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class tool_cohortroles_privacy_testcase extends \core_privacy\tests\provider_tes
|
||||
CONTEXT_COURSECAT
|
||||
];
|
||||
// Test the User's contexts equal the system and course category context.
|
||||
$this->assertEqualsCanonicalizing($expected, $contextlevels);
|
||||
$this->assertEquals($expected, $contextlevels, '', 0, 10, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2020110300; // Requires this Moodle version.
|
||||
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2020060900; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_cohortroles'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
$plugin->dependencies = array(
|
||||
|
||||
@@ -1,68 +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/>.
|
||||
|
||||
/**
|
||||
* Creates Formular for customlang file export
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Thomas Wedekind <Thomas.Wedekind@univie.ac.at>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_customlang\form;
|
||||
|
||||
use tool_customlang_utils;
|
||||
|
||||
/**
|
||||
* Formular for customlang file export
|
||||
*
|
||||
* @copyright 2020 Thomas Wedekind <Thomas.Wedekind@univie.ac.at>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class export extends \moodleform {
|
||||
|
||||
/**
|
||||
* Add elements to form
|
||||
*/
|
||||
public function definition() {
|
||||
$lng = $this->_customdata['lng'];
|
||||
$mform = $this->_form;
|
||||
|
||||
$langdir = tool_customlang_utils::get_localpack_location($lng);
|
||||
|
||||
// The export button only appears if a local lang is present.
|
||||
if (!check_dir_exists($langdir) || !count(glob("$langdir/*"))) {
|
||||
print_error('nolocallang', 'tool_customlang');
|
||||
}
|
||||
|
||||
$langfiles = scandir($langdir);
|
||||
$fileoptions = [];
|
||||
foreach ($langfiles as $file) {
|
||||
if (substr($file, 0, 1) != '.') {
|
||||
$fileoptions[$file] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
$mform->addElement('hidden', 'lng', $lng);
|
||||
$mform->setType('lng', PARAM_LANG);
|
||||
|
||||
$select = $mform->addElement('select', 'files', get_string('exportfilter', 'tool_customlang'), $fileoptions);
|
||||
$select->setMultiple(true);
|
||||
$mform->addRule('files', get_string('required'), 'required', null, 'client');
|
||||
$mform->setDefault('files', $fileoptions);
|
||||
|
||||
$this->add_action_buttons(true, get_string('export', 'tool_customlang'));
|
||||
}
|
||||
}
|
||||
@@ -1,68 +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/>.
|
||||
|
||||
/**
|
||||
* Upload a zip of custom lang php files.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_customlang\form;
|
||||
|
||||
use tool_customlang\local\importer;
|
||||
|
||||
/**
|
||||
* Upload a zip/php of custom lang php files.
|
||||
*
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import extends \moodleform {
|
||||
|
||||
/**
|
||||
* Form definition.
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
$mform->addElement('header', 'settingsheader', get_string('import', 'tool_customlang'));
|
||||
|
||||
$mform->addElement('hidden', 'lng');
|
||||
$mform->setType('lng', PARAM_LANG);
|
||||
$mform->setDefault('lng', $this->_customdata['lng']);
|
||||
|
||||
$filemanageroptions = array(
|
||||
'accepted_types' => array('.php', '.zip'),
|
||||
'maxbytes' => 0,
|
||||
'maxfiles' => 1,
|
||||
'subdirs' => 0
|
||||
);
|
||||
|
||||
$mform->addElement('filepicker', 'pack', get_string('langpack', 'tool_customlang'),
|
||||
null, $filemanageroptions);
|
||||
$mform->addRule('pack', null, 'required');
|
||||
|
||||
$modes = [
|
||||
importer::IMPORTALL => get_string('import_all', 'tool_customlang'),
|
||||
importer::IMPORTUPDATE => get_string('import_update', 'tool_customlang'),
|
||||
importer::IMPORTNEW => get_string('import_new', 'tool_customlang'),
|
||||
];
|
||||
$mform->addElement('select', 'importmode', get_string('import_mode', 'tool_customlang'), $modes);
|
||||
|
||||
$mform->addElement('submit', 'importcustomstrings', get_string('importfile', 'tool_customlang'));
|
||||
}
|
||||
}
|
||||
@@ -1,268 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Custom lang importer.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_customlang\local;
|
||||
|
||||
use tool_customlang\local\mlang\phpparser;
|
||||
use tool_customlang\local\mlang\logstatus;
|
||||
use tool_customlang\local\mlang\langstring;
|
||||
use core\output\notification;
|
||||
use stored_file;
|
||||
use coding_exception;
|
||||
use moodle_exception;
|
||||
use core_component;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class containing tha custom lang importer
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class importer {
|
||||
|
||||
/** @var int imports will only create new customizations */
|
||||
public const IMPORTNEW = 1;
|
||||
/** @var int imports will only update the current customizations */
|
||||
public const IMPORTUPDATE = 2;
|
||||
/** @var int imports all strings */
|
||||
public const IMPORTALL = 3;
|
||||
|
||||
/**
|
||||
* @var string the language name
|
||||
*/
|
||||
protected $lng;
|
||||
|
||||
/**
|
||||
* @var int the importation mode (new, update, all)
|
||||
*/
|
||||
protected $importmode;
|
||||
|
||||
/**
|
||||
* @var string request folder path
|
||||
*/
|
||||
private $folder;
|
||||
|
||||
/**
|
||||
* @var array import log messages
|
||||
*/
|
||||
private $log;
|
||||
|
||||
/**
|
||||
* Constructor for the importer class.
|
||||
*
|
||||
* @param string $lng the current language to import.
|
||||
* @param int $importmode the import method (IMPORTALL, IMPORTNEW, IMPORTUPDATE).
|
||||
*/
|
||||
public function __construct(string $lng, int $importmode = self::IMPORTALL) {
|
||||
$this->lng = $lng;
|
||||
$this->importmode = $importmode;
|
||||
$this->log = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last parse log.
|
||||
*
|
||||
* @return logstatus[] mlang logstatus with the messages
|
||||
*/
|
||||
public function get_log(): array {
|
||||
return $this->log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import customlang files.
|
||||
*
|
||||
* @param stored_file[] $files array of files to import
|
||||
*/
|
||||
public function import(array $files): void {
|
||||
// Create a temporal folder to store the files.
|
||||
$this->folder = make_request_directory(false);
|
||||
|
||||
$langfiles = $this->deploy_files($files);
|
||||
|
||||
$this->process_files($langfiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy all files into a request folder.
|
||||
*
|
||||
* @param stored_file[] $files array of files to deploy
|
||||
* @return string[] of file paths
|
||||
*/
|
||||
private function deploy_files(array $files): array {
|
||||
$result = [];
|
||||
// Desploy all files.
|
||||
foreach ($files as $file) {
|
||||
if ($file->get_mimetype() == 'application/zip') {
|
||||
$result = array_merge($result, $this->unzip_file($file));
|
||||
} else {
|
||||
$path = $this->folder.'/'.$file->get_filename();
|
||||
$file->copy_content_to($path);
|
||||
$result = array_merge($result, [$path]);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzip a file into the request folder.
|
||||
*
|
||||
* @param stored_file $file the zip file to unzip
|
||||
* @return string[] of zip content paths
|
||||
*/
|
||||
private function unzip_file(stored_file $file): array {
|
||||
$fp = get_file_packer('application/zip');
|
||||
$zipcontents = $fp->extract_to_pathname($file, $this->folder);
|
||||
if (!$zipcontents) {
|
||||
throw new moodle_exception("Error Unzipping file", 1);
|
||||
}
|
||||
$result = [];
|
||||
foreach ($zipcontents as $contentname => $success) {
|
||||
if ($success) {
|
||||
$result[] = $this->folder.'/'.$contentname;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import strings from a list of langfiles.
|
||||
*
|
||||
* @param string[] $langfiles an array with file paths
|
||||
*/
|
||||
private function process_files(array $langfiles): void {
|
||||
$parser = phpparser::get_instance();
|
||||
foreach ($langfiles as $filepath) {
|
||||
$component = $this->component_from_filepath($filepath);
|
||||
if ($component) {
|
||||
$strings = $parser->parse(file_get_contents($filepath));
|
||||
$this->import_strings($strings, $component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get the component from a filepath.
|
||||
*
|
||||
* @param string $filepath the filepath
|
||||
* @return stdCalss|null the DB record of that component
|
||||
*/
|
||||
private function component_from_filepath(string $filepath) {
|
||||
global $DB;
|
||||
|
||||
// Get component from filename.
|
||||
$pathparts = pathinfo($filepath);
|
||||
if (empty($pathparts['filename'])) {
|
||||
throw new coding_exception("Cannot get filename from $filepath", 1);
|
||||
}
|
||||
$filename = $pathparts['filename'];
|
||||
|
||||
$normalized = core_component::normalize_component($filename);
|
||||
if (count($normalized) == 1 || empty($normalized[1])) {
|
||||
$componentname = $normalized[0];
|
||||
} else {
|
||||
$componentname = implode('_', $normalized);
|
||||
}
|
||||
|
||||
$result = $DB->get_record('tool_customlang_components', ['name' => $componentname]);
|
||||
|
||||
if (!$result) {
|
||||
$this->log[] = new logstatus('notice_missingcomponent', notification::NOTIFY_ERROR, null, $componentname);
|
||||
return null;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import an array of strings into the customlang tables.
|
||||
*
|
||||
* @param langstring[] $strings the langstring to set
|
||||
* @param stdClass $component the target component
|
||||
*/
|
||||
private function import_strings(array $strings, stdClass $component): void {
|
||||
global $DB;
|
||||
|
||||
foreach ($strings as $newstring) {
|
||||
// Check current DB entry.
|
||||
$customlang = $DB->get_record('tool_customlang', [
|
||||
'componentid' => $component->id,
|
||||
'stringid' => $newstring->id,
|
||||
'lang' => $this->lng,
|
||||
]);
|
||||
if (!$customlang) {
|
||||
$customlang = null;
|
||||
}
|
||||
|
||||
if ($this->can_save_string($customlang, $newstring, $component)) {
|
||||
$customlang->local = $newstring->text;
|
||||
$customlang->timecustomized = $newstring->timemodified;
|
||||
$customlang->outdated = 0;
|
||||
$customlang->modified = 1;
|
||||
$DB->update_record('tool_customlang', $customlang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a specific string can be saved based on the current importmode.
|
||||
*
|
||||
* @param stdClass $customlang customlang original record
|
||||
* @param langstring $newstring the new strign to store
|
||||
* @param stdClass $component the component target
|
||||
* @return bool if the string can be stored
|
||||
*/
|
||||
private function can_save_string(?stdClass $customlang, langstring $newstring, stdClass $component): bool {
|
||||
$result = false;
|
||||
$message = 'notice_success';
|
||||
if (empty($customlang)) {
|
||||
$message = 'notice_inexitentstring';
|
||||
$this->log[] = new logstatus($message, notification::NOTIFY_ERROR, null, $component->name, $newstring);
|
||||
return $result;
|
||||
}
|
||||
|
||||
switch ($this->importmode) {
|
||||
case self::IMPORTNEW:
|
||||
$result = empty($customlang->local);
|
||||
$warningmessage = 'notice_ignoreupdate';
|
||||
break;
|
||||
case self::IMPORTUPDATE:
|
||||
$result = !empty($customlang->local);
|
||||
$warningmessage = 'notice_ignorenew';
|
||||
break;
|
||||
case self::IMPORTALL:
|
||||
$result = true;
|
||||
break;
|
||||
}
|
||||
if ($result) {
|
||||
$errorlevel = notification::NOTIFY_SUCCESS;
|
||||
} else {
|
||||
$errorlevel = notification::NOTIFY_ERROR;
|
||||
$message = $warningmessage;
|
||||
}
|
||||
$this->log[] = new logstatus($message, $errorlevel, null, $component->name, $newstring);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -1,177 +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/>.
|
||||
|
||||
/**
|
||||
* Language string based on David Mudrak langstring from local_amos.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_customlang\local\mlang;
|
||||
|
||||
use moodle_exception;
|
||||
use stdclass;
|
||||
|
||||
/**
|
||||
* Class containing a lang string cleaned.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a single string
|
||||
*/
|
||||
class langstring {
|
||||
|
||||
/** @var string identifier */
|
||||
public $id = null;
|
||||
|
||||
/** @var string */
|
||||
public $text = '';
|
||||
|
||||
/** @var int the time stamp when this string was saved */
|
||||
public $timemodified = null;
|
||||
|
||||
/** @var bool is deleted */
|
||||
public $deleted = false;
|
||||
|
||||
/** @var stdclass extra information about the string */
|
||||
public $extra = null;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string $id string identifier
|
||||
* @param string $text string text
|
||||
* @param int $timemodified
|
||||
* @param int $deleted
|
||||
* @param stdclass $extra
|
||||
*/
|
||||
public function __construct(string $id, string $text = '', int $timemodified = null,
|
||||
int $deleted = 0, stdclass $extra = null) {
|
||||
|
||||
if (is_null($timemodified)) {
|
||||
$timemodified = time();
|
||||
}
|
||||
$this->id = $id;
|
||||
$this->text = $text;
|
||||
$this->timemodified = $timemodified;
|
||||
$this->deleted = $deleted;
|
||||
$this->extra = $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string text, returns it being formatted properly for storing in AMOS repository.
|
||||
*
|
||||
* Note: This method is taken directly from local_amos as it is highly tested and robust.
|
||||
* The Moodle 1.x part is keep on puspose to make it easier the copy paste from both codes.
|
||||
* This could change in the future when AMOS stop suporting the 1.x langstrings.
|
||||
*
|
||||
* We need to know for what branch the string should be prepared due to internal changes in
|
||||
* format required by get_string()
|
||||
* - for get_string() in Moodle 1.6 - 1.9 use $format == 1
|
||||
* - for get_string() in Moodle 2.0 and higher use $format == 2
|
||||
*
|
||||
* Typical usages of this methods:
|
||||
* $t = langstring::fix_syntax($t); // sanity new translations of 2.x strings
|
||||
* $t = langstring::fix_syntax($t, 1); // sanity legacy 1.x strings
|
||||
* $t = langstring::fix_syntax($t, 2, 1); // convert format of 1.x strings into 2.x
|
||||
*
|
||||
* Backward converting 2.x format into 1.x is not supported
|
||||
*
|
||||
* @param string $text string text to be fixed
|
||||
* @param int $format target get_string() format version
|
||||
* @param int $from which format version does the text come from, defaults to the same as $format
|
||||
* @return string
|
||||
*/
|
||||
public static function fix_syntax(string $text, int $format = 2, ?int $from = null): string {
|
||||
if (is_null($from)) {
|
||||
$from = $format;
|
||||
}
|
||||
|
||||
// Common filter.
|
||||
$clean = trim($text);
|
||||
$search = [
|
||||
// Remove \r if it is part of \r\n.
|
||||
'/\r(?=\n)/',
|
||||
|
||||
// Control characters to be replaced with \n
|
||||
// LINE TABULATION, FORM FEED, CARRIAGE RETURN, END OF TRANSMISSION BLOCK,
|
||||
// END OF MEDIUM, SUBSTITUTE, BREAK PERMITTED HERE, NEXT LINE, START OF STRING,
|
||||
// STRING TERMINATOR and Unicode character categorys Zl and Zp.
|
||||
'/[\x{0B}-\r\x{17}\x{19}\x{1A}\x{82}\x{85}\x{98}\x{9C}\p{Zl}\p{Zp}]/u',
|
||||
|
||||
// Control characters to be removed
|
||||
// NULL, ENQUIRY, ACKNOWLEDGE, BELL, SHIFT {OUT,IN}, DATA LINK ESCAPE,
|
||||
// DEVICE CONTROL {ONE,TWO,THREE,FOUR}, NEGATIVE ACKNOWLEDGE, SYNCHRONOUS IDLE, ESCAPE,
|
||||
// DELETE, PADDING CHARACTER, HIGH OCTET PRESET, NO BREAK HERE, INDEX,
|
||||
// {START,END} OF SELECTED AREA, CHARACTER TABULATION {SET,WITH JUSTIFICATION},
|
||||
// LINE TABULATION SET, PARTIAL LINE {FORWARD,BACKWARD}, REVERSE LINE FEED,
|
||||
// SINGLE SHIFT {TWO,THREE}, DEVICE CONTROL STRING, PRIVATE USE {ONE,TWO},
|
||||
// SET TRANSMIT STATE, MESSAGE WAITING, {START,END} OF GUARDED AREA,
|
||||
// {SINGLE {GRAPHIC,} CHARACTER,CONTROL SEQUENCE} INTRODUCER, OPERATING SYSTEM COMMAND,
|
||||
// PRIVACY MESSAGE, APPLICATION PROGRAM COMMAND, ZERO WIDTH {,NO-BREAK} SPACE,
|
||||
// REPLACEMENT CHARACTER.
|
||||
'/[\0\x{05}-\x{07}\x{0E}-\x{16}\x{1B}\x{7F}\x{80}\x{81}\x{83}\x{84}\x{86}-\x{93}\x{95}-\x{97}\x{99}-\x{9B}\x{9D}-\x{9F}\x{200B}\x{FEFF}\x{FFFD}]++/u',
|
||||
|
||||
// Remove trailing whitespace at the end of lines in a multiline string.
|
||||
'/[ \t]+(?=\n)/',
|
||||
];
|
||||
$replace = [
|
||||
'',
|
||||
"\n",
|
||||
'',
|
||||
'',
|
||||
];
|
||||
$clean = preg_replace($search, $replace, $clean);
|
||||
|
||||
if (($format === 2) && ($from === 2)) {
|
||||
// Sanity translations of 2.x strings.
|
||||
$clean = preg_replace("/\n{3,}/", "\n\n\n", $clean); // Collapse runs of blank lines.
|
||||
|
||||
} else if (($format === 2) && ($from === 1)) {
|
||||
// Convert 1.x string into 2.x format.
|
||||
$clean = preg_replace("/\n{3,}/", "\n\n\n", $clean); // Collapse runs of blank lines.
|
||||
$clean = preg_replace('/%+/', '%', $clean); // Collapse % characters.
|
||||
$clean = str_replace('\$', '@@@___XXX_ESCAPED_DOLLAR__@@@', $clean); // Remember for later.
|
||||
$clean = str_replace("\\", '', $clean); // Delete all slashes.
|
||||
$clean = preg_replace('/(^|[^{])\$a\b(\->[a-zA-Z0-9_]+)?/', '\\1{$a\\2}', $clean); // Wrap placeholders.
|
||||
$clean = str_replace('@@@___XXX_ESCAPED_DOLLAR__@@@', '$', $clean);
|
||||
$clean = str_replace('$', '$', $clean);
|
||||
|
||||
} else if (($format === 1) && ($from === 1)) {
|
||||
// Sanity legacy 1.x strings.
|
||||
$clean = preg_replace("/\n{3,}/", "\n\n", $clean); // Collapse runs of blank lines.
|
||||
$clean = str_replace('\$', '@@@___XXX_ESCAPED_DOLLAR__@@@', $clean);
|
||||
$clean = str_replace("\\", '', $clean); // Delete all slashes.
|
||||
$clean = str_replace('$', '\$', $clean); // Escape all embedded variables.
|
||||
// Unescape placeholders: only $a and $a->something are allowed. All other $variables are left escaped.
|
||||
$clean = preg_replace('/\\\\\$a\b(\->[a-zA-Z0-9_]+)?/', '$a\\1', $clean); // Unescape placeholders.
|
||||
$clean = str_replace('@@@___XXX_ESCAPED_DOLLAR__@@@', '\$', $clean);
|
||||
$clean = str_replace('"', "\\\"", $clean); // Add slashes for ".
|
||||
$clean = preg_replace('/%+/', '%', $clean); // Collapse % characters.
|
||||
$clean = str_replace('%', '%%', $clean); // Duplicate %.
|
||||
|
||||
} else {
|
||||
throw new moodle_exception('Unknown get_string() format version');
|
||||
}
|
||||
return $clean;
|
||||
}
|
||||
}
|
||||
@@ -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/>.
|
||||
|
||||
/**
|
||||
* Language string based on David Mudrak langstring from local_amos.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_customlang\local\mlang;
|
||||
|
||||
use moodle_exception;
|
||||
use stdclass;
|
||||
|
||||
/**
|
||||
* Class containing a lang string cleaned.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a single string
|
||||
*/
|
||||
class logstatus {
|
||||
|
||||
/** @var langstring the current string */
|
||||
public $langstring = null;
|
||||
|
||||
/** @var string the component */
|
||||
public $component = null;
|
||||
|
||||
/** @var string the string ID */
|
||||
public $stringid = null;
|
||||
|
||||
/** @var string the original filename */
|
||||
public $filename = null;
|
||||
|
||||
/** @var int the error level */
|
||||
public $errorlevel = null;
|
||||
|
||||
/** @var string the message identifier */
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* Class creator.
|
||||
*
|
||||
* @param string $message the message identifier to display
|
||||
* @param string $errorlevel the notice level
|
||||
* @param string|null $filename the filename of this log
|
||||
* @param string|null $component the component of this log
|
||||
* @param langstring|null $langstring the langstring of this log
|
||||
*/
|
||||
public function __construct(string $message, string $errorlevel, ?string $filename = null,
|
||||
?string $component = null, ?langstring $langstring = null) {
|
||||
|
||||
$this->filename = $filename;
|
||||
$this->component = $component;
|
||||
$this->langstring = $langstring;
|
||||
$this->message = $message;
|
||||
$this->errorlevel = $errorlevel;
|
||||
|
||||
if ($langstring) {
|
||||
$this->stringid = $langstring->id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the log message.
|
||||
*
|
||||
* @return string the log message.
|
||||
*/
|
||||
public function get_message(): string {
|
||||
return get_string($this->message, 'tool_customlang', $this);
|
||||
}
|
||||
}
|
||||
@@ -1,260 +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/>.
|
||||
|
||||
/**
|
||||
* Mlang PHP based on David Mudrak phpparser for local_amos.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_customlang\local\mlang;
|
||||
|
||||
use coding_exception;
|
||||
use moodle_exception;
|
||||
|
||||
/**
|
||||
* Parser of Moodle strings defined as associative array.
|
||||
*
|
||||
* Moodle core just includes this file format directly as normal PHP code. However
|
||||
* for security reasons, we must not do this for files uploaded by anonymous users.
|
||||
* This parser reconstructs the associative $string array without actually including
|
||||
* the file.
|
||||
*/
|
||||
class phpparser {
|
||||
|
||||
/** @var holds the singleton instance of self */
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Prevents direct creation of object
|
||||
*/
|
||||
private function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent from cloning the instance
|
||||
*/
|
||||
public function __clone() {
|
||||
throw new coding_exception('Cloning os singleton is not allowed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton instance fo this class
|
||||
*
|
||||
* @return phpparser singleton instance of phpparser
|
||||
*/
|
||||
public static function get_instance(): phpparser {
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = new phpparser();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given data in Moodle PHP string format
|
||||
*
|
||||
* Note: This method is adapted from local_amos as it is highly tested and robust.
|
||||
* The priority is keeping it similar to the original one to make it easier to mantain.
|
||||
*
|
||||
* @param string $data definition of the associative array
|
||||
* @param int $format the data format on the input, defaults to the one used since 2.0
|
||||
* @return langstring[] array of langstrings of this file
|
||||
*/
|
||||
public function parse(string $data, int $format = 2): array {
|
||||
$result = [];
|
||||
$strings = $this->extract_strings($data);
|
||||
foreach ($strings as $id => $text) {
|
||||
$cleaned = clean_param($id, PARAM_STRINGID);
|
||||
if ($cleaned !== $id) {
|
||||
continue;
|
||||
}
|
||||
$text = langstring::fix_syntax($text, 2, $format);
|
||||
$result[] = new langstring($id, $text);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Low level parsing method
|
||||
*
|
||||
* Note: This method is adapted from local_amos as it is highly tested and robust.
|
||||
* The priority is keeping it similar to the original one to make it easier to mantain.
|
||||
*
|
||||
* @param string $data
|
||||
* @return string[] the data strings
|
||||
*/
|
||||
protected function extract_strings(string $data): array {
|
||||
|
||||
$strings = []; // To be returned.
|
||||
|
||||
if (empty($data)) {
|
||||
return $strings;
|
||||
}
|
||||
|
||||
// Tokenize data - we expect valid PHP code.
|
||||
$tokens = token_get_all($data);
|
||||
|
||||
// Get rid of all non-relevant tokens.
|
||||
$rubbish = [T_WHITESPACE, T_INLINE_HTML, T_COMMENT, T_DOC_COMMENT, T_OPEN_TAG, T_CLOSE_TAG];
|
||||
foreach ($tokens as $i => $token) {
|
||||
if (is_array($token)) {
|
||||
if (in_array($token[0], $rubbish)) {
|
||||
unset($tokens[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$id = null;
|
||||
$text = null;
|
||||
$line = 0;
|
||||
$expect = 'STRING_VAR'; // The first expected token is '$string'.
|
||||
|
||||
// Iterate over tokens and look for valid $string array assignment patterns.
|
||||
foreach ($tokens as $token) {
|
||||
$foundtype = null;
|
||||
$founddata = null;
|
||||
if (is_array($token)) {
|
||||
$foundtype = $token[0];
|
||||
$founddata = $token[1];
|
||||
if (!empty($token[2])) {
|
||||
$line = $token[2];
|
||||
}
|
||||
|
||||
} else {
|
||||
$foundtype = 'char';
|
||||
$founddata = $token;
|
||||
}
|
||||
|
||||
if ($expect == 'STRING_VAR') {
|
||||
if ($foundtype === T_VARIABLE and $founddata === '$string') {
|
||||
$expect = 'LEFT_BRACKET';
|
||||
continue;
|
||||
} else {
|
||||
// Allow other code at the global level.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($expect == 'LEFT_BRACKET') {
|
||||
if ($foundtype === 'char' and $founddata === '[') {
|
||||
$expect = 'STRING_ID';
|
||||
continue;
|
||||
} else {
|
||||
throw new moodle_exception('Parsing error. Expected character [ at line '.$line);
|
||||
}
|
||||
}
|
||||
|
||||
if ($expect == 'STRING_ID') {
|
||||
if ($foundtype === T_CONSTANT_ENCAPSED_STRING) {
|
||||
$id = $this->decapsulate($founddata);
|
||||
$expect = 'RIGHT_BRACKET';
|
||||
continue;
|
||||
} else {
|
||||
throw new moodle_exception('Parsing error. Expected T_CONSTANT_ENCAPSED_STRING array key at line '.$line);
|
||||
}
|
||||
}
|
||||
|
||||
if ($expect == 'RIGHT_BRACKET') {
|
||||
if ($foundtype === 'char' and $founddata === ']') {
|
||||
$expect = 'ASSIGNMENT';
|
||||
continue;
|
||||
} else {
|
||||
throw new moodle_exception('Parsing error. Expected character ] at line '.$line);
|
||||
}
|
||||
}
|
||||
|
||||
if ($expect == 'ASSIGNMENT') {
|
||||
if ($foundtype === 'char' and $founddata === '=') {
|
||||
$expect = 'STRING_TEXT';
|
||||
continue;
|
||||
} else {
|
||||
throw new moodle_exception('Parsing error. Expected character = at line '.$line);
|
||||
}
|
||||
}
|
||||
|
||||
if ($expect == 'STRING_TEXT') {
|
||||
if ($foundtype === T_CONSTANT_ENCAPSED_STRING) {
|
||||
$text = $this->decapsulate($founddata);
|
||||
$expect = 'SEMICOLON';
|
||||
continue;
|
||||
} else {
|
||||
throw new moodle_exception(
|
||||
'Parsing error. Expected T_CONSTANT_ENCAPSED_STRING array item value at line '.$line
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($expect == 'SEMICOLON') {
|
||||
if (is_null($id) or is_null($text)) {
|
||||
throw new moodle_exception('Parsing error. NULL string id or value at line '.$line);
|
||||
}
|
||||
if ($foundtype === 'char' and $founddata === ';') {
|
||||
if (!empty($id)) {
|
||||
$strings[$id] = $text;
|
||||
}
|
||||
$id = null;
|
||||
$text = null;
|
||||
$expect = 'STRING_VAR';
|
||||
continue;
|
||||
} else {
|
||||
throw new moodle_exception('Parsing error. Expected character ; at line '.$line);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given one T_CONSTANT_ENCAPSED_STRING, return its value without quotes
|
||||
*
|
||||
* Also processes escaped quotes inside the text.
|
||||
*
|
||||
* Note: This method is taken directly from local_amos as it is highly tested and robust.
|
||||
*
|
||||
* @param string $text value obtained by token_get_all()
|
||||
* @return string value without quotes
|
||||
*/
|
||||
protected function decapsulate(string $text): string {
|
||||
|
||||
if (strlen($text) < 2) {
|
||||
throw new moodle_exception('Parsing error. Expected T_CONSTANT_ENCAPSED_STRING in decapsulate()');
|
||||
}
|
||||
|
||||
if (substr($text, 0, 1) == "'" and substr($text, -1) == "'") {
|
||||
// Single quoted string.
|
||||
$text = trim($text, "'");
|
||||
$text = str_replace("\'", "'", $text);
|
||||
$text = str_replace('\\\\', '\\', $text);
|
||||
return $text;
|
||||
|
||||
} else if (substr($text, 0, 1) == '"' and substr($text, -1) == '"') {
|
||||
// Double quoted string.
|
||||
$text = trim($text, '"');
|
||||
$text = str_replace('\"', '"', $text);
|
||||
$text = str_replace('\\\\', '\\', $text);
|
||||
return $text;
|
||||
|
||||
} else {
|
||||
throw new moodle_exception(
|
||||
'Parsing error. Unexpected quotation in T_CONSTANT_ENCAPSED_STRING in decapsulate(): '.$text
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,9 +57,8 @@ class renderer extends \plugin_renderer_base {
|
||||
protected function render_tool_customlang_menu(\tool_customlang_menu $menu) {
|
||||
$output = '';
|
||||
foreach ($menu->get_items() as $item) {
|
||||
$button = $this->single_button($item->url, $item->title, $item->method);
|
||||
$output .= $this->box($button, 'menu');
|
||||
$output .= $this->single_button($item->url, $item->title, $item->method);
|
||||
}
|
||||
return $output;
|
||||
return $this->box($output, 'menu');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,135 +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/>.
|
||||
|
||||
/**
|
||||
* Export custom language strings to zip files.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @subpackage customlang
|
||||
* @copyright 2020 Thomas Wedekind <thomas.wedekind@univie.ac.at>
|
||||
* @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/$CFG->admin/tool/customlang/locallib.php");
|
||||
|
||||
$usage = <<<EOF
|
||||
"Export custom language files to a target folder.
|
||||
Useful for uploading custom langstrings to AMOS or importing or syncing them to other moodle instances.
|
||||
|
||||
Options:
|
||||
-l, --lang Comma seperated language ids to export, default: all
|
||||
-c, --components Comma seperated components to export, default: all
|
||||
-t, --target Target to copy the zip files to, default: $CFG->tempdir/customlang
|
||||
-o, --overwrite Overwrite existing files in the target folder.
|
||||
Note: If the target is not set, the files are always overwritten!
|
||||
-h, --help Print out this help
|
||||
|
||||
Examples:
|
||||
Export all custom language files to the default folder:
|
||||
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/export.php
|
||||
|
||||
Export just the english files of moodle core and the activity 'quiz' in a subfolder in my home folder:
|
||||
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/export.php --lang='en' --components='moodle,quiz' --target='~/customdir'
|
||||
|
||||
EOF;
|
||||
|
||||
$dafaulttarget = "$CFG->tempdir/customlang/";
|
||||
|
||||
// Now get cli options.
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'lang' => '',
|
||||
'components' => '',
|
||||
'target' => $dafaulttarget,
|
||||
'overwrite' => false,
|
||||
'help' => false,
|
||||
],
|
||||
['h' => 'help', 'c' => 'components', 't' => 'target', 'o' => 'overwrite']
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
echo $usage;
|
||||
die;
|
||||
}
|
||||
if (!file_exists($options['target'])) {
|
||||
mkdir($options['target'], 0777, true);
|
||||
}
|
||||
|
||||
cli_writeln(get_string('cliexportheading', 'tool_customlang'));
|
||||
$langs = [];
|
||||
if ($options['lang']) {
|
||||
$langs = explode(',', $options['lang']);
|
||||
} else {
|
||||
// No language set. We export all installed languages.
|
||||
$langs = array_keys(get_string_manager()->get_list_of_translations(true));
|
||||
}
|
||||
|
||||
foreach ($langs as $lang) {
|
||||
$filename = $options['target'] . get_string('exportzipfilename', 'tool_customlang', ['lang' => $lang]);
|
||||
// If the file exists and we are not using the temp folder it requires an ovewrite.
|
||||
if ($options['target'] != $dafaulttarget && file_exists($filename) && !$options['overwrite']) {
|
||||
cli_problem(get_string('cliexportfileexists', 'tool_customlang', $lang));
|
||||
continue;
|
||||
}
|
||||
cli_heading(get_string('cliexportstartexport', 'tool_customlang', $lang));
|
||||
$langdir = tool_customlang_utils::get_localpack_location($lang);
|
||||
if (!file_exists($langdir)) {
|
||||
// No custom files set for this language set.
|
||||
cli_writeln(get_string('cliexportnofilefoundforlang', 'tool_customlang', ['lang' => $lang]));
|
||||
continue;
|
||||
}
|
||||
$zipper = get_file_packer();
|
||||
$tempzip = tempnam($CFG->tempdir . '/', 'tool_customlang_export');
|
||||
$filelist = [];
|
||||
if ($options['components']) {
|
||||
$components = explode(',', $options['components']);
|
||||
foreach ($components as $component) {
|
||||
$filepath = "$langdir/$component.php";
|
||||
if (file_exists($filepath)) {
|
||||
$filelist["$component.php"] = $filepath;
|
||||
} else {
|
||||
cli_problem(
|
||||
get_string('cliexportfilenotfoundforcomponent', 'tool_customlang', ['lang' => $lang, 'file' => $filepath])
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$langfiles = scandir($langdir);
|
||||
foreach ($langfiles as $file) {
|
||||
if (substr($file, 0, 1) != '.') {
|
||||
$filelist[$file] = "$langdir/$file";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (empty($filelist)) {
|
||||
cli_problem(get_string('cliexportnofilefoundforlang', 'tool_customlang', ['lang' => $lang]));
|
||||
continue;
|
||||
}
|
||||
if ($zipper->archive_to_pathname($filelist, $filename)) {
|
||||
cli_writeln(get_string('cliexportzipdone', 'tool_customlang', $filename));
|
||||
} else {
|
||||
cli_problem(get_string('cliexportzipfail', 'tool_customlang', $filename));
|
||||
}
|
||||
}
|
||||
@@ -1,204 +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 customlang import tool.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @copyright 2020 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use tool_customlang\local\importer;
|
||||
use core\output\notification;
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__ . '/../../../../config.php');
|
||||
require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
|
||||
require_once("$CFG->libdir/clilib.php");
|
||||
|
||||
$usage =
|
||||
"Import lang customization.
|
||||
|
||||
It can get a single file or a folder.
|
||||
If no lang is provided it will try to infere from the filename
|
||||
|
||||
Options:
|
||||
--lang The target language (will get from filename if not provided)
|
||||
--source=path File or folder of the custom lang files (zip or php files)
|
||||
--mode What string should be imported. Options are:
|
||||
- all: all string will be imported (default)
|
||||
- new: only string with no previous customisation
|
||||
- update: only strings already modified
|
||||
--checkin Save strings to the language pack
|
||||
-h, --help Print out this help
|
||||
|
||||
Examples:
|
||||
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/import.php --lang=en --source=customlangs.zip
|
||||
|
||||
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/import.php --source=/tmp/customlangs --checkin
|
||||
|
||||
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/import.php --lang=en --source=/tmp/customlangs
|
||||
|
||||
";
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'help' => false,
|
||||
'lang' => false,
|
||||
'source' => false,
|
||||
'mode' => 'all',
|
||||
'checkin' => false,
|
||||
],
|
||||
['h' => 'help']
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
cli_write($usage);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$source = $options['source'] ?? null;
|
||||
$lang = $options['lang'] ?? null;
|
||||
$modeparam = $options['mode'] ?? 'all';
|
||||
$checkin = $options['checkin'] ?? false;
|
||||
|
||||
$modes = [
|
||||
'all' => importer::IMPORTALL,
|
||||
'update' => importer::IMPORTUPDATE,
|
||||
'new' => importer::IMPORTNEW,
|
||||
];
|
||||
if (!isset($modes[$modeparam])) {
|
||||
cli_error(get_string('climissingmode', 'tool_customlang'));
|
||||
}
|
||||
$mode = $modes[$modeparam];
|
||||
|
||||
if (empty($source)) {
|
||||
$source = $CFG->dataroot.'/temp/customlang';
|
||||
}
|
||||
|
||||
if (!file_exists($source)) {
|
||||
cli_error(get_string('climissingsource', 'tool_customlang'));
|
||||
}
|
||||
|
||||
// Emulate normal session - we use admin account by default.
|
||||
cron_setup_user();
|
||||
|
||||
// Get the file list.
|
||||
$files = [];
|
||||
$langfiles = [];
|
||||
|
||||
if (is_file($source)) {
|
||||
$files[] = $source;
|
||||
}
|
||||
if (is_dir($source)) {
|
||||
$filelist = glob("$source/*");
|
||||
foreach ($filelist as $filename) {
|
||||
$files[] = "$filename";
|
||||
}
|
||||
}
|
||||
|
||||
$countfiles = 0;
|
||||
foreach ($files as $filepath) {
|
||||
// Try to get the lang.
|
||||
$filelang = $lang;
|
||||
// Get component from filename.
|
||||
$pathparts = pathinfo($filepath);
|
||||
$filename = $pathparts['filename'];
|
||||
$extension = $pathparts['extension'];
|
||||
if ($extension == 'zip') {
|
||||
if (!$filelang) {
|
||||
// Try to get the lang from the filename.
|
||||
if (strrpos($filename, 'customlang_') === 0) {
|
||||
$parts = explode('_', $filename);
|
||||
if (!empty($parts[1])) {
|
||||
$filelang = $parts[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ($extension != 'php') {
|
||||
// Ignore any other file extension.
|
||||
continue;
|
||||
}
|
||||
if (empty($filelang)) {
|
||||
cli_error(get_string('climissinglang', 'tool_customlang'));
|
||||
}
|
||||
if (!isset($langfiles[$filelang])) {
|
||||
$langfiles[$filelang] = [];
|
||||
}
|
||||
$langfiles[$filelang][] = $filepath;
|
||||
$countfiles ++;
|
||||
}
|
||||
|
||||
if (!$countfiles) {
|
||||
cli_error(get_string('climissingfiles', 'tool_customlang'));
|
||||
}
|
||||
|
||||
foreach ($langfiles as $lng => $files) {
|
||||
$importer = new importer($lng, $mode);
|
||||
$storedfiles = [];
|
||||
$fs = get_file_storage();
|
||||
|
||||
cli_heading(get_string('clifiles', 'tool_customlang', $lng));
|
||||
|
||||
foreach ($files as $file) {
|
||||
// Generate a valid stored_file from this file.
|
||||
$record = (object)[
|
||||
'filearea' => 'draft',
|
||||
'component' => 'user',
|
||||
'filepath' => '/',
|
||||
'itemid' => file_get_unused_draft_itemid(),
|
||||
'license' => $CFG->sitedefaultlicense,
|
||||
'author' => '',
|
||||
'filename' => clean_param(basename($file), PARAM_FILE),
|
||||
'contextid' => \context_user::instance($USER->id)->id,
|
||||
'userid' => $USER->id,
|
||||
];
|
||||
cli_writeln($file);
|
||||
$storedfiles[] = $fs->create_file_from_pathname($record, $file);
|
||||
}
|
||||
cli_writeln("");
|
||||
|
||||
// Import files.
|
||||
cli_heading(get_string('cliimporting', 'tool_customlang', $modeparam));
|
||||
$importer->import($storedfiles);
|
||||
// Display logs.
|
||||
$log = $importer->get_log();
|
||||
if (empty($log)) {
|
||||
cli_problem(get_string('clinolog', 'tool_customlang', $lng));
|
||||
}
|
||||
foreach ($log as $message) {
|
||||
if ($message->errorlevel == notification::NOTIFY_ERROR) {
|
||||
cli_problem($message->get_message());
|
||||
} else {
|
||||
cli_writeln($message->get_message());
|
||||
}
|
||||
}
|
||||
// Do the checkin if necessary.
|
||||
if ($checkin) {
|
||||
tool_customlang_utils::checkin($lng);
|
||||
cli_writeln(get_string('savecheckin', 'tool_customlang'));
|
||||
}
|
||||
cli_writeln("");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
@@ -46,14 +46,5 @@ $capabilities = array(
|
||||
'manager' => CAP_ALLOW
|
||||
),
|
||||
),
|
||||
/* allows the user to export the current language customization */
|
||||
'tool/customlang:export' => array(
|
||||
'riskbitmask' => RISK_CONFIG,
|
||||
'captype' => 'read',
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => array(
|
||||
'manager' => CAP_ALLOW
|
||||
),
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
@@ -44,8 +44,5 @@ function xmldb_tool_customlang_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,68 +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/>.
|
||||
|
||||
/**
|
||||
* Performs the custom lang export.
|
||||
*
|
||||
* @package tool_customlang
|
||||
* @subpackage customlang
|
||||
* @copyright 2020 Thomas Wedekind <thomas.wedekind@univie.ac.at>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(__DIR__ . '/../../../config.php');
|
||||
require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
global $PAGE, $CFG;
|
||||
|
||||
require_login(SITEID, false);
|
||||
require_capability('tool/customlang:export', context_system::instance());
|
||||
|
||||
$lng = required_param('lng', PARAM_LANG);
|
||||
|
||||
admin_externalpage_setup('toolcustomlang', '', null,
|
||||
new moodle_url('/admin/tool/customlang/import.php', ['lng' => $lng]));
|
||||
|
||||
$form = new \tool_customlang\form\export(null, ['lng' => $lng]);
|
||||
|
||||
if ($form->is_cancelled()) {
|
||||
redirect('index.php');
|
||||
die();
|
||||
} else if ($formdata = $form->get_data()) {
|
||||
$tempzip = tempnam($CFG->tempdir . '/', 'tool_customlang_export');
|
||||
$filelist = [];
|
||||
foreach ($formdata->files as $file) {
|
||||
$filepath = tool_customlang_utils::get_localpack_location($lng). '/' . $file;
|
||||
if (file_exists($filepath)) {
|
||||
$filelist[$file] = $filepath;
|
||||
}
|
||||
}
|
||||
$zipper = new zip_packer();
|
||||
|
||||
if (!empty($filelist) && $zipper->archive_to_pathname($filelist, $tempzip)) {
|
||||
// Filename include the lang name so the file can be imported with automatic language detection.
|
||||
send_temp_file($tempzip, "customlang_$lng.zip");
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
$output = $PAGE->get_renderer('tool_customlang');
|
||||
|
||||
echo $output->header();
|
||||
echo $output->heading(get_string('pluginname', 'tool_customlang'));
|
||||
$form->display();
|
||||
echo $OUTPUT->footer();
|
||||
@@ -32,6 +32,7 @@ class tool_customlang_filter_form extends moodleform {
|
||||
|
||||
function definition() {
|
||||
$mform = $this->_form;
|
||||
$current = $this->_customdata['current'];
|
||||
|
||||
$mform->addElement('header', 'filtersettings', get_string('filter', 'tool_customlang'));
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user