Compare commits
975 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fdbcfa1b15 | |||
| cda2e48134 | |||
| d3b1e4da07 | |||
| b1bad4dbbc | |||
| 44883e4f32 | |||
| 6ade6d6060 | |||
| e3ce8c37bd | |||
| 56a9861094 | |||
| 6981b82c41 | |||
| f5644a9a79 | |||
| c110ef6c79 | |||
| 6904a25eb2 | |||
| dee4c975ae | |||
| 1c38f5031b | |||
| 188de51d23 | |||
| bbdb70f1d2 | |||
| c91ebee573 | |||
| a529aac615 | |||
| 0905aae5c6 | |||
| 5a4a2e9baa | |||
| 047d341465 | |||
| 759a87273f | |||
| 6c983fda3c | |||
| a08e8032c5 | |||
| fbd321ea90 | |||
| fe3ea2fe53 | |||
| 9d1b79c074 | |||
| a7eab36f96 | |||
| 3fd54014ae | |||
| 87002d24be | |||
| c3aba13f79 | |||
| ba32b852e5 | |||
| f4039ba2a9 | |||
| c11f5aa005 | |||
| c3367700c2 | |||
| b680dd8894 | |||
| 3259a19a6a | |||
| 11f8109d4c | |||
| 2172f91656 | |||
| ed7137f7f1 | |||
| de3a8678cd | |||
| a0af8ccba9 | |||
| 7eadd4979c | |||
| 63f9d1edc4 | |||
| 5231856a76 | |||
| cf86a03796 | |||
| 14c5642fa7 | |||
| 921e34a607 | |||
| 7d9ab768a4 | |||
| 4938cb25b1 | |||
| bb66f7e425 | |||
| f1a8f0059c | |||
| 543b0e0055 | |||
| df8a9bdde7 | |||
| 98d5109d91 | |||
| 9508492e28 | |||
| 590bfd9029 | |||
| 475784b2b5 | |||
| d77935d8ea | |||
| 31889f9b20 | |||
| 7526bfd8b7 | |||
| f4b822a178 | |||
| 3886236dae | |||
| b2b7a091b7 | |||
| 8858280766 | |||
| c95c319fad | |||
| 1a35908e1f | |||
| d474d4f3cf | |||
| cbc0b075b7 | |||
| 3698429d29 | |||
| 7b18e8ad63 | |||
| a052c15e6a | |||
| 1a84f17a20 | |||
| 8c0d6a1869 | |||
| ab42a71563 | |||
| 88f2c9bb45 | |||
| d7e367af90 | |||
| 28043b9b2e | |||
| 3f30ad9df0 | |||
| 001fdb5f29 | |||
| 79153d99cd | |||
| f75aed1c54 | |||
| 4436dd0fea | |||
| 296fa4b83d | |||
| bbc586af7e | |||
| 1ec11f0761 | |||
| 61e0c07247 | |||
| 8902acf217 | |||
| 38f0e86110 | |||
| df8978e969 | |||
| ab6a1b655b | |||
| d0c489dab7 | |||
| 437ce92e1b | |||
| 82d7777ca5 | |||
| c37c8fd6fa | |||
| 1d8d73c761 | |||
| 8ef225eb62 | |||
| 9cca971abc | |||
| 6509945bcd | |||
| b4a53cba59 | |||
| 5e0b235790 | |||
| e53e25af94 | |||
| 414a99535b | |||
| 1ae08553b7 | |||
| 97c3804ac3 | |||
| 55f0f4e0f4 | |||
| cd642570f1 | |||
| d7b4dd9a6a | |||
| dc02b1bbb2 | |||
| 18ce123c4e | |||
| 1a61b0bb6c | |||
| 93318586a5 | |||
| 177caaa3b5 | |||
| 33b1897e55 | |||
| abebddafc2 | |||
| dca920d105 | |||
| 254eb24e80 | |||
| 8552936427 | |||
| f683ec0990 | |||
| c4b81d09dc | |||
| 8d9ae08d7a | |||
| 889e427df0 | |||
| 2c99c5fa4d | |||
| c26e24b613 | |||
| 97c52ca3a1 | |||
| 42b3b6da8d | |||
| 8db30d32f8 | |||
| b35468292e | |||
| 141e369a01 | |||
| 0b8ab0da36 | |||
| 27bbd43730 | |||
| 666e68d5dc | |||
| 064b544465 | |||
| 32094232c7 | |||
| 27acd15fb4 | |||
| a8e813a289 | |||
| 789e0a41dc | |||
| 145a0690da | |||
| 10ac386fd2 | |||
| 91bf85846e | |||
| aceac725e6 | |||
| 744cd41a4d | |||
| 281fe1161a | |||
| dbb2deed8c | |||
| 59bcc16e26 | |||
| 9b1a88cbd9 | |||
| 1fe377b410 | |||
| 8888b7756f | |||
| 8f2dc4b229 | |||
| f993f02826 | |||
| 84b7fd82b6 | |||
| a6448908ed | |||
| 86a3a3d9c0 | |||
| 2184c2368f | |||
| 023b30e1bb | |||
| b2e715f33d | |||
| 34845eaad2 | |||
| 6c8db244c7 | |||
| 1169179385 | |||
| c431058d92 | |||
| 19c42ef49d | |||
| ec0c7a2788 | |||
| ef34b06efa | |||
| 96f8c0a106 | |||
| bf0bf4be24 | |||
| 9d7609f39c | |||
| 90553e9f6e | |||
| 06f1241f24 | |||
| 92ef33c4e0 | |||
| 20288fee39 | |||
| 50568e9382 | |||
| a8444275b1 | |||
| 2875fb574a | |||
| e519e93871 | |||
| f39af49969 | |||
| 44518ff64d | |||
| 952079533c | |||
| 7af2bad4e2 | |||
| 9416a1a399 | |||
| f006c73a17 | |||
| 7d883400d9 | |||
| c0d17ca8ba | |||
| 4d9b3c9839 | |||
| 984057c7cd | |||
| 825f039968 | |||
| d1a16f5f4a | |||
| f00b1a838e | |||
| baba4d8cc2 | |||
| eb4b144e13 | |||
| d20501ecf2 | |||
| 36afea55eb | |||
| afd07d1e42 | |||
| 320d99378c | |||
| 06f4976cab | |||
| 0bf0f82444 | |||
| 7b9adf44bf | |||
| 3d2710653e | |||
| 6dba57ee81 | |||
| ecc896f4b4 | |||
| 616e01911e | |||
| 524d855f6b | |||
| 0d855827c7 | |||
| 1d9d855172 | |||
| 1cb527de1c | |||
| df5626b1a3 | |||
| 27c2863777 | |||
| b169ba0121 | |||
| c317ee7de0 | |||
| 3f7c4d65e9 | |||
| e49bd4e798 | |||
| e555d057e9 | |||
| c5c13aa9ae | |||
| b01fee2008 | |||
| 3418b4d61c | |||
| dfd9b50595 | |||
| 5b60a837d1 | |||
| 00ad2a14da | |||
| 764d2cd510 | |||
| ddb0f7dc92 | |||
| 59303de673 | |||
| 1a7d05eca7 | |||
| 289d5f3faa | |||
| aa34b109a4 | |||
| c4cd3a61c8 | |||
| f4e4bfd3da | |||
| 3cd5cbd327 | |||
| 6d805b7774 | |||
| 38c8f8be7d | |||
| 180048ad9e | |||
| df1f4b8178 | |||
| d5e6b7e7eb | |||
| c9bd3a20b6 | |||
| a85d347227 | |||
| b4ed5e95b5 | |||
| 2700c84d7e | |||
| 24953e5d46 | |||
| a2487cbe55 | |||
| d88a746ec5 | |||
| 8e5396a6b1 | |||
| e2ea6b2a8a | |||
| a7d47d7813 | |||
| 3af0824487 | |||
| 9872e6f74f | |||
| 5368babac0 | |||
| d450c5931b | |||
| 74a5ef1332 | |||
| 689a57fa74 | |||
| 3d32032451 | |||
| eee7623eb8 | |||
| 30dbafdcdf | |||
| 169cb76c9e | |||
| 7edd9db682 | |||
| 583b3e5b3f | |||
| 45ea8119c6 | |||
| 56cc6bf703 | |||
| 9cd9153777 | |||
| 60c61a832a | |||
| 8430dc556f | |||
| e9b68a5f13 | |||
| b4493c2a16 | |||
| e51085274a | |||
| 3a886db065 | |||
| 816e396380 | |||
| fc40e74d15 | |||
| dc27423087 | |||
| d62139e86b | |||
| fa0dd0abab | |||
| 5d6424de33 | |||
| 3a70d7e816 | |||
| b3f611a14e | |||
| e3b8864cc4 | |||
| 7c46149ec5 | |||
| 3276137f1a | |||
| 1eaf570ea7 | |||
| 3afbd2a0ad | |||
| 02e99e4a4d | |||
| 80799bfec1 | |||
| 4d9a42c7d8 | |||
| 3eba3dc263 | |||
| 95c0628b61 | |||
| 5ee9422b3d | |||
| df530a7012 | |||
| 0a5b0201b4 | |||
| 320d38bb49 | |||
| 21478a1e5e | |||
| e69c09d756 | |||
| aba165140b | |||
| 9cd481431b | |||
| 5de4468345 | |||
| 632bbfafe1 | |||
| 152d919261 | |||
| 81f390069d | |||
| ca77344ead | |||
| 7e0b0bc14b | |||
| cdd954430f | |||
| 6ddf63486d | |||
| 21e1d60833 | |||
| d7f8f844bd | |||
| 643d5ec406 | |||
| 5ce0f28de8 | |||
| 3304dec7c5 | |||
| f1e67ccfa3 | |||
| 9ff194ffba | |||
| 6f5fc5f1ee | |||
| df56d5659d | |||
| 4938cbd0af | |||
| e6983a7a09 | |||
| ffac7011b3 | |||
| d59e83c423 | |||
| 2d337c94eb | |||
| 1dc488e333 | |||
| 54f90e39a1 | |||
| e46420e57e | |||
| 409fb784db | |||
| 00d62550c6 | |||
| 3d08e501fe | |||
| f215a8b9cc | |||
| acc1354295 | |||
| 9af9a0da85 | |||
| 789e3f42c0 | |||
| d24f96a248 | |||
| 76c7206927 | |||
| b82b0f6ce5 | |||
| 9a68b6ea7e | |||
| bd048774dd | |||
| a67daf6b24 | |||
| da4772d234 | |||
| d708740c3f | |||
| b20f6471b6 | |||
| 84f03ab16d | |||
| bebdb51753 | |||
| 4f14495420 | |||
| 1c843805eb | |||
| d08559b8ae | |||
| 1febfbebcd | |||
| ae317e6527 | |||
| d74f805126 | |||
| 30cc7e5c1e | |||
| 0acbe6914d | |||
| 9ddc556300 | |||
| be60921e14 | |||
| 4e8013e418 | |||
| 236b14a90f | |||
| be02cc3687 | |||
| 5bd5f5b4c9 | |||
| 493ef64d13 | |||
| dff5793807 | |||
| 3657cfa88c | |||
| 92f979948f | |||
| 5b90f71153 | |||
| 3e97c3ee83 | |||
| 844abeaf5d | |||
| e7e0609857 | |||
| 3b1ef88cb4 | |||
| 049288a65d | |||
| f5f40abd28 | |||
| 24a00a0d97 | |||
| 6e672c0a82 | |||
| ed369e32ef | |||
| fb049600c3 | |||
| a19e234dd3 | |||
| 5d6d91b706 | |||
| bf896b01dc | |||
| 8f090ac85d | |||
| 49705b1f40 | |||
| 4bd6777cfb | |||
| 497e9da529 | |||
| ad01614e9c | |||
| 152bdb1aa1 | |||
| 0a63b5c08d | |||
| 0693f196e7 | |||
| 8febbe3973 | |||
| f4172c491c | |||
| 190558640e | |||
| 7c7505e428 | |||
| 5b90938614 | |||
| 306fe2e5d8 | |||
| 02425dd8d6 | |||
| 4b434b3264 | |||
| ec77ff8474 | |||
| 52ae580ad6 | |||
| 4519964111 | |||
| f0d5a81699 | |||
| 92c332f491 | |||
| 49b55a357a | |||
| ffc2b63cd1 | |||
| e20149a2b4 | |||
| b3041d3a0f | |||
| 2190e59647 | |||
| 74b24ddc5f | |||
| c4b1115e8c | |||
| 4603578b43 | |||
| ab69d5373f | |||
| 89ee7a5fb7 | |||
| bd211c77e6 | |||
| a49411b80c | |||
| a920cd70e3 | |||
| f47c75b8ae | |||
| 796962c848 | |||
| 53a7ba2c5a | |||
| 383581d276 | |||
| d8f9c2f2a3 | |||
| bded9dee9d | |||
| c507f660f7 | |||
| c04f9ad6b3 | |||
| 0b319d563b | |||
| 03f4fb4c74 | |||
| 459334249b | |||
| 6846949785 | |||
| 26af1b6723 | |||
| 651bf5711d | |||
| 132dba3ed2 | |||
| 8b0fa0dc75 | |||
| 2ae6bde9dc | |||
| b2e9ca957a | |||
| 65d259ef55 | |||
| abca7c9ba0 | |||
| d50f0c1af6 | |||
| 5f396bff51 | |||
| aa9ee6b727 | |||
| 347054c624 | |||
| 842db17331 | |||
| 9b2a17d6cb | |||
| 1d926fabd4 | |||
| c2083cdfc1 | |||
| b3b2fb4681 | |||
| f238d324af | |||
| 96d1fbcaa5 | |||
| 401c26aa38 | |||
| fc0bd43f9d | |||
| 76102e0f11 | |||
| 630ccf76e3 | |||
| 6f01131eeb | |||
| 231a77fb58 | |||
| e61ec8f0a8 | |||
| 0022f54de5 | |||
| e198efde5a | |||
| 5c884e835e | |||
| cd11b40558 | |||
| d6ff7db956 | |||
| d30eabf344 | |||
| 9a0c490680 | |||
| 0a3c2be3a7 | |||
| e066c613c7 | |||
| 78f0557607 | |||
| 02cca91bfe | |||
| c3474f0fb7 | |||
| ae8059d346 | |||
| dd1a805bae | |||
| 00e3145a61 | |||
| 9b77e1974c | |||
| dfb8817998 | |||
| 76e2b6ef9f | |||
| d5c66fa1a4 | |||
| e9a7520a17 | |||
| c13b24dcaa | |||
| db67f81aa6 | |||
| 0e27c5f7a5 | |||
| c84606f5a7 | |||
| 547a925d39 | |||
| e851106c8f | |||
| 754b7af680 | |||
| d0fd8c6ff4 | |||
| b0388fdc49 | |||
| 3cbcba14ca | |||
| cdbdc89b32 | |||
| bcd0bdaf51 | |||
| 1b5c8d3be1 | |||
| d53fbbdd5c | |||
| b674666081 | |||
| cb0ab077ff | |||
| 4e3b6edaaf | |||
| 66401fdedb | |||
| a3d771cdca | |||
| a034c10238 | |||
| 1a7939778b | |||
| 68b3f1e4a7 | |||
| 357960c02f | |||
| 798edb457c | |||
| ce372c1185 | |||
| 4e0aa8af6c | |||
| 013378277a | |||
| 59ce247b72 | |||
| 9dca9da48c | |||
| ee48012f9c | |||
| a9a1791fe7 | |||
| 1f464b4045 | |||
| 8eb4217a49 | |||
| eb1ea16009 | |||
| b9277ef5e2 | |||
| 57d91f1f2a | |||
| 61421c7930 | |||
| 287d2a5e12 | |||
| ff60bfb0bf | |||
| 8a79df8f2a | |||
| f5342a222d | |||
| 1cc0b4832d | |||
| 3363d697f6 | |||
| b1837e6cf9 | |||
| 4fecc12ea1 | |||
| 2937e76650 | |||
| b1f8463bc1 | |||
| 1947886e0e | |||
| 38d68b8f3e | |||
| 1a225bc908 | |||
| c4b3e06f8a | |||
| 9ff2f0d7de | |||
| e9ae523134 | |||
| 16c5a3a0dd | |||
| 8dae0dec69 | |||
| e839fe812d | |||
| f164065979 | |||
| 58dd489eae | |||
| ba1c2e8d86 | |||
| 05875057c6 | |||
| 8ee995dfad | |||
| f313b73822 | |||
| 492bac151d | |||
| 241b6628f5 | |||
| 5f68f288a0 | |||
| 1c47240630 | |||
| a866652ea4 | |||
| 80b9cafca8 | |||
| b81c83e461 | |||
| 8eee29fb93 | |||
| b360784c5b | |||
| 306a4e04aa | |||
| 092213c80d | |||
| 321a8cb0ca | |||
| 0f62627d13 | |||
| 319a50649e | |||
| 5715b74d3a | |||
| c83345aa11 | |||
| 9d03236862 | |||
| 1b40599fbf | |||
| 7cd2e70ec9 | |||
| 15d70438bc | |||
| eb5cce9b4e | |||
| c096179b1c | |||
| 1a6985d6e2 | |||
| ed09a5ace4 | |||
| abb6bc93a6 | |||
| 2ccd0743fb | |||
| 80f90252b9 | |||
| b5d567068c | |||
| bfcaab9a0f | |||
| 350d1df507 | |||
| 0de2f98aaa | |||
| e658f9f04a | |||
| 017833a2ab | |||
| 8c9179174d | |||
| 8cb6079b4f | |||
| 39d606ec27 | |||
| d6cf61731e | |||
| 9294b6a37f | |||
| 4525bada77 | |||
| 993cc8ff8a | |||
| 5ac9ff15a0 | |||
| 15eec33f91 | |||
| 437db87b3e | |||
| 73d5d4d51f | |||
| 7d36cf9b34 | |||
| 0483366b23 | |||
| f374651109 | |||
| fef4736613 | |||
| 4a27fe0a25 | |||
| c1910fc822 | |||
| daf6a7c39e | |||
| fd82af2f5e | |||
| 0fa050c328 | |||
| 890828d9b4 | |||
| ffbea7e4fc | |||
| de0773cb42 | |||
| b5fc4139c8 | |||
| 1dab36ae65 | |||
| 60af848bb3 | |||
| cf7274f36e | |||
| 0476854339 | |||
| 25a9d276e1 | |||
| cb5943094d | |||
| af0e9fd216 | |||
| fdca502808 | |||
| 6f9a0826d7 | |||
| 8dc41648e3 | |||
| f62ae260f4 | |||
| fe7c20d157 | |||
| d069cb9337 | |||
| 30533452cf | |||
| ee2e8890f8 | |||
| 140f43198d | |||
| ef8eeba26c | |||
| 93b132bbd1 | |||
| 27b19d4daa | |||
| 31ad2a3e0e | |||
| 4d5fab8cf2 | |||
| d4af150760 | |||
| 0ba63f8913 | |||
| 4969af736f | |||
| 839740a522 | |||
| ac87f038e2 | |||
| 0a6c734fab | |||
| 62f71f1c81 | |||
| 2cc78b27de | |||
| cca619f966 | |||
| 1bd32a28e8 | |||
| 7be2023401 | |||
| 0397ea7e59 | |||
| f38397544a | |||
| a212b1ec3e | |||
| 945e79573f | |||
| b327defe5d | |||
| 2f0c3f4f7d | |||
| 7ff7ca5c6e | |||
| a5f36b8de2 | |||
| f99c21b543 | |||
| 004ceed0c1 | |||
| 10b6240719 | |||
| e475728710 | |||
| 634115240a | |||
| 5040b9b579 | |||
| 3d2ad7d76a | |||
| 0b31712cf4 | |||
| 573ee63a0e | |||
| 580dfbaeaa | |||
| e088975109 | |||
| 63fa452f51 | |||
| 09e0ba70ec | |||
| 56ae87b4d2 | |||
| 4572bf9827 | |||
| 3c82c11f72 | |||
| 41f365d633 | |||
| feeac598b1 | |||
| bab7bdc53e | |||
| 3c3090b6f9 | |||
| de95714ae0 | |||
| da07dbda3f | |||
| 54c4cf6ac1 | |||
| 1e7d038247 | |||
| 1a1684a6fc | |||
| 63c3c3f76e | |||
| 57d86b6a69 | |||
| c47a4021df | |||
| 1294e283ad | |||
| 787fee79c8 | |||
| 64fa2930e5 | |||
| 60a5ecfe46 | |||
| b59920cce3 | |||
| db9a86ff42 | |||
| 5463c97506 | |||
| 4fd50e8cd9 | |||
| fe88f321a2 | |||
| 6f78835258 | |||
| 191c8452d3 | |||
| 2e1636bb52 | |||
| ebb328750a | |||
| 5523816c38 | |||
| e3fe0299a1 | |||
| ab2a97b33d | |||
| 1bb9eb8467 | |||
| 42a0b73dc1 | |||
| ced2e3aca6 | |||
| 805bb41d5b | |||
| 50a2df69c3 | |||
| 066459d375 | |||
| 0551129c39 | |||
| 59b6d343bf | |||
| 2f22088b38 | |||
| 8516a494b6 | |||
| 53dd76348c | |||
| def51280c2 | |||
| 230e8d8485 | |||
| 91b88a51a5 | |||
| cdcfa083ff | |||
| 8a5e4412d9 | |||
| deae2cf2fd | |||
| 5666c34237 | |||
| 4535493590 | |||
| c4ed6da1c5 | |||
| 991056f698 | |||
| 937eab02f6 | |||
| e6441d7fdb | |||
| a12fbfae35 | |||
| 0074e485cd | |||
| aa168505a9 | |||
| bbff432ffa | |||
| 9c81a8e93f | |||
| 6dfe557c7e | |||
| cb53c504d3 | |||
| 41445fa1bf | |||
| 0be775af96 | |||
| 979fd06b47 | |||
| 0198546f6e | |||
| 12fc4c5e7a | |||
| 5b993c63c7 | |||
| 5673f75524 | |||
| efa7b639d0 | |||
| 948616f4a0 | |||
| 221b7618a1 | |||
| 5ceafdc943 | |||
| 40e58f8e3a | |||
| 2b84963424 | |||
| f35f522991 | |||
| bd26046264 | |||
| e2de61b74b | |||
| c2996f9301 | |||
| 9f26a1a312 | |||
| 2e7ca2f071 | |||
| 4cd34267b6 | |||
| f02b730069 | |||
| ceb4b0e0b4 | |||
| feb621d4de | |||
| 490929b3ba | |||
| d324358906 | |||
| f8c9d93455 | |||
| 14d4bfdd2a | |||
| 837e0cdce3 | |||
| 211419a9c6 | |||
| 92a2ccff5e | |||
| dce7206e8a | |||
| 65cc1b695a | |||
| b8602beb62 | |||
| e8ef35b7c9 | |||
| 9fb4b68799 | |||
| 8ed775e45f | |||
| fafa45112a | |||
| 9b8ce4d82b | |||
| 006b32290c | |||
| ba7c038739 | |||
| 4b2efd494e | |||
| 8e58b0bace | |||
| 7bca8a175f | |||
| 24d82b3e4a | |||
| eab32b304a | |||
| 86d0e4f7d7 | |||
| b9d50fc8fe | |||
| 8781ef341c | |||
| 4dfd7a290b | |||
| f3bfa720ad | |||
| 867cce4152 | |||
| 17bb38c307 | |||
| 47a4ef1e5e | |||
| b8bf53eb4b | |||
| eab8c74464 | |||
| 2d9c3446e9 | |||
| 79651c7d22 | |||
| fb5e0c453b | |||
| 6228f13bdd | |||
| 5bb2452ace | |||
| 8275662ed3 | |||
| f4eb5cb554 | |||
| f2fc73c674 | |||
| 9fc49012bd | |||
| 86f4f6864d | |||
| ca8715654b | |||
| d9a62c9fac | |||
| 4a9fa426bc | |||
| f1d4fd0db7 | |||
| 129d445908 | |||
| c6ad71859c | |||
| 2c58871a74 | |||
| 42d214d0cc | |||
| fb4a9db65e | |||
| f5e1074653 | |||
| 3ec081f2de | |||
| c374c271b1 | |||
| 09bdf8c905 | |||
| be3348d85e | |||
| cb9d48373b | |||
| 98018a490f | |||
| 1e1cd2fa6b | |||
| 603486e1f7 | |||
| 2409c05065 | |||
| df98fb57ee | |||
| 28e2f8bc2a | |||
| 2408bd007b | |||
| a22898e2af | |||
| d29cdb623e | |||
| eb4a12f1f0 | |||
| aee5fc1223 | |||
| 26a8d1fd81 | |||
| 137cfc18ee | |||
| 25212b83c3 | |||
| c6cc60cb79 | |||
| eaf62826c3 | |||
| 90f855220d | |||
| d0cedfa840 | |||
| c4920eab6d | |||
| 48f59ff4e6 | |||
| 264d4289da | |||
| a91c937935 | |||
| b5f4e35746 | |||
| 1201a5fad5 | |||
| 1d6529f5ea | |||
| 6cce66dcf7 | |||
| ead2f17b57 | |||
| 99935628cf | |||
| 825766216d | |||
| e17c20a424 | |||
| 76f327d195 | |||
| ffb62740c0 | |||
| 59c9a5f46b | |||
| 9009e1bd30 | |||
| dfb3226883 | |||
| e84729de92 | |||
| 7262d95895 | |||
| d4f34b0904 | |||
| 59bfaeda37 | |||
| 887e106a6c | |||
| be06a75a36 | |||
| ac39bac81b | |||
| 8a5e048594 | |||
| f91db6c35e | |||
| 66a3d9edba | |||
| f843322982 | |||
| 17e1d23c3f | |||
| fd2c90c29a | |||
| d2a6a5b164 | |||
| 7a5dabe6aa | |||
| de6d21497d | |||
| 0921c43e2c | |||
| 38db48744d | |||
| 582f1bc1fe | |||
| c496c5b819 | |||
| 9d40a13eb6 | |||
| 5990158a6f | |||
| cc262124db | |||
| 5ad18a4070 | |||
| ca4ac3e8b6 | |||
| c06e1de52d | |||
| daf1199956 | |||
| 5451d79a8c | |||
| 763a4a3dac | |||
| c9b5f15fb3 | |||
| 88667463ac | |||
| af1936faf4 | |||
| 2ea21b9ccf | |||
| 275c174cbf | |||
| 04757718b1 | |||
| b81a2f80f7 | |||
| 86cd6040f1 | |||
| c5ce22a2e6 | |||
| c18cf220a2 | |||
| 6bd67f0a5f | |||
| 8beef3f70b | |||
| b4c081fa08 | |||
| 7ee27356af | |||
| 1ecfc86f97 | |||
| 252dbc9605 | |||
| 9b9823a56a | |||
| 77134d5bb4 | |||
| e9aa483add | |||
| 95742edc54 | |||
| f3150d4a26 | |||
| d237a6312f | |||
| c36a037c20 | |||
| 3373632225 | |||
| c885df9202 | |||
| 1818370854 | |||
| 8ff3de4299 | |||
| 86899b14cb | |||
| b259811d7a | |||
| 7edd6995e5 | |||
| 35f7c54107 | |||
| 70d17adc0a | |||
| c05e07923f | |||
| f81b1125f5 | |||
| 454ec455bf | |||
| 5a1f0fd327 | |||
| 0a3eedbebf | |||
| 02bc67f6c5 | |||
| 7d4c2fb5f2 | |||
| f0066123a3 | |||
| b65077c4c0 | |||
| d58770969c | |||
| f7922dbe1d | |||
| 53f6f1ce05 | |||
| b4829f2475 | |||
| e8f9288606 | |||
| 72bdc3766e | |||
| d8ea630f24 | |||
| ac9e395ed6 | |||
| 8bdba9bdca | |||
| 99fc164199 | |||
| 64a7e06f61 | |||
| 9ec2c12f3d | |||
| 6ec89f6374 | |||
| 834c80849c | |||
| 674198a799 | |||
| 66c32a3687 | |||
| 0118227509 | |||
| 2e1478b094 | |||
| 6961258bc2 | |||
| b4f6816952 | |||
| 16b30d920b | |||
| 61d140e99f | |||
| cc5eb38cea | |||
| 3b7bba9e75 | |||
| 2e020b506a | |||
| 74cdb7c4c8 | |||
| ef8d381a2f | |||
| 39717b72b1 | |||
| e7ff99758e | |||
| 26492d4979 | |||
| 3abbcd9976 | |||
| 1456551ba6 | |||
| c1ebec7cbc | |||
| 812c8b37e5 | |||
| 8b2b7f97ee | |||
| f2ab11aa5b | |||
| 240b402523 | |||
| 34c4b3ce0c | |||
| 8b098b4a4e | |||
| 38a40c5e4b | |||
| 72580a5413 | |||
| 6253ab0170 | |||
| d25f2eeee6 | |||
| ff89abc311 | |||
| 7878d79359 | |||
| 93319747b2 | |||
| f46c1b4fa9 | |||
| a0297df86e | |||
| da9ab8a2f9 | |||
| 33829b8b68 | |||
| f5f468f6e1 | |||
| 6b4f55c91b | |||
| 63ed56bc7c | |||
| 841214dab2 | |||
| 43cbc05a2d | |||
| 973ea46697 | |||
| 98dbb93589 | |||
| 5fa19e43b3 | |||
| 0d3a2c9181 | |||
| 4f7bd72f72 | |||
| cc182408aa | |||
| 8b3913605a | |||
| 8ff67c91de | |||
| 4cbd6a0c6a | |||
| 203a55f57a | |||
| 5b05a9378c | |||
| b51257df71 | |||
| 81e5d425c4 | |||
| 6362d7b51c | |||
| 51d3df8d30 | |||
| a60a6d41a3 | |||
| d6ba7724ae | |||
| 4f1be71581 | |||
| 58ddfe84c2 | |||
| dd156a4160 | |||
| 3bc8fa20bf | |||
| 954ae33aa9 | |||
| 24dbcc0008 | |||
| ebb96c2850 | |||
| 870c5ffbde | |||
| 049e27a805 | |||
| 6c7fa91d59 | |||
| 7c84b92be3 | |||
| bb36c3a1bb | |||
| 990bfee024 | |||
| 17584f9c92 | |||
| f551072f9e | |||
| 3447ab640c | |||
| 3dbad11471 | |||
| 43b4b87fbf | |||
| 7d33385a1d | |||
| 657617ac21 | |||
| 205e4152cc | |||
| e36fb751e5 | |||
| a0c1acd7fd | |||
| 2184ea5b64 | |||
| c81b3dc384 | |||
| ca6a4b1953 | |||
| 20cefd70e2 | |||
| bc87d55a1f | |||
| 51c376cfca | |||
| e0034b0566 |
@@ -1,38 +1,53 @@
|
||||
{
|
||||
'plugins': [
|
||||
'@babel',
|
||||
'babel',
|
||||
'promise',
|
||||
'jsdoc'
|
||||
],
|
||||
'extends': [
|
||||
'eslint:recommended',
|
||||
'plugin:promise/recommended'
|
||||
'jsdoc',
|
||||
],
|
||||
'env': {
|
||||
'browser': true,
|
||||
// Enable ES6+ features by default.
|
||||
// See http://eslint.org/docs/user-guide/configuring#specifying-environments
|
||||
// Note: The YUI override must exactly match this when disabling the ES6+ version because those features are not supported by Shifter.
|
||||
'es2020': true,
|
||||
'amd': true
|
||||
},
|
||||
'globals': {
|
||||
'M': true,
|
||||
'Y': true
|
||||
},
|
||||
// Warn about unused eslint-disable statements.
|
||||
'reportUnusedDisableDirectives': true,
|
||||
'rules': {
|
||||
// See http://eslint.org/docs/rules/ for all rules and explanations of all
|
||||
// rules.
|
||||
|
||||
// === Possible Errors ===
|
||||
'comma-dangle': 'off',
|
||||
'no-compare-neg-zero': 'error',
|
||||
'no-cond-assign': 'error',
|
||||
'no-console': 'error',
|
||||
'no-constant-condition': 'error',
|
||||
'no-control-regex': 'error',
|
||||
'no-debugger': 'error',
|
||||
'no-dupe-args': 'error',
|
||||
'no-dupe-keys': 'error',
|
||||
'no-duplicate-case': 'error',
|
||||
'no-empty': 'warn',
|
||||
'no-empty-character-class': 'error',
|
||||
'no-ex-assign': 'error',
|
||||
'no-extra-boolean-cast': 'error',
|
||||
'no-extra-parens': 'off',
|
||||
'no-extra-semi': 'error',
|
||||
'no-func-assign': 'error',
|
||||
'no-inner-declarations': 'error',
|
||||
'no-invalid-regexp': 'error',
|
||||
'no-irregular-whitespace': 'error',
|
||||
'no-obj-calls': 'error',
|
||||
'no-prototype-builtins': 'off',
|
||||
'no-regex-spaces': 'error',
|
||||
'no-sparse-arrays': 'error',
|
||||
'no-unexpected-multiline': 'error',
|
||||
'no-unreachable': 'warn',
|
||||
'no-unsafe-finally': 'error',
|
||||
'no-unsafe-negation': 'error',
|
||||
'use-isnan': 'error',
|
||||
'valid-jsdoc': ['warn', { 'requireReturn': false, 'requireParamDescription': false, 'requireReturnDescription': false }],
|
||||
'valid-typeof': 'error',
|
||||
|
||||
// === Best Practices ===
|
||||
// (these mostly match our jshint config)
|
||||
@@ -44,12 +59,15 @@
|
||||
'dot-notation': 'warn',
|
||||
'no-alert': 'warn',
|
||||
'no-caller': 'error',
|
||||
'no-case-declarations': 'error',
|
||||
'no-div-regex': 'error',
|
||||
'no-empty-pattern': 'error',
|
||||
'no-empty-function': 'warn',
|
||||
'no-eq-null': 'error',
|
||||
'no-eval': 'error',
|
||||
'no-extend-native': 'error',
|
||||
'no-extra-bind': 'warn',
|
||||
'no-fallthrough': 'error',
|
||||
'no-floating-decimal': 'warn',
|
||||
'no-global-assign': 'warn',
|
||||
'no-implied-eval': 'error',
|
||||
@@ -61,22 +79,27 @@
|
||||
'no-multi-str': 'error',
|
||||
'no-new-func': 'error',
|
||||
'no-new-wrappers': 'error',
|
||||
'no-octal': 'error',
|
||||
'no-octal-escape': 'error',
|
||||
'no-proto': 'error',
|
||||
'no-redeclare': 'warn',
|
||||
'no-restricted-globals': ['error', { 'name': 'Notification' }],
|
||||
'no-return-assign': 'error',
|
||||
'no-script-url': 'error',
|
||||
'no-self-assign': 'error',
|
||||
'no-self-compare': 'error',
|
||||
'no-sequences': 'warn',
|
||||
'no-throw-literal': 'warn',
|
||||
'no-unmodified-loop-condition': 'error',
|
||||
'no-unused-expressions': 'error',
|
||||
'no-unused-labels': 'error',
|
||||
'no-useless-call': 'warn',
|
||||
'no-useless-escape': 'warn',
|
||||
'no-with': 'error',
|
||||
'wrap-iife': ['error', 'any'],
|
||||
|
||||
// === Variables ===
|
||||
'no-delete-var': 'error',
|
||||
'no-undef': 'error',
|
||||
'no-undef-init': 'error',
|
||||
'no-unused-vars': ['error', { 'caughtErrors': 'none' }],
|
||||
|
||||
@@ -109,6 +132,8 @@
|
||||
'max-statements-per-line': ['warn', { max: 2 }],
|
||||
'new-cap': ['warn', { 'properties': false }],
|
||||
'new-parens': 'warn',
|
||||
'newline-after-var': 'off',
|
||||
'newline-before-return': 'off',
|
||||
'newline-per-chained-call': 'off',
|
||||
'no-array-constructor': 'off',
|
||||
'no-bitwise': 'error',
|
||||
@@ -116,6 +141,7 @@
|
||||
'no-inline-comments': 'off',
|
||||
'no-lonely-if': 'off',
|
||||
'no-mixed-operators': 'off',
|
||||
'no-mixed-spaces-and-tabs': 'error',
|
||||
'no-multiple-empty-lines': 'warn',
|
||||
'no-negated-condition': 'off',
|
||||
'no-nested-ternary': 'warn',
|
||||
@@ -137,6 +163,7 @@
|
||||
'padded-blocks': 'off',
|
||||
'quote-props': ['warn', 'as-needed', {'unnecessary': false, 'keywords': true, 'numbers': true}],
|
||||
'quotes': 'off',
|
||||
'require-jsdoc': 'warn',
|
||||
'semi': 'error',
|
||||
'semi-spacing': ['warn', {'before': false, 'after': true}],
|
||||
'sort-vars': 'off',
|
||||
@@ -149,28 +176,26 @@
|
||||
'unicode-bom': 'error',
|
||||
'wrap-regex': 'off',
|
||||
|
||||
// === Promises (override plugin:promise/recommended) ===
|
||||
// === Promises ===
|
||||
'promise/always-return': 'warn',
|
||||
'promise/no-return-wrap': 'warn',
|
||||
'promise/param-names': 'warn',
|
||||
'promise/catch-or-return': ['warn', {terminationMethod: ['catch', 'fail', 'always'], allowFinally: true}],
|
||||
'promise/catch-or-return': ['warn', {terminationMethod: ['catch', 'fail']}],
|
||||
'promise/no-native': 'warn',
|
||||
'promise/no-promise-in-callback': 'warn',
|
||||
'promise/no-callback-in-promise': 'warn',
|
||||
'promise/avoid-new': 'warn',
|
||||
|
||||
// === Deprecations ===
|
||||
"no-restricted-properties": ['warn', {
|
||||
'object': 'M',
|
||||
'property': 'str',
|
||||
'message': 'Use "core/str" module or M.util.get_string()'
|
||||
'message': 'Use AMD module "core/str" or M.util.get_string()'
|
||||
}],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/yui/src/**/*.js"],
|
||||
'env': {
|
||||
// Disable ES6+ for YUI files.
|
||||
'es2020': false,
|
||||
},
|
||||
// Disable some rules which we can't safely define for YUI rollups.
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
@@ -196,11 +221,16 @@
|
||||
},
|
||||
{
|
||||
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile.js", ".grunt/*.js", ".grunt/tasks/*.js", "jsdoc.conf.js"],
|
||||
// We support es6 now. Woot!
|
||||
env: {
|
||||
es6: true
|
||||
},
|
||||
// We're using babel transpiling so use their parser
|
||||
// for linting.
|
||||
parser: '@babel/eslint-parser',
|
||||
// Check AMD with some slightly stricter rules.
|
||||
rules: {
|
||||
'no-unused-vars': 'error',
|
||||
'no-implicit-globals': 'error',
|
||||
// Disable all of the rules that have babel versions.
|
||||
'new-cap': 'off',
|
||||
@@ -212,37 +242,66 @@
|
||||
'semi': 'off',
|
||||
'no-unused-expressions': 'off',
|
||||
// Enable all of the babel version of these rules.
|
||||
'@babel/new-cap': ['warn', { 'properties': false }],
|
||||
'babel/new-cap': ['warn', { 'properties': false }],
|
||||
// Not using this rule for the time being because it isn't
|
||||
// compatible with jQuery and ES6.
|
||||
'@babel/no-invalid-this': 'off',
|
||||
'@babel/object-curly-spacing': 'warn',
|
||||
'@babel/semi': 'error',
|
||||
'@babel/no-unused-expressions': 'error',
|
||||
'babel/no-invalid-this': 'off',
|
||||
'babel/object-curly-spacing': 'warn',
|
||||
// This is off in the original style int.
|
||||
'babel/quotes': 'off',
|
||||
'babel/semi': 'error',
|
||||
'babel/no-unused-expressions': 'error',
|
||||
// === Promises ===
|
||||
// We have Promise now that we're using ES6.
|
||||
'promise/no-native': 'off',
|
||||
'promise/avoid-new': 'off',
|
||||
|
||||
// === JSDocs ===
|
||||
'jsdoc/check-access': 'error',
|
||||
'jsdoc/check-alignment': 1, // Recommended.
|
||||
'jsdoc/check-param-names': 'error',
|
||||
'jsdoc/check-property-names': 'error',
|
||||
'jsdoc/empty-tags': 'error',
|
||||
'jsdoc/implements-on-classes': 'error',
|
||||
'jsdoc/multiline-blocks': 'error',
|
||||
'jsdoc/require-jsdoc': 'error',
|
||||
'jsdoc/require-param': 'error',
|
||||
'jsdoc/require-param-name': 'error',
|
||||
'jsdoc/require-param-type': 'error',
|
||||
'jsdoc/require-property': 'error',
|
||||
'jsdoc/require-property-name': 'error',
|
||||
'jsdoc/require-property-type': 'error'
|
||||
"jsdoc/check-access": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/check-alignment": 1, // Recommended.
|
||||
"jsdoc/check-param-names": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/check-property-names": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/empty-tags": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/implements-on-classes": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/multiline-blocks": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-jsdoc": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-param": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-param-name": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-param-type": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-property": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-property-name": [
|
||||
'error',
|
||||
],
|
||||
"jsdoc/require-property-type": [
|
||||
'error',
|
||||
],
|
||||
},
|
||||
parserOptions: {
|
||||
'ecmaVersion': 9,
|
||||
'sourceType': 'module',
|
||||
'requireConfigFile': false
|
||||
'requireConfigFile': false,
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -7,15 +7,9 @@ on:
|
||||
- MOODLE_[0-9]+_STABLE
|
||||
tags-ignore:
|
||||
- v[0-9]+.[0-9]+.[0-9]+*
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
phpunit_extra_options:
|
||||
description: Additional options to apply to PHPUnit
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
env:
|
||||
php: 8.2
|
||||
php: 8.0
|
||||
|
||||
jobs:
|
||||
Grunt:
|
||||
@@ -60,35 +54,32 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# MySQL builds always run with the lowest PHP supported version.
|
||||
- os: ubuntu-22.04
|
||||
php: 8.0
|
||||
php: 7.3
|
||||
extensions:
|
||||
db: mysqli
|
||||
# PostgreSQL builds always run with the highest PHP supported version.
|
||||
- os: ubuntu-22.04
|
||||
php: 8.2
|
||||
php: 8.0
|
||||
db: pgsql
|
||||
extensions: xmlrpc-beta
|
||||
|
||||
steps:
|
||||
- name: Setting up DB mysql
|
||||
if: ${{ matrix.db == 'mysqli' }}
|
||||
uses: moodlehq/mysql-action@v1
|
||||
uses: johanmeiring/mysql-action@tmpfs-patch
|
||||
with:
|
||||
collation server: utf8mb4_bin
|
||||
mysql version: 8.0
|
||||
mysql version: 5.7
|
||||
mysql database: test
|
||||
mysql user: test
|
||||
mysql password: test
|
||||
use tmpfs: true
|
||||
tmpfs size: '1024M'
|
||||
extra conf: --skip-log-bin
|
||||
|
||||
- name: Setting up DB pgsql
|
||||
if: ${{ matrix.db == 'pgsql' }}
|
||||
uses: m4nu56/postgresql-action@v1
|
||||
with:
|
||||
postgresql version: 13
|
||||
postgresql version: 10
|
||||
postgresql db: test
|
||||
postgresql user: test
|
||||
postgresql password: test
|
||||
@@ -121,4 +112,4 @@ jobs:
|
||||
env:
|
||||
dbtype: ${{ matrix.db }}
|
||||
phpunit_options: ${{ secrets.phpunit_options }}
|
||||
run: vendor/bin/phpunit $phpunit_options ${{ inputs.phpunit_extra_options }}
|
||||
run: vendor/bin/phpunit $phpunit_options
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
name: Windows Testing
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
phpunit_extra_options:
|
||||
description: Additional options to apply to PHPUnit
|
||||
required: false
|
||||
default: ''
|
||||
env:
|
||||
php: 8.2
|
||||
|
||||
jobs:
|
||||
Grunt:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Set git to use LF
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
git config --global core.eol lf
|
||||
|
||||
- name: Checking out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Configuring node & npm
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Installing node stuff
|
||||
run: npm ci
|
||||
|
||||
- name: Running grunt
|
||||
run: npx grunt
|
||||
|
||||
- name: Looking for uncommitted changes
|
||||
# Add all files to the git index and then run diff --cached to see all changes.
|
||||
# This ensures that we get the status of all files, including new files.
|
||||
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
|
||||
run: |
|
||||
git add .
|
||||
git reset -- npm-shrinkwrap.json
|
||||
git diff --cached --exit-code
|
||||
|
||||
PHPUnit:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
php: 8.2
|
||||
# Ideally we should use mysql/mariadb, but they are 4x slower without tweaks and configuration
|
||||
# so let's run only postgres (1.5h vs 6h) only, If some day we want to improve the mysql runs,
|
||||
# this is the place to enable them.
|
||||
# db: mysqli
|
||||
db: pgsql
|
||||
extensions: exif, fileinfo, gd, intl, pgsql, mysql, redis, soap, sodium, zip
|
||||
- os: windows-latest
|
||||
php: 8.0
|
||||
db: pgsql
|
||||
extensions: exif, fileinfo, gd, intl, pgsql, mysql, redis, soap, sodium
|
||||
|
||||
steps:
|
||||
- name: Setting up DB mysql
|
||||
if: ${{ matrix.db == 'mysqli' }}
|
||||
uses: shogo82148/actions-setup-mysql@v1
|
||||
with:
|
||||
mysql-version: 8.0
|
||||
user: test
|
||||
password: test
|
||||
|
||||
- name: Creating DB mysql
|
||||
if: ${{ matrix.db == 'mysqli' }}
|
||||
run: mysql --host 127.0.0.1 -utest -ptest -e 'CREATE DATABASE IF NOT EXISTS test COLLATE = utf8mb4_bin;';
|
||||
|
||||
- name: Setting up DB pgsql
|
||||
if: ${{ matrix.db == 'pgsql' }}
|
||||
run: |
|
||||
# TODO: Remove these conf. modifications when php74 or php80 are lowest.
|
||||
# Change to old md5 auth, because php73 does not support it.
|
||||
# #password_encryption = scram-sha-256
|
||||
(Get-Content "$env:PGDATA\postgresql.conf"). `
|
||||
replace('#password_encryption = scram-sha-256', 'password_encryption = md5') | `
|
||||
Set-Content "$env:PGDATA\postgresql.conf"
|
||||
(Get-Content "$env:PGDATA\pg_hba.conf"). `
|
||||
replace('scram-sha-256', 'md5') | `
|
||||
Set-Content "$env:PGDATA\pg_hba.conf"
|
||||
$pgService = Get-Service -Name postgresql*
|
||||
Set-Service -InputObject $pgService -Status running -StartupType automatic
|
||||
Start-Process -FilePath "$env:PGBIN\pg_isready" -Wait -PassThru
|
||||
& $env:PGBIN\psql --command="CREATE USER test PASSWORD 'test'" --command="\du"
|
||||
|
||||
- name: Creating DB pgsql
|
||||
if: ${{ matrix.db == 'pgsql' }}
|
||||
run: |
|
||||
& $env:PGBIN\createdb --owner=test test
|
||||
$env:PGPASSWORD = 'test'
|
||||
& $env:PGBIN\psql --username=test --host=localhost --list test
|
||||
|
||||
- name: Configuring git vars
|
||||
uses: rlespinasse/github-slug-action@v4
|
||||
|
||||
- name: Setting up PHP ${{ matrix.php }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: ${{ matrix.extensions }}
|
||||
ini-values: max_input_vars=5000
|
||||
coverage: none
|
||||
|
||||
- name: Set git to use LF
|
||||
run: |
|
||||
git config --global core.autocrlf false
|
||||
git config --global core.eol lf
|
||||
|
||||
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Needs to be done after php is available, git configured and Moodle checkout has happened.
|
||||
- name: Setting up moodle-exttests service
|
||||
run: |
|
||||
git clone https://github.com/moodlehq/moodle-exttests.git
|
||||
nssm install php-built-in C:\tools\php\php.exe -S localhost:8080 -t D:\a\moodle\moodle\moodle-exttests
|
||||
nssm start php-built-in
|
||||
|
||||
- name: Setting up redis service
|
||||
run: |
|
||||
choco install redis-64 --version 3.0.503 --no-progress
|
||||
nssm install redis redis-server
|
||||
nssm start redis
|
||||
|
||||
- name: Setting up PHPUnit
|
||||
env:
|
||||
dbtype: ${{ matrix.db }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "pathtophp=$(which php)" >> $GITHUB_ENV # Inject installed pathtophp to env. The template config needs it.
|
||||
cp .github/workflows/config-template.php config.php
|
||||
mkdir ../moodledata
|
||||
php admin/tool/phpunit/cli/init.php --no-composer-self-update
|
||||
|
||||
- name: Running PHPUnit tests
|
||||
env:
|
||||
dbtype: ${{ matrix.db }}
|
||||
phpunit_options: ${{ secrets.phpunit_options }}
|
||||
run: vendor/bin/phpunit $phpunit_options ${{ inputs.phpunit_extra_options }}
|
||||
+2
-1
@@ -20,6 +20,7 @@
|
||||
*~
|
||||
#
|
||||
/config.php
|
||||
/lib/editor/tinymce/extra/tools/temp/
|
||||
/tags
|
||||
/TAGS
|
||||
/cscope.*
|
||||
@@ -53,5 +54,5 @@ moodle-plugin-ci.phar
|
||||
/admin/tool/componentlibrary/docs
|
||||
/admin/tool/componentlibrary/hugo/site/data/my-index.json
|
||||
.hugo_build.lock
|
||||
phpcs.xml
|
||||
.phpcs.xml
|
||||
jsconfig.json
|
||||
|
||||
+1
-151
@@ -156,7 +156,7 @@ const getThirdPartyLibsList = relativeTo => {
|
||||
* @returns {array}
|
||||
*/
|
||||
const getThirdPartyPaths = () => {
|
||||
const DOMParser = require('@xmldom/xmldom').DOMParser;
|
||||
const DOMParser = require('xmldom').DOMParser;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const xpath = require('xpath');
|
||||
@@ -232,155 +232,6 @@ const getOwningComponentDirectory = checkPath => {
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the latest tag in a remote GitHub repository.
|
||||
*
|
||||
* @param {string} url The remote repository.
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getRepositoryTags = async(url) => {
|
||||
const gtr = require('git-tags-remote');
|
||||
try {
|
||||
const tags = await gtr.get(url);
|
||||
if (tags !== undefined) {
|
||||
return tags;
|
||||
}
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of thirdparty libraries that could be upgraded.
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getThirdPartyLibsUpgradable = async() => {
|
||||
const libraries = getThirdPartyLibsData().filter((library) => !!library.repository);
|
||||
const upgradableLibraries = [];
|
||||
const versionCompare = (a, b) => {
|
||||
if (a === b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const aParts = a.split('.');
|
||||
const bParts = b.split('.');
|
||||
|
||||
for (let i = 0; i < Math.min(aParts.length, bParts.length); i++) {
|
||||
const aPart = parseInt(aParts[i], 10);
|
||||
const bPart = parseInt(bParts[i], 10);
|
||||
if (aPart > bPart) {
|
||||
// 1.1.0 > 1.0.9
|
||||
return 1;
|
||||
} else if (aPart < bPart) {
|
||||
// 1.0.9 < 1.1.0
|
||||
return -1;
|
||||
} else {
|
||||
// Same version.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (aParts.length > bParts.length) {
|
||||
// 1.0.1 > 1.0
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 1.0 < 1.0.1
|
||||
return -1;
|
||||
};
|
||||
|
||||
for (let library of libraries) {
|
||||
upgradableLibraries.push(
|
||||
getRepositoryTags(library.repository).then((tagMap) => {
|
||||
library.version = library.version.replace(/^v/, '');
|
||||
const currentVersion = library.version.replace(/moodle-/, '');
|
||||
const currentMajorVersion = library.version.split('.')[0];
|
||||
const tags = [...tagMap]
|
||||
.map((tagData) => tagData[0])
|
||||
.filter((tag) => !tag.match(/(alpha|beta|rc)/))
|
||||
.map((tag) => tag.replace(/^v/, ''))
|
||||
.sort((a, b) => versionCompare(b, a));
|
||||
if (!tags.length) {
|
||||
library.warning = "Unable to find any comparable tags.";
|
||||
return library;
|
||||
}
|
||||
|
||||
library.latestVersion = tags[0];
|
||||
tags.some((tag) => {
|
||||
if (!tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// See if the version part matches.
|
||||
const majorVersion = tag.split('.')[0];
|
||||
if (majorVersion === currentMajorVersion) {
|
||||
library.latestSameMajorVersion = tag;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
if (versionCompare(currentVersion, library.latestVersion) > 0) {
|
||||
// Moodle somehow has a newer version than the latest version.
|
||||
library.warning = `Newer version found: ${currentVersion} > ${library.latestVersion} for ${library.name}`;
|
||||
return library;
|
||||
}
|
||||
|
||||
|
||||
if (library.version !== library.latestVersion) {
|
||||
// Delete version and add it again at the end of the array. That way, current and new will stay closer.
|
||||
delete library.version;
|
||||
library.version = currentVersion;
|
||||
return library;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return (await Promise.all(upgradableLibraries)).filter((library) => !!library);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the list of thirdparty libraries.
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getThirdPartyLibsData = () => {
|
||||
const DOMParser = require('@xmldom/xmldom').DOMParser;
|
||||
const fs = require('fs');
|
||||
const xpath = require('xpath');
|
||||
const path = require('path');
|
||||
|
||||
const libraryList = [];
|
||||
const libraryFields = [
|
||||
'location',
|
||||
'name',
|
||||
'version',
|
||||
'repository',
|
||||
];
|
||||
|
||||
const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./'));
|
||||
thirdpartyfiles.forEach(function(libraryPath) {
|
||||
const xmlContent = fs.readFileSync(libraryPath, 'utf8');
|
||||
const doc = new DOMParser().parseFromString(xmlContent);
|
||||
const libraries = xpath.select("/libraries/library", doc);
|
||||
for (const library of libraries) {
|
||||
const libraryData = [];
|
||||
for (const field of libraryFields) {
|
||||
libraryData[field] = xpath.select(`${field}/text()`, library)?.toString();
|
||||
}
|
||||
libraryData.location = path.join(path.dirname(libraryPath), libraryData.location);
|
||||
libraryList.push(libraryData);
|
||||
}
|
||||
});
|
||||
|
||||
return libraryList.sort((a, b) => a.location.localeCompare(b.location));
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
fetchComponentData,
|
||||
getAmdSrcGlobList,
|
||||
@@ -390,5 +241,4 @@ module.exports = {
|
||||
getYuiSrcGlobList,
|
||||
getThirdPartyLibsList,
|
||||
getThirdPartyPaths,
|
||||
getThirdPartyLibsUpgradable,
|
||||
};
|
||||
|
||||
@@ -16,4 +16,4 @@ Moodle - the world's open source learning platform
|
||||
This generated documentation includes API documentation for JavaScript written in the AMD and ES2015 module formats within Moodle.
|
||||
|
||||
## Related information
|
||||
See [https://moodledev.io](https://moodledev.io) for other related Developer Documentation.
|
||||
See [https://docs.moodle.org/dev](https://docs.moodle.org/dev) for other related Developer Documentation.
|
||||
|
||||
@@ -114,7 +114,7 @@ module.exports = {
|
||||
],
|
||||
"menu": {
|
||||
"Developer Docs": {
|
||||
href: "https://moodledev.io",
|
||||
href: "https://docs.moodle.org/dev",
|
||||
target: "_blank",
|
||||
"class": "menu-item",
|
||||
id: "devdocs"
|
||||
|
||||
@@ -45,7 +45,6 @@ module.exports = grunt => {
|
||||
grunt.log.write(result);
|
||||
|
||||
if (error) {
|
||||
grunt.log.error(result.stdout);
|
||||
process.exit(code);
|
||||
}
|
||||
done();
|
||||
@@ -57,7 +56,7 @@ module.exports = grunt => {
|
||||
* @param {array} args
|
||||
* @returns {object}
|
||||
*/
|
||||
const spawnNodeCall = (args) => grunt.util.spawn({
|
||||
const spawnNodeCall = args => grunt.util.spawn({
|
||||
cmd: 'node',
|
||||
args,
|
||||
}, getSpawnHandler(grunt.task.current.async()));
|
||||
@@ -92,14 +91,13 @@ module.exports = grunt => {
|
||||
* @returns {Object} Reference to the spawned task
|
||||
*/
|
||||
const cssBuild = () => spawnNodeCall([
|
||||
'node_modules/sass/sass.js',
|
||||
'--style', 'expanded',
|
||||
'--source-map',
|
||||
'--embed-sources',
|
||||
'node_modules/node-sass/bin/node-sass',
|
||||
'--output-style', 'expanded',
|
||||
'--source-map', true,
|
||||
'--source-map-contents', true,
|
||||
'--precision', 6,
|
||||
'--load-path', process.cwd(),
|
||||
getCLPath('hugo/scss/docs.scss'),
|
||||
getCLPath('hugo/dist/css/docs.css'),
|
||||
'-o', getCLPath('hugo/dist/css/'),
|
||||
]);
|
||||
|
||||
// Register the various component library tasks.
|
||||
|
||||
@@ -39,7 +39,7 @@ module.exports = grunt => {
|
||||
{
|
||||
rule: {
|
||||
_attrs: {
|
||||
ref: './phpcs.xml.dist',
|
||||
ref: './.phpcs.xml.dist',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -52,7 +52,7 @@ module.exports = grunt => {
|
||||
});
|
||||
});
|
||||
|
||||
grunt.file.write('phpcs.xml', toXML(config, {
|
||||
grunt.file.write('.phpcs.xml', toXML(config, {
|
||||
header: true,
|
||||
indent: ' ',
|
||||
}) + "\n");
|
||||
|
||||
@@ -30,9 +30,10 @@
|
||||
* @param {String} srcPath the matched src path
|
||||
* @return {String} The rewritten destination path.
|
||||
*/
|
||||
|
||||
const babelRename = function(destPath, srcPath) {
|
||||
destPath = srcPath.replace(`amd/src`, `amd/build`);
|
||||
destPath = destPath.replace(/\.js$/, '.min.js');
|
||||
destPath = srcPath.replace('src', 'build');
|
||||
destPath = destPath.replace('.js', '.min.js');
|
||||
return destPath;
|
||||
};
|
||||
|
||||
@@ -151,7 +152,11 @@ module.exports = grunt => {
|
||||
//
|
||||
// It also adds the Moodle plugin name to the AMD module definition
|
||||
// so that it can be imported as expected in other modules.
|
||||
path.resolve('.grunt/babel-plugin-add-module-to-define.js')
|
||||
path.resolve('.grunt/babel-plugin-add-module-to-define.js'),
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-syntax-import-meta',
|
||||
['@babel/plugin-proposal-class-properties', {'loose': false}],
|
||||
'@babel/plugin-proposal-json-strings'
|
||||
],
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
|
||||
@@ -32,7 +32,7 @@ module.exports = grunt => {
|
||||
}
|
||||
},
|
||||
options: {
|
||||
implementation: require('sass'),
|
||||
implementation: require('node-sass'),
|
||||
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2023 Sara Arjona <sara@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
module.exports = grunt => {
|
||||
/**
|
||||
* Generate upgradable third-party libraries (utilising thirdpartylibs.xml data)
|
||||
*/
|
||||
grunt.registerTask('upgradablelibs', 'Generate upgradable third-party libraries', async function() {
|
||||
const done = this.async();
|
||||
|
||||
const path = require('path');
|
||||
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
|
||||
|
||||
// An array of third party libraries that have a newer version in their repositories.
|
||||
const thirdPartyLibs = await ComponentList.getThirdPartyLibsUpgradable({progress: true});
|
||||
for (let library of thirdPartyLibs) {
|
||||
grunt.log.ok(JSON.stringify(Object.assign({}, library), null, 4));
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ruleset name="MoodleCore">
|
||||
<rule ref="moodle"/>
|
||||
</ruleset>
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
# PLEASE NOTE: Travis is not currently utilised by the Moodle core integration
|
||||
# process (which uses our internal CI system) this file is here for the benefit
|
||||
# of community developers git clones - see MDL-51458.
|
||||
|
||||
notifications:
|
||||
email:
|
||||
if: env(MOODLE_EMAIL) != no
|
||||
|
||||
language: php
|
||||
|
||||
os: linux
|
||||
|
||||
dist: bionic
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- docker
|
||||
|
||||
addons:
|
||||
postgresql: "10"
|
||||
|
||||
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).
|
||||
# It will not stop the jobs from running.
|
||||
fast_finish: true
|
||||
|
||||
include:
|
||||
# First all the lowest php ones (7.3)
|
||||
- php: 7.3
|
||||
env: DB=none TASK=CITEST
|
||||
- php: 7.3
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/gallium'
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present
|
||||
php: 7.3
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
|
||||
php: 7.3
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
|
||||
# Then, conditionally, all the highest php ones (8.0)
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 8.0
|
||||
env: DB=none TASK=CITEST
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 8.0
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/gallium'
|
||||
|
||||
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present)
|
||||
php: 8.0
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
|
||||
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
|
||||
php: 8.0
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
- $HOME/.npm
|
||||
|
||||
before_install:
|
||||
- docker run -d -p 127.0.0.1:8080:80 --name exttests moodlehq/moodle-exttests
|
||||
# Avoid IPv6 default binding as service (causes redis not to start).
|
||||
- sudo service redis-server start --bind 127.0.0.1
|
||||
|
||||
install:
|
||||
- >
|
||||
if [ "$DB" = 'mysqli' ];
|
||||
then
|
||||
sudo mkdir /mnt/ramdisk
|
||||
sudo mount -t tmpfs -o size=1024m tmpfs /mnt/ramdisk
|
||||
sudo service mysql stop
|
||||
sudo mv /var/lib/mysql /mnt/ramdisk
|
||||
sudo ln -s /mnt/ramdisk/mysql /var/lib/mysql
|
||||
sudo service mysql restart
|
||||
fi
|
||||
- >
|
||||
if [ "$DB" = 'pgsql' ];
|
||||
then
|
||||
sudo mkdir /mnt/ramdisk
|
||||
sudo mount -t tmpfs -o size=1024m tmpfs /mnt/ramdisk
|
||||
sudo service postgresql stop
|
||||
sudo mv /var/lib/postgresql /mnt/ramdisk
|
||||
sudo ln -s /mnt/ramdisk/postgresql /var/lib/postgresql
|
||||
sudo service postgresql start 9.6
|
||||
fi
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
if [ -n "$GITHUB_APITOKEN" ]; then
|
||||
composer config github-oauth.github.com $GITHUB_APITOKEN;
|
||||
echo 'auth.json' >> .git/info/exclude
|
||||
fi
|
||||
|
||||
echo 'extension="redis.so"' > /tmp/redis.ini
|
||||
phpenv config-add /tmp/redis.ini
|
||||
|
||||
# Install composer dependencies.
|
||||
# We need --no-interaction in case we hit API limits for composer. This causes it to fall back to a standard clone.
|
||||
# Typically it should be able to use the Composer cache if any other job has already completed before we started here.
|
||||
travis_retry composer install --prefer-dist --no-interaction;
|
||||
fi
|
||||
|
||||
- >
|
||||
if [ "$TASK" = 'GRUNT' ];
|
||||
then
|
||||
nvm install $NVM_VERSION ;
|
||||
nvm use $NVM_VERSION ;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- if [[ ${TRAVIS_PHP_VERSION:0:1} -gt 7 ]]; then pecl install xmlrpc-beta; fi
|
||||
- echo 'max_input_vars=5000' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
|
||||
- phpenv config-rm xdebug.ini
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
# Copy generic configuration in place.
|
||||
cp config-dist.php config.php ;
|
||||
|
||||
# Create the moodledata directory.
|
||||
mkdir -p "$HOME"/roots/base
|
||||
|
||||
# The database name and password.
|
||||
sed -i \
|
||||
-e "s%= 'moodle'%= 'travis_ci_test'%" \
|
||||
-e "s%= 'password'%= ''%" \
|
||||
config.php ;
|
||||
|
||||
# The wwwroot and dataroot.
|
||||
sed -i \
|
||||
-e "s%http://example.com/moodle%https://localhost%" \
|
||||
-e "s%/home/example/moodledata%/home/travis/roots/base%" \
|
||||
config.php ;
|
||||
|
||||
if [ "$DB" = 'pgsql' ];
|
||||
then
|
||||
# Postgres-specific setup.
|
||||
sed -i \
|
||||
-e "s%= 'username'%= 'postgres'%" \
|
||||
config.php ;
|
||||
|
||||
psql -c 'CREATE DATABASE travis_ci_test;' -U postgres;
|
||||
fi
|
||||
|
||||
if [ "$DB" = 'mysqli' ];
|
||||
then
|
||||
# MySQL-specific setup.
|
||||
sed -i \
|
||||
-e "s%= 'pgsql'%= 'mysqli'%" \
|
||||
-e "s%= 'username'%= 'travis'%" \
|
||||
-e "s%=> 'utf8mb4_unicode_ci'%=> 'utf8mb4_bin'%" \
|
||||
config.php;
|
||||
|
||||
mysql -u root -e 'SET GLOBAL innodb_file_format=barracuda;' ;
|
||||
mysql -u root -e 'SET GLOBAL innodb_file_per_table=ON;' ;
|
||||
mysql -u root -e 'SET GLOBAL innodb_large_prefix=ON;' ;
|
||||
mysql -e 'CREATE DATABASE travis_ci_test DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_bin;' ;
|
||||
fi
|
||||
fi
|
||||
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
# Create a directory for the phpunit dataroot.
|
||||
mkdir -p "$HOME"/roots/phpunit
|
||||
|
||||
# The phpunit dataroot and prefix..
|
||||
sed -i \
|
||||
-e "/require_once/i \\\$CFG->phpunit_dataroot = '\/home\/travis\/roots\/phpunit';" \
|
||||
-e "/require_once/i \\\$CFG->phpunit_prefix = 'p_';" \
|
||||
config.php ;
|
||||
# Enable test external resources
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://127.0.0.1:8080');" \
|
||||
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://127.0.0.1:8080');" \
|
||||
config.php ;
|
||||
|
||||
# Redis cache store tests
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
|
||||
config.php ;
|
||||
# Redis session tests
|
||||
sed -i \
|
||||
-e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
|
||||
config.php ;
|
||||
|
||||
# Initialise PHPUnit for Moodle.
|
||||
php admin/tool/phpunit/cli/init.php
|
||||
fi
|
||||
|
||||
- >
|
||||
if [ "$TASK" = 'GRUNT' ];
|
||||
then
|
||||
npm install --no-spin;
|
||||
npm install --no-spin -g grunt ;
|
||||
fi
|
||||
|
||||
########################################################################
|
||||
# CI Tests
|
||||
########################################################################
|
||||
- >
|
||||
if [ "$TASK" = 'CITEST' ];
|
||||
then
|
||||
# Note - this is deliberately placed in the script section as we
|
||||
# should not add any code until after phpunit has run.
|
||||
|
||||
# The following repositories are required.
|
||||
# The local_ci repository does the actual checking.
|
||||
git clone https://github.com/moodlehq/moodle-local_ci.git local/ci
|
||||
|
||||
# We need the official upstream for comparison
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
git fetch upstream MOODLE_400_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`
|
||||
|
||||
# Variables required by our linter.
|
||||
export gitcmd=`which git`;
|
||||
export gitdir="$TRAVIS_BUILD_DIR";
|
||||
export phpcmd=`which php`;
|
||||
fi
|
||||
|
||||
script:
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
vendor/bin/phpunit --fail-on-risky --disallow-test-output --verbose;
|
||||
fi
|
||||
|
||||
- >
|
||||
if [ "$TASK" = 'CITEST' ];
|
||||
then
|
||||
bash local/ci/php_lint/php_lint.sh;
|
||||
fi
|
||||
|
||||
- >
|
||||
if [ "$TASK" = 'GRUNT' ];
|
||||
then
|
||||
grunt ;
|
||||
# Add all files to the git index and then run diff --cached to see all changes.
|
||||
# This ensures that we get the status of all files, including new files.
|
||||
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
|
||||
git add . ;
|
||||
git reset -- npm-shrinkwrap.json ;
|
||||
git diff --cached --exit-code ;
|
||||
fi
|
||||
|
||||
after_script:
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
EXTTESTS_HITS=$(docker logs exttests 2>&1 | grep -Fv -e 'AH00558' -e '[pid 1]' | wc -l)
|
||||
echo -e "\nTest local resources number of hits: ${EXTTESTS_HITS}.\n"
|
||||
fi
|
||||
+3
-3
@@ -6,7 +6,7 @@ of developers, designers, teachers, testers, translators and other users. We
|
||||
work in universities, schools, companies and other places. You are very welcome
|
||||
to join us and contribute to the project.
|
||||
|
||||
See <https://moodledev.io/general/community/contribute> for the many ways you
|
||||
See <https://docs.moodle.org/dev/Contributing_to_Moodle> for the many ways you
|
||||
can help, not only with coding.
|
||||
|
||||
Moodle is open to community contributions to core, though all code must go
|
||||
@@ -35,7 +35,7 @@ submitted patches has evolved.
|
||||
* New features are developed on the master branch. Bug fixes are also
|
||||
backported to currently supported maintenance (stable) branches.
|
||||
|
||||
For further details, see <https://moodledev.io/general/development/process>.
|
||||
For further details, see <https://docs.moodle.org/dev/Process>.
|
||||
|
||||
Moodle plugins
|
||||
--------------
|
||||
@@ -53,4 +53,4 @@ be easily installed and updated via the Moodle administration interface.
|
||||
the plugins directory. We do not pull from your code repository; you must do
|
||||
it explicitly.
|
||||
|
||||
For further details, see <https://moodledev.io/general/community/plugincontribution>.
|
||||
For further details, see <https://docs.moodle.org/dev/Plugin_contribution>.
|
||||
|
||||
@@ -260,8 +260,6 @@ module.exports = function(grunt) {
|
||||
addTask('watch', grunt);
|
||||
addTask('startup', grunt);
|
||||
|
||||
addTask('upgradablelibs', grunt);
|
||||
|
||||
// Register the default task.
|
||||
grunt.registerTask('default', ['startup']);
|
||||
};
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ Moodle is widely used around the world by universities, schools, companies and
|
||||
all manner of organisations and individuals.
|
||||
|
||||
Moodle is provided freely as open source software, under the GNU General Public
|
||||
License <https://moodledev.io/general/license>.
|
||||
License <https://docs.moodle.org/dev/License>.
|
||||
|
||||
Moodle is written in PHP and JavaScript and uses an SQL database for storing
|
||||
the data.
|
||||
|
||||
+35
-53
@@ -1,66 +1,48 @@
|
||||
MOODLE TRADEMARKS POLICY
|
||||
========================
|
||||
|
||||
The Moodle Trademark
|
||||
--------------------
|
||||
The word "Moodle" is trademarked in many countries around the world. The word
|
||||
was originally coined as an acronym: Modular Object-Oriented Dynamic Learning
|
||||
Environment. The trademark is owned by Martin Dougiamas, Founder and Director
|
||||
of Moodle.
|
||||
|
||||
The brand and word "Moodle" has trade mark protection in many countries around
|
||||
the world. Various Moodle™ trade marks are owned by either Moodle Pty Ltd or
|
||||
one of its associated entities. The law obligates trade mark owners to police
|
||||
their trade marks and prevent the use of confusingly similar names by
|
||||
third parties.
|
||||
The law obligates trademark owners to police their marks and prevent the use of
|
||||
confusingly similar names by third parties. Through this policy we’d like to
|
||||
make it clear how Moodle-related projects, organisations, and people can use
|
||||
the Moodle trademark. We’d also like to be clear about how use of the word is
|
||||
restricted when used to promote commercial Moodle services. We do this to
|
||||
protect the very business model that allows us to continue developing Moodle
|
||||
for you.
|
||||
|
||||
We have created a more concise and thorough set of Trademark Guidelines
|
||||
(https://moodle.com/wp-content/uploads/2023/02/Moodle-Trademark-Guidelines-2023-4.pdf)
|
||||
to help you understand how to comply with Moodle's trade mark requirements.
|
||||
The Trademark Guidelines will also assist our Moodle Certified Partners and the
|
||||
community to understand some of the principles that inform Moodle's stance
|
||||
whenever potential infringement has been detected by us or our community.
|
||||
Allowed uses
|
||||
------------
|
||||
|
||||
We need to be clear about use of the word "Moodle" and how we restrict its use
|
||||
when promoting commercial Moodle™ branded services. The proper use of
|
||||
trade marks reliably assures consumers about the quality of the associated
|
||||
products or services and where they have been derived from. Because the
|
||||
Moodle LMS is made available under the open source ‘GNU General Public License'
|
||||
that permits you to modify the copyrighted software, the distribution of such
|
||||
modified software in combination with Moodle trade marks can potentially
|
||||
mislead others in the community. To be clear, the GNU GPL does not include an
|
||||
implied right or licence to use Moodle's trade marks.
|
||||
The following uses don’t require any permission at all:
|
||||
|
||||
We do all this to protect the very business model that allows us to continue
|
||||
developing various Moodle software solutions for you.
|
||||
|
||||
Allowed uses of "Moodle"
|
||||
------------------------
|
||||
|
||||
The following uses don't require any permission at all:
|
||||
|
||||
* Referring to the software or the Moodle project as the "Moodle™ software"
|
||||
or the "Moodle™ project"
|
||||
* Describing your own implementation of the Moodle™ software platform
|
||||
(including within corporate settings).
|
||||
* Referring to the software or the Moodle project.
|
||||
* Describing your own Moodle implementation (including within corporate
|
||||
settings).
|
||||
* Describing a Moodle-based community hub.
|
||||
* Describing certain software you've made that integrates with Moodle™
|
||||
branded software (e.g. a Moodle™ integration feature on another system).
|
||||
* Describing some software you’ve made that integrates with Moodle
|
||||
(eg a Moodle integration feature on another system).
|
||||
|
||||
Restricted uses of "Moodle"
|
||||
---------------------------
|
||||
Restricted uses
|
||||
---------------
|
||||
|
||||
The following uses are generally prohibited without explicit and direct
|
||||
permission being granted to you by Moodle Pty Ltd. We do this to protect the
|
||||
Moodle™ project from software and sites which could confuse people. If in
|
||||
doubt, reach out for clarification at <trademarks@moodle.com>
|
||||
Moodle project from software and sites which could confuse people. Please
|
||||
contact us to ask for permission in writing.
|
||||
|
||||
* You can't use the word "Moodle" or any Moodle logos for commercial purposes
|
||||
without prior written permission from Moodle HQ.
|
||||
* You can't use "Moodle" in the name of your software (including Mobile apps).
|
||||
* You can't use "Moodle" in your company name.
|
||||
* You can't use "Moodle" in your domain name.
|
||||
* You can't use "Moodle" in advertising-related keywords (such as Adsense).
|
||||
* You can't use "Moodle" to describe services around Moodle
|
||||
(such as hosting, training, support, consulting, course creation services,
|
||||
theme development, customisation, installation, integration, analytics
|
||||
and certification) that cause consumers to be confused that you are
|
||||
associated with Moodle HQ if you are not.
|
||||
This applies even if you do not charge for the services.
|
||||
Note that usually only Moodle Partners have this permission.
|
||||
* You can’t use "Moodle" in the name of your software (including Mobile apps)
|
||||
* You can’t use "Moodle" in your company name
|
||||
* You can’t use "Moodle" in your domain name
|
||||
* You can’t use "Moodle" in advertising-related keywords (such as Adsense)
|
||||
* You can’t use "Moodle" to describe services around Moodle (such as hosting,
|
||||
training, support, consulting, course creation services, theme development,
|
||||
customisation, installation, integration and certification). This applies
|
||||
even if you do not charge for the services. Note that usually only Moodle
|
||||
Partners have this permission.
|
||||
|
||||
For information about the Moodle Partner Certification Mark as well as for how
|
||||
to contact us, please see <https://moodle.com/trademarks/>.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
define("core_admin/block_management_table",["exports","./plugin_management_table","core_table/dynamic","core/ajax","core/pending","core/notification"],(function(_exports,_plugin_management_table,_dynamic,_ajax,_pending,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_plugin_management_table=_interopRequireDefault(_plugin_management_table),_pending=_interopRequireDefault(_pending);class _default extends _plugin_management_table.default{constructor(){super(),this.addClickHandler(this.handleBlockProtectToggle)}setBlockProtectState(plugin,state){return(0,_ajax.call)([{methodname:"core_admin_set_block_protection",args:{plugin:plugin,state:state}}])[0]}async handleBlockProtectToggle(tableRoot,e){const stateToggle=e.target.closest('[data-action="toggleprotectstate"]');if(stateToggle){e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:processAction");await this.setBlockProtectState(stateToggle.dataset.plugin,"1"===stateToggle.dataset.targetState?1:0);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]);updatedRoot.querySelector('[data-action="toggleprotectstate"][data-plugin="'.concat(stateToggle.dataset.plugin,'"]')).focus(),pendingPromise.resolve()}}}return _exports.default=_default,_exports.default}));
|
||||
|
||||
//# sourceMappingURL=block_management_table.min.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"block_management_table.min.js","sources":["../src/block_management_table.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\nimport PluginManagementTable from './plugin_management_table';\nimport {refreshTableContent} from 'core_table/dynamic';\nimport {call as fetchMany} from 'core/ajax';\nimport Pending from 'core/pending';\nimport {fetchNotifications} from 'core/notification';\n\nexport default class extends PluginManagementTable {\n constructor() {\n super();\n this.addClickHandler(this.handleBlockProtectToggle);\n }\n\n /**\n * Set the block protection state.\n *\n * @param {string} plugin\n * @param {number} state\n * @returns {Promise}\n */\n setBlockProtectState(plugin, state) {\n return fetchMany([{\n methodname: 'core_admin_set_block_protection',\n args: {\n plugin,\n state,\n },\n }])[0];\n }\n\n /**\n * Handle toggling of block protection.\n *\n * @param {HTMLElement} tableRoot\n * @param {Event} e\n */\n async handleBlockProtectToggle(tableRoot, e) {\n const stateToggle = e.target.closest('[data-action=\"toggleprotectstate\"]');\n if (stateToggle) {\n e.preventDefault();\n const pendingPromise = new Pending('core_table/dynamic:processAction');\n\n await this.setBlockProtectState(\n stateToggle.dataset.plugin,\n stateToggle.dataset.targetState === '1' ? 1 : 0\n );\n\n const [updatedRoot] = await Promise.all([\n refreshTableContent(tableRoot),\n fetchNotifications(),\n ]);\n\n // Refocus on the link that as pressed in the first place.\n updatedRoot.querySelector(`[data-action=\"toggleprotectstate\"][data-plugin=\"${stateToggle.dataset.plugin}\"]`).focus();\n pendingPromise.resolve();\n }\n }\n}\n"],"names":["PluginManagementTable","constructor","addClickHandler","this","handleBlockProtectToggle","setBlockProtectState","plugin","state","methodname","args","tableRoot","e","stateToggle","target","closest","preventDefault","pendingPromise","Pending","dataset","targetState","updatedRoot","Promise","all","querySelector","focus","resolve"],"mappings":"uhBAqB6BA,iCACzBC,2BAESC,gBAAgBC,KAAKC,0BAU9BC,qBAAqBC,OAAQC,cAClB,cAAU,CAAC,CACdC,WAAY,kCACZC,KAAM,CACFH,OAAAA,OACAC,MAAAA,UAEJ,kCASuBG,UAAWC,SAChCC,YAAcD,EAAEE,OAAOC,QAAQ,yCACjCF,YAAa,CACbD,EAAEI,uBACIC,eAAiB,IAAIC,iBAAQ,0CAE7Bd,KAAKE,qBACPO,YAAYM,QAAQZ,OACgB,MAApCM,YAAYM,QAAQC,YAAsB,EAAI,SAG3CC,mBAAqBC,QAAQC,IAAI,EACpC,gCAAoBZ,YACpB,wCAIJU,YAAYG,wEAAiEX,YAAYM,QAAQZ,cAAYkB,QAC7GR,eAAeS"}
|
||||
@@ -1,3 +0,0 @@
|
||||
define("core_admin/plugin_management_table",["exports","core_table/dynamic","core_table/local/dynamic/selectors","core/ajax","core/pending","core/notification"],(function(_exports,_dynamic,Selectors,_ajax,_pending,_notification){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,Selectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Selectors),_pending=(obj=_pending)&&obj.__esModule?obj:{default:obj};let watching=!1;return _exports.default=class{constructor(){!function(obj,key,value){key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}(this,"clickHandlers",[]),this.addClickHandler(this.handleStateToggle),this.addClickHandler(this.handleMoveUpDown),this.registerEventListeners()}static init(){watching||(watching=!0,new this)}addClickHandler(handler){this.clickHandlers.push(handler.bind(this))}registerEventListeners(){document.addEventListener("click",function(e){const tableRoot=this.getTableRoot(e);tableRoot&&this.clickHandlers.forEach((handler=>handler(tableRoot,e)))}.bind(this))}getTableRoot(e){const tableRoot=e.target.closest(Selectors.main.region);return tableRoot||!1}setPluginState(methodname,plugin,state){return(0,_ajax.call)([{methodname:methodname,args:{plugin:plugin,state:state}}])[0]}setPluginOrder(methodname,plugin,direction){return(0,_ajax.call)([{methodname:methodname,args:{plugin:plugin,direction:direction}}])[0]}async handleStateToggle(tableRoot,e){const stateToggle=e.target.closest('[data-action="togglestate"][data-toggle-method]');if(stateToggle){e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:togglestate");await this.setPluginState(stateToggle.dataset.toggleMethod,stateToggle.dataset.plugin,"1"===stateToggle.dataset.state?0:1);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]);updatedRoot.querySelector('[data-action="togglestate"][data-plugin="'.concat(stateToggle.dataset.plugin,'"]')).focus(),pendingPromise.resolve()}}async handleMoveUpDown(tableRoot,e){const actionLink=e.target.closest('[data-action="move"][data-method][data-direction]');if(!actionLink)return;e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:processAction");await this.setPluginOrder(actionLink.dataset.method,actionLink.dataset.plugin,"up"===actionLink.dataset.direction?-1:1);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]),exactMatch=updatedRoot.querySelector('[data-action="move"][data-plugin="'.concat(actionLink.dataset.plugin,'"][data-direction="').concat(actionLink.dataset.direction,'"]'));var _updatedRoot$querySel;exactMatch?exactMatch.focus():null===(_updatedRoot$querySel=updatedRoot.querySelector('[data-action="move"][data-plugin="'.concat(actionLink.dataset.plugin,'"]')))||void 0===_updatedRoot$querySel||_updatedRoot$querySel.focus();pendingPromise.resolve()}},_exports.default}));
|
||||
|
||||
//# sourceMappingURL=plugin_management_table.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -1,72 +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/>.
|
||||
|
||||
import PluginManagementTable from './plugin_management_table';
|
||||
import {refreshTableContent} from 'core_table/dynamic';
|
||||
import {call as fetchMany} from 'core/ajax';
|
||||
import Pending from 'core/pending';
|
||||
import {fetchNotifications} from 'core/notification';
|
||||
|
||||
export default class extends PluginManagementTable {
|
||||
constructor() {
|
||||
super();
|
||||
this.addClickHandler(this.handleBlockProtectToggle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block protection state.
|
||||
*
|
||||
* @param {string} plugin
|
||||
* @param {number} state
|
||||
* @returns {Promise}
|
||||
*/
|
||||
setBlockProtectState(plugin, state) {
|
||||
return fetchMany([{
|
||||
methodname: 'core_admin_set_block_protection',
|
||||
args: {
|
||||
plugin,
|
||||
state,
|
||||
},
|
||||
}])[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle toggling of block protection.
|
||||
*
|
||||
* @param {HTMLElement} tableRoot
|
||||
* @param {Event} e
|
||||
*/
|
||||
async handleBlockProtectToggle(tableRoot, e) {
|
||||
const stateToggle = e.target.closest('[data-action="toggleprotectstate"]');
|
||||
if (stateToggle) {
|
||||
e.preventDefault();
|
||||
const pendingPromise = new Pending('core_table/dynamic:processAction');
|
||||
|
||||
await this.setBlockProtectState(
|
||||
stateToggle.dataset.plugin,
|
||||
stateToggle.dataset.targetState === '1' ? 1 : 0
|
||||
);
|
||||
|
||||
const [updatedRoot] = await Promise.all([
|
||||
refreshTableContent(tableRoot),
|
||||
fetchNotifications(),
|
||||
]);
|
||||
|
||||
// Refocus on the link that as pressed in the first place.
|
||||
updatedRoot.querySelector(`[data-action="toggleprotectstate"][data-plugin="${stateToggle.dataset.plugin}"]`).focus();
|
||||
pendingPromise.resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,179 +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/>.
|
||||
|
||||
import {refreshTableContent} from 'core_table/dynamic';
|
||||
import * as Selectors from 'core_table/local/dynamic/selectors';
|
||||
import {call as fetchMany} from 'core/ajax';
|
||||
import Pending from 'core/pending';
|
||||
import {fetchNotifications} from 'core/notification';
|
||||
|
||||
let watching = false;
|
||||
|
||||
export default class {
|
||||
/**
|
||||
* @property {function[]} clickHandlers a list of handlers to call on click.
|
||||
*/
|
||||
clickHandlers = [];
|
||||
|
||||
constructor() {
|
||||
this.addClickHandler(this.handleStateToggle);
|
||||
this.addClickHandler(this.handleMoveUpDown);
|
||||
this.registerEventListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise an instance of the class.
|
||||
*
|
||||
* This is just a way of making it easier to initialise an instance of the class from PHP.
|
||||
*/
|
||||
static init() {
|
||||
if (watching) {
|
||||
return;
|
||||
}
|
||||
watching = true;
|
||||
new this();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a click handler to the list of handlers.
|
||||
*
|
||||
* @param {Function} handler A handler to call on a click event
|
||||
*/
|
||||
addClickHandler(handler) {
|
||||
this.clickHandlers.push(handler.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the event listeners for this instance.
|
||||
*/
|
||||
registerEventListeners() {
|
||||
document.addEventListener('click', function(e) {
|
||||
const tableRoot = this.getTableRoot(e);
|
||||
|
||||
if (!tableRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clickHandlers.forEach((handler) => handler(tableRoot, e));
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table root from an event.
|
||||
*
|
||||
* @param {Event} e
|
||||
* @returns {HTMLElement|bool}
|
||||
*/
|
||||
getTableRoot(e) {
|
||||
const tableRoot = e.target.closest(Selectors.main.region);
|
||||
if (!tableRoot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return tableRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the plugin state (enabled or disabled)
|
||||
*
|
||||
* @param {string} methodname The web service to call
|
||||
* @param {string} plugin The name of the plugin to set the state for
|
||||
* @param {number} state The state to set
|
||||
* @returns {Promise}
|
||||
*/
|
||||
setPluginState(methodname, plugin, state) {
|
||||
return fetchMany([{
|
||||
methodname,
|
||||
args: {
|
||||
plugin,
|
||||
state,
|
||||
},
|
||||
}])[0];
|
||||
}
|
||||
|
||||
setPluginOrder(methodname, plugin, direction) {
|
||||
return fetchMany([{
|
||||
methodname,
|
||||
args: {
|
||||
plugin,
|
||||
direction,
|
||||
},
|
||||
}])[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle state toggling.
|
||||
*
|
||||
* @param {HTMLElement} tableRoot
|
||||
* @param {Event} e
|
||||
*/
|
||||
async handleStateToggle(tableRoot, e) {
|
||||
const stateToggle = e.target.closest('[data-action="togglestate"][data-toggle-method]');
|
||||
if (stateToggle) {
|
||||
e.preventDefault();
|
||||
const pendingPromise = new Pending('core_table/dynamic:togglestate');
|
||||
|
||||
await this.setPluginState(
|
||||
stateToggle.dataset.toggleMethod,
|
||||
stateToggle.dataset.plugin,
|
||||
stateToggle.dataset.state === '1' ? 0 : 1
|
||||
);
|
||||
|
||||
const [updatedRoot] = await Promise.all([
|
||||
refreshTableContent(tableRoot),
|
||||
fetchNotifications(),
|
||||
]);
|
||||
|
||||
// Refocus on the link that as pressed in the first place.
|
||||
updatedRoot.querySelector(`[data-action="togglestate"][data-plugin="${stateToggle.dataset.plugin}"]`).focus();
|
||||
pendingPromise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
async handleMoveUpDown(tableRoot, e) {
|
||||
const actionLink = e.target.closest('[data-action="move"][data-method][data-direction]');
|
||||
if (!actionLink) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
const pendingPromise = new Pending('core_table/dynamic:processAction');
|
||||
|
||||
await this.setPluginOrder(
|
||||
actionLink.dataset.method,
|
||||
actionLink.dataset.plugin,
|
||||
actionLink.dataset.direction === 'up' ? -1 : 1,
|
||||
);
|
||||
|
||||
const [updatedRoot] = await Promise.all([
|
||||
refreshTableContent(tableRoot),
|
||||
fetchNotifications(),
|
||||
]);
|
||||
|
||||
// Refocus on the link that as pressed in the first place.
|
||||
const exactMatch = updatedRoot.querySelector(
|
||||
`[data-action="move"][data-plugin="${actionLink.dataset.plugin}"][data-direction="${actionLink.dataset.direction}"]`
|
||||
);
|
||||
if (exactMatch) {
|
||||
exactMatch.focus();
|
||||
} else {
|
||||
// The move link is not present anymore, so we need to focus on the other one.
|
||||
updatedRoot.querySelector(`[data-action="move"][data-plugin="${actionLink.dataset.plugin}"]`)?.focus();
|
||||
}
|
||||
|
||||
pendingPromise.resolve();
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -28,7 +28,7 @@ if (empty($CFG->auth)) {
|
||||
}
|
||||
|
||||
if (!empty($auth) and !exists_auth_plugin($auth)) {
|
||||
throw new \moodle_exception('pluginnotinstalled', 'auth', $returnurl, $auth);
|
||||
print_error('pluginnotinstalled', 'auth', $returnurl, $auth);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -55,7 +55,7 @@ switch ($action) {
|
||||
$key = array_search($auth, $authsenabled);
|
||||
// check auth plugin is valid
|
||||
if ($key === false) {
|
||||
throw new \moodle_exception('pluginnotenabled', 'auth', $returnurl, $auth);
|
||||
print_error('pluginnotenabled', 'auth', $returnurl, $auth);
|
||||
}
|
||||
// move down the list
|
||||
if ($key < (count($authsenabled) - 1)) {
|
||||
@@ -72,7 +72,7 @@ switch ($action) {
|
||||
$key = array_search($auth, $authsenabled);
|
||||
// check auth is valid
|
||||
if ($key === false) {
|
||||
throw new \moodle_exception('pluginnotenabled', 'auth', $returnurl, $auth);
|
||||
print_error('pluginnotenabled', 'auth', $returnurl, $auth);
|
||||
}
|
||||
// move up the list
|
||||
if ($key >= 1) {
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
/**
|
||||
* Edit configuration for an individual auth plugin
|
||||
*/
|
||||
|
||||
require_once '../config.php';
|
||||
require_once $CFG->libdir.'/adminlib.php';
|
||||
|
||||
$auth = required_param('auth', PARAM_PLUGIN);
|
||||
$PAGE->set_pagetype('admin-auth-' . $auth);
|
||||
|
||||
admin_externalpage_setup('authsetting'.$auth);
|
||||
|
||||
$authplugin = get_auth_plugin($auth);
|
||||
$err = array();
|
||||
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageauths";
|
||||
|
||||
debugging("Use of config.html files in authentication plugins have been deprecated. " .
|
||||
" Please migrate your plugin to use the admin settings API", DEBUG_DEVELOPER);
|
||||
|
||||
// save configuration changes
|
||||
if ($frm = data_submitted() and confirm_sesskey()) {
|
||||
|
||||
$authplugin->validate_form($frm, $err);
|
||||
|
||||
if (count($err) == 0) {
|
||||
|
||||
// save plugin config
|
||||
if ($authplugin->process_config($frm)) {
|
||||
|
||||
// save field lock configuration
|
||||
foreach ($frm as $name => $value) {
|
||||
if (preg_match('/^lockconfig_(.+?)$/', $name, $matches)) {
|
||||
$plugin = "auth/$auth";
|
||||
$name = $matches[1];
|
||||
set_config($name, $value, $plugin);
|
||||
}
|
||||
}
|
||||
redirect($returnurl);
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
foreach ($err as $key => $value) {
|
||||
$focus = "form.$key";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$frmlegacystyle = get_config('auth/'.$auth);
|
||||
$frmnewstyle = get_config('auth_'.$auth);
|
||||
$frm = (object)array_merge((array)$frmlegacystyle, (array)$frmnewstyle);
|
||||
}
|
||||
|
||||
$user_fields = $authplugin->userfields;
|
||||
//$user_fields = array("firstname", "lastname", "email", "phone1", "phone2", "institution", "department", "address", "city", "country", "description", "idnumber", "lang");
|
||||
|
||||
/// Get the auth title (from core or own auth lang files)
|
||||
$authtitle = $authplugin->get_title();
|
||||
/// Get the auth descriptions (from core or own auth lang files)
|
||||
$authdescription = $authplugin->get_description();
|
||||
|
||||
// output configuration form
|
||||
echo $OUTPUT->header();
|
||||
|
||||
// choose an authentication method
|
||||
echo "<form id=\"authmenu\" method=\"post\" action=\"auth_config.php\">\n";
|
||||
echo "<div>\n";
|
||||
echo "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n";
|
||||
echo "<input type=\"hidden\" name=\"auth\" value=\"".$auth."\" />\n";
|
||||
|
||||
// auth plugin description
|
||||
echo $OUTPUT->box_start();
|
||||
echo $OUTPUT->heading($authtitle);
|
||||
echo $OUTPUT->box_start('informationbox');
|
||||
echo $authdescription;
|
||||
echo $OUTPUT->box_end();
|
||||
echo "<hr />\n";
|
||||
$authplugin->config_form($frm, $err, $user_fields);
|
||||
echo $OUTPUT->box_end();
|
||||
echo '<p style="text-align: center"><input type="submit" value="' . get_string("savechanges") . "\" /></p>\n";
|
||||
echo "</div>\n";
|
||||
echo "</form>\n";
|
||||
|
||||
$PAGE->requires->string_for_js('unmaskpassword', 'core_form');
|
||||
$PAGE->requires->yui_module('moodle-auth-passwordunmask', 'M.auth.passwordunmask');
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
|
||||
/// Functions /////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* auth field locking
|
||||
* Good enough for most auth plugins
|
||||
* but some may want a custom one if they are offering
|
||||
* other options
|
||||
* Note: lockconfig_ fields have special handling.
|
||||
*
|
||||
* @param string $auth authentication plugin shortname
|
||||
* @param array $user_fields user profile fields
|
||||
* @param string $helptext help text to be displayed at top of form
|
||||
* @param boolean $retrieveopts Map fields or lock only.
|
||||
* @param boolean $updateopts Allow remote updates
|
||||
* @param array $customfields list of custom profile fields
|
||||
* @deprecated since Moodle 3.3
|
||||
*/
|
||||
function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts, $updateopts, $customfields = array()) {
|
||||
global $DB, $OUTPUT;
|
||||
debugging("The function 'print_auth_lock_options' has been deprecated, " .
|
||||
"Please migrate your code to use the admin settings API and use the function 'display_auth_lock_options' instead. ",
|
||||
DEBUG_DEVELOPER);
|
||||
|
||||
echo '<tr><td colspan="3">';
|
||||
if ($retrieveopts) {
|
||||
echo $OUTPUT->heading(get_string('auth_data_mapping', 'auth'));
|
||||
} else {
|
||||
echo $OUTPUT->heading(get_string('auth_fieldlocks', 'auth'));
|
||||
}
|
||||
echo '</td></tr>';
|
||||
|
||||
$lockoptions = array ('unlocked' => get_string('unlocked', 'auth'),
|
||||
'unlockedifempty' => get_string('unlockedifempty', 'auth'),
|
||||
'locked' => get_string('locked', 'auth'));
|
||||
$updatelocaloptions = array('oncreate' => get_string('update_oncreate', 'auth'),
|
||||
'onlogin' => get_string('update_onlogin', 'auth'));
|
||||
$updateextoptions = array('0' => get_string('update_never', 'auth'),
|
||||
'1' => get_string('update_onupdate', 'auth'));
|
||||
|
||||
$pluginconfig = get_config("auth/$auth");
|
||||
|
||||
// Helptext is on a field with rowspan.
|
||||
if (empty($helptext)) {
|
||||
$helptext = ' ';
|
||||
}
|
||||
|
||||
// If we have custom fields then merge them with user fields.
|
||||
if (!empty($customfields)) {
|
||||
$user_fields = array_merge($user_fields, $customfields);
|
||||
}
|
||||
|
||||
if (!empty($customfields)) {
|
||||
$customfieldname = $DB->get_records('user_info_field', null, '', 'shortname, name');
|
||||
}
|
||||
foreach ($user_fields as $field) {
|
||||
// Define some vars we'll work with.
|
||||
if (!isset($pluginconfig->{"field_map_$field"})) {
|
||||
$pluginconfig->{"field_map_$field"} = '';
|
||||
}
|
||||
if (!isset($pluginconfig->{"field_updatelocal_$field"})) {
|
||||
$pluginconfig->{"field_updatelocal_$field"} = '';
|
||||
}
|
||||
if (!isset($pluginconfig->{"field_updateremote_$field"})) {
|
||||
$pluginconfig->{"field_updateremote_$field"} = '';
|
||||
}
|
||||
if (!isset($pluginconfig->{"field_lock_$field"})) {
|
||||
$pluginconfig->{"field_lock_$field"} = '';
|
||||
}
|
||||
|
||||
// Define the fieldname we display to the user.
|
||||
$fieldname = $field;
|
||||
if ($fieldname === 'lang') {
|
||||
$fieldname = get_string('language');
|
||||
} elseif (!empty($customfields) && in_array($field, $customfields)) {
|
||||
// If custom field then pick name from database.
|
||||
$fieldshortname = str_replace('profile_field_', '', $fieldname);
|
||||
$fieldname = $customfieldname[$fieldshortname]->name;
|
||||
if (core_text::strlen($fieldshortname) > 67) {
|
||||
// If custom profile field name is longer than 67 characters we will not be able to store the setting
|
||||
// such as 'field_updateremote_profile_field_NOTSOSHORTSHORTNAME' in the database because the character
|
||||
// limit for the setting name is 100.
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
$fieldname = get_string($fieldname);
|
||||
}
|
||||
if ($retrieveopts) {
|
||||
$varname = 'field_map_' . $field;
|
||||
|
||||
echo '<tr valign="top"><td align="right">';
|
||||
echo '<label for="lockconfig_'.$varname.'">'.$fieldname.'</label>';
|
||||
echo '</td><td>';
|
||||
|
||||
echo "<input id=\"lockconfig_{$varname}\" name=\"lockconfig_{$varname}\" type=\"text\" size=\"30\" value=\"{$pluginconfig->$varname}\" />";
|
||||
echo '<div style="text-align: right">';
|
||||
echo '<label for="menulockconfig_field_updatelocal_'.$field.'">'.get_string('auth_updatelocal', 'auth') . '</label> ';
|
||||
echo html_writer::select($updatelocaloptions, "lockconfig_field_updatelocal_{$field}", $pluginconfig->{"field_updatelocal_$field"}, false);
|
||||
echo '<br />';
|
||||
if ($updateopts) {
|
||||
echo '<label for="menulockconfig_field_updateremote_'.$field.'">'.get_string('auth_updateremote', 'auth') . '</label> ';
|
||||
echo html_writer::select($updateextoptions, "lockconfig_field_updateremote_{$field}", $pluginconfig->{"field_updateremote_$field"}, false);
|
||||
echo '<br />';
|
||||
}
|
||||
echo '<label for="menulockconfig_field_lock_'.$field.'">'.get_string('auth_fieldlock', 'auth') . '</label> ';
|
||||
echo html_writer::select($lockoptions, "lockconfig_field_lock_{$field}", $pluginconfig->{"field_lock_$field"}, false);
|
||||
echo '</div>';
|
||||
} else {
|
||||
echo '<tr valign="top"><td align="right">';
|
||||
echo '<label for="menulockconfig_field_lock_'.$field.'">'.$fieldname.'</label>';
|
||||
echo '</td><td>';
|
||||
echo html_writer::select($lockoptions, "lockconfig_field_lock_{$field}", $pluginconfig->{"field_lock_$field"}, false);
|
||||
}
|
||||
echo '</td>';
|
||||
if (!empty($helptext)) {
|
||||
echo '<td rowspan="' . count($user_fields) . '">' . $helptext . '</td>';
|
||||
$helptext = '';
|
||||
}
|
||||
echo '</tr>';
|
||||
}
|
||||
}
|
||||
+222
-77
@@ -1,94 +1,239 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Allows the admin to configure blocks (hide/show, uninstall and configure)
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
// Allows the admin to configure blocks (hide/show, uninstall and configure)
|
||||
|
||||
require_once('../config.php');
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
require_once("{$CFG->libdir}/blocklib.php");
|
||||
require_once("{$CFG->libdir}/tablelib.php");
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/blocklib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
|
||||
admin_externalpage_setup('manageblocks');
|
||||
admin_externalpage_setup('manageblocks');
|
||||
|
||||
$plugin = optional_param('plugin', '', PARAM_PLUGIN);
|
||||
$action = optional_param('action', '', PARAM_ALPHA);
|
||||
$unprotect = optional_param('unprotect', 0, PARAM_PLUGIN);
|
||||
$protect = optional_param('protect', 0, PARAM_PLUGIN);
|
||||
$confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$hide = optional_param('hide', 0, PARAM_INT);
|
||||
$show = optional_param('show', 0, PARAM_INT);
|
||||
$unprotect = optional_param('unprotect', 0, PARAM_INT);
|
||||
$protect = optional_param('protect', 0, PARAM_INT);
|
||||
|
||||
$strmanageblocks = get_string('manageblocks');
|
||||
/// Print headings
|
||||
|
||||
// If data submitted, then process and store.
|
||||
if (!empty($plugin) && !empty($action) && confirm_sesskey()) {
|
||||
$manager = \core_plugin_manager::resolve_plugininfo_class('block');
|
||||
$pluginname = get_string('pluginname', "block_{$plugin}");
|
||||
$strmanageblocks = get_string('manageblocks');
|
||||
$struninstall = get_string('uninstallplugin', 'core_admin');
|
||||
$strversion = get_string('version');
|
||||
$strhide = get_string('hide');
|
||||
$strshow = get_string('show');
|
||||
$strsettings = get_string('settings');
|
||||
$strcourses = get_string('blockinstances', 'admin');
|
||||
$strname = get_string('name');
|
||||
$strshowblockcourse = get_string('showblockcourse');
|
||||
$strprotecthdr = get_string('blockprotect', 'admin'). $OUTPUT->help_icon('blockprotect','admin');
|
||||
$strprotect = get_string('blockprotect', 'admin');
|
||||
$strunprotect = get_string('blockunprotect', 'admin');
|
||||
|
||||
if ($action === 'disable' && $manager::enable_plugin($plugin, 0)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_disabled', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
} else if ($action === 'enable' && $manager::enable_plugin($plugin, 1)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_enabled', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
|
||||
// If data submitted, then process and store.
|
||||
if (!empty($hide) && confirm_sesskey()) {
|
||||
if (!$block = $DB->get_record('block', ['id' => $hide])) {
|
||||
throw new \moodle_exception('blockdoesnotexist', 'error');
|
||||
}
|
||||
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('block');
|
||||
$class::enable_plugin($block->name, false);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
|
||||
// Redirect back to the page with out any params.
|
||||
redirect(new moodle_url('/admin/blocks.php'));
|
||||
}
|
||||
if (!empty($show) && confirm_sesskey() ) {
|
||||
if (!$block = $DB->get_record('block', ['id' => $show])) {
|
||||
throw new \moodle_exception('blockdoesnotexist', 'error');
|
||||
}
|
||||
|
||||
if (!empty($protect) && confirm_sesskey()) {
|
||||
block_manager::protect_block($protect);
|
||||
$pluginname = get_string('pluginname', "block_{$protect}");
|
||||
\core\notification::add(
|
||||
get_string('blockprotected', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('block');
|
||||
$class::enable_plugin($block->name, true);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
|
||||
if (!empty($unprotect) && confirm_sesskey()) {
|
||||
block_manager::unprotect_block($unprotect);
|
||||
$pluginname = get_string('pluginname', "block_{$unprotect}");
|
||||
\core\notification::add(
|
||||
get_string('blockunprotected', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
if (!empty($protect) && confirm_sesskey()) {
|
||||
block_manager::protect_block((int)$protect);
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($strmanageblocks);
|
||||
echo $OUTPUT->notification(get_string('noteunneededblocks', 'admin'), 'info', false);
|
||||
if (!empty($unprotect) && confirm_sesskey()) {
|
||||
block_manager::unprotect_block((int)$unprotect);
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
}
|
||||
|
||||
// Print the table of all blocks.
|
||||
$table = new \core_admin\table\block_management_table();
|
||||
$table->out();
|
||||
echo $OUTPUT->footer();
|
||||
$undeletableblocktypes = block_manager::get_undeletable_block_types();
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($strmanageblocks);
|
||||
|
||||
echo $OUTPUT->notification(get_string('noteunneededblocks', 'admin'), 'info');
|
||||
/// Main display starts here
|
||||
|
||||
/// Get and sort the existing blocks
|
||||
|
||||
if (!$blocks = $DB->get_records('block', array(), 'name ASC')) {
|
||||
print_error('noblocks', 'error'); // Should never happen
|
||||
}
|
||||
|
||||
$incompatible = array();
|
||||
|
||||
/// Print the table of all blocks
|
||||
|
||||
$table = new flexible_table('admin-blocks-compatible');
|
||||
|
||||
$table->define_columns(array('name', 'instances', 'version', 'hideshow', 'undeletable', 'settings', 'uninstall'));
|
||||
$table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strprotecthdr, $strsettings, $struninstall));
|
||||
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
|
||||
$table->set_attribute('class', 'admintable blockstable generaltable');
|
||||
$table->set_attribute('id', 'compatibleblockstable');
|
||||
$table->setup();
|
||||
$tablerows = array();
|
||||
|
||||
// Sort blocks using current locale.
|
||||
$blocknames = array();
|
||||
foreach ($blocks as $blockid=>$block) {
|
||||
$blockname = $block->name;
|
||||
if (file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
|
||||
$blocknames[$blockid] = get_string('pluginname', 'block_'.$blockname);
|
||||
} else {
|
||||
$blocknames[$blockid] = $blockname;
|
||||
}
|
||||
}
|
||||
core_collator::asort($blocknames);
|
||||
|
||||
foreach ($blocknames as $blockid=>$strblockname) {
|
||||
$block = $blocks[$blockid];
|
||||
$blockname = $block->name;
|
||||
$dbversion = get_config('block_'.$block->name, 'version');
|
||||
|
||||
if (!file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
|
||||
$blockobject = false;
|
||||
$strblockname = '<span class="notifyproblem">'.$strblockname.' ('.get_string('missingfromdisk').')</span>';
|
||||
$plugin = new stdClass();
|
||||
$plugin->version = $dbversion;
|
||||
|
||||
} else {
|
||||
$plugin = new stdClass();
|
||||
$plugin->version = '???';
|
||||
if (file_exists("$CFG->dirroot/blocks/$blockname/version.php")) {
|
||||
include("$CFG->dirroot/blocks/$blockname/version.php");
|
||||
}
|
||||
|
||||
if (!$blockobject = block_instance($block->name)) {
|
||||
$incompatible[] = $block;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$blockname, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
} else {
|
||||
$uninstall = '';
|
||||
}
|
||||
|
||||
$settings = ''; // By default, no configuration
|
||||
if ($blockobject and $blockobject->has_config()) {
|
||||
$blocksettings = admin_get_root()->locate('blocksetting' . $block->name);
|
||||
|
||||
if ($blocksettings instanceof admin_externalpage) {
|
||||
$settings = '<a href="' . $blocksettings->url . '">' . get_string('settings') . '</a>';
|
||||
} else if ($blocksettings instanceof admin_settingpage) {
|
||||
$settings = '<a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=blocksetting'.$block->name.'">'.$strsettings.'</a>';
|
||||
} else if (!file_exists($CFG->dirroot.'/blocks/'.$block->name.'/settings.php')) {
|
||||
// If the block's settings node was not found, we check that the block really provides the settings.php file.
|
||||
// Note that blocks can inject their settings to other nodes in the admin tree without using the default locations.
|
||||
// This can be done by assigning null to $setting in settings.php and it is a valid case.
|
||||
debugging('Warning: block_'.$block->name.' returns true in has_config() but does not provide a settings.php file',
|
||||
DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
|
||||
// MDL-11167, blocks can be placed on mymoodle, or the blogs page
|
||||
// and it should not show up on course search page
|
||||
|
||||
$totalcount = $DB->count_records('block_instances', array('blockname'=>$blockname));
|
||||
$count = $DB->count_records('block_instances', array('blockname'=>$blockname, 'pagetypepattern'=>'course-view-*'));
|
||||
|
||||
if ($count>0) {
|
||||
$blocklist = "<a href=\"{$CFG->wwwroot}/course/search.php?blocklist=$blockid&sesskey=".sesskey()."\" ";
|
||||
$blocklist .= "title=\"$strshowblockcourse\" >$totalcount</a>";
|
||||
}
|
||||
else {
|
||||
$blocklist = "$totalcount";
|
||||
}
|
||||
$class = ''; // Nothing fancy, by default
|
||||
|
||||
if (!$blockobject) {
|
||||
// ignore
|
||||
$visible = '';
|
||||
} else if ($blocks[$blockid]->visible) {
|
||||
$visible = '<a href="blocks.php?hide='.$blockid.'&sesskey='.sesskey().'" title="'.$strhide.'">'.
|
||||
$OUTPUT->pix_icon('t/hide', $strhide) . '</a>';
|
||||
} else {
|
||||
$visible = '<a href="blocks.php?show='.$blockid.'&sesskey='.sesskey().'" title="'.$strshow.'">'.
|
||||
$OUTPUT->pix_icon('t/show', $strshow) . '</a>';
|
||||
$class = 'dimmed_text';
|
||||
}
|
||||
|
||||
if ($dbversion == $plugin->version) {
|
||||
$version = $dbversion;
|
||||
} else {
|
||||
$version = "$dbversion ($plugin->version)";
|
||||
}
|
||||
|
||||
if (!$blockobject) {
|
||||
// ignore
|
||||
$undeletable = '';
|
||||
} else if (in_array($blockname, $undeletableblocktypes)) {
|
||||
$undeletable = '<a href="blocks.php?unprotect='.$blockid.'&sesskey='.sesskey().'" title="'.$strunprotect.'">'.
|
||||
$OUTPUT->pix_icon('t/unlock', $strunprotect) . '</a>';
|
||||
} else {
|
||||
$undeletable = '<a href="blocks.php?protect='.$blockid.'&sesskey='.sesskey().'" title="'.$strprotect.'">'.
|
||||
$OUTPUT->pix_icon('t/lock', $strprotect) . '</a>';
|
||||
}
|
||||
|
||||
$row = array(
|
||||
$strblockname,
|
||||
$blocklist,
|
||||
$version,
|
||||
$visible,
|
||||
$undeletable,
|
||||
$settings,
|
||||
$uninstall,
|
||||
);
|
||||
$table->add_data($row, $class);
|
||||
}
|
||||
|
||||
$table->print_html();
|
||||
|
||||
if (!empty($incompatible)) {
|
||||
echo $OUTPUT->heading(get_string('incompatibleblocks', 'blockstable', 'admin'));
|
||||
|
||||
$table = new flexible_table('admin-blocks-incompatible');
|
||||
|
||||
$table->define_columns(array('block', 'uninstall'));
|
||||
$table->define_headers(array($strname, $struninstall));
|
||||
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
|
||||
|
||||
$table->set_attribute('class', 'incompatibleblockstable generaltable');
|
||||
|
||||
$table->setup();
|
||||
|
||||
foreach ($incompatible as $block) {
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$block->name, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
} else {
|
||||
$uninstall = '';
|
||||
}
|
||||
$table->add_data(array(
|
||||
$block->name,
|
||||
$uninstall,
|
||||
));
|
||||
}
|
||||
$table->print_html();
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
+4
-3
@@ -41,11 +41,11 @@ $adminroot = admin_get_root(); // need all settings
|
||||
$settingspage = $adminroot->locate($category, true);
|
||||
|
||||
if (empty($settingspage) or !($settingspage instanceof admin_category)) {
|
||||
throw new \moodle_exception('categoryerror', 'error', "$CFG->wwwroot/$CFG->admin/");
|
||||
print_error('categoryerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
|
||||
}
|
||||
|
||||
if (!($settingspage->check_access())) {
|
||||
throw new \moodle_exception('accessdenied', 'admin');
|
||||
print_error('accessdenied', 'admin');
|
||||
}
|
||||
|
||||
$hassiteconfig = has_capability('moodle/site:config', $PAGE->context);
|
||||
@@ -131,7 +131,8 @@ if ($savebutton) {
|
||||
$outputhtml .= html_writer::end_tag('div');
|
||||
}
|
||||
|
||||
$PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $settingspage->visiblepath));
|
||||
$visiblepathtosection = array_reverse($settingspage->visiblepath);
|
||||
$PAGE->set_title("$SITE->shortname: " . implode(": ",$visiblepathtosection));
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
if ($buttons) {
|
||||
$PAGE->set_button($buttons);
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\admin;
|
||||
|
||||
use admin_setting;
|
||||
use core_plugin_manager;
|
||||
use core_text;
|
||||
|
||||
/**
|
||||
* Admin setting plugin manager.
|
||||
*
|
||||
* @package core_admin
|
||||
* @subpackage admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class admin_setting_plugin_manager extends admin_setting {
|
||||
/** @var core_plugin_manager The plugin manager instance */
|
||||
protected core_plugin_manager $pluginmanager;
|
||||
|
||||
/** @var string The plugintype that this manager covers */
|
||||
protected string $plugintype;
|
||||
|
||||
/** @var string The class of the management table to use */
|
||||
protected string $tableclass;
|
||||
|
||||
public function __construct(
|
||||
string $plugintype,
|
||||
string $tableclass,
|
||||
string $name,
|
||||
string $visiblename,
|
||||
string $description = '',
|
||||
string $defaultsetting = '',
|
||||
) {
|
||||
$this->nosave = true;
|
||||
$this->pluginmanager = core_plugin_manager::instance();
|
||||
$this->plugintype = $plugintype;
|
||||
$this->tableclass = $tableclass;
|
||||
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns true, does nothing
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function get_setting(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns true, does nothing
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function get_defaultsetting(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns '', does not write anything
|
||||
*
|
||||
* @return string Always returns ''
|
||||
*/
|
||||
// phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
public function write_setting($data): string {
|
||||
// Do not write any setting.
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if $query is one of the available editors
|
||||
*
|
||||
* @param string $query The string to search for
|
||||
* @return bool Returns true if found, false if not
|
||||
*/
|
||||
public function is_related($query) {
|
||||
if (parent::is_related($query)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$plugins = $this->pluginmanager->get_installed_plugins($this->plugintype);
|
||||
foreach (array_keys($plugins) as $plugin) {
|
||||
$plugin = "{$this->plugintype}_{$plugin}";
|
||||
if (str_contains($plugin, $query)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$pluginname = get_string('pluginname', $plugin);
|
||||
if (strpos(core_text::strtolower($pluginname), $query) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XHTML to display the control
|
||||
*
|
||||
* @param string $data Unused
|
||||
* @param string $query
|
||||
* @return string
|
||||
*/
|
||||
public function output_html($data, $query = ''): string {
|
||||
$table = new $this->tableclass();
|
||||
if (!($table instanceof \core_admin\table\plugin_management_table)) {
|
||||
throw new \coding_exception("{$this->tableclass} must be an instance of \\core_admin\\table\\plugin_management_table");
|
||||
}
|
||||
return highlight($query, $table->get_content());
|
||||
}
|
||||
}
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\external;
|
||||
|
||||
use block_manager;
|
||||
use core_external\external_api;
|
||||
use core_external\external_function_parameters;
|
||||
use core_external\external_single_structure;
|
||||
use core_external\external_value;
|
||||
|
||||
/**
|
||||
* Web Service to control the state of a plugin.
|
||||
*
|
||||
* @package core_admin
|
||||
* @category external
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_block_protection extends external_api {
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
|
||||
'state' => new external_value(PARAM_INT, 'The target state', VALUE_REQUIRED),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block protection state.
|
||||
*
|
||||
* @param string $plugin The name of the plugin
|
||||
* @param int $state The target state
|
||||
* @return null
|
||||
*/
|
||||
public static function execute(
|
||||
string $plugin,
|
||||
int $state,
|
||||
): array {
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'state' => $state,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'plugin' => $plugin,
|
||||
'state' => $state,
|
||||
]);
|
||||
|
||||
$context = \context_system::instance();
|
||||
self::validate_context($context);
|
||||
require_capability('moodle/site:config', $context);
|
||||
|
||||
[, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
|
||||
$displayname = get_string('pluginname', $plugin);
|
||||
|
||||
if ($state) {
|
||||
block_manager::protect_block($pluginname);
|
||||
\core\notification::add(
|
||||
get_string('blockprotected', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
} else {
|
||||
block_manager::unprotect_block($pluginname);
|
||||
\core\notification::add(
|
||||
get_string('blockunprotected', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe the return structure of the external service.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return new external_single_structure([]);
|
||||
}
|
||||
}
|
||||
-84
@@ -1,84 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\external;
|
||||
|
||||
use core_external\external_api;
|
||||
use core_external\external_function_parameters;
|
||||
use core_external\external_single_structure;
|
||||
use core_external\external_value;
|
||||
|
||||
/**
|
||||
* Web Service to control the order of a plugin.
|
||||
*
|
||||
* @package core_admin
|
||||
* @category external
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_plugin_order extends external_api {
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
|
||||
'direction' => new external_value(PARAM_INT, 'The direction to move', VALUE_REQUIRED),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the plugin state.
|
||||
*
|
||||
* @param string $plugin The name of the plugin
|
||||
* @param int $direction The direction to move the plugin
|
||||
* @return array
|
||||
*/
|
||||
public static function execute(
|
||||
string $plugin,
|
||||
int $direction,
|
||||
): array {
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'direction' => $direction,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'plugin' => $plugin,
|
||||
'direction' => $direction,
|
||||
]);
|
||||
|
||||
$context = \context_system::instance();
|
||||
self::validate_context($context);
|
||||
require_capability('moodle/site:config', $context);
|
||||
|
||||
[$plugintype, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
|
||||
|
||||
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
|
||||
$manager::change_plugin_order($pluginname, $direction);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe the return structure of the external service.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return new external_single_structure([]);
|
||||
}
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\external;
|
||||
|
||||
use core_external\external_api;
|
||||
use core_external\external_function_parameters;
|
||||
use core_external\external_single_structure;
|
||||
use core_external\external_value;
|
||||
|
||||
/**
|
||||
* Web Service to control the state of a plugin.
|
||||
*
|
||||
* @package core_admin
|
||||
* @category external
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_plugin_state extends external_api {
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
|
||||
'state' => new external_value(PARAM_INT, 'The target state', VALUE_REQUIRED),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the plugin state.
|
||||
*
|
||||
* @param string $plugin The name of the plugin
|
||||
* @param int $state The target state
|
||||
* @return null
|
||||
*/
|
||||
public static function execute(
|
||||
string $plugin,
|
||||
int $state,
|
||||
): array {
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'state' => $state,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'plugin' => $plugin,
|
||||
'state' => $state,
|
||||
]);
|
||||
|
||||
$context = \context_system::instance();
|
||||
self::validate_context($context);
|
||||
require_capability('moodle/site:config', $context);
|
||||
|
||||
[$plugintype, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
|
||||
|
||||
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
|
||||
$displayname = get_string('pluginname', $plugin);
|
||||
|
||||
if ($manager::enable_plugin($pluginname, $state)) {
|
||||
if (!empty($state)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_enabled', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
} else {
|
||||
\core\notification::add(
|
||||
get_string('plugin_disabled', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe the return structure of the external service.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return new external_single_structure([]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\local\entities;
|
||||
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\duration;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\helpers\format;
|
||||
use lang_string;
|
||||
use core_reportbuilder\local\entities\base;
|
||||
use core_reportbuilder\local\report\column;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Task log entity class implementation
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class task_log extends base {
|
||||
|
||||
/** @var int Result success */
|
||||
protected const SUCCESS = 0;
|
||||
|
||||
/** @var int Result failed */
|
||||
protected const FAILED = 1;
|
||||
|
||||
/**
|
||||
* Database tables that this entity uses and their default aliases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_default_table_aliases(): array {
|
||||
return ['task_log' => 'tl'];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default title for this entity in the list of columns/conditions/filters in the report builder
|
||||
*
|
||||
* @return lang_string
|
||||
*/
|
||||
protected function get_default_entity_title(): lang_string {
|
||||
return new lang_string('entitytasklog', 'admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* The default machine-readable name for this entity that will be used in the internal names of the columns/filters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_default_entity_name(): string {
|
||||
return 'task_log';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the entity
|
||||
*
|
||||
* @return base
|
||||
*/
|
||||
public function initialise(): base {
|
||||
$columns = $this->get_all_columns();
|
||||
foreach ($columns as $column) {
|
||||
$this->add_column($column);
|
||||
}
|
||||
|
||||
$filters = $this->get_all_filters();
|
||||
foreach ($filters as $filter) {
|
||||
$this->add_filter($filter);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all available columns
|
||||
*
|
||||
* @return column[]
|
||||
*/
|
||||
protected function get_all_columns(): array {
|
||||
|
||||
$tablealias = $this->get_table_alias('task_log');
|
||||
|
||||
// Name column.
|
||||
$columns[] = (new column(
|
||||
'name',
|
||||
new lang_string('name'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("$tablealias.classname")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(string $value): string {
|
||||
$output = '';
|
||||
if (class_exists($value)) {
|
||||
$task = new $value;
|
||||
if ($task instanceof \core\task\scheduled_task) {
|
||||
$output = $task->get_name();
|
||||
}
|
||||
}
|
||||
$output .= \html_writer::tag('div', "\\{$value}", [
|
||||
'class' => 'task-class',
|
||||
]);
|
||||
return $output;
|
||||
});
|
||||
|
||||
// Type column.
|
||||
$columns[] = (new column(
|
||||
'type',
|
||||
new lang_string('tasktype', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_field("{$tablealias}.type")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(int $value): string {
|
||||
if (\core\task\database_logger::TYPE_SCHEDULED === $value) {
|
||||
return get_string('task_type:scheduled', 'admin');
|
||||
}
|
||||
return get_string('task_type:adhoc', 'admin');
|
||||
});
|
||||
|
||||
// Start time column.
|
||||
$columns[] = (new column(
|
||||
'starttime',
|
||||
new lang_string('task_starttime', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TIMESTAMP)
|
||||
->add_field("{$tablealias}.timestart")
|
||||
->set_is_sortable(true)
|
||||
->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
|
||||
|
||||
// Duration column.
|
||||
$columns[] = (new column(
|
||||
'duration',
|
||||
new lang_string('task_duration', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_FLOAT)
|
||||
->add_field("{$tablealias}.timeend - {$tablealias}.timestart", 'duration')
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(float $value): string {
|
||||
$duration = round($value, 2);
|
||||
if (empty($duration)) {
|
||||
// The format_time function returns 'now' when the difference is exactly 0.
|
||||
// Note: format_time performs concatenation in exactly this fashion so we should do this for consistency.
|
||||
return '0 ' . get_string('secs', 'moodle');
|
||||
}
|
||||
return format_time($duration);
|
||||
});
|
||||
|
||||
// Hostname column.
|
||||
$columns[] = (new column(
|
||||
'hostname',
|
||||
new lang_string('hostname', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("$tablealias.hostname")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// PID column.
|
||||
$columns[] = (new column(
|
||||
'pid',
|
||||
new lang_string('pid', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_field("{$tablealias}.pid")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// Database column.
|
||||
$columns[] = (new column(
|
||||
'database',
|
||||
new lang_string('task_dbstats', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_fields("{$tablealias}.dbreads, {$tablealias}.dbwrites")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(int $value, stdClass $row): string {
|
||||
$output = '';
|
||||
$output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
|
||||
$output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
|
||||
return $output;
|
||||
});
|
||||
|
||||
// Result column.
|
||||
$columns[] = (new column(
|
||||
'result',
|
||||
new lang_string('task_result', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_field("$tablealias.result")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(int $value): string {
|
||||
if ($value) {
|
||||
return get_string('task_result:failed', 'admin');
|
||||
}
|
||||
return get_string('success');
|
||||
});
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of all available filters
|
||||
*
|
||||
* @return filter[]
|
||||
*/
|
||||
protected function get_all_filters(): array {
|
||||
$filters = [];
|
||||
|
||||
$tablealias = $this->get_table_alias('task_log');
|
||||
|
||||
// Name filter (Filter by classname).
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'name',
|
||||
new lang_string('classname', 'tool_task'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.classname"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Output filter (Filter by task output).
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'output',
|
||||
new lang_string('task_logoutput', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.output"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Result filter.
|
||||
$filters[] = (new filter(
|
||||
select::class,
|
||||
'result',
|
||||
new lang_string('task_result', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.result"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_options([
|
||||
self::SUCCESS => get_string('success'),
|
||||
self::FAILED => get_string('task_result:failed', 'admin'),
|
||||
]);
|
||||
|
||||
// Start time filter.
|
||||
$filters[] = (new filter(
|
||||
date::class,
|
||||
'timestart',
|
||||
new lang_string('task_starttime', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.timestart"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_limited_operators([
|
||||
date::DATE_ANY,
|
||||
date::DATE_RANGE,
|
||||
date::DATE_PREVIOUS,
|
||||
date::DATE_CURRENT,
|
||||
]);
|
||||
|
||||
// Duration filter.
|
||||
$filters[] = (new filter(
|
||||
duration::class,
|
||||
'duration',
|
||||
new lang_string('task_duration', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"${tablealias}.timeend - {$tablealias}.timestart"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
return $filters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\local\systemreports;
|
||||
|
||||
use context_system;
|
||||
use core_admin\local\entities\task_log;
|
||||
use core_reportbuilder\local\entities\user;
|
||||
use core_reportbuilder\local\report\action;
|
||||
use lang_string;
|
||||
use moodle_url;
|
||||
use pix_icon;
|
||||
use core_reportbuilder\system_report;
|
||||
|
||||
/**
|
||||
* Task logs system report class implementation
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class task_logs extends system_report {
|
||||
|
||||
/**
|
||||
* Initialise report, we need to set the main table, load our entities and set columns/filters
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
// Our main entity, it contains all of the column definitions that we need.
|
||||
$entitymain = new task_log();
|
||||
$entitymainalias = $entitymain->get_table_alias('task_log');
|
||||
|
||||
$this->set_main_table('task_log', $entitymainalias);
|
||||
$this->add_entity($entitymain);
|
||||
|
||||
// Any columns required by actions should be defined here to ensure they're always available.
|
||||
$this->add_base_fields("{$entitymainalias}.id");
|
||||
|
||||
// We can join the "user" entity to our "main" entity and use the fullname column from the user entity.
|
||||
$entityuser = new user();
|
||||
$entituseralias = $entityuser->get_table_alias('user');
|
||||
$this->add_entity($entityuser->add_join(
|
||||
"LEFT JOIN {user} {$entituseralias} ON {$entituseralias}.id = {$entitymainalias}.userid"
|
||||
));
|
||||
|
||||
// Now we can call our helper methods to add the content we want to include in the report.
|
||||
$this->add_columns();
|
||||
$this->add_filters();
|
||||
$this->add_actions();
|
||||
|
||||
// Set if report can be downloaded.
|
||||
$this->set_downloadable(true, get_string('tasklogs', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates access to view this report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_view(): bool {
|
||||
return has_capability('moodle/site:config', context_system::instance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the visible name of the report
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name(): string {
|
||||
return get_string('entitytasklog', 'admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the columns we want to display in the report
|
||||
*
|
||||
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
|
||||
* unique identifier
|
||||
*/
|
||||
public function add_columns(): void {
|
||||
$columns = [
|
||||
'task_log:name',
|
||||
'task_log:type',
|
||||
'user:fullname',
|
||||
'task_log:starttime',
|
||||
'task_log:duration',
|
||||
'task_log:hostname',
|
||||
'task_log:pid',
|
||||
'task_log:database',
|
||||
'task_log:result',
|
||||
];
|
||||
|
||||
$this->add_columns_from_entities($columns);
|
||||
|
||||
// It's possible to override the display name of a column, if you don't want to use the value provided by the entity.
|
||||
if ($column = $this->get_column('user:fullname')) {
|
||||
$column->set_title(new lang_string('user', 'admin'));
|
||||
}
|
||||
|
||||
// It's possible to set a default initial sort direction for one column.
|
||||
$this->set_initial_sort_column('task_log:starttime', SORT_DESC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the filters we want to display in the report
|
||||
*
|
||||
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
|
||||
* unique identifier
|
||||
*/
|
||||
protected function add_filters(): void {
|
||||
$filters = [
|
||||
'task_log:name',
|
||||
'task_log:output',
|
||||
'task_log:result',
|
||||
'task_log:timestart',
|
||||
'task_log:duration',
|
||||
];
|
||||
|
||||
$this->add_filters_from_entities($filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the system report actions. An extra column will be appended to each row, containing all actions added here
|
||||
*
|
||||
* Note the use of ":id" placeholder which will be substituted according to actual values in the row
|
||||
*/
|
||||
protected function add_actions(): void {
|
||||
|
||||
// Action to view individual task log on a popup window.
|
||||
$this->add_action((new action(
|
||||
new moodle_url('/admin/tasklogs.php', ['logid' => ':id']),
|
||||
new pix_icon('e/search', ''),
|
||||
[],
|
||||
true,
|
||||
new lang_string('view'),
|
||||
)));
|
||||
|
||||
// Action to download individual task log.
|
||||
$this->add_action((new action(
|
||||
new moodle_url('/admin/tasklogs.php', ['logid' => ':id', 'download' => true]),
|
||||
new pix_icon('t/download', ''),
|
||||
[],
|
||||
false,
|
||||
new lang_string('download'),
|
||||
)));
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_admin\reportbuilder\datasource;
|
||||
|
||||
use core_admin\reportbuilder\local\entities\task_log;
|
||||
use core_reportbuilder\datasource;
|
||||
use core_reportbuilder\local\entities\user;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
|
||||
/**
|
||||
* Task logs datasource
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2022 Paul Holden <paulh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class task_logs extends datasource {
|
||||
|
||||
/**
|
||||
* Return user friendly name of the report source
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name(): string {
|
||||
return get_string('tasklogs', 'core_admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise report
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
$tasklogentity = new task_log();
|
||||
|
||||
$tasklogalias = $tasklogentity->get_table_alias('task_log');
|
||||
$this->set_main_table('task_log', $tasklogalias);
|
||||
|
||||
$this->add_entity($tasklogentity);
|
||||
|
||||
// Join the user entity to represent the associated user.
|
||||
$userentity = new user();
|
||||
$useralias = $userentity->get_table_alias('user');
|
||||
$this->add_entity($userentity->add_join("
|
||||
LEFT JOIN {user} {$useralias}
|
||||
ON {$useralias}.id = {$tasklogalias}.userid")
|
||||
);
|
||||
|
||||
// Add report elements from each of the entities we added to the report.
|
||||
$this->add_all_from_entities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the columns that will be added to the report upon creation
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_columns(): array {
|
||||
return [
|
||||
'task_log:name',
|
||||
'task_log:starttime',
|
||||
'task_log:duration',
|
||||
'task_log:result',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column sorting that will be added to the report upon creation
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_default_column_sorting(): array {
|
||||
return [
|
||||
'task_log:starttime' => SORT_DESC,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filters that will be added to the report upon creation
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_filters(): array {
|
||||
return [
|
||||
'task_log:timestart',
|
||||
'task_log:result',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the conditions that will be added to the report upon creation
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_conditions(): array {
|
||||
return [
|
||||
'task_log:type',
|
||||
'task_log:timestart',
|
||||
'task_log:result',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the condition values that will be set for the report upon creation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_condition_values(): array {
|
||||
return [
|
||||
'task_log:type_operator' => select::EQUAL_TO,
|
||||
'task_log:type_value' => \core\task\database_logger::TYPE_SCHEDULED,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,427 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\reportbuilder\local\entities;
|
||||
|
||||
use core_reportbuilder\local\filters\date;
|
||||
use core_reportbuilder\local\filters\duration;
|
||||
use core_reportbuilder\local\filters\number;
|
||||
use core_reportbuilder\local\filters\select;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\filters\autocomplete;
|
||||
use core_reportbuilder\local\helpers\format;
|
||||
use lang_string;
|
||||
use core_reportbuilder\local\entities\base;
|
||||
use core_reportbuilder\local\report\column;
|
||||
use core_reportbuilder\local\report\filter;
|
||||
use stdClass;
|
||||
use core_collator;
|
||||
|
||||
/**
|
||||
* Task log entity class implementation
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class task_log extends base {
|
||||
|
||||
/** @var int Result success */
|
||||
protected const SUCCESS = 0;
|
||||
|
||||
/** @var int Result failed */
|
||||
protected const FAILED = 1;
|
||||
|
||||
/**
|
||||
* Database tables that this entity uses and their default aliases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_default_table_aliases(): array {
|
||||
return ['task_log' => 'tl'];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default title for this entity in the list of columns/conditions/filters in the report builder
|
||||
*
|
||||
* @return lang_string
|
||||
*/
|
||||
protected function get_default_entity_title(): lang_string {
|
||||
return new lang_string('entitytasklog', 'admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the entity
|
||||
*
|
||||
* @return base
|
||||
*/
|
||||
public function initialise(): base {
|
||||
$columns = $this->get_all_columns();
|
||||
foreach ($columns as $column) {
|
||||
$this->add_column($column);
|
||||
}
|
||||
|
||||
// All the filters defined by the entity can also be used as conditions.
|
||||
$filters = $this->get_all_filters();
|
||||
foreach ($filters as $filter) {
|
||||
$this
|
||||
->add_filter($filter)
|
||||
->add_condition($filter);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all available columns
|
||||
*
|
||||
* @return column[]
|
||||
*/
|
||||
protected function get_all_columns(): array {
|
||||
global $DB;
|
||||
|
||||
$tablealias = $this->get_table_alias('task_log');
|
||||
|
||||
// Name column.
|
||||
$columns[] = (new column(
|
||||
'name',
|
||||
new lang_string('name'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("$tablealias.classname")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(string $classname): string {
|
||||
$output = '';
|
||||
if (class_exists($classname)) {
|
||||
$task = new $classname;
|
||||
if ($task instanceof \core\task\task_base) {
|
||||
$output = $task->get_name();
|
||||
}
|
||||
}
|
||||
$output .= \html_writer::tag('div', "\\{$classname}", [
|
||||
'class' => 'small text-muted',
|
||||
]);
|
||||
return $output;
|
||||
});
|
||||
|
||||
// Component column.
|
||||
$columns[] = (new column(
|
||||
'component',
|
||||
new lang_string('plugin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("{$tablealias}.component")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// Type column.
|
||||
$columns[] = (new column(
|
||||
'type',
|
||||
new lang_string('tasktype', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("{$tablealias}.type")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function($value): string {
|
||||
if (\core\task\database_logger::TYPE_SCHEDULED === (int) $value) {
|
||||
return get_string('task_type:scheduled', 'admin');
|
||||
}
|
||||
return get_string('task_type:adhoc', 'admin');
|
||||
});
|
||||
|
||||
// Start time column.
|
||||
$columns[] = (new column(
|
||||
'starttime',
|
||||
new lang_string('task_starttime', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TIMESTAMP)
|
||||
->add_field("{$tablealias}.timestart")
|
||||
->set_is_sortable(true)
|
||||
->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
|
||||
|
||||
// End time column.
|
||||
$columns[] = (new column(
|
||||
'endtime',
|
||||
new lang_string('task_endtime', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TIMESTAMP)
|
||||
->add_field("{$tablealias}.timeend")
|
||||
->set_is_sortable(true)
|
||||
->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
|
||||
|
||||
// Duration column.
|
||||
$columns[] = (new column(
|
||||
'duration',
|
||||
new lang_string('task_duration', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_FLOAT)
|
||||
->add_field("{$tablealias}.timeend - {$tablealias}.timestart", 'duration')
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(float $value): string {
|
||||
$duration = round($value, 2);
|
||||
if (empty($duration)) {
|
||||
// The format_time function returns 'now' when the difference is exactly 0.
|
||||
// Note: format_time performs concatenation in exactly this fashion so we should do this for consistency.
|
||||
return '0 ' . get_string('secs', 'moodle');
|
||||
}
|
||||
return format_time($duration);
|
||||
});
|
||||
|
||||
// Hostname column.
|
||||
$columns[] = (new column(
|
||||
'hostname',
|
||||
new lang_string('hostname', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TEXT)
|
||||
->add_field("$tablealias.hostname")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// PID column.
|
||||
$columns[] = (new column(
|
||||
'pid',
|
||||
new lang_string('pid', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_field("{$tablealias}.pid")
|
||||
->set_is_sortable(true)
|
||||
// Although this is an integer column, it doesn't make sense to perform numeric aggregation on it.
|
||||
->set_disabled_aggregation(['avg', 'count', 'countdistinct', 'max', 'min', 'sum']);
|
||||
|
||||
// Database column.
|
||||
$columns[] = (new column(
|
||||
'database',
|
||||
new lang_string('task_dbstats', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_fields("{$tablealias}.dbreads, {$tablealias}.dbwrites")
|
||||
->set_is_sortable(true, ["{$tablealias}.dbreads", "{$tablealias}.dbwrites"])
|
||||
->add_callback(static function(int $value, stdClass $row): string {
|
||||
$output = '';
|
||||
$output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
|
||||
$output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
|
||||
return $output;
|
||||
})
|
||||
// Although this is an integer column, it doesn't make sense to perform numeric aggregation on it.
|
||||
->set_disabled_aggregation(['avg', 'count', 'countdistinct', 'max', 'min', 'sum']);
|
||||
|
||||
// Database reads column.
|
||||
$columns[] = (new column(
|
||||
'dbreads',
|
||||
new lang_string('task_dbreads', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_fields("{$tablealias}.dbreads")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// Database writes column.
|
||||
$columns[] = (new column(
|
||||
'dbwrites',
|
||||
new lang_string('task_dbwrites', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_INTEGER)
|
||||
->add_fields("{$tablealias}.dbwrites")
|
||||
->set_is_sortable(true);
|
||||
|
||||
// Result column.
|
||||
$columns[] = (new column(
|
||||
'result',
|
||||
new lang_string('task_result', 'admin'),
|
||||
$this->get_entity_name()
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_BOOLEAN)
|
||||
// For accurate aggregation, we need to return boolean success = true by xor'ing the field value.
|
||||
->add_field($DB->sql_bitxor("{$tablealias}.result", 1), 'success')
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function(bool $success): string {
|
||||
if (!$success) {
|
||||
return get_string('task_result:failed', 'admin');
|
||||
}
|
||||
return get_string('success');
|
||||
});
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of all available filters
|
||||
*
|
||||
* @return filter[]
|
||||
*/
|
||||
protected function get_all_filters(): array {
|
||||
global $DB;
|
||||
|
||||
$tablealias = $this->get_table_alias('task_log');
|
||||
|
||||
// Name filter (Filter by classname).
|
||||
$filters[] = (new filter(
|
||||
autocomplete::class,
|
||||
'name',
|
||||
new lang_string('classname', 'tool_task'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.classname"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_options_callback(static function(): array {
|
||||
global $DB;
|
||||
$classnames = $DB->get_fieldset_sql('SELECT DISTINCT classname FROM {task_log} ORDER BY classname ASC');
|
||||
|
||||
$options = [];
|
||||
foreach ($classnames as $classname) {
|
||||
if (class_exists($classname)) {
|
||||
$task = new $classname;
|
||||
$options[$classname] = $task->get_name();
|
||||
}
|
||||
}
|
||||
|
||||
core_collator::asort($options);
|
||||
return $options;
|
||||
});
|
||||
|
||||
// Component filter.
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'component',
|
||||
new lang_string('plugin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.component"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Type filter.
|
||||
$filters[] = (new filter(
|
||||
select::class,
|
||||
'type',
|
||||
new lang_string('tasktype', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.type"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_options([
|
||||
\core\task\database_logger::TYPE_ADHOC => new lang_string('task_type:adhoc', 'admin'),
|
||||
\core\task\database_logger::TYPE_SCHEDULED => new lang_string('task_type:scheduled', 'admin'),
|
||||
]);
|
||||
|
||||
// Output filter (Filter by task output).
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'output',
|
||||
new lang_string('task_logoutput', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
$DB->sql_cast_to_char("{$tablealias}.output")
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Start time filter.
|
||||
$filters[] = (new filter(
|
||||
date::class,
|
||||
'timestart',
|
||||
new lang_string('task_starttime', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.timestart"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_limited_operators([
|
||||
date::DATE_ANY,
|
||||
date::DATE_RANGE,
|
||||
date::DATE_PREVIOUS,
|
||||
date::DATE_CURRENT,
|
||||
]);
|
||||
|
||||
// End time.
|
||||
$filters[] = (new filter(
|
||||
date::class,
|
||||
'timeend',
|
||||
new lang_string('task_endtime', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.timeend"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_limited_operators([
|
||||
date::DATE_ANY,
|
||||
date::DATE_RANGE,
|
||||
date::DATE_PREVIOUS,
|
||||
date::DATE_CURRENT,
|
||||
]);
|
||||
|
||||
// Duration filter.
|
||||
$filters[] = (new filter(
|
||||
duration::class,
|
||||
'duration',
|
||||
new lang_string('task_duration', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.timeend - {$tablealias}.timestart"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Database reads.
|
||||
$filters[] = (new filter(
|
||||
number::class,
|
||||
'dbreads',
|
||||
new lang_string('task_dbreads', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.dbreads"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Database writes.
|
||||
$filters[] = (new filter(
|
||||
number::class,
|
||||
'dbwrites',
|
||||
new lang_string('task_dbwrites', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.dbwrites"
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Result filter.
|
||||
$filters[] = (new filter(
|
||||
select::class,
|
||||
'result',
|
||||
new lang_string('task_result', 'admin'),
|
||||
$this->get_entity_name(),
|
||||
"{$tablealias}.result"
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_options([
|
||||
self::SUCCESS => get_string('success'),
|
||||
self::FAILED => get_string('task_result:failed', 'admin'),
|
||||
]);
|
||||
|
||||
return $filters;
|
||||
}
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\reportbuilder\local\systemreports;
|
||||
|
||||
use context_system;
|
||||
use core_admin\reportbuilder\local\entities\task_log;
|
||||
use core_reportbuilder\local\entities\user;
|
||||
use core_reportbuilder\local\report\action;
|
||||
use lang_string;
|
||||
use moodle_url;
|
||||
use pix_icon;
|
||||
use core_reportbuilder\system_report;
|
||||
|
||||
/**
|
||||
* Task logs system report class implementation
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2021 David Matamoros <davidmc@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class task_logs extends system_report {
|
||||
|
||||
/**
|
||||
* Initialise report, we need to set the main table, load our entities and set columns/filters
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
// Our main entity, it contains all of the column definitions that we need.
|
||||
$entitymain = new task_log();
|
||||
$entitymainalias = $entitymain->get_table_alias('task_log');
|
||||
|
||||
$this->set_main_table('task_log', $entitymainalias);
|
||||
$this->add_entity($entitymain);
|
||||
|
||||
// Any columns required by actions should be defined here to ensure they're always available.
|
||||
$this->add_base_fields("{$entitymainalias}.id");
|
||||
|
||||
// We can join the "user" entity to our "main" entity and use the fullname column from the user entity.
|
||||
$entityuser = new user();
|
||||
$entituseralias = $entityuser->get_table_alias('user');
|
||||
$this->add_entity($entityuser->add_join(
|
||||
"LEFT JOIN {user} {$entituseralias} ON {$entituseralias}.id = {$entitymainalias}.userid"
|
||||
));
|
||||
|
||||
// Now we can call our helper methods to add the content we want to include in the report.
|
||||
$this->add_columns();
|
||||
$this->add_filters();
|
||||
$this->add_actions();
|
||||
|
||||
// Set if report can be downloaded.
|
||||
$this->set_downloadable(true, get_string('tasklogs', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates access to view this report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function can_view(): bool {
|
||||
return has_capability('moodle/site:config', context_system::instance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the visible name of the report
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name(): string {
|
||||
return get_string('entitytasklog', 'admin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the columns we want to display in the report
|
||||
*
|
||||
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
|
||||
* unique identifier
|
||||
*/
|
||||
public function add_columns(): void {
|
||||
$columns = [
|
||||
'task_log:name',
|
||||
'task_log:type',
|
||||
'user:fullname',
|
||||
'task_log:starttime',
|
||||
'task_log:duration',
|
||||
'task_log:hostname',
|
||||
'task_log:pid',
|
||||
'task_log:database',
|
||||
'task_log:result',
|
||||
];
|
||||
|
||||
$this->add_columns_from_entities($columns);
|
||||
|
||||
// It's possible to override the display name of a column, if you don't want to use the value provided by the entity.
|
||||
if ($column = $this->get_column('user:fullname')) {
|
||||
$column->set_title(new lang_string('user', 'admin'));
|
||||
}
|
||||
|
||||
// It's possible to set a default initial sort direction for one column.
|
||||
$this->set_initial_sort_column('task_log:starttime', SORT_DESC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the filters we want to display in the report
|
||||
*
|
||||
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
|
||||
* unique identifier
|
||||
*/
|
||||
protected function add_filters(): void {
|
||||
$filters = [
|
||||
'task_log:name',
|
||||
'task_log:type',
|
||||
'task_log:output',
|
||||
'task_log:result',
|
||||
'task_log:timestart',
|
||||
'task_log:duration',
|
||||
];
|
||||
|
||||
$this->add_filters_from_entities($filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the system report actions. An extra column will be appended to each row, containing all actions added here
|
||||
*
|
||||
* Note the use of ":id" placeholder which will be substituted according to actual values in the row
|
||||
*/
|
||||
protected function add_actions(): void {
|
||||
|
||||
// Action to view individual task log on a popup window.
|
||||
$this->add_action((new action(
|
||||
new moodle_url('/admin/tasklogs.php', ['logid' => ':id']),
|
||||
new pix_icon('e/search', ''),
|
||||
[],
|
||||
true,
|
||||
new lang_string('view'),
|
||||
)));
|
||||
|
||||
// Action to download individual task log.
|
||||
$this->add_action((new action(
|
||||
new moodle_url('/admin/tasklogs.php', ['logid' => ':id', 'download' => true]),
|
||||
new pix_icon('t/download', ''),
|
||||
[],
|
||||
false,
|
||||
new lang_string('download'),
|
||||
)));
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use core_plugin_manager;
|
||||
use dml_exception;
|
||||
use html_writer;
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Activity Module admin settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class activity_management_table extends plugin_management_table {
|
||||
|
||||
public function setup() {
|
||||
$this->set_attribute('id', 'modules');
|
||||
$this->set_attribute('class', 'admintable generaltable');
|
||||
parent::setup();
|
||||
}
|
||||
|
||||
protected function get_table_id(): string {
|
||||
return 'module-administration-table';
|
||||
}
|
||||
|
||||
protected function get_plugintype(): string {
|
||||
return 'mod';
|
||||
}
|
||||
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl(
|
||||
new moodle_url('/admin/modules.php')
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/modules.php', $params);
|
||||
}
|
||||
|
||||
protected function get_column_list(): array {
|
||||
$columns = parent::get_column_list();
|
||||
return array_merge(
|
||||
array_slice($columns, 0, 1, true),
|
||||
['activities' => get_string('activities')],
|
||||
array_slice($columns, 1, null, true),
|
||||
);
|
||||
}
|
||||
|
||||
protected function col_name(stdClass $row): string {
|
||||
global $OUTPUT;
|
||||
|
||||
$status = $row->plugininfo->get_status();
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
return html_writer::span(
|
||||
get_string('pluginmissingfromdisk', 'core', $row->plugininfo),
|
||||
'notifyproblem'
|
||||
);
|
||||
}
|
||||
|
||||
return html_writer::span(
|
||||
html_writer::img(
|
||||
$OUTPUT->image_url('monologo', $row->plugininfo->name),
|
||||
'',
|
||||
[
|
||||
'class' => 'icon',
|
||||
],
|
||||
) . get_string('modulename', $row->plugininfo->name)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the number of activities present, with a link to courses containing activity if relevant.
|
||||
*
|
||||
* @param mixed $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_activities(stdClass $row): string {
|
||||
global $DB, $OUTPUT;
|
||||
try {
|
||||
$count = $DB->count_records_select($row->plugininfo->name, "course <> 0");
|
||||
} catch (dml_exception $e) {
|
||||
$count = -1;
|
||||
}
|
||||
|
||||
if ($count > 0) {
|
||||
return $OUTPUT->action_link(
|
||||
new moodle_url('/course/search.php', [
|
||||
'modulelist' => $row->plugininfo->name,
|
||||
]),
|
||||
$count,
|
||||
null,
|
||||
['title' => get_string('showmodulecourse')]
|
||||
);
|
||||
} else if ($count < 0) {
|
||||
return get_string('error');
|
||||
} else {
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use html_writer;
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Tiny admin settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class block_management_table extends \core_admin\table\plugin_management_table {
|
||||
|
||||
/** @var plugininfo[] A list of blocks which cannot be deleted */
|
||||
protected array $undeletableblocktypes;
|
||||
|
||||
/** @var stdClass[] A list of basic block data */
|
||||
protected array $blockdata;
|
||||
|
||||
/** @var array<string,int> A list of course counts */
|
||||
protected array $courseblocks;
|
||||
|
||||
public function __construct() {
|
||||
global $DB;
|
||||
parent::__construct();
|
||||
$this->undeletableblocktypes = \block_manager::get_undeletable_block_types();
|
||||
|
||||
$sql = 'SELECT b.name,
|
||||
b.id,
|
||||
COUNT(DISTINCT binst.id) as totalcount
|
||||
FROM {block} b
|
||||
LEFT JOIN {block_instances} binst ON binst.blockname = b.name
|
||||
GROUP BY b.id,
|
||||
b.name
|
||||
ORDER BY b.name ASC';
|
||||
$this->blockdata = $DB->get_records_sql($sql);
|
||||
|
||||
$sql = "SELECT blockname
|
||||
FROM {block_instances}
|
||||
WHERE pagetypepattern = 'course-view-*'
|
||||
GROUP BY blockname";
|
||||
$this->courseblocks = $DB->get_records_sql($sql);
|
||||
}
|
||||
|
||||
protected function get_plugintype(): string {
|
||||
return 'block';
|
||||
}
|
||||
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl(
|
||||
new moodle_url('/admin/blocks.php')
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/blocks.php', $params);
|
||||
}
|
||||
|
||||
|
||||
protected function get_table_js_module(): string {
|
||||
return 'core_admin/block_management_table';
|
||||
}
|
||||
|
||||
protected function get_column_list(): array {
|
||||
$columns = parent::get_column_list();
|
||||
return array_merge(
|
||||
array_slice($columns, 0, 1, true),
|
||||
['instances' => get_string('blockinstances', 'admin')],
|
||||
array_slice($columns, 1, 2, true),
|
||||
['protect' => get_string('blockprotect', 'admin')],
|
||||
array_slice($columns, 3, null, true),
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_columns_with_help(): array {
|
||||
return [
|
||||
'protect' => new \help_icon('blockprotect', 'admin'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the instances column
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_instances(stdClass $row): string {
|
||||
$blockdata = $this->blockdata[$row->plugininfo->name];
|
||||
if (array_key_exists($blockdata->name, $this->courseblocks)) {
|
||||
return html_writer::link(
|
||||
new moodle_url('/course/search.php', [
|
||||
'blocklist' => $blockdata->id,
|
||||
]),
|
||||
$blockdata->totalcount,
|
||||
);
|
||||
}
|
||||
|
||||
return $blockdata->totalcount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the protect column.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_protect(stdClass $row): string {
|
||||
global $OUTPUT;
|
||||
|
||||
$params = [
|
||||
'sesskey' => sesskey(),
|
||||
];
|
||||
|
||||
$protected = in_array($row->plugininfo->name, $this->undeletableblocktypes);
|
||||
|
||||
$pluginname = $row->plugininfo->displayname;
|
||||
if ($protected) {
|
||||
$params['unprotect'] = $row->plugininfo->name;
|
||||
$icon = $OUTPUT->pix_icon('t/unlock', get_string('blockunprotectblock', 'admin', $pluginname));
|
||||
} else {
|
||||
$params['protect'] = $row->plugininfo->name;
|
||||
$icon = $OUTPUT->pix_icon('t/lock', get_string('blockprotectblock', 'admin', $pluginname));
|
||||
}
|
||||
|
||||
return html_writer::link(
|
||||
$this->get_action_url($params),
|
||||
$icon,
|
||||
[
|
||||
'data-action' => 'toggleprotectstate',
|
||||
'data-plugin' => $row->plugin,
|
||||
'data-target-state' => $protected ? 0 : 1,
|
||||
],
|
||||
);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Tiny admin settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class editor_management_table extends \core_admin\table\plugin_management_table {
|
||||
protected function get_plugintype(): string {
|
||||
return 'editor';
|
||||
}
|
||||
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl(
|
||||
new moodle_url('/admin/settings.php', ['section' => 'manageeditors'])
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/editors.php', $params);
|
||||
}
|
||||
|
||||
protected function order_plugins(array $plugins): array {
|
||||
global $CFG;
|
||||
|
||||
// The Editor list is stored in an ordered string.
|
||||
$activeeditors = explode(',', $CFG->texteditors);
|
||||
|
||||
$sortedplugins = [];
|
||||
foreach ($activeeditors as $editor) {
|
||||
if (isset($plugins[$editor])) {
|
||||
$sortedplugins[$editor] = $plugins[$editor];
|
||||
unset($plugins[$editor]);
|
||||
}
|
||||
}
|
||||
|
||||
$otherplugins = parent::order_plugins($plugins);
|
||||
return array_merge(
|
||||
$sortedplugins,
|
||||
$otherplugins
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use core_plugin_manager;
|
||||
use flexible_table;
|
||||
use html_writer;
|
||||
use stdClass;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
require_once("{$CFG->libdir}/tablelib.php");
|
||||
|
||||
/**
|
||||
* Plugin Management table.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class hook_list_table extends flexible_table {
|
||||
|
||||
/** @var \core\plugininfo\base[] The plugin list */
|
||||
protected array $plugins = [];
|
||||
|
||||
/** @var int The number of enabled plugins of this type */
|
||||
protected int $enabledplugincount = 0;
|
||||
|
||||
/** @var core_plugin_manager */
|
||||
protected core_plugin_manager $pluginmanager;
|
||||
|
||||
/** @var string The plugininfo class for this plugintype */
|
||||
protected string $plugininfoclass;
|
||||
|
||||
/** @var stdClass[] The list of emitted hooks with metadata */
|
||||
protected array $emitters;
|
||||
|
||||
public function __construct() {
|
||||
global $CFG;
|
||||
|
||||
$this->define_baseurl('/admin/hooks.php');
|
||||
parent::__construct('core_admin-hook_list_table');
|
||||
|
||||
// Add emitted hooks.
|
||||
$this->emitters = \core\hook\manager::discover_known_hooks();
|
||||
|
||||
$this->setup_column_configuration();
|
||||
$this->setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the column configuration for this table.
|
||||
*/
|
||||
protected function setup_column_configuration(): void {
|
||||
$columnlist = [
|
||||
'details' => get_string('hookname', 'core_admin'),
|
||||
'callbacks' => get_string('hookcallbacks', 'core_admin'),
|
||||
'deprecates' => get_string('hookdeprecates', 'core_admin'),
|
||||
];
|
||||
$this->define_columns(array_keys($columnlist));
|
||||
$this->define_headers(array_values($columnlist));
|
||||
|
||||
$columnswithhelp = [
|
||||
'callbacks' => new \help_icon('hookcallbacks', 'admin'),
|
||||
];
|
||||
$columnhelp = array_map(function (string $column) use ($columnswithhelp): ?\renderable {
|
||||
if (array_key_exists($column, $columnswithhelp)) {
|
||||
return $columnswithhelp[$column];
|
||||
}
|
||||
|
||||
return null;
|
||||
}, array_keys($columnlist));
|
||||
$this->define_help_for_headers($columnhelp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the table.
|
||||
*/
|
||||
public function out(): void {
|
||||
// All hook consumers referenced from the db/hooks.php files.
|
||||
$hookmanager = \core\hook\manager::get_instance();
|
||||
$allhooks = (array)$hookmanager->get_all_callbacks();
|
||||
|
||||
// Add any unused hooks.
|
||||
foreach (array_keys($this->emitters) as $classname) {
|
||||
if (isset($allhooks[$classname])) {
|
||||
continue;
|
||||
}
|
||||
$allhooks[$classname] = [];
|
||||
}
|
||||
|
||||
// Order rows by hook name, putting core first.
|
||||
\core_collator::ksort($allhooks);
|
||||
$corehooks = [];
|
||||
foreach ($allhooks as $classname => $consumers) {
|
||||
if (str_starts_with($classname, 'core\\')) {
|
||||
$corehooks[$classname] = $consumers;
|
||||
unset($allhooks[$classname]);
|
||||
}
|
||||
}
|
||||
$allhooks = array_merge($corehooks, $allhooks);
|
||||
|
||||
foreach ($allhooks as $classname => $consumers) {
|
||||
$this->add_data_keyed(
|
||||
$this->format_row((object) [
|
||||
'classname' => $classname,
|
||||
'callbacks' => $consumers,
|
||||
]),
|
||||
$this->get_row_class($classname),
|
||||
);
|
||||
}
|
||||
|
||||
$this->finish_output(false);
|
||||
}
|
||||
|
||||
protected function col_details(stdClass $row): string {
|
||||
return $row->classname .
|
||||
$this->get_description($row) .
|
||||
html_writer::div($this->get_tags_for_row($row));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the name column content.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function get_description(stdClass $row): string {
|
||||
if (!array_key_exists($row->classname, $this->emitters)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return html_writer::tag(
|
||||
'small',
|
||||
clean_text(markdown_to_html($this->emitters[$row->classname]['description']), FORMAT_HTML),
|
||||
);
|
||||
}
|
||||
|
||||
protected function col_deprecates(stdClass $row): string {
|
||||
if (!class_exists($row->classname)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$rc = new \ReflectionClass($row->classname);
|
||||
if (!$rc->implementsInterface(\core\hook\deprecated_callback_replacement::class)) {
|
||||
return '';
|
||||
}
|
||||
$deprecates = call_user_func([$row->classname, 'get_deprecated_plugin_callbacks']);
|
||||
if (count($deprecates) === 0) {
|
||||
return '';
|
||||
}
|
||||
$content = html_writer::start_tag('ul');
|
||||
|
||||
foreach ($deprecates as $deprecatedmethod) {
|
||||
$content .= html_writer::tag('li', $deprecatedmethod);
|
||||
}
|
||||
$content .= html_writer::end_tag('ul');
|
||||
return $content;
|
||||
}
|
||||
|
||||
protected function col_callbacks(stdClass $row): string {
|
||||
global $CFG;
|
||||
|
||||
$hookclass = $row->classname;
|
||||
$cbinfo = [];
|
||||
foreach ($row->callbacks as $definition) {
|
||||
$iscallable = is_callable($definition['callback'], false, $callbackname);
|
||||
$isoverridden = isset($CFG->hooks_callback_overrides[$hookclass][$definition['callback']]);
|
||||
$info = "{$callbackname} ({$definition['priority']})";
|
||||
if (!$iscallable) {
|
||||
$info .= ' ';
|
||||
$info .= $this->get_tag(
|
||||
get_string('error'),
|
||||
'danger',
|
||||
get_string('hookcallbacknotcallable', 'core_admin', $callbackname),
|
||||
);
|
||||
}
|
||||
if ($isoverridden) {
|
||||
// The lang string meaning should be close enough here.
|
||||
$info .= $this->get_tag(
|
||||
get_string('hookconfigoverride', 'core_admin'),
|
||||
'warning',
|
||||
get_string('hookconfigoverride_help', 'core_admin'),
|
||||
);
|
||||
}
|
||||
|
||||
$cbinfo[] = $info;
|
||||
}
|
||||
|
||||
if ($cbinfo) {
|
||||
$output = html_writer::start_tag('ol');
|
||||
foreach ($cbinfo as $callback) {
|
||||
$class = '';
|
||||
if ($definition['disabled']) {
|
||||
$class = 'dimmed_text';
|
||||
}
|
||||
$output .= html_writer::tag('li', $callback, ['class' => $class]);
|
||||
}
|
||||
$output .= html_writer::end_tag('ol');
|
||||
return $output;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML to display the badge with tooltip.
|
||||
*
|
||||
* @param string $tag The main text to display
|
||||
* @param null|string $type The pill type
|
||||
* @param null|string $tooltip The content of the tooltip
|
||||
* @return string
|
||||
*/
|
||||
protected function get_tag(
|
||||
string $tag,
|
||||
?string $type = null,
|
||||
?string $tooltip = null,
|
||||
): string {
|
||||
$attributes = [];
|
||||
|
||||
if ($type === null) {
|
||||
$type = 'info';
|
||||
}
|
||||
|
||||
if ($tooltip) {
|
||||
$attributes['data-toggle'] = 'tooltip';
|
||||
$attributes['title'] = $tooltip;
|
||||
}
|
||||
return html_writer::span($tag, "badge badge-{$type}", $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the code to display a set of tags for this table row.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function get_tags_for_row(stdClass $row): string {
|
||||
if (!array_key_exists($row->classname, $this->emitters)) {
|
||||
// This hook has been defined in the db/hooks.php file
|
||||
// but does not refer to a hook in this version of Moodle.
|
||||
return $this->get_tag(
|
||||
get_string('hookunknown', 'core_admin'),
|
||||
'warning',
|
||||
get_string('hookunknown_desc', 'core_admin'),
|
||||
);
|
||||
}
|
||||
|
||||
if (!class_exists($row->classname)) {
|
||||
// This hook has been defined in a hook discovery agent, but the class it refers to could not be found.
|
||||
return $this->get_tag(
|
||||
get_string('hookclassmissing', 'core_admin'),
|
||||
'warning',
|
||||
get_string('hookclassmissing_desc', 'core_admin'),
|
||||
);
|
||||
}
|
||||
|
||||
$tags = $this->emitters[$row->classname]['tags'] ?? [];
|
||||
$taglist = array_map(function($tag): string {
|
||||
if (is_array($tag)) {
|
||||
return $this->get_tag(...$tag);
|
||||
}
|
||||
return $this->get_tag($tag, 'badge badge-info');
|
||||
}, $tags);
|
||||
|
||||
return implode("\n", $taglist);
|
||||
}
|
||||
|
||||
protected function get_row_class(string $classname): string {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -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/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Media plugin admin settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_management_table extends \core_admin\table\plugin_management_table {
|
||||
/** @var array The list of used extensions */
|
||||
protected array $usedextensions = [];
|
||||
|
||||
protected function get_plugintype(): string {
|
||||
return 'media';
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/media.php', $params);
|
||||
}
|
||||
|
||||
protected function get_column_list(): array {
|
||||
$columns = parent::get_column_list();
|
||||
return array_merge(
|
||||
array_slice($columns, 0, 1, true),
|
||||
['supports' => get_string('supports', 'core_media')],
|
||||
array_slice($columns, 1, null, true),
|
||||
);
|
||||
}
|
||||
|
||||
protected function col_name(stdClass $row): string {
|
||||
global $OUTPUT, $PAGE;
|
||||
|
||||
$name = $row->plugininfo->name;
|
||||
if ($PAGE->theme->resolve_image_location('icon', 'media_' . $name, false)) {
|
||||
$icon = $OUTPUT->pix_icon('icon', '', "media_{$name}", ['class' => 'icon pluginicon']);
|
||||
} else {
|
||||
$icon = $OUTPUT->pix_icon('spacer', '', 'moodle', ['class' => 'icon pluginicon noicon']);
|
||||
}
|
||||
|
||||
$help = '';
|
||||
if (get_string_manager()->string_exists('pluginname_help', 'media_' . $name)) {
|
||||
$help = ' ' . $OUTPUT->help_icon('pluginname', 'media_' . $name);
|
||||
}
|
||||
|
||||
return $icon . $row->plugininfo->displayname . $help;
|
||||
}
|
||||
|
||||
protected function col_supports(stdClass $row): string {
|
||||
return $row->plugininfo->supports($this->usedextensions);
|
||||
}
|
||||
}
|
||||
@@ -1,503 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use context_system;
|
||||
use core_plugin_manager;
|
||||
use core_table\dynamic as dynamic_table;
|
||||
use flexible_table;
|
||||
use html_writer;
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
require_once("{$CFG->libdir}/tablelib.php");
|
||||
|
||||
/**
|
||||
* Plugin Management table.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class plugin_management_table extends flexible_table implements dynamic_table {
|
||||
|
||||
/** @var \core\plugininfo\base[] The plugin list */
|
||||
protected array $plugins = [];
|
||||
|
||||
/** @var int The number of enabled plugins of this type */
|
||||
protected int $enabledplugincount = 0;
|
||||
|
||||
/** @var core_plugin_manager */
|
||||
protected core_plugin_manager $pluginmanager;
|
||||
|
||||
/** @var string The plugininfo class for this plugintype */
|
||||
protected string $plugininfoclass;
|
||||
|
||||
public function __construct() {
|
||||
global $CFG;
|
||||
|
||||
parent::__construct($this->get_table_id());
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
// Fetch the plugininfo class.
|
||||
$this->pluginmanager = core_plugin_manager::instance();
|
||||
$this->plugininfoclass = $this->pluginmanager::resolve_plugininfo_class($this->get_plugintype());
|
||||
|
||||
$this->guess_base_url();
|
||||
|
||||
$this->plugins = $this->get_sorted_plugins();
|
||||
$this->enabledplugincount = count(array_filter($this->plugins, function ($plugin) {
|
||||
return $plugin->is_enabled();
|
||||
}));
|
||||
|
||||
$this->setup_column_configuration();
|
||||
$this->set_filterset(new plugin_management_table_filterset());
|
||||
$this->setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of sorted plugins.
|
||||
*
|
||||
* @return \core\plugininfo\base[]
|
||||
*/
|
||||
protected function get_sorted_plugins(): array {
|
||||
if ($this->plugininfoclass::plugintype_supports_ordering()) {
|
||||
return $this->plugininfoclass::get_sorted_plugins();
|
||||
} else {
|
||||
$plugins = $this->pluginmanager->get_plugins_of_type($this->get_plugintype());
|
||||
return self::sort_plugins($plugins);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the plugins list.
|
||||
*
|
||||
* Note: This only applies to plugins which do not support ordering.
|
||||
*
|
||||
* @param \core\plugininfo\base[] $plugins
|
||||
* @return \core\plugininfo\base[]
|
||||
*/
|
||||
protected function sort_plugins(array $plugins): array {
|
||||
// The asort functions work by reference.
|
||||
\core_collator::asort_objects_by_property($plugins, 'displayname');
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the column configuration for this table.
|
||||
*/
|
||||
protected function setup_column_configuration(): void {
|
||||
$columnlist = $this->get_column_list();
|
||||
$this->define_columns(array_keys($columnlist));
|
||||
$this->define_headers(array_values($columnlist));
|
||||
|
||||
$columnswithhelp = $this->get_columns_with_help();
|
||||
$columnhelp = array_map(function (string $column) use ($columnswithhelp): ?\renderable {
|
||||
if (array_key_exists($column, $columnswithhelp)) {
|
||||
return $columnswithhelp[$column];
|
||||
}
|
||||
|
||||
return null;
|
||||
}, array_keys($columnlist));
|
||||
$this->define_help_for_headers($columnhelp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the standard order of the plugins.
|
||||
*
|
||||
* @param array $plugins
|
||||
* @return array
|
||||
*/
|
||||
protected function order_plugins(array $plugins): array {
|
||||
uasort($plugins, function ($a, $b) {
|
||||
if ($a->is_enabled() && !$b->is_enabled()) {
|
||||
return -1;
|
||||
} else if (!$a->is_enabled() && $b->is_enabled()) {
|
||||
return 1;
|
||||
}
|
||||
return strnatcasecmp($a->name, $b->name);
|
||||
});
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugintype for this table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function get_plugintype(): string;
|
||||
|
||||
/**
|
||||
* Get the action URL for this table.
|
||||
*
|
||||
* The action URL is used to perform all actions when JS is not available.
|
||||
*
|
||||
* @param array $params
|
||||
* @return moodle_url
|
||||
*/
|
||||
abstract protected function get_action_url(array $params = []): moodle_url;
|
||||
|
||||
/**
|
||||
* Provide a default implementation for guessing the base URL from the action URL.
|
||||
*/
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl($this->get_action_url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the web service method used to toggle state.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function get_toggle_service(): ?string {
|
||||
return 'core_admin_set_plugin_state';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the web service method used to order plugins.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function get_sortorder_service(): ?string {
|
||||
return 'core_admin_set_plugin_order';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_table_id(): string {
|
||||
return 'plugin_management_table-' . $this->get_plugintype();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of the column titles
|
||||
* @return string[]
|
||||
*/
|
||||
protected function get_column_list(): array {
|
||||
$columns = [
|
||||
'name' => get_string('name', 'core'),
|
||||
'version' => get_string('version', 'core'),
|
||||
];
|
||||
|
||||
if ($this->supports_disabling()) {
|
||||
$columns['enabled'] = get_string('pluginenabled', 'core_plugin');
|
||||
}
|
||||
|
||||
if ($this->supports_ordering()) {
|
||||
$columns['order'] = get_string('order', 'core');
|
||||
}
|
||||
|
||||
$columns['settings'] = get_string('settings', 'core');
|
||||
$columns['uninstall'] = get_string('uninstallplugin', 'core_admin');
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
protected function get_columns_with_help(): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the context for this table.
|
||||
*
|
||||
* @return context_system
|
||||
*/
|
||||
public function get_context(): context_system {
|
||||
return context_system::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table content.
|
||||
*/
|
||||
public function get_content(): string {
|
||||
ob_start();
|
||||
$this->out();
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the table.
|
||||
*/
|
||||
public function out(): void {
|
||||
$plugintype = $this->get_plugintype();
|
||||
foreach ($this->plugins as $plugininfo) {
|
||||
$plugin = "{$plugintype}_{$plugininfo->name}";
|
||||
$rowdata = (object) [
|
||||
'plugin' => $plugin,
|
||||
'plugininfo' => $plugininfo,
|
||||
'name' => $plugininfo->displayname,
|
||||
'version' => $plugininfo->versiondb,
|
||||
];
|
||||
$this->add_data_keyed(
|
||||
$this->format_row($rowdata),
|
||||
$this->get_row_class($rowdata)
|
||||
);
|
||||
}
|
||||
|
||||
$this->finish_output(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This table is not downloadable.
|
||||
* @param bool $downloadable
|
||||
* @return bool
|
||||
*/
|
||||
// phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
public function is_downloadable($downloadable = null): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the name column content.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_name(stdClass $row): string {
|
||||
$status = $row->plugininfo->get_status();
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
return html_writer::span(
|
||||
get_string('pluginmissingfromdisk', 'core', $row->plugininfo),
|
||||
'notifyproblem'
|
||||
);
|
||||
}
|
||||
|
||||
if ($row->plugininfo->is_installed_and_upgraded()) {
|
||||
return $row->plugininfo->displayname;
|
||||
}
|
||||
|
||||
return html_writer::span(
|
||||
$row->plugininfo->displayname,
|
||||
'notifyproblem'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the enable/disable column content.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_enabled(stdClass $row): string {
|
||||
global $OUTPUT;
|
||||
|
||||
$enabled = $row->plugininfo->is_enabled();
|
||||
$params = [
|
||||
'sesskey' => sesskey(),
|
||||
'plugin' => $row->plugininfo->name,
|
||||
'action' => $enabled ? 'disable' : 'enable',
|
||||
];
|
||||
|
||||
if ($enabled) {
|
||||
$icon = $OUTPUT->pix_icon('t/hide', get_string('disableplugin', 'core_admin', $row->plugininfo->displayname));
|
||||
} else {
|
||||
$icon = $OUTPUT->pix_icon('t/show', get_string('enableplugin', 'core_admin', $row->plugininfo->displayname));
|
||||
}
|
||||
|
||||
return html_writer::link(
|
||||
$this->get_action_url($params),
|
||||
$icon,
|
||||
[
|
||||
'data-toggle-method' => $this->get_toggle_service(),
|
||||
'data-action' => 'togglestate',
|
||||
'data-plugin' => $row->plugin,
|
||||
'data-state' => $enabled ? 1 : 0,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
protected function col_order(stdClass $row): string {
|
||||
global $OUTPUT;
|
||||
|
||||
if (!$this->supports_ordering()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$row->plugininfo->is_enabled()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($this->enabledplugincount <= 1) {
|
||||
// There is only one row.
|
||||
return '';
|
||||
}
|
||||
|
||||
$hasup = true;
|
||||
$hasdown = true;
|
||||
|
||||
if (empty($this->currentrow)) {
|
||||
// This is the top row.
|
||||
$hasup = false;
|
||||
}
|
||||
|
||||
if ($this->currentrow === ($this->enabledplugincount - 1)) {
|
||||
// This is the last row.
|
||||
$hasdown = false;
|
||||
}
|
||||
|
||||
if ($this->supports_ordering()) {
|
||||
$dataattributes = [
|
||||
'data-method' => $this->get_sortorder_service(),
|
||||
'data-action' => 'move',
|
||||
'data-plugin' => $row->plugin,
|
||||
];
|
||||
} else {
|
||||
$dataattributes = [];
|
||||
}
|
||||
|
||||
if ($hasup) {
|
||||
$upicon = html_writer::link(
|
||||
$this->get_action_url([
|
||||
'sesskey' => sesskey(),
|
||||
'action' => 'up',
|
||||
'plugin' => $row->plugininfo->name,
|
||||
]),
|
||||
$OUTPUT->pix_icon('t/up', get_string('moveup')),
|
||||
array_merge($dataattributes, ['data-direction' => 'up']),
|
||||
);
|
||||
} else {
|
||||
$upicon = $OUTPUT->spacer();
|
||||
}
|
||||
|
||||
if ($hasdown) {
|
||||
$downicon = html_writer::link(
|
||||
$this->get_action_url([
|
||||
'sesskey' => sesskey(),
|
||||
'action' => 'down',
|
||||
'plugin' => $row->plugininfo->name,
|
||||
]),
|
||||
$OUTPUT->pix_icon('t/down', get_string('movedown')),
|
||||
array_merge($dataattributes, ['data-direction' => 'down']),
|
||||
);
|
||||
} else {
|
||||
$downicon = $OUTPUT->spacer();
|
||||
}
|
||||
|
||||
// For now just add the up/down icons.
|
||||
return html_writer::span($upicon . $downicon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the settings column content.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_settings(stdClass $row): string {
|
||||
if ($settingsurl = $row->plugininfo->get_settings_url()) {
|
||||
return html_writer::link($settingsurl, get_string('settings'));
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the Uninstall column content.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_uninstall(stdClass $row): string {
|
||||
$status = $row->plugininfo->get_status();
|
||||
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_NEW) {
|
||||
return get_string('status_new', 'core_plugin');
|
||||
}
|
||||
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
$uninstall = get_string('status_missing', 'core_plugin') . '<br/>';
|
||||
} else {
|
||||
$uninstall = '';
|
||||
}
|
||||
|
||||
if ($uninstallurl = $this->pluginmanager->get_uninstall_url($row->plugin)) {
|
||||
$uninstall .= html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'));
|
||||
}
|
||||
|
||||
return $uninstall;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JS module used to manage this table.
|
||||
*
|
||||
* This should be a class which extends 'core_admin/plugin_management_table'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_table_js_module(): string {
|
||||
return 'core_admin/plugin_management_table';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add JS specific to this implementation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_dynamic_table_html_end(): string {
|
||||
global $PAGE;
|
||||
|
||||
$PAGE->requires->js_call_amd($this->get_table_js_module(), 'init');
|
||||
return parent::get_dynamic_table_html_end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any class to add to the row.
|
||||
*
|
||||
* @param mixed $row
|
||||
* @return string
|
||||
*/
|
||||
protected function get_row_class($row): string {
|
||||
$plugininfo = $row->plugininfo;
|
||||
if ($plugininfo->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$plugininfo->is_enabled()) {
|
||||
return 'dimmed_text';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function get_filterset_class(): string {
|
||||
return self::class . '_filterset';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this plugin type supports the disabling of plugins.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function supports_disabling(): bool {
|
||||
return $this->plugininfoclass::plugintype_supports_disabling();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this table should show ordering fields.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function supports_ordering(): bool {
|
||||
return $this->plugininfoclass::plugintype_supports_ordering();
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
/**
|
||||
* This file contains the dynamic interface.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class plugin_management_table_filterset extends \core_table\local\filter\filterset {
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Admin tool settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_plugin_management_table extends \core_admin\table\plugin_management_table {
|
||||
protected function get_plugintype(): string {
|
||||
return 'tool';
|
||||
}
|
||||
|
||||
protected function get_column_list(): array {
|
||||
$columns = parent::get_column_list();
|
||||
|
||||
unset($columns['settings']);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/settings.php', array_merge(['section' => 'toolsmanagement'], $params));
|
||||
}
|
||||
}
|
||||
+29
-72
@@ -27,28 +27,23 @@ define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once("{$CFG->libdir}/clilib.php");
|
||||
require_once("{$CFG->libdir}/cronlib.php");
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'execute' => false,
|
||||
'help' => false,
|
||||
'keep-alive' => 0,
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'execute' => false,
|
||||
'keep-alive' => 0,
|
||||
'ignorelimits' => false,
|
||||
'force' => false,
|
||||
'id' => null,
|
||||
'classname' => null,
|
||||
'taskslimit' => null,
|
||||
'failed' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'e' => 'execute',
|
||||
'k' => 'keep-alive',
|
||||
'i' => 'ignorelimits',
|
||||
'f' => 'force',
|
||||
'c' => 'classname',
|
||||
'l' => 'taskslimit',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -57,7 +52,8 @@ if ($unrecognized) {
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
$help = <<<EOT
|
||||
if ($options['help'] or empty($options['execute'])) {
|
||||
$help = <<<EOT
|
||||
Ad hoc cron tasks.
|
||||
|
||||
Options:
|
||||
@@ -68,32 +64,22 @@ Options:
|
||||
-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
|
||||
--id Run (failed) task with id
|
||||
-c, --classname Run tasks with a certain classname (FQN)
|
||||
-l, --taskslimit=N Run at most N tasks
|
||||
--failed Run only tasks that failed, ie those with a fail delay
|
||||
|
||||
Run all queued tasks:
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
|
||||
|
||||
Run all queued tasks of specific class:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --classname=\\\\core_course\\\\task\\\\course_delete_modules
|
||||
|
||||
Double backslash for the shell escape reasons.
|
||||
Run a specific task:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --id=123456
|
||||
|
||||
Run a specific task with debugging:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --id=123456 --showsql --showdebugging
|
||||
|
||||
To profile a long running task:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --taskslimit=1 --classname='\\some\\class\\name' --ignorelimits
|
||||
|
||||
EOT;
|
||||
|
||||
if ($options['help']) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
die;
|
||||
}
|
||||
|
||||
if ($options['showdebugging']) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if ($options['showsql']) {
|
||||
$DB->set_debug(true);
|
||||
}
|
||||
|
||||
if (CLI_MAINTENANCE) {
|
||||
@@ -106,18 +92,17 @@ if (moodle_needs_upgrading()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (empty($options['execute'])) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Common debugging options.
|
||||
if ($options['showdebugging']) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if ($options['showsql']) {
|
||||
$DB->set_debug(true);
|
||||
if (empty($options['keep-alive'])) {
|
||||
$options['keep-alive'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($CFG->showcronsql)) {
|
||||
@@ -127,48 +112,20 @@ if (!empty($CFG->showcrondebugging)) {
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
// Process params.
|
||||
$checklimits = empty($options['ignorelimits']);
|
||||
|
||||
core_php_time_limit::raise();
|
||||
|
||||
// Increase memory limit.
|
||||
raise_memory_limit(MEMORY_EXTRA);
|
||||
|
||||
// Emulate normal session - we use admin account by default.
|
||||
\core\cron::setup_user();
|
||||
cron_setup_user();
|
||||
|
||||
$humantimenow = date('r', time());
|
||||
$keepalive = (int)$options['keep-alive'];
|
||||
|
||||
\core\local\cli\shutdown::script_supports_graceful_exit();
|
||||
$humantimenow = date('r', time());
|
||||
|
||||
mtrace("Server Time: {$humantimenow}\n");
|
||||
|
||||
$classname = $options['classname'];
|
||||
|
||||
// Run a single adhoc task only, if requested.
|
||||
if (!empty($options['id'])) {
|
||||
$taskid = (int) $options['id'];
|
||||
\core\cron::run_adhoc_task($taskid);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Run all failed tasks.
|
||||
if (!empty($options['failed'])) {
|
||||
\core\cron::run_failed_adhoc_tasks($classname);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Examine params and determine if we should run.
|
||||
$execute = (bool) $options['execute'];
|
||||
$keepalive = empty($options['keep-alive']) ? 0 : (int) $options['keep-alive'];
|
||||
$taskslimit = empty($options['taskslimit']) ? null : (int) $options['taskslimit'];
|
||||
$checklimits = empty($options['ignorelimits']);
|
||||
|
||||
if ($classname || $keepalive || $taskslimit) {
|
||||
$execute = true;
|
||||
}
|
||||
|
||||
// Output the help text if no criteria for running the adhoc tasks are given.
|
||||
if (!$execute) {
|
||||
echo $help;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
\core\cron::run_adhoc_tasks(time(), $keepalive, $checklimits, null, $taskslimit, $classname);
|
||||
cron_run_adhoc_tasks(time(), $keepalive, $checklimits);
|
||||
|
||||
@@ -30,6 +30,7 @@ define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php'); // cli only functions
|
||||
require_once($CFG->libdir.'/cronlib.php');
|
||||
|
||||
// now get cli options
|
||||
list($options, $unrecognized) = cli_get_params(array('help'=>false),
|
||||
@@ -79,10 +80,10 @@ if (!empty($CFG->showcrondebugging)) {
|
||||
|
||||
$starttime = microtime();
|
||||
|
||||
// Emulate normal session.
|
||||
\core\cron::setup_user();
|
||||
/// emulate normal session
|
||||
cron_setup_user();
|
||||
|
||||
// Start output log.
|
||||
/// Start output log
|
||||
$timenow = time();
|
||||
|
||||
mtrace("Server Time: ".date('r',$timenow)."\n\n");
|
||||
@@ -95,4 +96,4 @@ backup_cron_automated_helper::run_automated_backup(backup_cron_automated_helper:
|
||||
mtrace("Automated cron backups completed correctly");
|
||||
|
||||
$difftime = microtime_diff($starttime, microtime());
|
||||
mtrace("Execution took ".$difftime." seconds");
|
||||
mtrace("Execution took ".$difftime." seconds");
|
||||
+13
-21
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
@@ -29,11 +30,12 @@
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir . '/clilib.php');
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php'); // cli only functions
|
||||
require_once($CFG->libdir.'/cronlib.php');
|
||||
|
||||
// Now get cli option.
|
||||
[$options, $unrecognized] = cli_get_params(
|
||||
// now get cli options
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'help' => false,
|
||||
'stop' => false,
|
||||
@@ -42,9 +44,7 @@ require_once($CFG->libdir . '/clilib.php');
|
||||
'enable' => false,
|
||||
'disable' => false,
|
||||
'disable-wait' => false,
|
||||
'keep-alive' => null,
|
||||
],
|
||||
[
|
||||
], [
|
||||
'h' => 'help',
|
||||
's' => 'stop',
|
||||
'l' => 'list',
|
||||
@@ -52,7 +52,6 @@ require_once($CFG->libdir . '/clilib.php');
|
||||
'e' => 'enable',
|
||||
'd' => 'disable',
|
||||
'w' => 'disable-wait',
|
||||
'k' => 'keep-alive',
|
||||
]
|
||||
);
|
||||
|
||||
@@ -63,7 +62,7 @@ if ($unrecognized) {
|
||||
|
||||
if ($options['help']) {
|
||||
$help =
|
||||
"Execute periodic cron actions.
|
||||
"Execute periodic cron actions.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
@@ -73,9 +72,6 @@ Options:
|
||||
-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)
|
||||
-k, --keep-alive=N Keep this script alive for N seconds and poll for new tasks
|
||||
The default value can be set by administrators in:
|
||||
Site administration > Server > Tasks > Task processing > Keep alive time
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/cron.php
|
||||
@@ -109,8 +105,7 @@ 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,
|
||||
printf ($format,
|
||||
'PID',
|
||||
'HOST',
|
||||
'TYPE',
|
||||
@@ -118,8 +113,7 @@ if ($options['list']) {
|
||||
'CLASSNAME'
|
||||
);
|
||||
foreach ($tasks as $task) {
|
||||
printf(
|
||||
$format,
|
||||
printf ($format,
|
||||
$task->pid,
|
||||
substr($task->hostname, 0, 12),
|
||||
$task->type,
|
||||
@@ -143,7 +137,7 @@ if ($wait = $options['disable-wait']) {
|
||||
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.');
|
||||
mtrace('Allocating '. format_time($waitsec) . ' for the tasks to finish.');
|
||||
|
||||
$lastcount = 0;
|
||||
while ($wait) {
|
||||
@@ -157,7 +151,7 @@ if ($wait = $options['disable-wait']) {
|
||||
|
||||
if (time() - $started >= $waitsec) {
|
||||
mtrace('');
|
||||
mtrace('Wait time (' . format_time($waitsec) . ') elapsed, but ' . count($tasks) . ' task(s) still running.');
|
||||
mtrace('Wait time ('. format_time($waitsec) . ') elapsed, but ' . count($tasks) . ' task(s) still running.');
|
||||
mtrace('Exiting with code 1.');
|
||||
exit(1);
|
||||
}
|
||||
@@ -181,6 +175,4 @@ if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
|
||||
\core\local\cli\shutdown::script_supports_graceful_exit();
|
||||
|
||||
|
||||
$keepalive = $options['keep-alive'];
|
||||
\core\cron::run_main_process($keepalive);
|
||||
cron_run();
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* CLI script to delete a course.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @author Mikhail Golenkov <mikhailgolenkov@catalyst-au.net>
|
||||
* @copyright 2022 Catalyst IT
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir . '/clilib.php');
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
'courseid' => false,
|
||||
'help' => false,
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'disablerecyclebin' => false,
|
||||
'non-interactive' => false,
|
||||
], [
|
||||
'c' => 'courseid',
|
||||
'h' => 'help',
|
||||
]
|
||||
);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help'] || empty($options['courseid'])) {
|
||||
$help = <<<EOT
|
||||
CLI script to delete a course.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
--showsql Show sql queries before they are executed
|
||||
--showdebugging Show developer level debugging information
|
||||
--disablerecyclebin Skip backing up the course
|
||||
--non-interactive No interactive questions or confirmations
|
||||
-c, --courseid Course id to be deleted
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/delete_course.php --courseid=123456
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/delete_course.php --courseid=123456 --showdebugging
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/delete_course.php --courseid=123456 --disablerecyclebin
|
||||
|
||||
EOT;
|
||||
|
||||
echo $help;
|
||||
die;
|
||||
}
|
||||
|
||||
$interactive = empty($options['non-interactive']);
|
||||
|
||||
if ($options['showdebugging']) {
|
||||
mtrace('Enabling debugging...');
|
||||
set_debugging(DEBUG_DEVELOPER, true);
|
||||
}
|
||||
|
||||
if ($options['showsql']) {
|
||||
mtrace('Enabling SQL debugging...');
|
||||
$DB->set_debug(true);
|
||||
}
|
||||
|
||||
if (CLI_MAINTENANCE) {
|
||||
cli_error('CLI maintenance mode active, CLI execution suspended');
|
||||
}
|
||||
|
||||
if (moodle_needs_upgrading()) {
|
||||
cli_error('Moodle upgrade pending, CLI execution suspended');
|
||||
}
|
||||
|
||||
$course = $DB->get_record('course', array('id' => $options['courseid']));
|
||||
if (empty($course)) {
|
||||
cli_error('Course not found');
|
||||
}
|
||||
|
||||
mtrace('Deleting course id ' . $course->id);
|
||||
mtrace('Course name: ' . $course->fullname);
|
||||
mtrace('Short name: ' . $course->shortname);
|
||||
|
||||
if ($interactive) {
|
||||
mtrace('');
|
||||
$input = cli_input('Are you sure you wish to delete this course? (y/N)', 'N', ['y', 'Y', 'n', 'N']);
|
||||
if (strtolower($input) != 'y') {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if ($options['disablerecyclebin']) {
|
||||
mtrace('Disabling recycle bin...');
|
||||
$overrideconfig = ['tool_recyclebin' => ['coursebinenable' => false, 'categorybinenable' => false]];
|
||||
$CFG->forced_plugin_settings = array_merge($CFG->forced_plugin_settings, $overrideconfig);
|
||||
}
|
||||
|
||||
core_php_time_limit::raise();
|
||||
delete_course($course);
|
||||
|
||||
mtrace('Updating course count in categories...');
|
||||
fix_course_sortorder();
|
||||
|
||||
mtrace('Done!');
|
||||
@@ -1,209 +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 you to view and change the emailstop flag of any user.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2023 Stephan Robotta (stephan.robotta@bfh.ch)
|
||||
* @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');
|
||||
|
||||
// Define the input options.
|
||||
$longparams = [
|
||||
'email' => '',
|
||||
'help' => false,
|
||||
'id' => '',
|
||||
'quiet' => false,
|
||||
'stop' => '',
|
||||
'username' => '',
|
||||
];
|
||||
|
||||
$shortparams = [
|
||||
'e' => 'email',
|
||||
'h' => 'help',
|
||||
'i' => 'id',
|
||||
'q' => 'quiet',
|
||||
's' => 'stop',
|
||||
'u' => 'username',
|
||||
];
|
||||
|
||||
// Define exit codes.
|
||||
$exitsuccess = 0;
|
||||
$exitunknownoption = 1;
|
||||
$exitmissinguserarg = 2;
|
||||
$exittoomanyuserarg = 3;
|
||||
$exitnosearchargs = 4;
|
||||
$exitnousersfound = 5;
|
||||
$exitinvalidstopflag = 6;
|
||||
$exiterrordb = 7;
|
||||
|
||||
// Now get cli options that are set by the caller.
|
||||
list($options, $unrecognized) = cli_get_params($longparams, $shortparams);
|
||||
|
||||
$verbose = empty($options['quiet']);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
if ($verbose) {
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), $exitunknownoption);
|
||||
}
|
||||
exit($exitunknownoption);
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
$help =
|
||||
"Set/unset or show status of emailstop flag for a user, identified by username or email.
|
||||
|
||||
There are no security checks here because anybody who is able to
|
||||
execute this file may execute any PHP too.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
-e, --email=email Specify user by email, separate many users by comma
|
||||
-i, --id=id Specify user by id, separate many users by comma
|
||||
-q, --quiet No output to stdout
|
||||
-s, --stop=0|1|off|on Set new value for emailstop flag
|
||||
-u, --username=username Specify user by username, separate many users by comma
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/emailstop.php --email=student1@example.com --stop=1
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/emailstop.php --email=student1@example.com,student2@example.com
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/emailstop.php --u=student1,student2 -s=on
|
||||
";
|
||||
|
||||
echo $help;
|
||||
exit($exitsuccess);
|
||||
}
|
||||
|
||||
$cntempty = 0;
|
||||
$cntfilled = 0;
|
||||
$searchargs = [];
|
||||
|
||||
// Try to find out which option is used to fetch the users from. Also do sanitize etc.
|
||||
foreach (['email', 'username', 'id'] as $option) {
|
||||
if (empty($options[$option])) {
|
||||
$cntempty++;
|
||||
} else {
|
||||
$cntfilled++;
|
||||
$argname = $option;
|
||||
// The search args must be: split by the comma, trimmed, and empty elements filtered out.
|
||||
$searchargs = array_flip(array_filter(
|
||||
array_map(
|
||||
function ($item) {
|
||||
return trim($item);
|
||||
},
|
||||
explode(',', $options[$option])
|
||||
),
|
||||
function ($item) {
|
||||
return $item !== '';
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
if ($cntempty === 3) {
|
||||
if ($verbose) {
|
||||
cli_error('One of username, email, or id must be set.', $exitmissinguserarg);
|
||||
}
|
||||
exit($exitmissinguserarg);
|
||||
}
|
||||
if ($cntfilled > 1) {
|
||||
if ($verbose) {
|
||||
cli_error('Only one of email, username, or id can be set to identify a user.', $exittoomanyuserarg);
|
||||
}
|
||||
exit($exittoomanyuserarg);
|
||||
}
|
||||
if (empty($searchargs)) {
|
||||
if ($verbose) {
|
||||
cli_error('No values are provided for users.', $exitnosearchargs);
|
||||
}
|
||||
exit($exitnosearchargs);
|
||||
}
|
||||
try {
|
||||
$users = $DB->get_records_list('user', $argname, array_keys($searchargs));
|
||||
} catch (Exception $e) {
|
||||
if ($verbose) {
|
||||
cli_error("Could not fetch data from db by {$argname}: '{$options[$argname]}'.", $exiterrordb);
|
||||
}
|
||||
exit($exiterrordb);
|
||||
}
|
||||
if (empty($users)) {
|
||||
if ($verbose) {
|
||||
cli_error("Can not find any user by {$argname}: '{$options[$argname]}'.", $exitnousersfound);
|
||||
}
|
||||
exit($exitnousersfound);
|
||||
}
|
||||
|
||||
// No stop flag set, then just print the user and the current emailstop flag state.
|
||||
if ($options['stop'] === '') {
|
||||
foreach ($users as $user) {
|
||||
if ($verbose) {
|
||||
echo 'user=' . $user->{$argname} . ' - emailstop=' . (int)$user->emailstop . PHP_EOL;
|
||||
unset($searchargs[$user->{$argname}]);
|
||||
}
|
||||
}
|
||||
if ($verbose) {
|
||||
foreach (array_keys($searchargs) as $arg) {
|
||||
echo 'user=' . $arg . ' - not found' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
exit($exitsuccess);
|
||||
}
|
||||
|
||||
// Allowed values for the stop flag enabled are 1 and on, for disabled are 0 and off.
|
||||
$validvalues = ['0', '1', 'off', 'on'];
|
||||
$stopflag = strtolower($options['stop']);
|
||||
if (!in_array($stopflag, $validvalues)) {
|
||||
if ($verbose) {
|
||||
cli_error('Value for the emailstop flag must be one of: ' . implode(', ', $validvalues) . '.', $exitinvalidstopflag);
|
||||
}
|
||||
exit($exitinvalidstopflag);
|
||||
}
|
||||
|
||||
foreach ($validvalues as $value) {
|
||||
if ($value === $stopflag) {
|
||||
$stopflag = ($value === '1' || $value === 'on') ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Update each user with the stop flag to be set if it is necessary.
|
||||
foreach ($users as $user) {
|
||||
$line = 'Update user ' . $user->{$argname} . ($argname !== 'id' ? ' (' . $user->id . ')' : '') . ' - ';
|
||||
if ((int)$user->emailstop !== $stopflag) {
|
||||
$DB->set_field('user', 'emailstop', $stopflag, ['id' => $user->id]);
|
||||
$line .= 'ok';
|
||||
} else {
|
||||
$line .= 'already done';
|
||||
}
|
||||
if ($verbose) {
|
||||
echo $line . PHP_EOL;
|
||||
unset($searchargs[$user->{$argname}]);
|
||||
}
|
||||
|
||||
}
|
||||
if ($verbose) {
|
||||
foreach (array_keys($searchargs) as $arg) {
|
||||
echo 'user=' . $arg . ' - not found' . PHP_EOL;
|
||||
}
|
||||
}
|
||||
exit($exitsuccess);
|
||||
|
||||
@@ -39,6 +39,8 @@ if ($unrecognized) {
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
// TODO: MDL-71421 - Remove the openssl alternative once sodium becomes a requirement in Moodle 4.2.
|
||||
|
||||
if ($options['help']) {
|
||||
echo "Generate secure key
|
||||
|
||||
@@ -52,7 +54,9 @@ may be manually installed on multiple servers.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
--method <method> Generate key for specified encryption method instead of default (sodium)
|
||||
--method <method> Generate key for specified encryption method instead of default.
|
||||
* sodium
|
||||
* openssl-aes-256-ctr
|
||||
|
||||
Example:
|
||||
php admin/cli/generate_key.php
|
||||
|
||||
@@ -57,7 +57,6 @@ Options:
|
||||
--fullname=STRING Name of the site
|
||||
--shortname=STRING Name of the site
|
||||
--summary=STRING The summary to be displayed on the front page
|
||||
--supportemail=STRING Email address for support and help.
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
@@ -99,7 +98,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'fullname' => '',
|
||||
'shortname' => '',
|
||||
'summary' => '',
|
||||
'supportemail' => '',
|
||||
'agree-license' => false,
|
||||
'help' => false
|
||||
),
|
||||
@@ -138,15 +136,6 @@ if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
|
||||
// Validate that the supportemail provided was an e-mail address.
|
||||
if (!empty($options['supportemail']) && !validate_email($options['supportemail'])) {
|
||||
$a = (object) [
|
||||
'option' => 'supportemail',
|
||||
'value' => $options['supportemail']
|
||||
];
|
||||
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
|
||||
}
|
||||
|
||||
$options['lang'] = clean_param($options['lang'], PARAM_SAFEDIR);
|
||||
if (!file_exists($CFG->dirroot.'/install/lang/'.$options['lang'])) {
|
||||
$options['lang'] = 'en';
|
||||
|
||||
@@ -69,19 +69,19 @@ if ($options['showdebugging']) {
|
||||
}
|
||||
|
||||
if (!$admin = get_admin()) {
|
||||
throw new \moodle_exception('noadmins');
|
||||
print_error('noadmins');
|
||||
}
|
||||
|
||||
if (!file_exists($options['file'])) {
|
||||
throw new \moodle_exception('filenotfound');
|
||||
print_error('filenotfound');
|
||||
}
|
||||
|
||||
if (!$category = $DB->get_record('course_categories', ['id' => $options['categoryid']], 'id')) {
|
||||
throw new \moodle_exception('invalidcategoryid');
|
||||
print_error('invalidcategoryid');
|
||||
}
|
||||
|
||||
$backupdir = restore_controller::get_tempdir_name(SITEID, $USER->id);
|
||||
$path = make_backup_temp_directory($backupdir);
|
||||
$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');
|
||||
@@ -102,7 +102,7 @@ try {
|
||||
} catch (Exception $e) {
|
||||
cli_heading(get_string('cleaningtempdata'));
|
||||
fulldelete($path);
|
||||
throw new \moodle_exception('generalexceptionmessage', 'error', '', $e->getMessage());
|
||||
print_error('generalexceptionmessage', 'error', '', $e->getMessage());
|
||||
}
|
||||
|
||||
cli_heading(get_string('restoredcourseid', 'backup', $courseid));
|
||||
|
||||
@@ -27,6 +27,7 @@ define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__ . '/../../config.php');
|
||||
require_once("$CFG->libdir/clilib.php");
|
||||
require_once("$CFG->libdir/cronlib.php");
|
||||
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
[
|
||||
@@ -36,8 +37,6 @@ list($options, $unrecognized) = cli_get_params(
|
||||
'showsql' => false,
|
||||
'showdebugging' => false,
|
||||
'force' => false,
|
||||
'disable' => false,
|
||||
'enable' => false,
|
||||
], [
|
||||
'h' => 'help',
|
||||
'f' => 'force',
|
||||
@@ -49,15 +48,11 @@ if ($unrecognized) {
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
$commands = ['list', 'execute', 'disable', 'enable'];
|
||||
$hascommand = count(array_filter($commands, fn($command) => $options[$command])) > 0;
|
||||
if ($options['help'] || !$hascommand) {
|
||||
if ($options['help'] or (!$options['list'] and !$options['execute'])) {
|
||||
$help =
|
||||
"Scheduled cron tasks.
|
||||
|
||||
Options:
|
||||
--disable=\\some\\task Disable scheduled task
|
||||
--enable=\\some\\task Enable scheduled task
|
||||
--execute=\\some\\task Execute scheduled task manually
|
||||
--list List all scheduled tasks
|
||||
--showsql Show sql queries before they are executed
|
||||
@@ -125,43 +120,17 @@ if ($options['list']) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (moodle_needs_upgrading()) {
|
||||
mtrace("Moodle upgrade pending, cannot manage tasks.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ($disable = $options['disable']) {
|
||||
if (!$task = \core\task\manager::get_scheduled_task($disable)) {
|
||||
mtrace("Task '$disable' not found");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
$task->disable();
|
||||
mtrace("Disabled '$disable'");
|
||||
} catch (Exception $e) {
|
||||
mtrace("$e->getMessage()");
|
||||
exit(1);
|
||||
}
|
||||
} else if ($enable = $options['enable']) {
|
||||
if (!$task = \core\task\manager::get_scheduled_task($enable)) {
|
||||
mtrace("Task '$enable' not found");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
$task->enable();
|
||||
mtrace("Enabled '$enable'");
|
||||
} catch (Exception $e) {
|
||||
mtrace("$e->getMessage()");
|
||||
exit(1);
|
||||
}
|
||||
} else if ($execute = $options['execute']) {
|
||||
if ($execute = $options['execute']) {
|
||||
if (!$task = \core\task\manager::get_scheduled_task($execute)) {
|
||||
mtrace("Task '$execute' not found");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (moodle_needs_upgrading()) {
|
||||
mtrace("Moodle upgrade pending, cannot execute tasks.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!get_config('core', 'cron_enabled') && !$options['force']) {
|
||||
mtrace('Cron is disabled. Use --force to override.');
|
||||
exit(1);
|
||||
@@ -173,7 +142,7 @@ if ($disable = $options['disable']) {
|
||||
raise_memory_limit(MEMORY_EXTRA);
|
||||
|
||||
// Emulate normal session - we use admin account by default.
|
||||
\core\cron::setup_user();
|
||||
cron_setup_user();
|
||||
|
||||
// Execute the task.
|
||||
\core\local\cli\shutdown::script_supports_graceful_exit();
|
||||
@@ -195,5 +164,5 @@ if ($disable = $options['disable']) {
|
||||
$task->set_cron_lock($cronlock);
|
||||
}
|
||||
|
||||
\core\cron::run_inner_scheduled_task($task);
|
||||
cron_run_inner_scheduled_task($task);
|
||||
}
|
||||
|
||||
+28
-114
@@ -48,16 +48,12 @@ require_once($CFG->libdir.'/environmentlib.php');
|
||||
$lang = isset($SESSION->lang) ? $SESSION->lang : $CFG->lang;
|
||||
list($options, $unrecognized) = cli_get_params(
|
||||
array(
|
||||
'allow-unstable' => false,
|
||||
'help' => false,
|
||||
'is-maintenance-required' => false,
|
||||
'is-pending' => false,
|
||||
'lang' => $lang,
|
||||
'maintenance' => true,
|
||||
'non-interactive' => false,
|
||||
'set-ui-upgrade-lock' => false,
|
||||
'unset-ui-upgrade-lock' => false,
|
||||
'verbose-settings' => false,
|
||||
'non-interactive' => false,
|
||||
'allow-unstable' => false,
|
||||
'help' => false,
|
||||
'lang' => $lang,
|
||||
'verbose-settings' => false,
|
||||
'is-pending' => false,
|
||||
),
|
||||
array(
|
||||
'h' => 'help'
|
||||
@@ -83,35 +79,19 @@ Please note you must execute this script with the same uid as apache!
|
||||
Site defaults may be changed via local/defaults.php.
|
||||
|
||||
Options:
|
||||
--allow-unstable Upgrade even if the version is not marked as stable yet,
|
||||
required in non-interactive mode.
|
||||
-h, --help Print out this help.
|
||||
--is-maintenance-required Returns exit code 2 if the upgrade requires maintenance mode.
|
||||
Returns exit code 3 if no maintenance is required for the upgrade.
|
||||
--is-pending Exit with error code 2 if an upgrade is required.
|
||||
--lang=CODE Set preferred language for CLI output. Defaults to the
|
||||
site language if not set. Defaults to 'en' if the lang
|
||||
parameter is invalid or if the language pack is not
|
||||
installed.
|
||||
--maintenance Sets whether this upgrade will use maintenance mode.
|
||||
If not possible, the upgrade will not happen and the script will exit.
|
||||
WARNING: Caches (except theme) will be STALE and MUST be purged after upgrading.
|
||||
DO NOT USE if the upgrade contains known breaking changes to the way data
|
||||
and the database interact.
|
||||
RECOMMENDED for lightweight deployments, to allow for a graceful purge and
|
||||
rebuild of the cache.
|
||||
--non-interactive No interactive questions or confirmations.
|
||||
--set-ui-upgrade-lock Sets the upgrade to CLI only and unable to be triggered from the frontend.
|
||||
If called with --maintenance=false, the lock WILL NOT be released when the
|
||||
upgrade finishes, and MUST be manually removed.
|
||||
If called with --is-maintenance-required before an upgrade,
|
||||
The lock WILL be released when the upgrade finishes.
|
||||
--unset-ui-upgrade-lock Removes the frontend upgrade lock, if the lock exists.
|
||||
Useful when an error during the upgrade leaves the upgrade locked,
|
||||
or there is need to control the time where the unlock happens.
|
||||
--verbose-settings Show new settings values. By default only the name of
|
||||
new core or plugin settings are displayed. This option
|
||||
outputs the new values as well as the setting name.
|
||||
--non-interactive No interactive questions or confirmations
|
||||
--allow-unstable Upgrade even if the version is not marked as stable yet,
|
||||
required in non-interactive mode.
|
||||
--lang=CODE Set preferred language for CLI output. Defaults to the
|
||||
site language if not set. Defaults to 'en' if the lang
|
||||
parameter is invalid or if the language pack is not
|
||||
installed.
|
||||
--verbose-settings Show new settings values. By default only the name of
|
||||
new core or plugin settings are displayed. This option
|
||||
outputs the new values as well as the setting name.
|
||||
--is-pending If an upgrade is needed it exits with an error code of
|
||||
2 so it distinct from other types of errors.
|
||||
-h, --help Print out this help
|
||||
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/upgrade.php
|
||||
@@ -135,58 +115,12 @@ if ($version < $CFG->version) {
|
||||
$oldversion = "$CFG->release ($CFG->version)";
|
||||
$newversion = "$release ($version)";
|
||||
|
||||
if ($options['unset-ui-upgrade-lock']) {
|
||||
// Unconditionally unset this config if requested.
|
||||
set_config('outagelessupgrade', false);
|
||||
cli_writeln(get_string('cliupgradeunsetlock', 'admin'));
|
||||
}
|
||||
|
||||
$allhash = core_component::get_all_component_hash();
|
||||
|
||||
// Initialise allcomponent hash if not set. It will be correctly set after upgrade.
|
||||
$CFG->allcomponenthash = $CFG->allcomponenthash ?? '';
|
||||
if (!$options['maintenance']) {
|
||||
if ($allhash !== $CFG->allcomponenthash) {
|
||||
// Throw an error here, we can't proceed, this needs to set maintenance.
|
||||
cli_error(get_string('cliupgrademaintenancerequired', 'core_admin'), 2);
|
||||
}
|
||||
|
||||
// Set a constant to stop any upgrade var from being set during processing.
|
||||
// This protects against the upgrade setting timeouts and maintenance during the upgrade.
|
||||
define('CLI_UPGRADE_RUNNING', true);
|
||||
|
||||
// This database control is the control to block the GUI from doing upgrade related actions.
|
||||
set_config('outagelessupgrade', true);
|
||||
}
|
||||
|
||||
// We should ignore all upgrade locks here.
|
||||
if (!moodle_needs_upgrading(false)) {
|
||||
if (!moodle_needs_upgrading()) {
|
||||
cli_error(get_string('cliupgradenoneed', 'core_admin', $newversion), 0);
|
||||
}
|
||||
|
||||
// Handle exit based options for outputting upgrade state.
|
||||
if ($options['is-pending'] || $options['is-maintenance-required']) {
|
||||
// If we aren't doing a maintenance check, plain pending check.
|
||||
if (!$options['is-maintenance-required']) {
|
||||
cli_error(get_string('cliupgradepending', 'core_admin'), 2);
|
||||
}
|
||||
|
||||
// Can we do this safely with no maintenance/outage? Detect if there is a schema or other application state change.
|
||||
if ($allhash !== $CFG->allcomponenthash) {
|
||||
// State change here, we need to do this in maintenance.
|
||||
cli_writeln(get_string('cliupgradepending', 'core_admin'));
|
||||
cli_error(get_string('cliupgrademaintenancerequired', 'core_admin'), 2);
|
||||
}
|
||||
|
||||
// If requested, we should always set the upgrade lock here, so this cannot be run from frontend.
|
||||
if ($options['set-ui-upgrade-lock']) {
|
||||
set_config('outagelessupgrade', true);
|
||||
cli_writeln(get_string('cliupgradesetlock', 'admin'));
|
||||
}
|
||||
|
||||
// We can do an upgrade without maintenance!
|
||||
cli_writeln(get_string('cliupgradepending', 'core_admin'));
|
||||
cli_error(get_string('cliupgrademaintenancenotrequired', 'core_admin'), 3);
|
||||
if ($options['is-pending']) {
|
||||
cli_error(get_string('cliupgradepending', 'core_admin'), 2);
|
||||
}
|
||||
|
||||
// Test environment first.
|
||||
@@ -253,18 +187,12 @@ if ($interactive) {
|
||||
}
|
||||
|
||||
if ($version > $CFG->version) {
|
||||
|
||||
// Only purge caches if this is a plain upgrade.
|
||||
// In the case of a no-outage upgrade, we will gracefully roll caches after upgrade.
|
||||
if ($options['maintenance']) {
|
||||
// We purge all of MUC's caches here.
|
||||
// Caches are disabled for upgrade by CACHE_DISABLE_ALL so we must set the first arg to true.
|
||||
// This ensures a real config object is loaded and the stores will be purged.
|
||||
// This is the only way we can purge custom caches such as memcache or APC.
|
||||
// Note: all other calls to caches will still used the disabled API.
|
||||
cache_helper::purge_all(true);
|
||||
}
|
||||
|
||||
// We purge all of MUC's caches here.
|
||||
// Caches are disabled for upgrade by CACHE_DISABLE_ALL so we must set the first arg to true.
|
||||
// This ensures a real config object is loaded and the stores will be purged.
|
||||
// This is the only way we can purge custom caches such as memcache or APC.
|
||||
// Note: all other calls to caches will still used the disabled API.
|
||||
cache_helper::purge_all(true);
|
||||
upgrade_core($version, true);
|
||||
}
|
||||
set_config('release', $release);
|
||||
@@ -302,18 +230,4 @@ foreach ($settingsoutput as $setting => $value) {
|
||||
upgrade_themes();
|
||||
|
||||
echo get_string('cliupgradefinished', 'admin', $a)."\n";
|
||||
|
||||
if (!$options['maintenance']) {
|
||||
cli_writeln(get_string('cliupgradecompletenomaintenanceupgrade', 'admin'));
|
||||
|
||||
// Here we check if upgrade lock has not been specifically set during this upgrade run.
|
||||
// This supports wider server orchestration actions happening, which should call with no-maintenance AND set-ui-upgrade-lock,
|
||||
// such as a new docker container deployment, of which the moodle upgrade is only a component.
|
||||
if (!$options['set-ui-upgrade-lock']) {
|
||||
// In this case we should release the lock now, as the upgrade is finished.
|
||||
// We weren't told to keep the lock with set-ui-upgrade-lock, so release.
|
||||
set_config('outagelessupgrade', false);
|
||||
}
|
||||
}
|
||||
|
||||
exit(0); // 0 means success
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Communication and its plugins settings.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage communication
|
||||
* @copyright 2023 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$name = required_param('name', PARAM_PLUGIN);
|
||||
|
||||
$syscontext = context_system::instance();
|
||||
$PAGE->set_url('/admin/communication.php');
|
||||
$PAGE->set_context($syscontext);
|
||||
|
||||
require_admin();
|
||||
require_sesskey();
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', ['section' => 'managecommunicationproviders']);
|
||||
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('communication');
|
||||
$sortorder = array_flip(array_keys($plugins));
|
||||
|
||||
if (!isset($plugins[$name])) {
|
||||
throw new moodle_exception('communicationprovidernotfound', 'core_communication', $return, $name);
|
||||
}
|
||||
|
||||
$plugintypename = $plugins[$name]->type . '_' . $plugins[$name]->name;
|
||||
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
if ($plugins[$name]->is_enabled()) {
|
||||
$class = core_plugin_manager::resolve_plugininfo_class('communication');
|
||||
$class::enable_plugin($name, false);
|
||||
}
|
||||
break;
|
||||
case 'enable':
|
||||
if (!$plugins[$name]->is_enabled()) {
|
||||
$class = core_plugin_manager::resolve_plugininfo_class('communication');
|
||||
$class::enable_plugin($name, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
redirect($return);
|
||||
@@ -42,7 +42,7 @@ $plugins = core_plugin_manager::instance()->get_plugins_of_type('contenttype');
|
||||
$sortorder = array_flip(array_keys($plugins));
|
||||
|
||||
if (!isset($plugins[$name])) {
|
||||
throw new \moodle_exception('contenttypenotfound', 'error', $return, $name);
|
||||
print_error('contenttypenotfound', 'error', $return, $name);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Reset course indentation
|
||||
*
|
||||
* @copyright 2023 Amaia Anabitarte <amaia@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../../config.php');
|
||||
|
||||
require_admin();
|
||||
|
||||
$format = required_param('format', PARAM_PLUGIN);
|
||||
$confirm = optional_param('confirm', false, PARAM_BOOL);
|
||||
$backurl = new moodle_url('/admin/settings.php', ['section' => 'formatsetting'.$format]);
|
||||
|
||||
$PAGE->set_url('/admin/course/resetindentation.php', ['format' => $format]);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
if ($confirm) {
|
||||
require_sesskey();
|
||||
$courses = $DB->get_records('course', ['format' => $format], 'id', 'id');
|
||||
if (!empty($courses)) {
|
||||
$courseids = array_keys($courses);
|
||||
list($courseinsql, $courseparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, 'course');
|
||||
$DB->set_field_select('course_modules', 'indent', '0', "course $courseinsql AND indent <> 0", $courseparams);
|
||||
rebuild_course_cache(0, true);
|
||||
}
|
||||
redirect(
|
||||
$backurl,
|
||||
get_string('resetindentationsuccess', 'admin'),
|
||||
null,
|
||||
\core\output\notification::NOTIFY_SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
$strtitle = get_string('resetindentation', 'admin');
|
||||
|
||||
$PAGE->set_title($strtitle);
|
||||
$PAGE->set_heading($strtitle);
|
||||
|
||||
navigation_node::override_active_url(new moodle_url(
|
||||
'/admin/course/resetindentation.php',
|
||||
['action' => 'confirm', 'format' => $format]
|
||||
));
|
||||
|
||||
echo $OUTPUT->header();
|
||||
|
||||
$displayoptions = ['confirmtitle' => get_string('resetindentation_title', 'admin')];
|
||||
$confirmbutton = new single_button(
|
||||
new moodle_url('/admin/course/resetindentation.php', ['confirm' => 1, 'format' => $format, 'sesskey' => sesskey()]),
|
||||
get_string('resetindentation', 'admin'),
|
||||
'post',
|
||||
single_button::BUTTON_DANGER
|
||||
);
|
||||
$cancelbutton = new single_button($backurl, get_string('cancel'));
|
||||
echo $OUTPUT->confirm(
|
||||
get_string('resetindentation_help', 'admin', ['format' => get_string('pluginname', 'format_'.$format)]),
|
||||
$confirmbutton,
|
||||
$cancelbutton,
|
||||
$displayoptions
|
||||
);
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
@@ -41,7 +41,7 @@ $formatplugins = core_plugin_manager::instance()->get_plugins_of_type('format');
|
||||
$sortorder = array_flip(array_keys($formatplugins));
|
||||
|
||||
if (!isset($formatplugins[$formatname])) {
|
||||
throw new \moodle_exception('courseformatnotfound', 'error', $return, $formatname);
|
||||
print_error('courseformatnotfound', 'error', $return, $formatname);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
|
||||
+9
-8
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
@@ -35,7 +36,6 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
// phpcs:ignoreFile moodle.Files.MoodleInternal.MoodleInternalGlobalState
|
||||
|
||||
if (defined('STDIN')) {
|
||||
fwrite(STDERR, "ERROR: This script no longer supports CLI, please use admin/cli/cron.php instead\n");
|
||||
@@ -49,7 +49,8 @@ define('WEB_CRON_EMULATED_CLI', 'defined'); // ugly ugly hack, do not use elsewh
|
||||
define('NO_OUTPUT_BUFFERING', true);
|
||||
|
||||
require('../config.php');
|
||||
require_once($CFG->libdir . '/clilib.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
require_once($CFG->libdir.'/cronlib.php');
|
||||
|
||||
// extra safety
|
||||
\core\session\manager::write_close();
|
||||
@@ -57,7 +58,7 @@ require_once($CFG->libdir . '/clilib.php');
|
||||
// check if execution allowed
|
||||
if (!empty($CFG->cronclionly)) {
|
||||
// This script can only be run via the cli.
|
||||
throw new \moodle_exception('cronerrorclionly', 'admin');
|
||||
print_error('cronerrorclionly', 'admin');
|
||||
exit;
|
||||
}
|
||||
// This script is being called via the web, so check the password if there is one.
|
||||
@@ -65,16 +66,16 @@ if (!empty($CFG->cronremotepassword)) {
|
||||
$pass = optional_param('password', '', PARAM_RAW);
|
||||
if ($pass != $CFG->cronremotepassword) {
|
||||
// wrong password.
|
||||
throw new \moodle_exception('cronerrorpassword', 'admin');
|
||||
print_error('cronerrorpassword', 'admin');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Send mime type and encoding.
|
||||
// send mime type and encoding
|
||||
@header('Content-Type: text/plain; charset=utf-8');
|
||||
|
||||
// We do not want html markup in emulated CLI.
|
||||
// we do not want html markup in emulated CLI
|
||||
@ini_set('html_errors', 'off');
|
||||
|
||||
// Execute the cron, disabling keepalive.
|
||||
\core\cron::run_main_process(0);
|
||||
// execute the cron
|
||||
cron_run();
|
||||
|
||||
@@ -41,7 +41,7 @@ $customfieldplugins = core_plugin_manager::instance()->get_plugins_of_type('cust
|
||||
$sortorder = array_flip(array_keys($customfieldplugins));
|
||||
|
||||
if (!isset($customfieldplugins[$customfieldname])) {
|
||||
throw new \moodle_exception('customfieldnotfound', 'error', $return, $customfieldname);
|
||||
print_error('customfieldnotfound', 'error', $return, $customfieldname);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
|
||||
@@ -42,7 +42,7 @@ $plugins = core_plugin_manager::instance()->get_plugins_of_type('dataformat');
|
||||
$sortorder = array_flip(array_keys($plugins));
|
||||
|
||||
if (!isset($plugins[$name])) {
|
||||
throw new \moodle_exception('courseformatnotfound', 'error', $return, $name);
|
||||
print_error('courseformatnotfound', 'error', $return, $name);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
|
||||
+47
-53
@@ -1,95 +1,87 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* A page to manage editor plugins.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* Allows admin to configure editors.
|
||||
*/
|
||||
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/tablelib.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$plugin = required_param('plugin', PARAM_PLUGIN);
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$editor = required_param('editor', PARAM_PLUGIN);
|
||||
$confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
|
||||
$PAGE->set_url('/admin/editors.php', ['action' => $action, 'editor' => $plugin]);
|
||||
$PAGE->set_url('/admin/editors.php', array('action'=>$action, 'editor'=>$editor));
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_sesskey();
|
||||
|
||||
$returnurl = new moodle_url('/admin/settings.php', ['section' => 'manageeditors']);
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageeditors";
|
||||
|
||||
// Get currently installed and enabled auth plugins.
|
||||
$availableeditors = editors_get_available();
|
||||
if (!empty($plugin) && empty($availableeditors[$plugin])) {
|
||||
redirect($returnurl);
|
||||
// get currently installed and enabled auth plugins
|
||||
$available_editors = editors_get_available();
|
||||
if (!empty($editor) and empty($available_editors[$editor])) {
|
||||
redirect ($returnurl);
|
||||
}
|
||||
|
||||
$activeeditors = explode(',', $CFG->texteditors);
|
||||
foreach ($activeeditors as $key => $active) {
|
||||
if (empty($availableeditors[$active])) {
|
||||
unset($activeeditors[$key]);
|
||||
$active_editors = explode(',', $CFG->texteditors);
|
||||
foreach ($active_editors as $key=>$active) {
|
||||
if (empty($available_editors[$active])) {
|
||||
unset($active_editors[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// process actions
|
||||
|
||||
if (!confirm_sesskey()) {
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
$return = true;
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
// Remove from enabled list.
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
|
||||
$class::enable_plugin($plugin, false);
|
||||
$class::enable_plugin($editor, false);
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
// Add to enabled list.
|
||||
if (!in_array($plugin, $activeeditors)) {
|
||||
if (!in_array($editor, $active_editors)) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
|
||||
$class::enable_plugin($plugin, true);
|
||||
$class::enable_plugin($editor, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'down':
|
||||
$key = array_search($plugin, $activeeditors);
|
||||
$key = array_search($editor, $active_editors);
|
||||
// check auth plugin is valid
|
||||
if ($key !== false) {
|
||||
// Move down the list.
|
||||
if ($key < (count($activeeditors) - 1)) {
|
||||
$fsave = $activeeditors[$key];
|
||||
$activeeditors[$key] = $activeeditors[$key + 1];
|
||||
$activeeditors[$key + 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key + 1, $plugin);
|
||||
set_config('texteditors', implode(',', $activeeditors));
|
||||
// move down the list
|
||||
if ($key < (count($active_editors) - 1)) {
|
||||
$fsave = $active_editors[$key];
|
||||
$active_editors[$key] = $active_editors[$key + 1];
|
||||
$active_editors[$key + 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key + 1, $editor);
|
||||
set_config('texteditors', implode(',', $active_editors));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'up':
|
||||
$key = array_search($plugin, $activeeditors);
|
||||
$key = array_search($editor, $active_editors);
|
||||
// check auth is valid
|
||||
if ($key !== false) {
|
||||
// Move up the list.
|
||||
// move up the list
|
||||
if ($key >= 1) {
|
||||
$fsave = $activeeditors[$key];
|
||||
$activeeditors[$key] = $activeeditors[$key - 1];
|
||||
$activeeditors[$key - 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key - 1, $plugin);
|
||||
set_config('texteditors', implode(',', $activeeditors));
|
||||
$fsave = $active_editors[$key];
|
||||
$active_editors[$key] = $active_editors[$key - 1];
|
||||
$active_editors[$key - 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key - 1, $editor);
|
||||
set_config('texteditors', implode(',', $active_editors));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
}
|
||||
@@ -99,4 +91,6 @@ switch ($action) {
|
||||
break;
|
||||
}
|
||||
|
||||
redirect($returnurl);
|
||||
if ($return) {
|
||||
redirect ($returnurl);
|
||||
}
|
||||
|
||||
@@ -55,11 +55,11 @@ if ($action == 'updatecomponent' && confirm_sesskey()) {
|
||||
$a = new stdClass();
|
||||
$a->url = 'https://download.moodle.org/environment/environment.zip';
|
||||
$a->dest = $CFG->dataroot . '/';
|
||||
throw new \moodle_exception($cd->get_error(), 'error', $PAGE->url, $a);
|
||||
print_error($cd->get_error(), 'error', $PAGE->url, $a);
|
||||
die();
|
||||
|
||||
} else {
|
||||
throw new \moodle_exception($cd->get_error(), 'error', $PAGE->url);
|
||||
print_error($cd->get_error(), 'error', $PAGE->url);
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
@@ -3371,7 +3371,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.3.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -3558,7 +3557,6 @@
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.3.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -3751,7 +3749,6 @@
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="7.4.0" level="required">
|
||||
<RESTRICT function="restrict_php_version_82" message="unsupportedphpversion82" />
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
@@ -3925,575 +3922,4 @@
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.2" requires="3.11.8">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.6.7" />
|
||||
<VENDOR name="mysql" version="8.0" />
|
||||
<VENDOR name="postgres" version="13" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="8.0.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="required"/>
|
||||
<PHP_EXTENSION name="exif" level="optional"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="sixtyfourbitsrequired" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="iscustomadminwarnings" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.3" requires="3.11.8">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.6.7" />
|
||||
<VENDOR name="mysql" version="8.0" />
|
||||
<VENDOR name="postgres" version="13" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="8.0.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="required"/>
|
||||
<PHP_EXTENSION name="exif" level="optional"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="sixtyfourbitsrequired" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="iscustomadminwarnings" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_db_prefix_length" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="4.4" requires="4.1.2">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.6.7" />
|
||||
<VENDOR name="mysql" version="8.0" />
|
||||
<VENDOR name="postgres" version="13" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="19" />
|
||||
</DATABASE>
|
||||
<PHP version="8.1.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="required"/>
|
||||
<PHP_EXTENSION name="exif" level="optional"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="sixtyfourbitsrequired" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="iscustomadminwarnings" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_db_prefix_length" level="required">
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<?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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Hooks overview page.
|
||||
*
|
||||
* @package core
|
||||
* @author Petr Skoda
|
||||
* @copyright 2022 Open LMS
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/tablelib.php');
|
||||
|
||||
admin_externalpage_setup('hooksoverview');
|
||||
require_capability('moodle/site:config', \core\context\system::instance());
|
||||
|
||||
$hookmanager = \core\hook\manager::get_instance();
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('hooksoverview', 'core_admin'));
|
||||
|
||||
$table = new \core_admin\table\hook_list_table();
|
||||
$table->out();
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
+325
-334
@@ -174,17 +174,15 @@ $documentationlink = '<a href="http://docs.moodle.org/en/Installation">Installat
|
||||
// Check some PHP server settings
|
||||
|
||||
if (ini_get_bool('session.auto_start')) {
|
||||
throw new \moodle_exception('phpvaroff', 'debug', '',
|
||||
(object)array('name' => 'session.auto_start', 'link' => $documentationlink));
|
||||
print_error('phpvaroff', 'debug', '', (object)array('name'=>'session.auto_start', 'link'=>$documentationlink));
|
||||
}
|
||||
|
||||
if (!ini_get_bool('file_uploads')) {
|
||||
throw new \moodle_exception('phpvaron', 'debug', '',
|
||||
(object)array('name' => 'file_uploads', 'link' => $documentationlink));
|
||||
print_error('phpvaron', 'debug', '', (object)array('name'=>'file_uploads', 'link'=>$documentationlink));
|
||||
}
|
||||
|
||||
if (is_float_problem()) {
|
||||
throw new \moodle_exception('phpfloatproblem', 'admin', '', $documentationlink);
|
||||
print_error('phpfloatproblem', 'admin', '', $documentationlink);
|
||||
}
|
||||
|
||||
// Set some necessary variables during set-up to avoid PHP warnings later on this page
|
||||
@@ -205,7 +203,7 @@ require("$CFG->dirroot/version.php"); // defines $version, $release, $bran
|
||||
$CFG->target_release = $release; // used during installation and upgrades
|
||||
|
||||
if (!$version or !$release) {
|
||||
throw new \moodle_exception('withoutversion', 'debug'); // Without version, stop.
|
||||
print_error('withoutversion', 'debug'); // without version, stop
|
||||
}
|
||||
|
||||
if (!core_tables_exist()) {
|
||||
@@ -224,7 +222,7 @@ if (!core_tables_exist()) {
|
||||
$strlicense = get_string('license');
|
||||
|
||||
$PAGE->navbar->add($strlicense);
|
||||
$PAGE->set_title($strinstallation . moodle_page::TITLE_SEPARATOR . 'Moodle ' . $CFG->target_release, false);
|
||||
$PAGE->set_title($strinstallation.' - Moodle '.$CFG->target_release);
|
||||
$PAGE->set_heading($strinstallation);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
@@ -267,7 +265,7 @@ if (!core_tables_exist()) {
|
||||
upgrade_init_javascript();
|
||||
|
||||
$PAGE->navbar->add($strdatabasesetup);
|
||||
$PAGE->set_title($strinstallation . moodle_page::TITLE_SEPARATOR . $CFG->target_release, false);
|
||||
$PAGE->set_title($strinstallation.' - Moodle '.$CFG->target_release);
|
||||
$PAGE->set_heading($strinstallation);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
@@ -277,7 +275,7 @@ if (!core_tables_exist()) {
|
||||
if (!$DB->setup_is_unicodedb()) {
|
||||
if (!$DB->change_db_encoding()) {
|
||||
// If could not convert successfully, throw error, and prevent installation
|
||||
throw new \moodle_exception('unicoderequired', 'admin');
|
||||
print_error('unicoderequired', 'admin');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,80 +297,265 @@ $stradministration = get_string('administration');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
if (empty($CFG->version)) {
|
||||
throw new \moodle_exception('missingconfigversion', 'debug');
|
||||
print_error('missingconfigversion', 'debug');
|
||||
}
|
||||
|
||||
// If an upgrade is running, an admin page starting a frontend upgrade could corrupt the
|
||||
// DB if the upgrade collided with an already running upgrade process at the wrong time.
|
||||
// Pull the value direct from the DB, this needs to *always* be correct.
|
||||
$outagelessupgrade = !empty($DB->get_field('config', 'value', ['name' => 'outagelessupgrade']));
|
||||
if (!$outagelessupgrade) {
|
||||
// Detect config cache inconsistency, this happens when you switch branches on dev servers.
|
||||
if ($CFG->version != $DB->get_field('config', 'value', array('name' => 'version'))) {
|
||||
purge_all_caches();
|
||||
redirect(new moodle_url($PAGE->url), 'Config cache inconsistency detected, resetting caches...');
|
||||
// Detect config cache inconsistency, this happens when you switch branches on dev servers.
|
||||
if ($CFG->version != $DB->get_field('config', 'value', array('name'=>'version'))) {
|
||||
purge_all_caches();
|
||||
redirect(new moodle_url($PAGE->url), 'Config cache inconsistency detected, resetting caches...');
|
||||
}
|
||||
|
||||
if (!$cache and $version > $CFG->version) { // upgrade
|
||||
|
||||
$PAGE->set_url(new moodle_url($PAGE->url, array(
|
||||
'confirmupgrade' => $confirmupgrade,
|
||||
'confirmrelease' => $confirmrelease,
|
||||
'confirmplugincheck' => $confirmplugins,
|
||||
)));
|
||||
|
||||
check_upgrade_key($upgradekeyhash);
|
||||
|
||||
// Warning about upgrading a test site.
|
||||
$testsite = false;
|
||||
if (defined('BEHAT_SITE_RUNNING')) {
|
||||
$testsite = 'behat';
|
||||
}
|
||||
|
||||
if (!$cache && $version > $CFG->version && !$outagelessupgrade) { // Upgrade.
|
||||
if (isset($CFG->themerev)) {
|
||||
// Store the themerev to restore after purging caches.
|
||||
$themerev = $CFG->themerev;
|
||||
}
|
||||
|
||||
$PAGE->set_url(new moodle_url($PAGE->url, array(
|
||||
'confirmupgrade' => $confirmupgrade,
|
||||
'confirmrelease' => $confirmrelease,
|
||||
'confirmplugincheck' => $confirmplugins,
|
||||
)));
|
||||
// We purge all of MUC's caches here.
|
||||
// Caches are disabled for upgrade by CACHE_DISABLE_ALL so we must set the first arg to true.
|
||||
// This ensures a real config object is loaded and the stores will be purged.
|
||||
// This is the only way we can purge custom caches such as memcache or APC.
|
||||
// Note: all other calls to caches will still used the disabled API.
|
||||
cache_helper::purge_all(true);
|
||||
// We then purge the regular caches.
|
||||
purge_all_caches();
|
||||
|
||||
check_upgrade_key($upgradekeyhash);
|
||||
if (isset($themerev)) {
|
||||
// Restore the themerev
|
||||
set_config('themerev', $themerev);
|
||||
}
|
||||
|
||||
// Warning about upgrading a test site.
|
||||
$testsite = false;
|
||||
if (defined('BEHAT_SITE_RUNNING')) {
|
||||
$testsite = 'behat';
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
|
||||
if (upgrade_stale_php_files_present()) {
|
||||
$PAGE->set_title($stradministration);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
echo $output->upgrade_stale_php_files_page();
|
||||
die();
|
||||
}
|
||||
|
||||
if (empty($confirmupgrade)) {
|
||||
$a = new stdClass();
|
||||
$a->oldversion = "$CFG->release (".sprintf('%.2f', $CFG->version).")";
|
||||
$a->newversion = "$release (".sprintf('%.2f', $version).")";
|
||||
$strdatabasechecking = get_string('databasechecking', '', $a);
|
||||
|
||||
$PAGE->set_title($stradministration);
|
||||
$PAGE->set_heading($strdatabasechecking);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite);
|
||||
die();
|
||||
|
||||
} else if (empty($confirmrelease)) {
|
||||
require_once($CFG->libdir.'/environmentlib.php');
|
||||
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
|
||||
$strcurrentrelease = get_string('currentrelease');
|
||||
|
||||
$PAGE->navbar->add($strcurrentrelease);
|
||||
$PAGE->set_title($strcurrentrelease);
|
||||
$PAGE->set_heading($strcurrentrelease);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
|
||||
die();
|
||||
|
||||
} else if (empty($confirmplugins)) {
|
||||
$strplugincheck = get_string('plugincheck');
|
||||
|
||||
$PAGE->navbar->add($strplugincheck);
|
||||
$PAGE->set_title($strplugincheck);
|
||||
$PAGE->set_heading($strplugincheck);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
|
||||
// Check for available updates.
|
||||
if ($fetchupdates) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
$updateschecker = \core\update\checker::instance();
|
||||
if ($updateschecker->enabled()) {
|
||||
$updateschecker->fetch();
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
|
||||
if (isset($CFG->themerev)) {
|
||||
// Store the themerev to restore after purging caches.
|
||||
$themerev = $CFG->themerev;
|
||||
// Cancel all plugin installations.
|
||||
if ($abortinstallx) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
$abortables = $pluginman->list_cancellable_installations();
|
||||
if ($abortables) {
|
||||
if ($confirmabortinstall) {
|
||||
foreach ($abortables as $plugin) {
|
||||
$pluginman->cancel_plugin_installation($plugin->component);
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
} else {
|
||||
$continue = new moodle_url($PAGE->url, array('abortinstallx' => $abortinstallx, 'confirmabortinstall' => 1));
|
||||
echo $output->upgrade_confirm_abort_install_page($abortables, $continue);
|
||||
die();
|
||||
}
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
|
||||
// We purge all of MUC's caches here.
|
||||
// Caches are disabled for upgrade by CACHE_DISABLE_ALL so we must set the first arg to true.
|
||||
// This ensures a real config object is loaded and the stores will be purged.
|
||||
// This is the only way we can purge custom caches such as memcache or APC.
|
||||
// Note: all other calls to caches will still used the disabled API.
|
||||
cache_helper::purge_all(true);
|
||||
// We then purge the regular caches.
|
||||
purge_all_caches();
|
||||
|
||||
if (isset($themerev)) {
|
||||
// Restore the themerev.
|
||||
set_config('themerev', $themerev);
|
||||
// Cancel single plugin installation.
|
||||
if ($abortinstall) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
if ($confirmabortinstall) {
|
||||
$pluginman->cancel_plugin_installation($abortinstall);
|
||||
redirect($PAGE->url);
|
||||
} else {
|
||||
$continue = new moodle_url($PAGE->url, array('abortinstall' => $abortinstall, 'confirmabortinstall' => 1));
|
||||
$abortable = $pluginman->get_plugin_info($abortinstall);
|
||||
if ($pluginman->can_cancel_plugin_installation($abortable)) {
|
||||
echo $output->upgrade_confirm_abort_install_page(array($abortable), $continue);
|
||||
die();
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel all plugins upgrades (that is, restore archived versions).
|
||||
if ($abortupgradex) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
$restorable = $pluginman->list_restorable_archives();
|
||||
if ($restorable) {
|
||||
upgrade_install_plugins($restorable, $confirmabortupgrade,
|
||||
get_string('cancelupgradehead', 'core_plugin'),
|
||||
new moodle_url($PAGE->url, array('abortupgradex' => 1, 'confirmabortupgrade' => 1))
|
||||
);
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
|
||||
// Cancel single plugin upgrade (that is, install the archived version).
|
||||
if ($abortupgrade) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
$restorable = $pluginman->list_restorable_archives();
|
||||
if (isset($restorable[$abortupgrade])) {
|
||||
$restorable = array($restorable[$abortupgrade]);
|
||||
upgrade_install_plugins($restorable, $confirmabortupgrade,
|
||||
get_string('cancelupgradehead', 'core_plugin'),
|
||||
new moodle_url($PAGE->url, array('abortupgrade' => $abortupgrade, 'confirmabortupgrade' => 1))
|
||||
);
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
|
||||
// Install all available missing dependencies.
|
||||
if ($installdepx) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
$installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
|
||||
upgrade_install_plugins($installable, $confirminstalldep,
|
||||
get_string('dependencyinstallhead', 'core_plugin'),
|
||||
new moodle_url($PAGE->url, array('installdepx' => 1, 'confirminstalldep' => 1))
|
||||
);
|
||||
}
|
||||
|
||||
// Install single available missing dependency.
|
||||
if ($installdep) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
$installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
|
||||
if (!empty($installable[$installdep])) {
|
||||
$installable = array($installable[$installdep]);
|
||||
upgrade_install_plugins($installable, $confirminstalldep,
|
||||
get_string('dependencyinstallhead', 'core_plugin'),
|
||||
new moodle_url($PAGE->url, array('installdep' => $installdep, 'confirminstalldep' => 1))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Install all available updates.
|
||||
if ($installupdatex) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
$installable = $pluginman->filter_installable($pluginman->available_updates());
|
||||
upgrade_install_plugins($installable, $confirminstallupdate,
|
||||
get_string('updateavailableinstallallhead', 'core_admin'),
|
||||
new moodle_url($PAGE->url, array('installupdatex' => 1, 'confirminstallupdate' => 1))
|
||||
);
|
||||
}
|
||||
|
||||
// Install single available update.
|
||||
if ($installupdate and $installupdateversion) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
if ($pluginman->is_remote_plugin_installable($installupdate, $installupdateversion)) {
|
||||
$installable = array($pluginman->get_remote_plugin_info($installupdate, $installupdateversion, true));
|
||||
upgrade_install_plugins($installable, $confirminstallupdate,
|
||||
get_string('updateavailableinstallallhead', 'core_admin'),
|
||||
new moodle_url($PAGE->url, array('installupdate' => $installupdate,
|
||||
'installupdateversion' => $installupdateversion, 'confirminstallupdate' => 1)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
echo $output->upgrade_plugin_check_page(core_plugin_manager::instance(), \core\update\checker::instance(),
|
||||
$version, $showallplugins, $PAGE->url, new moodle_url($PAGE->url, array('confirmplugincheck' => 1)));
|
||||
die();
|
||||
|
||||
} else {
|
||||
// Always verify plugin dependencies!
|
||||
$failed = array();
|
||||
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
|
||||
array('confirmplugincheck' => 0)));
|
||||
die();
|
||||
}
|
||||
unset($failed);
|
||||
|
||||
// Launch main upgrade.
|
||||
upgrade_core($version, true);
|
||||
}
|
||||
} else if ($version < $CFG->version) {
|
||||
// better stop here, we can not continue with plugin upgrades or anything else
|
||||
throw new moodle_exception('downgradedcore', 'error', new moodle_url('/admin/'));
|
||||
}
|
||||
|
||||
// Updated human-readable release version if necessary
|
||||
if (!$cache and $release <> $CFG->release) { // Update the release version
|
||||
set_config('release', $release);
|
||||
}
|
||||
|
||||
if (!$cache and $branch <> $CFG->branch) { // Update the branch
|
||||
set_config('branch', $branch);
|
||||
}
|
||||
|
||||
if (!$cache and moodle_needs_upgrading()) {
|
||||
|
||||
$PAGE->set_url(new moodle_url($PAGE->url, array(
|
||||
'confirmrelease' => $confirmrelease,
|
||||
'confirmplugincheck' => $confirmplugins,
|
||||
)));
|
||||
|
||||
check_upgrade_key($upgradekeyhash);
|
||||
|
||||
if (!$PAGE->headerprinted) {
|
||||
// means core upgrade or installation was not already done
|
||||
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
|
||||
if (upgrade_stale_php_files_present()) {
|
||||
$PAGE->set_title($stradministration);
|
||||
$PAGE->set_cacheable(false);
|
||||
if (empty($confirmrelease)) {
|
||||
require_once($CFG->libdir . '/environmentlib.php');
|
||||
|
||||
echo $output->upgrade_stale_php_files_page();
|
||||
die();
|
||||
}
|
||||
|
||||
if (empty($confirmupgrade)) {
|
||||
$a = new stdClass();
|
||||
$a->oldversion = "$CFG->release (".sprintf('%.2f', $CFG->version).")";
|
||||
$a->newversion = "$release (".sprintf('%.2f', $version).")";
|
||||
$strdatabasechecking = get_string('databasechecking', '', $a);
|
||||
|
||||
$PAGE->set_title($stradministration);
|
||||
$PAGE->set_heading($strdatabasechecking);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite);
|
||||
die();
|
||||
|
||||
} else if (empty($confirmrelease)) {
|
||||
require_once($CFG->libdir.'/environmentlib.php');
|
||||
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
|
||||
$strcurrentrelease = get_string('currentrelease');
|
||||
|
||||
@@ -384,7 +567,7 @@ if (!$outagelessupgrade) {
|
||||
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
|
||||
die();
|
||||
|
||||
} else if (empty($confirmplugins)) {
|
||||
} else if (!$confirmplugins) {
|
||||
$strplugincheck = get_string('plugincheck');
|
||||
|
||||
$PAGE->navbar->add($strplugincheck);
|
||||
@@ -392,11 +575,9 @@ if (!$outagelessupgrade) {
|
||||
$PAGE->set_heading($strplugincheck);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
|
||||
// Check for available updates.
|
||||
if ($fetchupdates) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
require_sesskey();
|
||||
$updateschecker = \core\update\checker::instance();
|
||||
if ($updateschecker->enabled()) {
|
||||
$updateschecker->fetch();
|
||||
@@ -406,7 +587,7 @@ if (!$outagelessupgrade) {
|
||||
|
||||
// Cancel all plugin installations.
|
||||
if ($abortinstallx) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
require_sesskey();
|
||||
$abortables = $pluginman->list_cancellable_installations();
|
||||
if ($abortables) {
|
||||
if ($confirmabortinstall) {
|
||||
@@ -415,7 +596,8 @@ if (!$outagelessupgrade) {
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
} else {
|
||||
$continue = new moodle_url($PAGE->url, ['abortinstallx' => $abortinstallx, 'confirmabortinstall' => 1]);
|
||||
$continue = new moodle_url($PAGE->url, array('abortinstallx' => $abortinstallx,
|
||||
'confirmabortinstall' => 1));
|
||||
echo $output->upgrade_confirm_abort_install_page($abortables, $continue);
|
||||
die();
|
||||
}
|
||||
@@ -425,7 +607,7 @@ if (!$outagelessupgrade) {
|
||||
|
||||
// Cancel single plugin installation.
|
||||
if ($abortinstall) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
require_sesskey();
|
||||
if ($confirmabortinstall) {
|
||||
$pluginman->cancel_plugin_installation($abortinstall);
|
||||
redirect($PAGE->url);
|
||||
@@ -442,7 +624,7 @@ if (!$outagelessupgrade) {
|
||||
|
||||
// Cancel all plugins upgrades (that is, restore archived versions).
|
||||
if ($abortupgradex) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
require_sesskey();
|
||||
$restorable = $pluginman->list_restorable_archives();
|
||||
if ($restorable) {
|
||||
upgrade_install_plugins($restorable, $confirmabortupgrade,
|
||||
@@ -455,7 +637,7 @@ if (!$outagelessupgrade) {
|
||||
|
||||
// Cancel single plugin upgrade (that is, install the archived version).
|
||||
if ($abortupgrade) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
require_sesskey();
|
||||
$restorable = $pluginman->list_restorable_archives();
|
||||
if (isset($restorable[$abortupgrade])) {
|
||||
$restorable = array($restorable[$abortupgrade]);
|
||||
@@ -469,7 +651,7 @@ if (!$outagelessupgrade) {
|
||||
|
||||
// Install all available missing dependencies.
|
||||
if ($installdepx) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
require_sesskey();
|
||||
$installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
|
||||
upgrade_install_plugins($installable, $confirminstalldep,
|
||||
get_string('dependencyinstallhead', 'core_plugin'),
|
||||
@@ -479,7 +661,7 @@ if (!$outagelessupgrade) {
|
||||
|
||||
// Install single available missing dependency.
|
||||
if ($installdep) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
require_sesskey();
|
||||
$installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
|
||||
if (!empty($installable[$installdep])) {
|
||||
$installable = array($installable[$installdep]);
|
||||
@@ -492,7 +674,7 @@ if (!$outagelessupgrade) {
|
||||
|
||||
// Install all available updates.
|
||||
if ($installupdatex) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
require_sesskey();
|
||||
$installable = $pluginman->filter_installable($pluginman->available_updates());
|
||||
upgrade_install_plugins($installable, $confirminstallupdate,
|
||||
get_string('updateavailableinstallallhead', 'core_admin'),
|
||||
@@ -502,7 +684,7 @@ if (!$outagelessupgrade) {
|
||||
|
||||
// Install single available update.
|
||||
if ($installupdate and $installupdateversion) {
|
||||
// No sesskey support guaranteed here, because sessions might not work yet.
|
||||
require_sesskey();
|
||||
if ($pluginman->is_remote_plugin_installable($installupdate, $installupdateversion)) {
|
||||
$installable = array($pluginman->get_remote_plugin_info($installupdate, $installupdateversion, true));
|
||||
upgrade_install_plugins($installable, $confirminstallupdate,
|
||||
@@ -514,280 +696,89 @@ if (!$outagelessupgrade) {
|
||||
}
|
||||
}
|
||||
|
||||
echo $output->upgrade_plugin_check_page(core_plugin_manager::instance(), \core\update\checker::instance(),
|
||||
$version, $showallplugins, $PAGE->url, new moodle_url($PAGE->url, array('confirmplugincheck' => 1)));
|
||||
// Show plugins info.
|
||||
echo $output->upgrade_plugin_check_page($pluginman, \core\update\checker::instance(),
|
||||
$version, $showallplugins,
|
||||
new moodle_url($PAGE->url),
|
||||
new moodle_url($PAGE->url, array('confirmplugincheck' => 1, 'cache' => 0)));
|
||||
die();
|
||||
|
||||
} else {
|
||||
// Always verify plugin dependencies!
|
||||
$failed = array();
|
||||
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
|
||||
array('confirmplugincheck' => 0)));
|
||||
die();
|
||||
}
|
||||
unset($failed);
|
||||
|
||||
// Launch main upgrade.
|
||||
upgrade_core($version, true);
|
||||
}
|
||||
} else if ($version < $CFG->version) {
|
||||
// Better stop here, we can not continue with plugin upgrades or anything else.
|
||||
throw new moodle_exception('downgradedcore', 'error', new moodle_url('/admin/'));
|
||||
}
|
||||
|
||||
// Updated human-readable release version if necessary.
|
||||
if (!$cache && $release <> $CFG->release ) { // Update the release version.
|
||||
set_config('release', $release);
|
||||
}
|
||||
|
||||
if (!$cache && $branch <> $CFG->branch) { // Update the branch.
|
||||
set_config('branch', $branch);
|
||||
}
|
||||
|
||||
if (!$cache && moodle_needs_upgrading()) {
|
||||
|
||||
$PAGE->set_url(new moodle_url($PAGE->url, array(
|
||||
'confirmrelease' => $confirmrelease,
|
||||
'confirmplugincheck' => $confirmplugins,
|
||||
)));
|
||||
|
||||
check_upgrade_key($upgradekeyhash);
|
||||
|
||||
if (!$PAGE->headerprinted) {
|
||||
// Means core upgrade or installation was not already done.
|
||||
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
// Make sure plugin dependencies are always checked.
|
||||
$failed = array();
|
||||
if (!$pluginman->all_plugins_ok($version, $failed, $CFG->branch)) {
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
|
||||
if (empty($confirmrelease)) {
|
||||
require_once($CFG->libdir . '/environmentlib.php');
|
||||
|
||||
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
|
||||
$strcurrentrelease = get_string('currentrelease');
|
||||
|
||||
$PAGE->navbar->add($strcurrentrelease);
|
||||
$PAGE->set_title($strcurrentrelease);
|
||||
$PAGE->set_heading($strcurrentrelease);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
|
||||
die();
|
||||
|
||||
} else if (!$confirmplugins) {
|
||||
$strplugincheck = get_string('plugincheck');
|
||||
|
||||
$PAGE->navbar->add($strplugincheck);
|
||||
$PAGE->set_title($strplugincheck);
|
||||
$PAGE->set_heading($strplugincheck);
|
||||
$PAGE->set_cacheable(false);
|
||||
|
||||
// Check for available updates.
|
||||
if ($fetchupdates) {
|
||||
require_sesskey();
|
||||
$updateschecker = \core\update\checker::instance();
|
||||
if ($updateschecker->enabled()) {
|
||||
$updateschecker->fetch();
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
|
||||
// Cancel all plugin installations.
|
||||
if ($abortinstallx) {
|
||||
require_sesskey();
|
||||
$abortables = $pluginman->list_cancellable_installations();
|
||||
if ($abortables) {
|
||||
if ($confirmabortinstall) {
|
||||
foreach ($abortables as $plugin) {
|
||||
$pluginman->cancel_plugin_installation($plugin->component);
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
} else {
|
||||
$continue = new moodle_url($PAGE->url, array('abortinstallx' => $abortinstallx,
|
||||
'confirmabortinstall' => 1));
|
||||
echo $output->upgrade_confirm_abort_install_page($abortables, $continue);
|
||||
die();
|
||||
}
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
|
||||
// Cancel single plugin installation.
|
||||
if ($abortinstall) {
|
||||
require_sesskey();
|
||||
if ($confirmabortinstall) {
|
||||
$pluginman->cancel_plugin_installation($abortinstall);
|
||||
redirect($PAGE->url);
|
||||
} else {
|
||||
$continue = new moodle_url($PAGE->url, array('abortinstall' => $abortinstall, 'confirmabortinstall' => 1));
|
||||
$abortable = $pluginman->get_plugin_info($abortinstall);
|
||||
if ($pluginman->can_cancel_plugin_installation($abortable)) {
|
||||
echo $output->upgrade_confirm_abort_install_page(array($abortable), $continue);
|
||||
die();
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel all plugins upgrades (that is, restore archived versions).
|
||||
if ($abortupgradex) {
|
||||
require_sesskey();
|
||||
$restorable = $pluginman->list_restorable_archives();
|
||||
if ($restorable) {
|
||||
upgrade_install_plugins($restorable, $confirmabortupgrade,
|
||||
get_string('cancelupgradehead', 'core_plugin'),
|
||||
new moodle_url($PAGE->url, array('abortupgradex' => 1, 'confirmabortupgrade' => 1))
|
||||
);
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
|
||||
// Cancel single plugin upgrade (that is, install the archived version).
|
||||
if ($abortupgrade) {
|
||||
require_sesskey();
|
||||
$restorable = $pluginman->list_restorable_archives();
|
||||
if (isset($restorable[$abortupgrade])) {
|
||||
$restorable = array($restorable[$abortupgrade]);
|
||||
upgrade_install_plugins($restorable, $confirmabortupgrade,
|
||||
get_string('cancelupgradehead', 'core_plugin'),
|
||||
new moodle_url($PAGE->url, array('abortupgrade' => $abortupgrade, 'confirmabortupgrade' => 1))
|
||||
);
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
|
||||
// Install all available missing dependencies.
|
||||
if ($installdepx) {
|
||||
require_sesskey();
|
||||
$installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
|
||||
upgrade_install_plugins($installable, $confirminstalldep,
|
||||
get_string('dependencyinstallhead', 'core_plugin'),
|
||||
new moodle_url($PAGE->url, array('installdepx' => 1, 'confirminstalldep' => 1))
|
||||
);
|
||||
}
|
||||
|
||||
// Install single available missing dependency.
|
||||
if ($installdep) {
|
||||
require_sesskey();
|
||||
$installable = $pluginman->filter_installable($pluginman->missing_dependencies(true));
|
||||
if (!empty($installable[$installdep])) {
|
||||
$installable = array($installable[$installdep]);
|
||||
upgrade_install_plugins($installable, $confirminstalldep,
|
||||
get_string('dependencyinstallhead', 'core_plugin'),
|
||||
new moodle_url($PAGE->url, array('installdep' => $installdep, 'confirminstalldep' => 1))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Install all available updates.
|
||||
if ($installupdatex) {
|
||||
require_sesskey();
|
||||
$installable = $pluginman->filter_installable($pluginman->available_updates());
|
||||
upgrade_install_plugins($installable, $confirminstallupdate,
|
||||
get_string('updateavailableinstallallhead', 'core_admin'),
|
||||
new moodle_url($PAGE->url, array('installupdatex' => 1, 'confirminstallupdate' => 1))
|
||||
);
|
||||
}
|
||||
|
||||
// Install single available update.
|
||||
if ($installupdate && $installupdateversion) {
|
||||
require_sesskey();
|
||||
if ($pluginman->is_remote_plugin_installable($installupdate, $installupdateversion)) {
|
||||
$installable = array($pluginman->get_remote_plugin_info($installupdate, $installupdateversion, true));
|
||||
upgrade_install_plugins($installable, $confirminstallupdate,
|
||||
get_string('updateavailableinstallallhead', 'core_admin'),
|
||||
new moodle_url($PAGE->url, array('installupdate' => $installupdate,
|
||||
'installupdateversion' => $installupdateversion, 'confirminstallupdate' => 1)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Show plugins info.
|
||||
echo $output->upgrade_plugin_check_page($pluginman, \core\update\checker::instance(),
|
||||
$version, $showallplugins,
|
||||
new moodle_url($PAGE->url),
|
||||
new moodle_url($PAGE->url, array('confirmplugincheck' => 1, 'cache' => 0)));
|
||||
die();
|
||||
}
|
||||
|
||||
// Make sure plugin dependencies are always checked.
|
||||
$failed = array();
|
||||
if (!$pluginman->all_plugins_ok($version, $failed, $CFG->branch)) {
|
||||
$output = $PAGE->get_renderer('core', 'admin');
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
|
||||
array('confirmplugincheck' => 0)));
|
||||
die();
|
||||
}
|
||||
unset($failed);
|
||||
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
|
||||
array('confirmplugincheck' => 0)));
|
||||
die();
|
||||
}
|
||||
|
||||
// Install/upgrade all plugins and other parts.
|
||||
upgrade_noncore(true);
|
||||
unset($failed);
|
||||
}
|
||||
|
||||
// If this is the first install, indicate that this site is fully configured,
|
||||
// Except the admin password.
|
||||
if (during_initial_install()) {
|
||||
set_config('rolesactive', 1); // After this, during_initial_install will return false.
|
||||
set_config('adminsetuppending', 1);
|
||||
set_config('registrationpending', 1); // Remind to register site after all other setup is finished.
|
||||
// install/upgrade all plugins and other parts
|
||||
upgrade_noncore(true);
|
||||
}
|
||||
|
||||
// Apply default preset, if it is defined in $CFG and has a valid value.
|
||||
if (!empty($CFG->setsitepresetduringinstall)) {
|
||||
\core_adminpresets\helper::change_default_preset($CFG->setsitepresetduringinstall);
|
||||
}
|
||||
// If this is the first install, indicate that this site is fully configured
|
||||
// except the admin password
|
||||
if (during_initial_install()) {
|
||||
set_config('rolesactive', 1); // after this, during_initial_install will return false.
|
||||
set_config('adminsetuppending', 1);
|
||||
set_config('registrationpending', 1); // Remind to register site after all other setup is finished.
|
||||
|
||||
// We need this redirect to setup proper session.
|
||||
upgrade_finished("index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
// Apply default preset, if it is defined in $CFG and has a valid value.
|
||||
if (!empty($CFG->setsitepresetduringinstall)) {
|
||||
\core_adminpresets\helper::change_default_preset($CFG->setsitepresetduringinstall);
|
||||
}
|
||||
|
||||
// Make sure admin user is created - this is the last step,
|
||||
// We need session to be working properly in order to edit admin account.
|
||||
if (!empty($CFG->adminsetuppending)) {
|
||||
$sessionstarted = optional_param('sessionstarted', 0, PARAM_BOOL);
|
||||
if (!$sessionstarted) {
|
||||
redirect("index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
// we need this redirect to setup proper session
|
||||
upgrade_finished("index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
}
|
||||
|
||||
// make sure admin user is created - this is the last step because we need
|
||||
// session to be working properly in order to edit admin account
|
||||
if (!empty($CFG->adminsetuppending)) {
|
||||
$sessionstarted = optional_param('sessionstarted', 0, PARAM_BOOL);
|
||||
if (!$sessionstarted) {
|
||||
redirect("index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
} else {
|
||||
$sessionverify = optional_param('sessionverify', 0, PARAM_BOOL);
|
||||
if (!$sessionverify) {
|
||||
$SESSION->sessionverify = 1;
|
||||
redirect("index.php?sessionstarted=1&sessionverify=1&lang=$CFG->lang");
|
||||
} else {
|
||||
$sessionverify = optional_param('sessionverify', 0, PARAM_BOOL);
|
||||
if (!$sessionverify) {
|
||||
$SESSION->sessionverify = 1;
|
||||
redirect("index.php?sessionstarted=1&sessionverify=1&lang=$CFG->lang");
|
||||
} else {
|
||||
if (empty($SESSION->sessionverify)) {
|
||||
throw new \moodle_exception('installsessionerror', 'admin', "index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
}
|
||||
unset($SESSION->sessionverify);
|
||||
if (empty($SESSION->sessionverify)) {
|
||||
print_error('installsessionerror', 'admin', "index.php?sessionstarted=1&lang=$CFG->lang");
|
||||
}
|
||||
unset($SESSION->sessionverify);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup SESSION to make sure other code does not complain in the future.
|
||||
unset($SESSION->has_timed_out);
|
||||
unset($SESSION->wantsurl);
|
||||
// Cleanup SESSION to make sure other code does not complain in the future.
|
||||
unset($SESSION->has_timed_out);
|
||||
unset($SESSION->wantsurl);
|
||||
|
||||
// At this stage there can be only one admin unless more were added by install,
|
||||
// Users may change username, so do not rely on that.
|
||||
$adminids = explode(',', $CFG->siteadmins);
|
||||
$adminuser = get_complete_user_data('id', reset($adminids));
|
||||
// at this stage there can be only one admin unless more were added by install - users may change username, so do not rely on that
|
||||
$adminids = explode(',', $CFG->siteadmins);
|
||||
$adminuser = get_complete_user_data('id', reset($adminids));
|
||||
|
||||
if ($adminuser->password === 'adminsetuppending') {
|
||||
// Prevent installation hijacking.
|
||||
if ($adminuser->lastip !== getremoteaddr()) {
|
||||
throw new \moodle_exception('installhijacked', 'admin');
|
||||
}
|
||||
// Login user and let him set password and admin details.
|
||||
$adminuser->newadminuser = 1;
|
||||
complete_user_login($adminuser);
|
||||
redirect("$CFG->wwwroot/user/editadvanced.php?id=$adminuser->id"); // Edit thyself.
|
||||
|
||||
} else {
|
||||
unset_config('adminsetuppending');
|
||||
if ($adminuser->password === 'adminsetuppending') {
|
||||
// prevent installation hijacking
|
||||
if ($adminuser->lastip !== getremoteaddr()) {
|
||||
print_error('installhijacked', 'admin');
|
||||
}
|
||||
// login user and let him set password and admin details
|
||||
$adminuser->newadminuser = 1;
|
||||
complete_user_login($adminuser);
|
||||
redirect("$CFG->wwwroot/user/editadvanced.php?id=$adminuser->id"); // Edit thyself
|
||||
|
||||
} else {
|
||||
// Just make sure upgrade logging is properly terminated.
|
||||
upgrade_finished('upgradesettings.php');
|
||||
unset_config('adminsetuppending');
|
||||
}
|
||||
|
||||
} else {
|
||||
// just make sure upgrade logging is properly terminated
|
||||
upgrade_finished('upgradesettings.php');
|
||||
}
|
||||
|
||||
if (has_capability('moodle/site:config', context_system::instance())) {
|
||||
@@ -818,7 +809,7 @@ $context = context_system::instance();
|
||||
|
||||
if (!has_capability('moodle/site:config', $context)) {
|
||||
// Do not throw exception display an empty page with administration menu if visible for current user.
|
||||
$PAGE->set_title(get_string('home'));
|
||||
$PAGE->set_title($SITE->fullname);
|
||||
$PAGE->set_heading($SITE->fullname);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
+9
-5
@@ -55,7 +55,7 @@ function admin_page_type_list($pagetype, $parentcontext, $currentcontext) {
|
||||
function core_admin_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
|
||||
global $CFG;
|
||||
|
||||
if (in_array($filearea, ['logo', 'logocompact', 'favicon'])) {
|
||||
if (in_array($filearea, ['logo', 'logocompact'])) {
|
||||
$size = array_shift($args); // The path hides the size.
|
||||
$itemid = clean_param(array_shift($args), PARAM_INT);
|
||||
$filename = clean_param(array_shift($args), PARAM_FILE);
|
||||
@@ -96,16 +96,20 @@ function core_admin_pluginfile($course, $cm, $context, $filearea, $args, $forced
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
// Check whether width/height are specified, and we can resize the image (some types such as ICO cannot be resized).
|
||||
if (($maxwidth === 0 && $maxheight === 0) ||
|
||||
!$filedata = $file->resize_image($maxwidth, $maxheight)) {
|
||||
|
||||
// No need for resizing, but if the file should be cached we save it so we can serve it fast next time.
|
||||
if (empty($maxwidth) && empty($maxheight)) {
|
||||
if ($lifetime) {
|
||||
file_safe_save_content($file->get_content(), $candidate);
|
||||
}
|
||||
send_stored_file($file, $lifetime, 0, false, $options);
|
||||
}
|
||||
|
||||
// Proceed with the resizing.
|
||||
$filedata = $file->resize_image($maxwidth, $maxheight);
|
||||
if (!$filedata) {
|
||||
send_file_not_found();
|
||||
}
|
||||
|
||||
// If we don't want to cached the file, serve now and quit.
|
||||
if (!$lifetime) {
|
||||
send_content_uncached($filedata, $filename);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* Displays the list of found local plugins, their version (if found) and
|
||||
* a link to delete the local plugin.
|
||||
*
|
||||
* @see https://moodledev.io/docs/apis/plugintypes/local
|
||||
* @see http://docs.moodle.org/dev/Local_customisation
|
||||
* @package admin
|
||||
* @copyright 2010 David Mudrak <david.mudrak@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
|
||||
@@ -45,7 +45,7 @@ if (isset($_ENV['TMPDIR']) && is_dir($_ENV['TMPDIR'])) {
|
||||
$tmpfile = $tmpdir . '/moodle-mailout.log';
|
||||
$fh = fopen($tmpfile, 'a+', false)
|
||||
or mdie("Error openning $tmpfile on append\n");
|
||||
fwrite($fh, "==== ".date("D M d H:i:s Y", time())." ====\n");
|
||||
fwrite($fh, "==== ".strftime("%a %b %e %H:%M:%S %Y", time())." ====\n");
|
||||
fwrite($fh, "==== Commandline: " . implode(' ',$argv) . "\n");
|
||||
|
||||
$stdin = fopen('php://stdin', 'r');
|
||||
|
||||
+29
-22
@@ -23,11 +23,14 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../config.php');
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
define('NO_OUTPUT_BUFFERING', true);
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$plugin = required_param('plugin', PARAM_PLUGIN);
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$media = required_param('media', PARAM_PLUGIN);
|
||||
$confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
|
||||
$PAGE->set_url('/admin/media.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
@@ -35,38 +38,42 @@ $PAGE->set_context(context_system::instance());
|
||||
require_admin();
|
||||
require_sesskey();
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', [
|
||||
'section' => 'managemediaplayers',
|
||||
]);
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('media');
|
||||
$sortorder = array_values(\core\plugininfo\media::get_enabled_plugins());
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section' => 'managemediaplayers'));
|
||||
|
||||
if (!array_key_exists($media, $plugins)) {
|
||||
redirect($return);
|
||||
}
|
||||
|
||||
$displayname = get_string('pluginname', "media_{$plugin}");
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('media');
|
||||
if ($class::enable_plugin($plugin, false)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_disabled', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
$class::enable_plugin($media, false);
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('media');
|
||||
if ($class::enable_plugin($plugin, true)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_enabled', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
$class::enable_plugin($media, true);
|
||||
break;
|
||||
|
||||
case 'up':
|
||||
$class::change_plugin_order($plugin, $class::MOVE_UP);
|
||||
if (($pos = array_search($media, $sortorder)) > 0) {
|
||||
$tmp = $sortorder[$pos - 1];
|
||||
$sortorder[$pos - 1] = $sortorder[$pos];
|
||||
$sortorder[$pos] = $tmp;
|
||||
\core\plugininfo\media::set_enabled_plugins($sortorder);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'down':
|
||||
$class::change_plugin_order($plugin, $class::MOVE_DOWN);
|
||||
if ((($pos = array_search($media, $sortorder)) !== false) && ($pos < count($sortorder) - 1)) {
|
||||
$tmp = $sortorder[$pos + 1];
|
||||
$sortorder[$pos + 1] = $sortorder[$pos];
|
||||
$sortorder[$pos] = $tmp;
|
||||
\core\plugininfo\media::set_enabled_plugins($sortorder);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ require_once(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
include_once($CFG->dirroot.'/mnet/lib.php');
|
||||
|
||||
$sort = optional_param('sort', 'username', PARAM_ALPHAEXT);
|
||||
$sort = optional_param('sort', 'username', PARAM_ALPHA);
|
||||
$dir = optional_param('dir', 'ASC', PARAM_ALPHA);
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
$perpage = optional_param('perpage', 30, PARAM_INT);
|
||||
@@ -15,7 +15,7 @@ $action = trim(strtolower(optional_param('action', '', PARAM_ALPHA)));
|
||||
admin_externalpage_setup('ssoaccesscontrol');
|
||||
|
||||
if (!extension_loaded('openssl')) {
|
||||
throw new \moodle_exception('requiresopenssl', 'mnet');
|
||||
print_error('requiresopenssl', 'mnet');
|
||||
}
|
||||
|
||||
$sitecontext = context_system::instance();
|
||||
@@ -35,13 +35,13 @@ if (!empty($action) and confirm_sesskey()) {
|
||||
|
||||
// boot if insufficient permission
|
||||
if (!has_capability('moodle/user:delete', $sitecontext)) {
|
||||
throw new \moodle_exception('nomodifyacl', 'mnet');
|
||||
print_error('nomodifyacl','mnet');
|
||||
}
|
||||
|
||||
// fetch the record in question
|
||||
$id = required_param('id', PARAM_INT);
|
||||
if (!$idrec = $DB->get_record('mnet_sso_access_control', array('id'=>$id))) {
|
||||
throw new \moodle_exception('recordnoexists', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
print_error('recordnoexists','mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
@@ -56,7 +56,7 @@ if (!empty($action) and confirm_sesskey()) {
|
||||
// require the access parameter, and it must be 'allow' or 'deny'
|
||||
$accessctrl = trim(strtolower(required_param('accessctrl', PARAM_ALPHA)));
|
||||
if ($accessctrl != 'allow' and $accessctrl != 'deny') {
|
||||
throw new \moodle_exception('invalidaccessparam', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
print_error('invalidaccessparam', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
}
|
||||
|
||||
if (mnet_update_sso_access_control($idrec->username, $idrec->mnet_host_id, $accessctrl)) {
|
||||
@@ -71,7 +71,7 @@ if (!empty($action) and confirm_sesskey()) {
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \moodle_exception('invalidactionparam', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
print_error('invalidactionparam', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ if ($form = data_submitted() and confirm_sesskey()) {
|
||||
|
||||
// check permissions and verify form input
|
||||
if (!has_capability('moodle/user:delete', $sitecontext)) {
|
||||
throw new \moodle_exception('nomodifyacl', 'mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
print_error('nomodifyacl','mnet', "$CFG->wwwroot/$CFG->admin/mnet/access_control.php");
|
||||
}
|
||||
if (empty($form->username)) {
|
||||
$formerror['username'] = get_string('enterausername','mnet');
|
||||
@@ -117,6 +117,7 @@ if ($form = data_submitted() and confirm_sesskey()) {
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render(mnet_get_deprecation_notice());
|
||||
|
||||
// Explain
|
||||
echo $OUTPUT->box(get_string('ssoacldescr','mnet'));
|
||||
@@ -153,15 +154,7 @@ foreach ($columns as $column) {
|
||||
$headings[$column] = "<a href=\"?sort=$column&dir=$columndir&\">".$string[$column]."</a>$columnicon";
|
||||
}
|
||||
$headings['delete'] = '';
|
||||
|
||||
$sortorder = get_safe_orderby([
|
||||
'username' => 'username',
|
||||
'mnet_host_id' => 'mnet_host_id',
|
||||
'access' => 'accessctrl',
|
||||
'default' => 'username',
|
||||
], $sort, $dir, false);
|
||||
|
||||
$acl = $DB->get_records('mnet_sso_access_control', null, $sortorder);
|
||||
$acl = $DB->get_records('mnet_sso_access_control', null, "$sort $dir", '*'); //, $page * $perpage, $perpage);
|
||||
$aclcount = $DB->count_records('mnet_sso_access_control');
|
||||
|
||||
if (!$acl) {
|
||||
|
||||
+8
-22
@@ -17,13 +17,13 @@
|
||||
if (!extension_loaded('openssl')) {
|
||||
echo $OUTPUT->header();
|
||||
set_config('mnet_dispatcher_mode', 'off');
|
||||
throw new \moodle_exception('requiresopenssl', 'mnet');
|
||||
print_error('requiresopenssl', 'mnet');
|
||||
}
|
||||
|
||||
if (!function_exists('curl_init') ) {
|
||||
echo $OUTPUT->header();
|
||||
set_config('mnet_dispatcher_mode', 'off');
|
||||
throw new \moodle_exception('nocurl', 'mnet');
|
||||
print_error('nocurl', 'mnet');
|
||||
}
|
||||
|
||||
if (!isset($CFG->mnet_dispatcher_mode)) {
|
||||
@@ -37,7 +37,7 @@
|
||||
if (set_config('mnet_dispatcher_mode', $form->mode)) {
|
||||
redirect('index.php', get_string('changessaved'));
|
||||
} else {
|
||||
throw new \moodle_exception('invalidaction', '', 'index.php');
|
||||
print_error('invalidaction', '', 'index.php');
|
||||
}
|
||||
}
|
||||
} elseif (!empty($form->submit) && $form->submit == get_string('delete')) {
|
||||
@@ -46,23 +46,11 @@
|
||||
|
||||
$formcontinue = new single_button(new moodle_url('index.php', array('confirm' => md5($mnet->public_key))), get_string('yes'));
|
||||
$formcancel = new single_button(new moodle_url('index.php', array()), get_string('no'));
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->confirm(get_string("deletekeycheck", "mnet"), $formcontinue, $formcancel);
|
||||
echo $OUTPUT->footer();
|
||||
exit;
|
||||
} else {
|
||||
// We're deleting
|
||||
|
||||
// If no/cancel then redirect back to the network setting page.
|
||||
if (!isset($form->confirm)) {
|
||||
redirect(
|
||||
new moodle_url('/admin/mnet/index.php'),
|
||||
get_string('keydeletedcancelled', 'mnet'),
|
||||
null,
|
||||
\core\output\notification::NOTIFY_SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
if (!isset($SESSION->mnet_confirm_delete_key)) {
|
||||
// fail - you're being attacked?
|
||||
@@ -75,27 +63,25 @@
|
||||
|
||||
if($time < time() - 60) {
|
||||
// fail - you're out of time.
|
||||
redirect(
|
||||
new moodle_url('/admin/mnet/index.php'),
|
||||
get_string('deleteoutoftime', 'mnet'),
|
||||
null,
|
||||
\core\output\notification::NOTIFY_WARNING
|
||||
);
|
||||
print_error ('deleteoutoftime', 'mnet', 'index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($key != md5(sha1($mnet->keypair['keypair_PEM']))) {
|
||||
// fail - you're being attacked?
|
||||
throw new \moodle_exception ('deletewrongkeyvalue', 'mnet', 'index.php');
|
||||
print_error ('deletewrongkeyvalue', 'mnet', 'index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$mnet->replace_keys();
|
||||
redirect('index.php', get_string('keydeleted','mnet'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
$hosts = $DB->get_records_select('mnet_host', "id <> ? AND deleted = 0", array($CFG->mnet_localhost_id), 'wwwroot ASC');
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render(mnet_get_deprecation_notice());
|
||||
?>
|
||||
<form method="post" action="index.php">
|
||||
<table align="center" width="635" class="generaltable" border="0" cellpadding="5" cellspacing="0">
|
||||
|
||||
+14
-3
@@ -51,12 +51,18 @@ if ($hostid && $DB->get_field('mnet_host', 'deleted', array('id' => $hostid)) !=
|
||||
$PAGE->set_url('/admin/mnet/peers.php');
|
||||
admin_externalpage_setup($adminsection);
|
||||
|
||||
$deprecatenotify = mnet_get_deprecation_notice();
|
||||
|
||||
if (!extension_loaded('openssl')) {
|
||||
throw new \moodle_exception('requiresopenssl', 'mnet');
|
||||
print_error('requiresopenssl', 'mnet');
|
||||
}
|
||||
|
||||
if (!function_exists('curl_init') ) {
|
||||
throw new \moodle_exception('nocurl', 'mnet');
|
||||
print_error('nocurl', 'mnet');
|
||||
}
|
||||
|
||||
if (!function_exists('xmlrpc_encode_request')) {
|
||||
print_error('xmlrpc-missing', 'mnet');
|
||||
}
|
||||
|
||||
if (!isset($CFG->mnet_dispatcher_mode)) {
|
||||
@@ -83,8 +89,10 @@ if ($formdata = $simpleform->get_data()) {
|
||||
$mnet_peer->bootstrap($formdata->wwwroot, null, $application);
|
||||
// bootstrap the second form straight with the data from the first form
|
||||
$reviewform = new mnet_review_host_form(null, array('peer' => $mnet_peer)); // the second step (also the edit host form)
|
||||
$formdata->oldpublickey = $mnet_peer->public_key; // set this so we can confirm on form post without having to recreate the mnet_peer object
|
||||
$reviewform->set_data($mnet_peer);
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render($deprecatenotify);
|
||||
echo $OUTPUT->box_start();
|
||||
$reviewform->display();
|
||||
echo $OUTPUT->box_end();
|
||||
@@ -114,6 +122,7 @@ if (!empty($hostid)) {
|
||||
}
|
||||
$credentials = $mnet_peer->check_credentials($mnet_peer->public_key);
|
||||
$reviewform = new mnet_review_host_form(null, array('peer' => $mnet_peer)); // the second step (also the edit host form)
|
||||
$mnet_peer->oldpublickey = $mnet_peer->public_key; // set this so we can confirm on form post without having to recreate the mnet_peer object
|
||||
$reviewform->set_data((object)$mnet_peer);
|
||||
echo $OUTPUT->box_start();
|
||||
$reviewform->display();
|
||||
@@ -167,10 +176,11 @@ if ($formdata = $reviewform->get_data()) {
|
||||
if ($mnet_peer->commit()) {
|
||||
redirect(new moodle_url('/admin/mnet/peers.php', array('hostid' => $mnet_peer->id)), get_string('changessaved'));
|
||||
} else {
|
||||
throw new \moodle_exception('invalidaction', 'error', 'index.php');
|
||||
print_error('invalidaction', 'error', 'index.php');
|
||||
}
|
||||
} else if ($reviewform->is_submitted()) { // submitted, but errors
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render($deprecatenotify);
|
||||
echo $OUTPUT->box_start();
|
||||
$reviewform->display();
|
||||
echo $OUTPUT->box_end();
|
||||
@@ -181,6 +191,7 @@ if ($formdata = $reviewform->get_data()) {
|
||||
|
||||
// normal flow - just display all hosts with links
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render($deprecatenotify);
|
||||
$hosts = mnet_get_hosts(true);
|
||||
|
||||
// print the table to display the register all hosts setting
|
||||
|
||||
@@ -44,4 +44,5 @@ if (isset($mnet_peer->id) && $mnet_peer->id > 0) {
|
||||
} else {
|
||||
$tabs[] = new tabobject('mnetdetails', '#', $strmnetedithost, $strmnetedithost, false);
|
||||
}
|
||||
echo $OUTPUT->render(mnet_get_deprecation_notice());
|
||||
print_tabs(array($tabs), $currenttab);
|
||||
|
||||
@@ -18,7 +18,7 @@ require_once($CFG->libdir.'/adminlib.php');
|
||||
include_once($CFG->dirroot.'/mnet/lib.php');
|
||||
|
||||
if ($CFG->mnet_dispatcher_mode === 'off') {
|
||||
throw new \moodle_exception('mnetdisabled', 'mnet');
|
||||
print_error('mnetdisabled', 'mnet');
|
||||
}
|
||||
|
||||
admin_externalpage_setup('mnettestclient');
|
||||
@@ -27,7 +27,7 @@ error_reporting(DEBUG_ALL);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
if (!extension_loaded('openssl')) {
|
||||
throw new \moodle_exception('requiresopenssl', 'mnet', '', null, true);
|
||||
print_error('requiresopenssl', 'mnet', '', NULL, true);
|
||||
}
|
||||
|
||||
// optional drilling down parameters
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->render(mnet_get_deprecation_notice());
|
||||
?>
|
||||
<div id="trustedhosts"><!-- See theme/standard/styles_layout.css #trustedhosts .generaltable for rules -->
|
||||
<table cellspacing="0" cellpadding="5" class="generaltable generalbox" >
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
if (!extension_loaded('openssl')) {
|
||||
echo $OUTPUT->header();
|
||||
throw new \moodle_exception('requiresopenssl', 'mnet', '', null, true);
|
||||
print_error('requiresopenssl', 'mnet', '', NULL, true);
|
||||
}
|
||||
|
||||
$site = get_site();
|
||||
|
||||
+139
-55
@@ -1,67 +1,151 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
// Allows the admin to manage activity modules
|
||||
|
||||
/**
|
||||
* A page to manage activity modules.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
require_once('../config.php');
|
||||
require_once('../course/lib.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
|
||||
require_once('../config.php');
|
||||
require_once('../course/lib.php');
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
require_once("{$CFG->libdir}/tablelib.php");
|
||||
// defines
|
||||
define('MODULE_TABLE','module_administration_table');
|
||||
|
||||
define('MODULE_TABLE', 'module_administration_table');
|
||||
admin_externalpage_setup('managemodules');
|
||||
|
||||
admin_externalpage_setup('managemodules');
|
||||
$show = optional_param('show', '', PARAM_PLUGIN);
|
||||
$hide = optional_param('hide', '', PARAM_PLUGIN);
|
||||
|
||||
$plugin = optional_param('plugin', '', PARAM_PLUGIN);
|
||||
$action = optional_param('action', '', PARAM_ALPHA);
|
||||
|
||||
// If data submitted, then process and store.
|
||||
if (!empty($action) && !empty($plugin) && confirm_sesskey()) {
|
||||
$manager = \core_plugin_manager::resolve_plugininfo_class('mod');
|
||||
$pluginname = get_string('pluginname', $plugin);
|
||||
/// Print headings
|
||||
|
||||
if ($action === 'disable' && $manager::enable_plugin($plugin, 0)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_disabled', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
} else if ($action === 'enable' && $manager::enable_plugin($plugin, 1)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_enabled', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
$stractivities = get_string("activities");
|
||||
$struninstall = get_string('uninstallplugin', 'core_admin');
|
||||
$strversion = get_string("version");
|
||||
$strhide = get_string("hide");
|
||||
$strshow = get_string("show");
|
||||
$strsettings = get_string("settings");
|
||||
$stractivities = get_string("activities");
|
||||
$stractivitymodule = get_string("activitymodule");
|
||||
$strshowmodulecourse = get_string('showmodulecourse');
|
||||
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
/// If data submitted, then process and store.
|
||||
|
||||
if (!empty($hide) and confirm_sesskey()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('mod');
|
||||
$class::enable_plugin($hide, false);
|
||||
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
redirect(new moodle_url('/admin/modules.php'));
|
||||
}
|
||||
|
||||
// Redirect back to the modules page with out any params.
|
||||
redirect(new moodle_url('/admin/modules.php'));
|
||||
}
|
||||
if (!empty($show) and confirm_sesskey()) {
|
||||
$canenablemodule = true;
|
||||
$modulename = $show;
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string("activities"));
|
||||
$table = new \core_admin\table\activity_management_table();
|
||||
$table->out();
|
||||
echo $OUTPUT->footer();
|
||||
// Invoking a callback function that enables plugins to force additional actions (e.g. displaying notifications,
|
||||
// modals, etc.) and also specify through its returned value (bool) whether the process of enabling the plugin
|
||||
// should continue after these actions or not.
|
||||
if (component_callback_exists("mod_{$modulename}", 'pre_enable_plugin_actions')) {
|
||||
$canenablemodule = component_callback("mod_{$modulename}", 'pre_enable_plugin_actions');
|
||||
}
|
||||
|
||||
if ($canenablemodule) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('mod');
|
||||
$class::enable_plugin($show, true);
|
||||
admin_get_root(true, false); // Settings not required - only pages.
|
||||
redirect(new moodle_url('/admin/modules.php'));
|
||||
}
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($stractivities);
|
||||
|
||||
/// Get and sort the existing modules
|
||||
|
||||
if (!$modules = $DB->get_records('modules', array(), 'name ASC')) {
|
||||
print_error('moduledoesnotexist', 'error');
|
||||
}
|
||||
|
||||
/// Print the table of all modules
|
||||
// construct the flexible table ready to display
|
||||
$table = new flexible_table(MODULE_TABLE);
|
||||
$table->define_columns(array('name', 'instances', 'version', 'hideshow', 'uninstall', 'settings'));
|
||||
$table->define_headers(array($stractivitymodule, $stractivities, $strversion, "$strhide/$strshow", $strsettings, $struninstall));
|
||||
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/modules.php');
|
||||
$table->set_attribute('id', 'modules');
|
||||
$table->set_attribute('class', 'admintable generaltable');
|
||||
$table->setup();
|
||||
|
||||
$pluginmanager = core_plugin_manager::instance();
|
||||
|
||||
foreach ($modules as $module) {
|
||||
$plugininfo = $pluginmanager->get_plugin_info('mod_'.$module->name);
|
||||
$status = $plugininfo->get_status();
|
||||
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
$strmodulename = '<span class="notifyproblem">'.$module->name.' ('.get_string('missingfromdisk').')</span>';
|
||||
$missing = true;
|
||||
} else {
|
||||
// took out hspace="\10\", because it does not validate. don't know what to replace with.
|
||||
$icon = "<img src=\"" . $OUTPUT->image_url('monologo', $module->name) . "\" class=\"icon\" alt=\"\" />";
|
||||
$strmodulename = $icon.' '.get_string('modulename', $module->name);
|
||||
$missing = false;
|
||||
}
|
||||
|
||||
$uninstall = '';
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('mod_'.$module->name, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
}
|
||||
|
||||
if (file_exists("$CFG->dirroot/mod/$module->name/settings.php") ||
|
||||
file_exists("$CFG->dirroot/mod/$module->name/settingstree.php")) {
|
||||
$settings = "<a href=\"settings.php?section=modsetting$module->name\">$strsettings</a>";
|
||||
} else {
|
||||
$settings = "";
|
||||
}
|
||||
|
||||
try {
|
||||
$count = $DB->count_records_select($module->name, "course<>0");
|
||||
} catch (dml_exception $e) {
|
||||
$count = -1;
|
||||
}
|
||||
if ($count>0) {
|
||||
$countlink = $OUTPUT->action_link(new moodle_url('/course/search.php', ['modulelist' => $module->name]),
|
||||
$count, null, ['title' => $strshowmodulecourse]);
|
||||
} else if ($count < 0) {
|
||||
$countlink = get_string('error');
|
||||
} else {
|
||||
$countlink = "$count";
|
||||
}
|
||||
|
||||
if ($missing) {
|
||||
$visible = '';
|
||||
$class = '';
|
||||
} else if ($module->visible) {
|
||||
$visible = "<a href=\"modules.php?hide=$module->name&sesskey=".sesskey()."\" title=\"$strhide\">".
|
||||
$OUTPUT->pix_icon('t/hide', $strhide) . '</a>';
|
||||
$class = '';
|
||||
} else {
|
||||
$visible = "<a href=\"modules.php?show=$module->name&sesskey=".sesskey()."\" title=\"$strshow\">".
|
||||
$OUTPUT->pix_icon('t/show', $strshow) . '</a>';
|
||||
$class = 'dimmed_text';
|
||||
}
|
||||
if ($module->name == "forum") {
|
||||
$uninstall = "";
|
||||
$visible = "";
|
||||
$class = "";
|
||||
}
|
||||
$version = get_config('mod_'.$module->name, 'version');
|
||||
|
||||
$table->add_data(array(
|
||||
$strmodulename,
|
||||
$countlink,
|
||||
$version,
|
||||
$visible,
|
||||
$settings,
|
||||
$uninstall,
|
||||
), $class);
|
||||
}
|
||||
|
||||
$table->print_html();
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* MoodleNet callback.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2023 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core\moodlenet\moodlenet_client;
|
||||
use core\oauth2\api;
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
require_login();
|
||||
|
||||
// Parameters.
|
||||
$issuerid = required_param('issuerid', PARAM_INT);
|
||||
$error = optional_param('error', '', PARAM_RAW);
|
||||
$message = optional_param('error_description', null, PARAM_RAW);
|
||||
|
||||
// Headers to make it not cacheable.
|
||||
header('Cache-Control: no-cache, must-revalidate');
|
||||
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
|
||||
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_url('/admin/moodlenet_oauth2_callback.php');
|
||||
$PAGE->set_pagelayout('popup');
|
||||
|
||||
// Wait as long as it takes for this script to finish.
|
||||
core_php_time_limit::raise();
|
||||
|
||||
$issuer = api::get_issuer($issuerid);
|
||||
$returnurl = new moodle_url('/admin/moodlenet_oauth2_callback.php');
|
||||
$returnurl->param('issuerid', $issuerid);
|
||||
$returnurl->param('callback', 'yes');
|
||||
$returnurl->param('sesskey', sesskey());
|
||||
$oauthclient = api::get_user_oauth_client($issuer, $returnurl, moodlenet_client::API_SCOPE_CREATE_RESOURCE, true);
|
||||
$oauthclient->is_logged_in(); // Will upgrade the auth code to a token.
|
||||
|
||||
echo $OUTPUT->header();
|
||||
$PAGE->requires->js_call_amd('core/moodlenet/oauth2callback', 'init', [$error, $message]);
|
||||
echo $OUTPUT->footer();
|
||||
+12
-23
@@ -30,36 +30,25 @@
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
|
||||
// The state parameter we've given (used in moodle as a redirect url).
|
||||
// Per https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1, state is required, even during error responses.
|
||||
$state = required_param('state', PARAM_LOCALURL);
|
||||
$redirecturl = new moodle_url($state);
|
||||
$params = $redirecturl->params();
|
||||
|
||||
$error = optional_param('error', '', PARAM_RAW);
|
||||
|
||||
if ($error) {
|
||||
$message = optional_param('error_description', null, PARAM_RAW);
|
||||
|
||||
// Errors can occur for authenticated users, such as when a user denies authorization for some internal service call.
|
||||
// In such cases, propagate the error to the component redirect URI.
|
||||
if (isloggedin()) {
|
||||
if (isset($params['sesskey']) && confirm_sesskey($params['sesskey'])) {
|
||||
$redirecturl->param('error', $error);
|
||||
if ($message) {
|
||||
$redirecturl->param('error_description', $message);
|
||||
}
|
||||
redirect($redirecturl);
|
||||
}
|
||||
$message = optional_param('error_description', '', PARAM_RAW);
|
||||
if ($message) {
|
||||
$SESSION->loginerrormsg = $message;
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
} else {
|
||||
$SESSION->loginerrormsg = $error;
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
}
|
||||
|
||||
// Not logged in or the sesskey verification failed, redirect to login + show errors.
|
||||
$SESSION->loginerrormsg = $message ?? $error;
|
||||
redirect(new moodle_url(get_login_url()));
|
||||
}
|
||||
|
||||
// The authorization code generated by the authorization server.
|
||||
$code = required_param('code', PARAM_RAW);
|
||||
// The state parameter we've given (used in moodle as a redirect url).
|
||||
$state = required_param('state', PARAM_LOCALURL);
|
||||
|
||||
$redirecturl = new moodle_url($state);
|
||||
$params = $redirecturl->params();
|
||||
|
||||
if (isset($params['sesskey']) and confirm_sesskey($params['sesskey'])) {
|
||||
$redirecturl->param('oauth2code', $code);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* Displays the list of found plagiarism plugins, their version (if found) and
|
||||
* a link to uninstall the plagiarism plugin.
|
||||
*
|
||||
* @see https://moodledev.io/docs/apis/subsystems/plagiarism
|
||||
* @see http://docs.moodle.org/dev/Plagiarism_API
|
||||
* @package admin
|
||||
* @copyright 2012 Dan Marsden <dan@danmarsden.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
|
||||
+2
-2
@@ -116,13 +116,13 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
$instance = portfolio_instance($portfolio);
|
||||
if ($sure) {
|
||||
if (!confirm_sesskey()) {
|
||||
throw new \moodle_exception('confirmsesskeybad', '', $baseurl);
|
||||
print_error('confirmsesskeybad', '', $baseurl);
|
||||
}
|
||||
if ($instance->delete()) {
|
||||
$deletedstr = get_string('instancedeleted', 'portfolio');
|
||||
redirect($baseurl, $deletedstr, 1);
|
||||
} else {
|
||||
throw new \moodle_exception('instancenotdeleted', 'portfolio', $baseurl);
|
||||
print_error('instancenotdeleted', 'portfolio', $baseurl);
|
||||
}
|
||||
exit;
|
||||
} else {
|
||||
|
||||
@@ -190,8 +190,8 @@ class helper {
|
||||
static::add_item($presetid, 'showdataretentionsummary', '0', 'tool_dataprivacy');
|
||||
static::add_item($presetid, 'forum_maxattachments', '3');
|
||||
static::add_item($presetid, 'guestloginbutton', '0');
|
||||
// Set Activity chooser tabs to "Starred, Recommended, All".
|
||||
static::add_item($presetid, 'activitychoosertabmode', '4');
|
||||
// Set Activity chooser tabs to "Starred, All, Recommended".
|
||||
static::add_item($presetid, 'activitychoosertabmode', '1');
|
||||
|
||||
// Modules: Hide chat, database, external tool (lti), IMS content package (imscp), lesson, SCORM, survey, wiki, workshop.
|
||||
static::add_plugin($presetid, 'mod', 'chat', false);
|
||||
@@ -278,6 +278,9 @@ class helper {
|
||||
static::add_plugin($presetid, 'repository', 'url', false);
|
||||
static::add_plugin($presetid, 'repository', 'wikimedia', false);
|
||||
|
||||
// Text editors: Disable TinyMCE HTML editor.
|
||||
static::add_plugin($presetid, 'editor', 'tinymce', false);
|
||||
|
||||
// Create the "Full" site admin preset.
|
||||
$data = [
|
||||
'name' => get_string('fullpreset', 'core_adminpresets'),
|
||||
@@ -298,8 +301,8 @@ class helper {
|
||||
static::add_item($presetid, 'showdataretentionsummary', '1', 'tool_dataprivacy');
|
||||
static::add_item($presetid, 'forum_maxattachments', '9');
|
||||
static::add_item($presetid, 'guestloginbutton', '1');
|
||||
// Set Activity chooser tabs to the default value ("Starred, Recommended, All, Activities, Resources").
|
||||
static::add_item($presetid, 'activitychoosertabmode', '3');
|
||||
// Set Activity chooser tabs to the default value ("Starred, All, Activities, Resources, Recommended").
|
||||
static::add_item($presetid, 'activitychoosertabmode', '0');
|
||||
|
||||
// Modules: Enable chat, database, external tool (lti), IMS content package (imscp), lesson, SCORM, survey, wiki, workshop.
|
||||
static::add_plugin($presetid, 'mod', 'chat', true);
|
||||
@@ -380,5 +383,8 @@ class helper {
|
||||
static::add_plugin($presetid, 'repository', 'local', true);
|
||||
static::add_plugin($presetid, 'repository', 'url', true);
|
||||
static::add_plugin($presetid, 'repository', 'wikimedia', true);
|
||||
|
||||
// Text editors: Enable TinyMCE HTML editor.
|
||||
static::add_plugin($presetid, 'editor', 'tinymce', true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
namespace core_adminpresets\local\setting;
|
||||
|
||||
use admin_setting_configcheckbox;
|
||||
|
||||
/**
|
||||
* Checkbox setting.
|
||||
*
|
||||
@@ -28,15 +26,15 @@ use admin_setting_configcheckbox;
|
||||
*/
|
||||
class adminpresets_admin_setting_configcheckbox extends adminpresets_setting {
|
||||
|
||||
/**
|
||||
* Sets the visible name for the setting selected value
|
||||
*/
|
||||
protected function set_visiblevalue() {
|
||||
/** @var admin_setting_configcheckbox $settingdata */
|
||||
$settingdata = $this->get_settingdata();
|
||||
protected function set_value($value) {
|
||||
$this->value = clean_param($value, PARAM_BOOL);
|
||||
$this->set_visiblevalue();
|
||||
|
||||
// We need to compare the "yes" value of the inner checkbox, which isn't necessarily boolean.
|
||||
if ($this->value == $settingdata->yes) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function set_visiblevalue() {
|
||||
if ($this->value) {
|
||||
$str = get_string('yes');
|
||||
} else {
|
||||
$str = get_string('no');
|
||||
|
||||
+29
-4
@@ -26,8 +26,34 @@ namespace core_adminpresets\local\setting;
|
||||
*/
|
||||
class adminpresets_admin_setting_configmultiselect extends adminpresets_setting {
|
||||
|
||||
/** @var \admin_setting_configmultiselect $settingdata */
|
||||
protected $settingdata;
|
||||
/**
|
||||
* Ensure that the $value values are setting choices.
|
||||
*
|
||||
* @param mixed $value Setting value
|
||||
* @return mixed Returns false if wrong param value
|
||||
*/
|
||||
protected function set_value($value) {
|
||||
if ($value) {
|
||||
$options = explode(',', $value);
|
||||
foreach ($options as $option) {
|
||||
|
||||
foreach ($this->settingdata->choices as $key => $choice) {
|
||||
|
||||
if ($key == $option) {
|
||||
$this->value = $option;
|
||||
$this->set_visiblevalue();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$value = implode(',', $options);
|
||||
}
|
||||
$this->value = $value;
|
||||
$this->set_visiblevalue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function set_visiblevalue() {
|
||||
$values = explode(',', $this->value);
|
||||
@@ -35,8 +61,7 @@ class adminpresets_admin_setting_configmultiselect extends adminpresets_setting
|
||||
|
||||
foreach ($values as $value) {
|
||||
|
||||
// Ensure that each value exists as a setting choice.
|
||||
if (array_key_exists($value, $this->settingdata->choices)) {
|
||||
if (!empty($this->settingdata->choices[$value])) {
|
||||
$visiblevalues[] = $this->settingdata->choices[$value];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +26,6 @@ namespace core_adminpresets\local\setting;
|
||||
*/
|
||||
class adminpresets_admin_setting_configselect extends adminpresets_setting {
|
||||
|
||||
/** @var \admin_setting_configselect $settingdata */
|
||||
protected $settingdata;
|
||||
|
||||
/**
|
||||
* Sets the setting value cleaning it.
|
||||
*
|
||||
@@ -37,7 +34,7 @@ class adminpresets_admin_setting_configselect extends adminpresets_setting {
|
||||
*/
|
||||
protected function set_value($value) {
|
||||
// When we intantiate the class we need the choices.
|
||||
if (empty($this->settingdata->choices) && method_exists($this->settingdata, 'load_choices')) {
|
||||
if (empty($this->settindata->choices) && method_exists($this->settingdata, 'load_choices')) {
|
||||
$this->settingdata->load_choices();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,6 @@ namespace core_adminpresets\local\setting;
|
||||
*/
|
||||
class adminpresets_admin_setting_configtime extends adminpresets_setting {
|
||||
|
||||
/** @var \admin_setting_configtime $settingdata */
|
||||
protected $settingdata;
|
||||
|
||||
/**
|
||||
* To check that the value is one of the options
|
||||
*
|
||||
|
||||
@@ -19,8 +19,6 @@ namespace core_adminpresets\local\setting;
|
||||
/**
|
||||
* Reimplementation to allow human friendly view of the selected regexps.
|
||||
*
|
||||
* @deprecated Moodle 4.3 MDL-78468 - No longer used since the devicedetectregex was removed.
|
||||
* @todo Final deprecation on Moodle 4.7 MDL-79052
|
||||
* @package core_adminpresets
|
||||
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
|
||||
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
|
||||
@@ -28,16 +26,7 @@ namespace core_adminpresets\local\setting;
|
||||
*/
|
||||
class adminpresets_admin_setting_devicedetectregex extends adminpresets_admin_setting_configtext {
|
||||
|
||||
/**
|
||||
* @deprecated Moodle 4.3 MDL-78468 - No longer used since the devicedetectregex was removed.
|
||||
* @todo Final deprecation on Moodle 4.7 MDL-79052
|
||||
*/
|
||||
public function set_visiblevalue() {
|
||||
debugging(
|
||||
__FUNCTION__ . '() is deprecated.' .
|
||||
'All functions associated with devicedetectregex theme setting are being removed.',
|
||||
DEBUG_DEVELOPER
|
||||
);
|
||||
$values = json_decode($this->get_value());
|
||||
|
||||
if (!$values) {
|
||||
|
||||
@@ -28,9 +28,6 @@ namespace core_adminpresets\local\setting;
|
||||
*/
|
||||
class adminpresets_admin_setting_special_backupdays extends adminpresets_setting {
|
||||
|
||||
/** @var \admin_setting_special_backupdays $settingdata */
|
||||
protected $settingdata;
|
||||
|
||||
protected function set_value($value) {
|
||||
$this->value = clean_param($value, PARAM_SEQUENCE);
|
||||
$this->set_visiblevalue();
|
||||
|
||||
-3
@@ -26,9 +26,6 @@ namespace core_adminpresets\local\setting;
|
||||
*/
|
||||
class adminpresets_admin_setting_users_with_capability extends adminpresets_admin_setting_configmultiselect {
|
||||
|
||||
/** @var \admin_setting_configmultiselect $settingdata */
|
||||
protected $settingdata;
|
||||
|
||||
protected function set_behaviors() {
|
||||
$this->behaviors['loadchoices'] = &$this->settingdata;
|
||||
}
|
||||
|
||||
@@ -68,9 +68,6 @@ class adminpresets_setting {
|
||||
*/
|
||||
protected $attributesvalues;
|
||||
|
||||
/** @var array To store the behaviors. */
|
||||
protected array $behaviors = [];
|
||||
|
||||
/**
|
||||
* Stores the setting data and the selected value
|
||||
*
|
||||
@@ -170,7 +167,7 @@ class adminpresets_setting {
|
||||
/**
|
||||
* Saves the setting attributes values
|
||||
*
|
||||
* @return array|false Array of inserted ids (in config_log) or false if nothing was inserted
|
||||
* @return array Array of inserted ids (in config_log)
|
||||
*/
|
||||
public function save_attributes_values() {
|
||||
// Plugin name or null.
|
||||
@@ -209,6 +206,8 @@ class adminpresets_setting {
|
||||
* @param bool $name Setting name to store.
|
||||
* @param mixed $value Setting value to store.
|
||||
* @return int|false config_log inserted id or false whenever the new value is the same as old value.
|
||||
* @throws dml_exception
|
||||
* @throws moodle_exception
|
||||
*/
|
||||
public function save_value($name = false, $value = null) {
|
||||
// Object values if no arguments.
|
||||
|
||||
@@ -105,6 +105,7 @@ class manager {
|
||||
'adminpresets_auth_shibboleth_admin_setting_special_idp_configtextarea' => 'adminpresets_admin_setting_configtext',
|
||||
'adminpresets_auth_shibboleth_admin_setting_special_wayf_select' => 'adminpresets_admin_setting_configselect',
|
||||
'adminpresets_editor_atto_toolbar_setting' => 'adminpresets_admin_setting_configtext',
|
||||
'adminpresets_editor_tinymce_json_setting_textarea' => 'adminpresets_admin_setting_configtext',
|
||||
'adminpresets_enrol_database_admin_setting_category' => 'adminpresets_admin_setting_configselect',
|
||||
'adminpresets_enrol_flatfile_role_setting' => 'adminpresets_admin_setting_configtext',
|
||||
'adminpresets_enrol_ldap_admin_setting_category' => 'adminpresets_admin_setting_configselect',
|
||||
@@ -183,8 +184,7 @@ class manager {
|
||||
* @param boolean $sitedbvalues Indicates if $dbsettings comes from the site db or not
|
||||
* @param array $settings Array format $array['plugin']['settingname'] = settings_types child class
|
||||
* @param array|false $children Array of admin_category children or false
|
||||
* @return \core_adminpresets\local\setting\adminpresets_setting[][] Array format
|
||||
* $array['plugin']['settingname'] = adminpresets_setting child class
|
||||
* @return array Array format $array['plugin']['settingname'] = settings_types child class
|
||||
*/
|
||||
public function get_settings(array $dbsettings, bool $sitedbvalues = false, array $settings = [], $children = false): array {
|
||||
global $DB;
|
||||
@@ -309,17 +309,11 @@ class manager {
|
||||
|
||||
$classname = null;
|
||||
|
||||
// Getting the appropriate class to get the correct setting value.
|
||||
// Getting the appropiate class to get the correct setting value.
|
||||
$settingtype = get_class($settingdata);
|
||||
// Check if it is a setting from a plugin.
|
||||
$namespacedata = explode('\\', $settingtype);
|
||||
if (count($namespacedata) > 1) {
|
||||
$plugindata = explode('_', $namespacedata[0]);
|
||||
$settingtype = end($namespacedata);
|
||||
} else {
|
||||
$plugindata = explode('_', $settingtype, 2);
|
||||
}
|
||||
|
||||
// Check if it is a setting from a plugin.
|
||||
$plugindata = explode('_', $settingtype);
|
||||
$types = \core_component::get_plugin_types();
|
||||
if (array_key_exists($plugindata[0], $types)) {
|
||||
$plugins = \core_component::get_plugin_list($plugindata[0]);
|
||||
|
||||
@@ -99,7 +99,7 @@ class provider implements
|
||||
/**
|
||||
* Delete all data for all users in the specified context.
|
||||
*
|
||||
* @param \context $context The specific context to delete data for.
|
||||
* @param context $context The specific context to delete data for.
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||
// None of the the data from these tables should be deleted.
|
||||
|
||||
@@ -133,8 +133,8 @@ class manager_test extends \advanced_testcase {
|
||||
$settingpage = $adminroot->locate('modsettingquiz');
|
||||
$settingdata = $settingpage->settings->quizbrowsersecurity;;
|
||||
$result = $manager->get_setting($settingdata, '');
|
||||
$this->assertInstanceOf(\mod_quiz\adminpresets\adminpresets_browser_security_setting::class, $result);
|
||||
$this->assertNotEquals(\core_adminpresets\local\setting\adminpresets_setting::class, get_class($result));
|
||||
$this->assertInstanceOf('\mod_quiz\adminpresets\adminpresets_mod_quiz_admin_setting_browsersecurity', $result);
|
||||
$this->assertNotEquals('core_adminpresets\local\setting\adminpresets_setting', get_class($result));
|
||||
|
||||
// Check the adminpresets_setting class is returned when no specific class exists.
|
||||
$settingpage = $adminroot->locate('managecustomfields');
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
|
||||
use core\event\qbank_plugin_enabled;
|
||||
use core\event\qbank_plugin_disabled;
|
||||
use qbank_columnsortorder\column_manager;
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$name = required_param('name', PARAM_PLUGIN);
|
||||
@@ -50,11 +49,12 @@ if (!isset($plugins[$name])) {
|
||||
}
|
||||
|
||||
$plugintypename = $plugins[$name]->type . '_' . $plugins[$name]->name;
|
||||
$columnsortordermanager = new column_manager();
|
||||
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
if ($plugins[$name]->is_enabled()) {
|
||||
qbank_plugin_disabled::create_for_plugin($plugintypename)->trigger();
|
||||
$columnsortordermanager->disable_columns($plugintypename);
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('qbank');
|
||||
$class::enable_plugin($name, false);
|
||||
set_config('disabled', 1, 'qbank_'. $name);
|
||||
@@ -62,7 +62,7 @@ switch ($action) {
|
||||
break;
|
||||
case 'enable':
|
||||
if (!$plugins[$name]->is_enabled()) {
|
||||
qbank_plugin_enabled::create_for_plugin($plugintypename)->trigger();
|
||||
$columnsortordermanager->enable_columns($plugintypename);
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('qbank');
|
||||
$class::enable_plugin($name, true);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ if (!empty($config->disabledbehaviours)) {
|
||||
// Disable.
|
||||
if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
if (!isset($behaviours[$disable])) {
|
||||
throw new \moodle_exception('unknownbehaviour', 'question', $thispageurl, $disable);
|
||||
print_error('unknownbehaviour', 'question', $thispageurl, $disable);
|
||||
}
|
||||
|
||||
if (array_search($disable, $disabledbehaviours) === false) {
|
||||
@@ -97,11 +97,11 @@ if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey(
|
||||
// Enable.
|
||||
if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
if (!isset($behaviours[$enable])) {
|
||||
throw new \moodle_exception('unknownbehaviour', 'question', $thispageurl, $enable);
|
||||
print_error('unknownbehaviour', 'question', $thispageurl, $enable);
|
||||
}
|
||||
|
||||
if (!$archetypal[$enable]) {
|
||||
throw new \moodle_exception('cannotenablebehaviour', 'question', $thispageurl, $enable);
|
||||
print_error('cannotenablebehaviour', 'question', $thispageurl, $enable);
|
||||
}
|
||||
|
||||
if (($key = array_search($enable, $disabledbehaviours)) !== false) {
|
||||
@@ -114,7 +114,7 @@ if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey())
|
||||
// Move up in order.
|
||||
if (($up = optional_param('up', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
if (!isset($behaviours[$up])) {
|
||||
throw new \moodle_exception('unknownbehaviour', 'question', $thispageurl, $up);
|
||||
print_error('unknownbehaviour', 'question', $thispageurl, $up);
|
||||
}
|
||||
|
||||
// This function works fine for behaviours, as well as qtypes.
|
||||
@@ -126,7 +126,7 @@ if (($up = optional_param('up', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
// Move down in order.
|
||||
if (($down = optional_param('down', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
if (!isset($behaviours[$down])) {
|
||||
throw new \moodle_exception('unknownbehaviour', 'question', $thispageurl, $down);
|
||||
print_error('unknownbehaviour', 'question', $thispageurl, $down);
|
||||
}
|
||||
|
||||
// This function works fine for behaviours, as well as qtypes.
|
||||
|
||||
+34
-22
@@ -24,7 +24,6 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core_question\local\bank\question_version_status;
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
require_once($CFG->libdir . '/questionlib.php');
|
||||
@@ -43,23 +42,36 @@ $qtypes = question_bank::get_all_qtypes();
|
||||
$pluginmanager = core_plugin_manager::instance();
|
||||
|
||||
// Get some data we will need - question counts and which types are needed.
|
||||
// The second JOIN on question_versions (qv2) is to get the latest version of each question.
|
||||
// (Using this sort of JOIN is a known trick for doing this in the fastest possible way.)
|
||||
$counts = $DB->get_records_sql("
|
||||
SELECT q.qtype,
|
||||
COUNT(qv.id) AS numquestions,
|
||||
SUM(CASE WHEN qv.status = :hiddenstatus THEN 1 ELSE 0 END) AS numhidden,
|
||||
SUM(CASE WHEN qv.status = :draftstatus THEN 1 ELSE 0 END) AS numdraft
|
||||
FROM {question} q
|
||||
JOIN {question_versions} qv ON q.id = qv.questionid
|
||||
LEFT JOIN {question_versions} qv2 ON qv.questionbankentryid = qv2.questionbankentryid AND qv.version < qv2.version
|
||||
WHERE qv2.questionbankentryid IS NULL
|
||||
GROUP BY q.qtype
|
||||
", [
|
||||
'hiddenstatus' => question_version_status::QUESTION_STATUS_HIDDEN,
|
||||
'draftstatus' => question_version_status::QUESTION_STATUS_DRAFT,
|
||||
]);
|
||||
$hiddenstatus = \core_question\local\bank\question_version_status::QUESTION_STATUS_HIDDEN;
|
||||
$draftstatus = \core_question\local\bank\question_version_status::QUESTION_STATUS_DRAFT;
|
||||
|
||||
$sql = "SELECT result.qtype,
|
||||
SUM(result.numquestions) AS numquestions,
|
||||
SUM(result.numhidden) AS numhidden,
|
||||
SUM(result.numdraft) AS numdraft
|
||||
FROM (SELECT data.qtype,
|
||||
data.versionid,
|
||||
COUNT(data.numquestions) AS numquestions,
|
||||
(SELECT COUNT(qv.id)
|
||||
FROM {question_versions} qv
|
||||
WHERE qv.id = data.versionid
|
||||
AND qv.status = :hiddenstatus) AS numhidden,
|
||||
(SELECT COUNT(qv.id)
|
||||
FROM {question_versions} qv
|
||||
WHERE qv.id = data.versionid
|
||||
AND qv.status = :draftstatus) AS numdraft
|
||||
FROM (SELECT q.qtype, qv.id AS versionid, 1 AS numquestions
|
||||
FROM {question} q
|
||||
JOIN {question_versions} qv ON qv.questionid = q.id
|
||||
JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
|
||||
AND qv.version = (SELECT MAX(v.version)
|
||||
FROM {question_versions} v
|
||||
JOIN {question_bank_entries} be ON be.id = v.questionbankentryid
|
||||
WHERE be.id = qbe.id)) data
|
||||
GROUP BY data.qtype, data.versionid) result
|
||||
GROUP BY result.qtype";
|
||||
|
||||
$counts = $DB->get_records_sql($sql, ['hiddenstatus' => $hiddenstatus, 'draftstatus' => $draftstatus]);
|
||||
$needed = [];
|
||||
foreach ($qtypes as $qtypename => $qtype) {
|
||||
if (!isset($counts[$qtypename])) {
|
||||
@@ -94,7 +106,7 @@ $sortedqtypes = question_bank::sort_qtype_array($sortedqtypes, $config);
|
||||
// Disable.
|
||||
if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
if (!isset($qtypes[$disable])) {
|
||||
throw new \moodle_exception('unknownquestiontype', 'question', $thispageurl, $disable);
|
||||
print_error('unknownquestiontype', 'question', $thispageurl, $disable);
|
||||
}
|
||||
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('qtype');
|
||||
@@ -105,11 +117,11 @@ if (($disable = optional_param('disable', '', PARAM_PLUGIN)) && confirm_sesskey(
|
||||
// Enable.
|
||||
if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
if (!isset($qtypes[$enable])) {
|
||||
throw new \moodle_exception('unknownquestiontype', 'question', $thispageurl, $enable);
|
||||
print_error('unknownquestiontype', 'question', $thispageurl, $enable);
|
||||
}
|
||||
|
||||
if (!$qtypes[$enable]->menu_name()) {
|
||||
throw new \moodle_exception('cannotenable', 'question', $thispageurl, $enable);
|
||||
print_error('cannotenable', 'question', $thispageurl, $enable);
|
||||
}
|
||||
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('qtype');
|
||||
@@ -120,7 +132,7 @@ if (($enable = optional_param('enable', '', PARAM_PLUGIN)) && confirm_sesskey())
|
||||
// Move up in order.
|
||||
if (($up = optional_param('up', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
if (!isset($qtypes[$up])) {
|
||||
throw new \moodle_exception('unknownquestiontype', 'question', $thispageurl, $up);
|
||||
print_error('unknownquestiontype', 'question', $thispageurl, $up);
|
||||
}
|
||||
|
||||
$neworder = question_reorder_qtypes($sortedqtypes, $up, -1);
|
||||
@@ -131,7 +143,7 @@ if (($up = optional_param('up', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
// Move down in order.
|
||||
if (($down = optional_param('down', '', PARAM_PLUGIN)) && confirm_sesskey()) {
|
||||
if (!isset($qtypes[$down])) {
|
||||
throw new \moodle_exception('unknownquestiontype', 'question', $thispageurl, $down);
|
||||
print_error('unknownquestiontype', 'question', $thispageurl, $down);
|
||||
}
|
||||
|
||||
$neworder = question_reorder_qtypes($sortedqtypes, $down, +1);
|
||||
|
||||
@@ -39,7 +39,7 @@ if ($publickey !== false) {
|
||||
|
||||
// Encrypt data.
|
||||
$message = $CFG->release;
|
||||
$success = openssl_public_encrypt(\core_text::convert($message, 'ISO-8859-1', 'UTF-8'), $encrypteddata, $publickeystr);
|
||||
$success = openssl_public_encrypt(utf8_encode($message), $encrypteddata, $publickeystr);
|
||||
|
||||
if ($success) {
|
||||
echo base64_encode($encrypteddata);
|
||||
|
||||
+24
-10
@@ -44,7 +44,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$output .= $this->heading(get_string('copyrightnotice'));
|
||||
$output .= $this->box($copyrightnotice, 'copyrightnotice');
|
||||
$output .= html_writer::empty_tag('br');
|
||||
$output .= $this->confirm(get_string('doyouagree'), $continue, "https://moodledev.io/general/license");
|
||||
$output .= $this->confirm(get_string('doyouagree'), $continue, "http://docs.moodle.org/dev/License");
|
||||
$output .= $this->footer();
|
||||
|
||||
return $output;
|
||||
@@ -213,7 +213,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$output .= $this->container_end();
|
||||
}
|
||||
|
||||
$button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get', single_button::BUTTON_PRIMARY);
|
||||
$button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get', true);
|
||||
$button->class = 'continuebutton';
|
||||
$output .= $this->render($button);
|
||||
$output .= $this->footer();
|
||||
@@ -296,6 +296,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$output .= $this->header();
|
||||
$output .= $this->output->heading(get_string('notifications', 'admin'));
|
||||
$output .= $this->maturity_info($maturity);
|
||||
$output .= $this->legacy_log_store_writing_error();
|
||||
$output .= empty($CFG->disableupdatenotifications) ? $this->available_updates($availableupdates, $availableupdatesfetch) : '';
|
||||
$output .= $this->insecure_dataroot_warning($insecuredataroot);
|
||||
$output .= $this->development_libs_directories_warning($devlibdir);
|
||||
@@ -745,10 +746,10 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//// IT IS ILLEGAL AND A VIOLATION OF THE GPL TO HIDE, REMOVE OR MODIFY THIS COPYRIGHT NOTICE ///
|
||||
$copyrighttext = '<a href="http://moodle.org/">Moodle</a> '.
|
||||
'<a href="https://moodledev.io/general/releases" title="'.$CFG->version.'">'.$CFG->release.'</a><br />'.
|
||||
'<a href="http://docs.moodle.org/dev/Releases" title="'.$CFG->version.'">'.$CFG->release.'</a><br />'.
|
||||
'Copyright © 1999 onwards, Martin Dougiamas<br />'.
|
||||
'and <a href="http://moodle.org/dev">many other contributors</a>.<br />'.
|
||||
'<a href="https://moodledev.io/general/license">GNU Public License</a>';
|
||||
'<a href="http://docs.moodle.org/dev/License">GNU Public License</a>';
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
return $this->box($copyrighttext, 'copyright');
|
||||
@@ -897,8 +898,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$url = "https://campaign.moodle.org/current/lms/{$lang}/install/";
|
||||
$params = [
|
||||
'url' => $url,
|
||||
'iframeid' => 'campaign-content',
|
||||
'title' => get_string('campaign', 'admin'),
|
||||
'iframeid' => 'campaign-content'
|
||||
];
|
||||
|
||||
return $this->render_from_template('core/external_content_banner', $params);
|
||||
@@ -919,8 +919,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$url = "https://campaign.moodle.org/current/lms/{$lang}/servicesandsupport/";
|
||||
$params = [
|
||||
'url' => $url,
|
||||
'iframeid' => 'services-support-content',
|
||||
'title' => get_string('supportandservices', 'admin'),
|
||||
'iframeid' => 'services-support-content'
|
||||
];
|
||||
|
||||
return $this->render_from_template('core/external_content_banner', $params);
|
||||
@@ -992,7 +991,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
* @return string HTML to output.
|
||||
*/
|
||||
protected function release_notes_link() {
|
||||
$releasenoteslink = get_string('releasenoteslink', 'admin', 'https://moodledev.io/general/releases');
|
||||
$releasenoteslink = get_string('releasenoteslink', 'admin', 'http://docs.moodle.org/dev/Releases');
|
||||
$releasenoteslink = str_replace('target="_blank"', 'onclick="this.target=\'_blank\'"', $releasenoteslink); // extremely ugly validation hack
|
||||
return $this->box($releasenoteslink, 'generalbox alert alert-info');
|
||||
}
|
||||
@@ -2081,7 +2080,7 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
$errorline = true;
|
||||
} else {
|
||||
if ($status) { //Handle ok result (ok)
|
||||
$status = get_string('statusok');
|
||||
$status = get_string('ok');
|
||||
} else {
|
||||
if ($environment_result->getLevel() == 'optional') {//Handle check result (warning)
|
||||
$status = get_string('check');
|
||||
@@ -2193,6 +2192,21 @@ class core_admin_renderer extends plugin_renderer_base {
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if writing to the deprecated legacy log store is enabled.
|
||||
*
|
||||
* @return string An error message if writing to the legacy log store is enabled.
|
||||
*/
|
||||
protected function legacy_log_store_writing_error() {
|
||||
$enabled = get_config('logstore_legacy', 'loglegacy');
|
||||
$plugins = explode(',', get_config('tool_log', 'enabled_stores'));
|
||||
$enabled = $enabled && in_array('logstore_legacy', $plugins);
|
||||
|
||||
if ($enabled) {
|
||||
return $this->warning(get_string('legacylogginginuse'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display message about the benefits of registering on Moodle.org
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user