Compare commits
598 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f2979d0e5 | |||
| 385cd9ee23 | |||
| 3d517153fa | |||
| 1d19128f68 | |||
| c0ba953afc | |||
| 67d1edca87 | |||
| b930e2005c | |||
| 0c89600969 | |||
| 801964cabb | |||
| 3a4cd8db0f | |||
| 1a9f295e47 | |||
| 2adc935709 | |||
| 98c04f38cd | |||
| 02bc1d3b88 | |||
| 0996a2966c | |||
| c556c5fca5 | |||
| 7b15a36320 | |||
| c0ce8e7ae5 | |||
| 4f46506fdb | |||
| 2f5e10392c | |||
| bc65073a61 | |||
| 41b330abe1 | |||
| d942f0311c | |||
| 419f4c47e4 | |||
| 1777d32cb2 | |||
| a8753fb85a | |||
| 980bd08bdc | |||
| 3a8b5c11d2 | |||
| 3423321b32 | |||
| 7610449b02 | |||
| 142d17da19 | |||
| 67e6cefa41 | |||
| 025e0130c9 | |||
| 5a0a0a4d7e | |||
| 860a35db66 | |||
| 82d0bd3246 | |||
| ae7f9ead0e | |||
| 5856c76917 | |||
| 777a4a2d2e | |||
| d45b318a5d | |||
| f81f6bbda5 | |||
| 40c3419184 | |||
| 47cbd1b42d | |||
| 3fc06c5776 | |||
| 6d55d3b4f8 | |||
| c74f4582c2 | |||
| 05fde3409f | |||
| aa79c57c1e | |||
| fb124fc068 | |||
| 17d14ff177 | |||
| 54659b0a06 | |||
| dc129d0b68 | |||
| 7a26c7b0c3 | |||
| e7199f8944 | |||
| 567f1c3c4c | |||
| e48f0ef106 | |||
| 4a84177457 | |||
| cd7544d403 | |||
| 0691b264e2 | |||
| 0b2c4cf27d | |||
| a4f64284aa | |||
| b60e213341 | |||
| 2af7590d98 | |||
| 8ce0acb5de | |||
| ad02c3adf0 | |||
| d1d1d24396 | |||
| 8972c8627d | |||
| ce4d2810a0 | |||
| 965fcec3a1 | |||
| 89273142e2 | |||
| 2e8d88fe22 | |||
| 8e3f31debe | |||
| 23e1349810 | |||
| abf8b970be | |||
| b13273c21f | |||
| 7871b634b2 | |||
| eb98d24713 | |||
| 3e8064b84a | |||
| c1b716ed30 | |||
| 3e0a9b33d9 | |||
| 7c4c64d821 | |||
| 62a20889ef | |||
| ca37641c24 | |||
| 90e175670a | |||
| 9b7d060c5e | |||
| 346cd40859 | |||
| 81de8dc4c1 | |||
| d932630feb | |||
| c7828a7e89 | |||
| 499c254bd9 | |||
| b349a501bf | |||
| 088528038c | |||
| 8e78b057a3 | |||
| 49ec7f8b7a | |||
| 327132f929 | |||
| c69966dc7b | |||
| 40765660a8 | |||
| e5871c89f5 | |||
| 623ecdaddb | |||
| 4facd41f67 | |||
| 8dac9b29d4 | |||
| bf8ebd6d96 | |||
| 13513264fa | |||
| 3b6d698f51 | |||
| 965271de64 | |||
| 4c796650e6 | |||
| eff9e9ddea | |||
| 7907689825 | |||
| 582d2448b5 | |||
| b0d06e3c2c | |||
| 6d29831de6 | |||
| bbef2dc030 | |||
| aeae977eed | |||
| 5b5635628f | |||
| adc2d84d49 | |||
| bbfc652b71 | |||
| d89a43f195 | |||
| 9e44b9e55d | |||
| 1d19a5eb47 | |||
| 3b6b8abc57 | |||
| 4193196b8f | |||
| cbb3c3e0b9 | |||
| 933a5e26cc | |||
| b451b66b40 | |||
| 570bcd8274 | |||
| a777a3f222 | |||
| 5a0a9c8e73 | |||
| fd4ae15898 | |||
| c2a0ce47db | |||
| 29010702b2 | |||
| 31aa2496d1 | |||
| 029972ac7c | |||
| 8c37f8667e | |||
| fee1d071bd | |||
| 6dbe2aaacb | |||
| 2562ce63d4 | |||
| 615d97944e | |||
| 413288345c | |||
| 6e09b240bf | |||
| 2fef7540f1 | |||
| d0be17a749 | |||
| c71949dc53 | |||
| cd20ea8b95 | |||
| bc1a1aaf32 | |||
| 51208a3c32 | |||
| 01b3b79a94 | |||
| 50885a5b23 | |||
| 9d759a8b9e | |||
| 183c8315d9 | |||
| 9c9f81b9e7 | |||
| fb06f2a87c | |||
| 14d2791057 | |||
| 66296d8f06 | |||
| 6992979404 | |||
| 537361c5e4 | |||
| f6fa9b4997 | |||
| 330930ae62 | |||
| 02ee1effbd | |||
| aa0a762aa4 | |||
| b6e389b74a | |||
| d4f82690a5 | |||
| 744c5a5bb8 | |||
| 4ef0f57dbc | |||
| d88c3438c5 | |||
| 8ff5016cef | |||
| 2efaa63376 | |||
| 1a7bdd06d7 | |||
| d35759ae7d | |||
| 4cd93d2596 | |||
| f678a6eec0 | |||
| 077eaa11a1 | |||
| a56d0af3f6 | |||
| c237de3747 | |||
| 59c638dc00 | |||
| 421f72704e | |||
| e49a94cd14 | |||
| 0444eedad7 | |||
| 127b75e161 | |||
| 42a3d7709d | |||
| 69a1435d46 | |||
| 892dba30c6 | |||
| caf3cb78e5 | |||
| 811f699514 | |||
| 851bc55bde | |||
| 6f1b265a2b | |||
| 1736fc82fa | |||
| 2daaae15ea | |||
| 5157d7e013 | |||
| 08d1c32b45 | |||
| a5dcc1b90f | |||
| 4b74b4791f | |||
| 5a554e9746 | |||
| 6c05d34bf4 | |||
| f790a5d1e4 | |||
| 9cc1cf5808 | |||
| cf14d5d951 | |||
| 39baf6a0e2 | |||
| ed1b321918 | |||
| 5dcbbcc117 | |||
| 8ee8195650 | |||
| f8e680ca11 | |||
| a942187816 | |||
| fdcf4144dc | |||
| da8ee816a7 | |||
| 3c68e824d7 | |||
| 9d472d7319 | |||
| f53c8c2a02 | |||
| f324728737 | |||
| ecf17cfd73 | |||
| e8b9d60c27 | |||
| 4ee8f04bef | |||
| b3b4c00d5b | |||
| cfa002f6ee | |||
| e5636f9aa4 | |||
| 18202cbed7 | |||
| bb4bc850f4 | |||
| 5f7d350f72 | |||
| 7ce3c31e12 | |||
| e9f173e2d4 | |||
| 916ac383ef | |||
| d1d546a0c4 | |||
| b26f0f688f | |||
| bcda2f3745 | |||
| d11eec562a | |||
| dc7b914677 | |||
| 8f018d49ac | |||
| 5a71a6b7e5 | |||
| 0fee379892 | |||
| 51483fe057 | |||
| cb2cf4a6a7 | |||
| b9acc1422a | |||
| 2ca3c8ad0d | |||
| c1108ed7fc | |||
| c408fe813c | |||
| b3ec0280ea | |||
| ac6f7b18be | |||
| c3bec9f51e | |||
| d186a97e10 | |||
| c1452371db | |||
| 835bbc41fd | |||
| 1a0d12e4a2 | |||
| 032f18c4a5 | |||
| d7f66ebe07 | |||
| 7f5bd0da0e | |||
| 98c38993fd | |||
| 77067fbb3a | |||
| 8e8ee75304 | |||
| 9a1dc85511 | |||
| e2e7e35da3 | |||
| 8c45d46d36 | |||
| 17b8efa585 | |||
| 71c1cfb143 | |||
| 1ce4f44df7 | |||
| 9bf7fea937 | |||
| f3895b00a5 | |||
| 1b1d0419a4 | |||
| a86de7c0d9 | |||
| ec2a1ba2fe | |||
| 9b94fabcb0 | |||
| 2cd81b11b1 | |||
| 6cb5fe8472 | |||
| 33b16dd3cd | |||
| d4b4f96e6c | |||
| 5e3fca4d3b | |||
| eaa13b3809 | |||
| a2d176c2ed | |||
| d9e191b89e | |||
| 813c1136bc | |||
| 149017a96c | |||
| e945517d66 | |||
| c712250d6b | |||
| e39a1db7b6 | |||
| d63c8ec710 | |||
| 62383073f5 | |||
| 0013192227 | |||
| 1be0ead2d4 | |||
| 5c8bc25cd1 | |||
| 0706e7ac17 | |||
| 8069916549 | |||
| f293278132 | |||
| e6a09c5359 | |||
| 06e7de3d96 | |||
| ed402015bb | |||
| 9495b310e5 | |||
| e3a371a7a1 | |||
| a3a4c4f028 | |||
| 986ee9fd2a | |||
| 95bfd8108b | |||
| 23eee911ef | |||
| bbaf38b921 | |||
| a0deded716 | |||
| cdf4ba9549 | |||
| 4127b60cb5 | |||
| eaba80f68d | |||
| 32f86cd8e9 | |||
| 00d5b5c9a3 | |||
| a81b8267c7 | |||
| 9fb9aa7215 | |||
| 0309e1e39d | |||
| 895d6c75a4 | |||
| 4358b705e5 | |||
| 39daab950a | |||
| 3c3c41682c | |||
| 93e4b10b8e | |||
| f8ef412113 | |||
| 0c19d0828a | |||
| ee0cb8eb8d | |||
| 5ff4e7ad7b | |||
| 08c051c00b | |||
| 6a2192e887 | |||
| 6a7b2dd0cb | |||
| 796987c5f6 | |||
| 8a5908a9b3 | |||
| ee056895a3 | |||
| e61f453067 | |||
| 2607a4e671 | |||
| 1ac7e7e5c8 | |||
| e5bb411fe4 | |||
| a65ba62f66 | |||
| 197824b5f8 | |||
| 4a1a78244e | |||
| 53318d9fce | |||
| a1be2ce57d | |||
| 19a6d37b9f | |||
| 34acf52a3f | |||
| 837c7f5696 | |||
| 1498e02eba | |||
| 1007677df4 | |||
| 38bf1824f8 | |||
| e08df28765 | |||
| 0de51e6ad1 | |||
| 52388b1bb4 | |||
| 19a4bdb7f4 | |||
| cfd867e7d9 | |||
| e8062e2cfe | |||
| e115db6dce | |||
| dd97173944 | |||
| 5f155af825 | |||
| c40fbd5e14 | |||
| 8fc43b0d64 | |||
| 8543e7c0d0 | |||
| fa35ed9955 | |||
| b6f2ac8c59 | |||
| c41e9a3312 | |||
| 0ccc3820c4 | |||
| 42adb9f74a | |||
| 5e67fb9442 | |||
| 4d83fde993 | |||
| fb3a9ecb92 | |||
| 768d7fca5f | |||
| f5095227d3 | |||
| 0485403978 | |||
| 81e0be88e9 | |||
| da1af82875 | |||
| 52c475e082 | |||
| 2f2e2a3cc2 | |||
| 4140295c9f | |||
| 9d40bd98be | |||
| c58cafbbaa | |||
| d902884587 | |||
| 2a5a747fec | |||
| 19ddaeb782 | |||
| 43d7576332 | |||
| a1b54310e1 | |||
| 728b068e24 | |||
| 772f17a280 | |||
| db4f496b52 | |||
| 58611999f3 | |||
| 1bfd51f16b | |||
| c40624308f | |||
| 7fc9e24121 | |||
| 4b55cb7109 | |||
| 27b7886b44 | |||
| 5ac077568d | |||
| 1927f330c4 | |||
| e9e274d60b | |||
| 55f4e4c9cf | |||
| e712433e97 | |||
| e5e43e747a | |||
| eb5fab4fd9 | |||
| 10787caae9 | |||
| e2ca0b6e67 | |||
| 36e07617ed | |||
| 7dedfc8b79 | |||
| 88045d94ae | |||
| 1cc2d506aa | |||
| 2d21dc38c6 | |||
| d09ef20526 | |||
| 351460000d | |||
| 742bb09d38 | |||
| 71d8fb3c66 | |||
| 7955764966 | |||
| 7d621c689b | |||
| eced61f6d1 | |||
| 11d14cacb9 | |||
| 5ff1820a1f | |||
| 886fc0ba20 | |||
| e51a432d0f | |||
| c8d1553d0e | |||
| 538b837c62 | |||
| b99dcf40fd | |||
| 1ae727b538 | |||
| d705b4abb4 | |||
| c3c06055f0 | |||
| 6d2a555f8e | |||
| 08fe5496d1 | |||
| 2721dc593e | |||
| 8efba305f2 | |||
| 7d33c56890 | |||
| 6dbfaf2235 | |||
| be72c3df67 | |||
| 996e83fdd4 | |||
| 1758e6efc0 | |||
| c1e53206d1 | |||
| 8527d33766 | |||
| c7b415e792 | |||
| 2615ec14ad | |||
| cf862db4bc | |||
| 608ab1c385 | |||
| badfcb70e4 | |||
| c582672225 | |||
| d406c3893e | |||
| 8e602172ff | |||
| d21f9cc2dd | |||
| 240d90b149 | |||
| 47f8e3e117 | |||
| f57728674e | |||
| 0f2786da69 | |||
| cd32489d7a | |||
| 0ea62d56c4 | |||
| 16008dfd92 | |||
| 811b80a4c5 | |||
| bbc9f54a6b | |||
| 8d7fa47e0d | |||
| 32623b4d3c | |||
| c01741c8cc | |||
| d128e18674 | |||
| 8794018916 | |||
| 664749aaea | |||
| c2ca02e489 | |||
| 55d31273e3 | |||
| ccd4382245 | |||
| e47d8445b9 | |||
| f93ff30cde | |||
| bc8acaffc1 | |||
| eb9845115b | |||
| f2512fddb3 | |||
| a3d579f922 | |||
| d9dbcdf893 | |||
| ec148b2574 | |||
| b7df272247 | |||
| 6ba6b23280 | |||
| d444af3d74 | |||
| a9e99ebd02 | |||
| b4e4c37e52 | |||
| f9212fb311 | |||
| b070387e03 | |||
| e0d460673a | |||
| 808836c60b | |||
| e22f5c6d87 | |||
| e807911c99 | |||
| 0619c4ecc4 | |||
| 8624dcbc4d | |||
| 89a50d82e3 | |||
| 93e80c9b45 | |||
| 42fb2c1b70 | |||
| fbcc8eba37 | |||
| 0f9a1675cd | |||
| 7f1b995194 | |||
| 1d663d1776 | |||
| b9aa500ea9 | |||
| 94fa39d226 | |||
| 64bef5f9f6 | |||
| 0a4b99f35b | |||
| 36843ff28b | |||
| 49fad98ab2 | |||
| 5baa2de21e | |||
| fd7dd8f237 | |||
| ea1dba053d | |||
| 0c2d24e908 | |||
| 751fe02a01 | |||
| b8bf3fe36b | |||
| b94e9188e7 | |||
| 08d18b09c1 | |||
| be39358439 | |||
| c34e3ca994 | |||
| 12fd2baec7 | |||
| 16dab5d9c7 | |||
| 3209753b78 | |||
| 54924b24c7 | |||
| 05de057c00 | |||
| f7751d8cd6 | |||
| 9e84f9063e | |||
| 932d1d33d1 | |||
| c4862951d8 | |||
| 7204bbf743 | |||
| d794cb3935 | |||
| 0a79d25826 | |||
| 4101e04265 | |||
| 99046d557e | |||
| 4ef8b1d07e | |||
| b1660e619b | |||
| a3fcd87495 | |||
| be8c5c6944 | |||
| c3ae3253d9 | |||
| 77d0becd77 | |||
| 4bc1c5994d | |||
| 01f0148c64 | |||
| 02a9c25040 | |||
| c0339626a2 | |||
| 4f431ffe43 | |||
| 727bbbfa03 | |||
| 482ad496c7 | |||
| b1a5caec65 | |||
| 4c7ec86fcd | |||
| b8e75114c9 | |||
| 3a389c1d46 | |||
| 592608b287 | |||
| 8060eb6fc7 | |||
| cc8cc5c8b0 | |||
| 895661bf74 | |||
| 3ea79917c9 | |||
| 87a27b23a1 | |||
| 53aad1f086 | |||
| 9cdcf8748d | |||
| fad0019cb2 | |||
| cf539782c0 | |||
| d6ee0f6897 | |||
| 016c76ec57 | |||
| 5cb7093166 | |||
| bb04cfe20e | |||
| abde87bf41 | |||
| 5663c1771f | |||
| 67258145ea | |||
| 23be970b7f | |||
| 58873bcae3 | |||
| 3c2c8a0628 | |||
| 6ec0c5fba5 | |||
| 39a765703e | |||
| 87fd4f6b0d | |||
| 21acd586a8 | |||
| 8d8124fa9f | |||
| b6c5e8f790 | |||
| 8736f9b956 | |||
| d8088471b0 | |||
| ea505f1b35 | |||
| bad69e63f5 | |||
| 54fbcc3105 | |||
| c35f3e97da | |||
| 9455b8b96b | |||
| 4050f60b55 | |||
| 55526a8a53 | |||
| 44242e1a40 | |||
| 6d01dfe627 | |||
| d8ace7dd74 | |||
| 1a17ca8bdd | |||
| 79dfb73824 | |||
| 4d82d742c5 | |||
| 4bb1c9764e | |||
| 135aeaacc4 | |||
| 0612ff1f56 | |||
| 807e21f64e | |||
| 2229917a8f | |||
| 1a72a44f97 | |||
| 0d87b1f548 | |||
| f09cb26d51 | |||
| dd8b3324ef | |||
| 3fca7fd7c7 | |||
| 3622940192 | |||
| 655193dc84 | |||
| a34b18ad21 | |||
| 65b61b07e0 | |||
| f61d29c317 | |||
| 62d334e985 | |||
| 0f9b21a5d7 | |||
| 116f2c5714 | |||
| a4ff234c80 | |||
| b2959e1323 | |||
| 10a40946c6 | |||
| 5d911423dc | |||
| fbfa01b847 | |||
| 4567c1c3a0 | |||
| b610727b5b | |||
| 1118c28a51 | |||
| 1879f64350 | |||
| 8b215b4110 | |||
| 69023cd3e9 | |||
| f4a201cdf2 | |||
| 086f4b6e4f | |||
| cf1a558531 | |||
| 3338ba48d9 | |||
| f9db06b107 | |||
| f300e1021b | |||
| 49308a3f57 | |||
| 0d2a4f8ee9 | |||
| 06085cc6d4 | |||
| 7b414d50a8 | |||
| 73639b4124 |
@@ -0,0 +1,103 @@
|
||||
<?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 fixes orphaned question categories.
|
||||
*
|
||||
* Orphaned question categories have had their associated context deleted
|
||||
* but the category itself remains in the database with an invalid context.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage cli
|
||||
* @copyright 2013 Tyler Bannister (tyler.bannister@remote-learner.net)
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('CLI_SCRIPT', true);
|
||||
|
||||
require(__DIR__.'/../../config.php');
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
require_once($CFG->libdir.'/questionlib.php');
|
||||
|
||||
$long = array('fix' => false, 'help' => false);
|
||||
$short = array('f' => 'fix', 'h' => 'help');
|
||||
|
||||
// Now get cli options.
|
||||
list($options, $unrecognized) = cli_get_params($long, $short);
|
||||
|
||||
if ($unrecognized) {
|
||||
$unrecognized = implode("\n ", $unrecognized);
|
||||
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
|
||||
}
|
||||
|
||||
if ($options['help']) {
|
||||
$help =
|
||||
"Fix orphaned question categories.
|
||||
|
||||
This scripts detects question categories that have had their
|
||||
context deleted, thus severing them from their original purpose.
|
||||
|
||||
This script will find the orphaned categories and delete the unused
|
||||
questions in each category found. Used questions will not be
|
||||
deleted, instead they will be moved to a rescue question category.
|
||||
|
||||
Options:
|
||||
-h, --help Print out this help
|
||||
-f, --fix Fix the orphaned question categories in the DB.
|
||||
If not specified only check and report problems to STDERR.
|
||||
Example:
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_question_categories.php
|
||||
\$sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_question_categories.php -f
|
||||
";
|
||||
|
||||
echo $help;
|
||||
die;
|
||||
}
|
||||
|
||||
cli_heading('Checking for orphaned categories');
|
||||
|
||||
|
||||
$sql = 'SELECT qc.id, qc.contextid, qc.name
|
||||
FROM {question_categories} qc
|
||||
LEFT JOIN {context} c ON qc.contextid = c.id
|
||||
WHERE c.id IS NULL';
|
||||
$categories = $DB->get_recordset_sql($sql);
|
||||
|
||||
$i = 0;
|
||||
foreach ($categories as $category) {
|
||||
$i += 1;
|
||||
echo "Found orphaned category: {$category->name}\n";
|
||||
if (!empty($options['fix'])) {
|
||||
echo "Cleaning...";
|
||||
// One transaction per category.
|
||||
$transaction = $DB->start_delegated_transaction();
|
||||
question_category_delete_safe($category);
|
||||
$transaction->allow_commit();
|
||||
echo " Done!\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (($i > 0) && !empty($options['fix'])) {
|
||||
echo "Found and removed {$i} orphaned question categories\n";
|
||||
} else if ($i > 0) {
|
||||
echo "Found {$i} orphaned question categories. To fix, run:\n";
|
||||
echo "\$sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_question_categories.php --fix\n";
|
||||
} else {
|
||||
echo "No orphaned question categories found.\n";
|
||||
}
|
||||
|
||||
|
||||
$categories->close();
|
||||
@@ -1257,6 +1257,154 @@
|
||||
<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_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="2.9" requires="2.2">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="5.5.31" />
|
||||
<VENDOR name="mysql" version="5.5.31" />
|
||||
<VENDOR name="postgres" version="9.1" />
|
||||
<VENDOR name="mssql" version="10.0" />
|
||||
<VENDOR name="oracle" version="10.2" />
|
||||
</DATABASE>
|
||||
<PHP version="5.4.4" 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="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="mbstringrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opensslrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlrpc" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="xmlrpcrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="intlrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
</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_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
+21
-16
@@ -561,31 +561,36 @@ $cronoverdue = ($lastcron < time() - 3600 * 24);
|
||||
$dbproblems = $DB->diagnose();
|
||||
$maintenancemode = !empty($CFG->maintenance_enabled);
|
||||
|
||||
// Available updates for Moodle core
|
||||
// Available updates for Moodle core.
|
||||
$updateschecker = \core\update\checker::instance();
|
||||
$availableupdates = array();
|
||||
$availableupdates['core'] = $updateschecker->get_update_info('core',
|
||||
array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
|
||||
$availableupdatesfetch = null;
|
||||
|
||||
// Available updates for contributed plugins
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) {
|
||||
foreach ($plugintypeinstances as $pluginname => $plugininfo) {
|
||||
if (!empty($plugininfo->availableupdates)) {
|
||||
foreach ($plugininfo->availableupdates as $pluginavailableupdate) {
|
||||
if ($pluginavailableupdate->version > $plugininfo->versiondisk) {
|
||||
if (!isset($availableupdates[$plugintype.'_'.$pluginname])) {
|
||||
$availableupdates[$plugintype.'_'.$pluginname] = array();
|
||||
if (empty($CFG->disableupdatenotifications)) {
|
||||
// Only compute the update information when it is going to be displayed to the user.
|
||||
$availableupdates['core'] = $updateschecker->get_update_info('core',
|
||||
array('minmaturity' => $CFG->updateminmaturity, 'notifybuilds' => $CFG->updatenotifybuilds));
|
||||
|
||||
// Available updates for contributed plugins
|
||||
$pluginman = core_plugin_manager::instance();
|
||||
foreach ($pluginman->get_plugins() as $plugintype => $plugintypeinstances) {
|
||||
foreach ($plugintypeinstances as $pluginname => $plugininfo) {
|
||||
if (!empty($plugininfo->availableupdates)) {
|
||||
foreach ($plugininfo->availableupdates as $pluginavailableupdate) {
|
||||
if ($pluginavailableupdate->version > $plugininfo->versiondisk) {
|
||||
if (!isset($availableupdates[$plugintype.'_'.$pluginname])) {
|
||||
$availableupdates[$plugintype.'_'.$pluginname] = array();
|
||||
}
|
||||
$availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate;
|
||||
}
|
||||
$availableupdates[$plugintype.'_'.$pluginname][] = $pluginavailableupdate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The timestamp of the most recent check for available updates
|
||||
$availableupdatesfetch = $updateschecker->get_last_timefetched();
|
||||
// The timestamp of the most recent check for available updates
|
||||
$availableupdatesfetch = $updateschecker->get_last_timefetched();
|
||||
}
|
||||
|
||||
$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
|
||||
//check if the site is registered on Moodle.org
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
echo '<div class="phpinfo">';
|
||||
|
||||
ob_start();
|
||||
phpinfo(INFO_GENERAL + INFO_CONFIGURATION + INFO_MODULES);
|
||||
phpinfo(INFO_GENERAL + INFO_CONFIGURATION + INFO_MODULES + INFO_VARIABLES);
|
||||
$html = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ if (!empty($registeredhub) and $registeredhub->token == $token) {
|
||||
$registeredhub->hubname = $hubname;
|
||||
$registrationmanager->update_registeredhub($registeredhub);
|
||||
|
||||
//display notficiation message
|
||||
// Display notification message.
|
||||
$notificationmessage = $OUTPUT->notification(
|
||||
get_string('registrationconfirmedon', 'hub', $hublink), 'notifysuccess');
|
||||
echo $notificationmessage;
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
|
||||
* @copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com
|
||||
*
|
||||
* On this page the administrator selects which hub he wants to register,
|
||||
* except for MOOCH. Admins can register with MOOCH with the top admin menu "Registration" link.
|
||||
* On this page the administrator can also unregister from any hubs, including MOOCH.
|
||||
* On this page the administrator selects which hub he wants to register (except for moodle.net)
|
||||
* Admins can register with moodle.net via the site admin menu "Registration" link.
|
||||
* On this page the administrator can also unregister from any hubs including moodle.net.
|
||||
*/
|
||||
|
||||
require('../../config.php');
|
||||
|
||||
+22
-23
@@ -53,31 +53,30 @@ class registration_manager {
|
||||
public function cron() {
|
||||
global $CFG;
|
||||
if (extension_loaded('xmlrpc')) {
|
||||
//check if the last registration cron update was less than a week ago
|
||||
$lastcron = get_config('registration', 'crontime');
|
||||
if ($lastcron === false or $lastcron < strtotime("-7 day")) { //set to a week, see MDL-23704
|
||||
$function = 'hub_update_site_info';
|
||||
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
|
||||
$function = 'hub_update_site_info';
|
||||
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
|
||||
|
||||
//update all hub where the site is registered on
|
||||
$hubs = $this->get_registered_on_hubs();
|
||||
foreach ($hubs as $hub) {
|
||||
//update the registration
|
||||
$siteinfo = $this->get_site_info($hub->huburl);
|
||||
$params = array('siteinfo' => $siteinfo);
|
||||
$serverurl = $hub->huburl . "/local/hub/webservice/webservices.php";
|
||||
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
|
||||
try {
|
||||
$result = $xmlrpcclient->call($function, $params);
|
||||
mtrace(get_string('siteupdatedcron', 'hub', $hub->hubname));
|
||||
} catch (Exception $e) {
|
||||
$errorparam = new stdClass();
|
||||
$errorparam->errormessage = $e->getMessage();
|
||||
$errorparam->hubname = $hub->hubname;
|
||||
mtrace(get_string('errorcron', 'hub', $errorparam));
|
||||
}
|
||||
// Update all hubs where the site is registered.
|
||||
$hubs = $this->get_registered_on_hubs();
|
||||
if (empty($hubs)) {
|
||||
mtrace(get_string('registrationwarning', 'admin'));
|
||||
}
|
||||
foreach ($hubs as $hub) {
|
||||
// Update the registration.
|
||||
$siteinfo = $this->get_site_info($hub->huburl);
|
||||
$params = array('siteinfo' => $siteinfo);
|
||||
$serverurl = $hub->huburl . "/local/hub/webservice/webservices.php";
|
||||
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
|
||||
try {
|
||||
$result = $xmlrpcclient->call($function, $params);
|
||||
$this->update_registeredhub($hub); // To update timemodified.
|
||||
mtrace(get_string('siteupdatedcron', 'hub', $hub->hubname));
|
||||
} catch (Exception $e) {
|
||||
$errorparam = new stdClass();
|
||||
$errorparam->errormessage = $e->getMessage();
|
||||
$errorparam->hubname = $hub->hubname;
|
||||
mtrace(get_string('errorcron', 'hub', $errorparam));
|
||||
}
|
||||
set_config('crontime', time(), 'registration');
|
||||
}
|
||||
} else {
|
||||
mtrace(get_string('errorcronnoxmlrpc', 'hub'));
|
||||
|
||||
@@ -177,6 +177,13 @@ if (!empty($error)) {
|
||||
|
||||
//some Moodle.org resitration explanation
|
||||
if ($huburl == HUB_MOODLEORGHUBURL) {
|
||||
if (!empty($registeredhub->token)) {
|
||||
$registrationmessage = get_string('pleaserefreshregistration', 'admin');
|
||||
} else {
|
||||
$registrationmessage = get_string('registrationwarning', 'admin');
|
||||
}
|
||||
echo $OUTPUT->notification($registrationmessage);
|
||||
|
||||
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
|
||||
$renderer = $PAGE->get_renderer('core', 'register');
|
||||
echo $renderer->moodleorg_registration_message();
|
||||
|
||||
@@ -36,13 +36,18 @@ class core_register_renderer extends plugin_renderer_base {
|
||||
* @return string
|
||||
*/
|
||||
public function moodleorg_registration_message() {
|
||||
$moodleorgurl = html_writer::link('http://moodle.org', 'Moodle.org');
|
||||
$moodleorgstatsurl = html_writer::link('http://moodle.org/stats', get_string('statsmoodleorg', 'admin'));
|
||||
$moochurl = html_writer::link(HUB_MOODLEORGHUBURL, get_string('moodleorghubname', 'admin'));
|
||||
$moodleorgregmsg = get_string('registermoodleorg', 'admin', $moodleorgurl);
|
||||
|
||||
$moodleorgstatslink = html_writer::link('http://moodle.net/stats',
|
||||
get_string('statsmoodleorg', 'admin'),
|
||||
array('target' => '_blank'));
|
||||
|
||||
$hublink = html_writer::link('https://moodle.net/mod/page/view.php?id=1',
|
||||
get_string('moodleorghubname', 'admin'),
|
||||
array('target' => '_blank'));
|
||||
|
||||
$moodleorgregmsg = get_string('registermoodleorg', 'admin', $hublink);
|
||||
$items = array(get_string('registermoodleorgli1', 'admin'),
|
||||
get_string('registermoodleorgli2', 'admin', $moodleorgstatsurl),
|
||||
get_string('registermoodleorgli3', 'admin', $moochurl));
|
||||
get_string('registermoodleorgli2', 'admin', $moodleorgstatslink));
|
||||
$moodleorgregmsg .= html_writer::alist($items);
|
||||
return $moodleorgregmsg;
|
||||
}
|
||||
|
||||
+14
-4
@@ -264,6 +264,7 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
$strshow = get_string('on', 'repository');
|
||||
$strhide = get_string('off', 'repository');
|
||||
$strdelete = get_string('disabled', 'repository');
|
||||
$struninstall = get_string('uninstallplugin', 'core_admin');
|
||||
|
||||
$actionchoicesforexisting = array(
|
||||
'show' => $strshow,
|
||||
@@ -286,9 +287,9 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
|
||||
// Table to list plug-ins
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('name'), get_string('isactive', 'repository'), get_string('order'), $settingsstr);
|
||||
$table->head = array(get_string('name'), get_string('isactive', 'repository'), get_string('order'), $settingsstr, $struninstall);
|
||||
|
||||
$table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
|
||||
$table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
|
||||
$table->id = 'repositoriessetting';
|
||||
$table->data = array();
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
@@ -384,7 +385,12 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
|
||||
$updowncount++;
|
||||
|
||||
$table->data[] = array($i->get_readablename(), $OUTPUT->render($select), $updown, $settings);
|
||||
$uninstall = '';
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('repository_' . $typename, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
}
|
||||
|
||||
$table->data[] = array($i->get_readablename(), $OUTPUT->render($select), $updown, $settings, $uninstall);
|
||||
|
||||
if (!in_array($typename, $alreadyplugins)) {
|
||||
$alreadyplugins[] = $typename;
|
||||
@@ -400,7 +406,11 @@ if (($action == 'edit') || ($action == 'new')) {
|
||||
if (!in_array($plugin, $alreadyplugins)) {
|
||||
$select = new single_select(repository_action_url($plugin, 'repos'), 'action', $actionchoicesfornew, 'delete', null, 'applyto' . basename($plugin));
|
||||
$select->set_label(get_string('action'), array('class' => 'accesshide'));
|
||||
$table->data[] = array(get_string('pluginname', 'repository_'.$plugin), $OUTPUT->render($select), '', '');
|
||||
$uninstall = '';
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('repository_' . $plugin, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
}
|
||||
$table->data[] = array(get_string('pluginname', 'repository_'.$plugin), $OUTPUT->render($select), '', '', $uninstall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,7 +472,9 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
|
||||
}
|
||||
|
||||
protected function get_description_field($id) {
|
||||
return print_textarea(true, 10, 50, 50, 10, 'description', $this->role->description, 0, true);
|
||||
return '<textarea class="form-textarea" id="'. s($id) .'" name="description" rows="10" cols="50">' .
|
||||
htmlspecialchars($this->role->description) .
|
||||
'</textarea>';
|
||||
}
|
||||
|
||||
protected function get_archetype_field($id) {
|
||||
|
||||
@@ -46,7 +46,7 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
|
||||
$ADMIN->add('courses',
|
||||
new admin_externalpage('restorecourse', new lang_string('restorecourse', 'admin'),
|
||||
new moodle_url('/backup/restorefile.php', array('contextid' => context_system::instance()->id)),
|
||||
array('moodle/course:create')
|
||||
array('moodle/restore:restorecourse')
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@ if (has_capability('moodle/grade:manage', $systemcontext)
|
||||
$temp->add(new admin_setting_special_gradepointmax());
|
||||
|
||||
$temp->add(new admin_setting_special_gradepointdefault());
|
||||
|
||||
$temp->add(new admin_setting_special_grademinmaxtouse());
|
||||
}
|
||||
$ADMIN->add('grades', $temp);
|
||||
|
||||
|
||||
@@ -114,6 +114,30 @@ class behat_admin extends behat_base {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified site settings. A table with | config | value | (optional)plugin | is expected.
|
||||
*
|
||||
* @Given /^the following config values are set as admin:$/
|
||||
* @param TableNode $table
|
||||
*/
|
||||
public function the_following_config_values_are_set_as_admin(TableNode $table) {
|
||||
|
||||
if (!$data = $table->getRowsHash()) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($data as $config => $value) {
|
||||
// Default plugin value is null.
|
||||
$plugin = null;
|
||||
|
||||
if (is_array($value)) {
|
||||
$plugin = $value[1];
|
||||
$value = $value[0];
|
||||
}
|
||||
set_config($config, $value, $plugin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits with the provided params if we are running a JS session.
|
||||
*
|
||||
|
||||
@@ -7,10 +7,10 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email | auth | confirmed |
|
||||
| user1 | User | One | one@asd.com | manual | 0 |
|
||||
| user2 | User | Two | two@asd.com | ldap | 1 |
|
||||
| user3 | User | Three | three@asd.com | manual | 1 |
|
||||
| user4 | User | Four | four@asd.com | ldap | 0 |
|
||||
| user1 | User | One | one@example.com | manual | 0 |
|
||||
| user2 | User | Two | two@example.com | ldap | 1 |
|
||||
| user3 | User | Three | three@example.com | manual | 1 |
|
||||
| user4 | User | Four | four@example.com | ldap | 0 |
|
||||
And the following "cohorts" exist:
|
||||
| name | idnumber |
|
||||
| Cohort 1 | CH1 |
|
||||
@@ -23,8 +23,8 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
|
||||
| user2 | C1 | student |
|
||||
| user3 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I add "User Two (two@asd.com)" user to "CH1" cohort members
|
||||
And I add "User Three (three@asd.com)" user to "CH1" cohort members
|
||||
And I add "User Two (two@example.com)" user to "CH1" cohort members
|
||||
And I add "User Three (three@example.com)" user to "CH1" cohort members
|
||||
And I follow "Browse list of users"
|
||||
|
||||
@javascript
|
||||
|
||||
@@ -13,15 +13,13 @@ Feature: Set admin settings value
|
||||
And I should not see "C_shortname Course fullname"
|
||||
|
||||
Scenario: set admin value with full name
|
||||
Given I set the following administration settings values:
|
||||
| Display extended course names | 1 |
|
||||
When I press "Save changes"
|
||||
Given the following config values are set as admin:
|
||||
| courselistshortnames | 1 |
|
||||
And I am on homepage
|
||||
Then I should see "C_shortname Course fullname"
|
||||
|
||||
Scenario: set admin value with short name
|
||||
Given I set the following administration settings values:
|
||||
Given the following config values are set as admin:
|
||||
| courselistshortnames | 1 |
|
||||
When I press "Save changes"
|
||||
And I am on homepage
|
||||
Then I should see "C_shortname Course fullname"
|
||||
@@ -21,7 +21,7 @@ Feature: Upload users
|
||||
And I should see "Tom"
|
||||
And I should see "Jones"
|
||||
And I should see "verysecret"
|
||||
And I should see "jonest@someplace.edu"
|
||||
And I should see "jonest@example.com"
|
||||
And I should see "Reznor"
|
||||
And I should see "course1"
|
||||
And I should see "math102"
|
||||
@@ -32,7 +32,7 @@ Feature: Upload users
|
||||
And I follow "Browse list of users"
|
||||
And I should see "Tom Jones"
|
||||
And I should see "Trent Reznor"
|
||||
And I should see "reznor@someplace.edu"
|
||||
And I should see "reznor@example.com"
|
||||
And I am on homepage
|
||||
And I follow "Maths"
|
||||
And I expand "Users" node
|
||||
|
||||
@@ -13,8 +13,8 @@ Feature: Manage availability conditions
|
||||
Then I should not see "Availability restrictions"
|
||||
|
||||
# Enable it and check I can now see and click on it.
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
And I am on homepage
|
||||
And I navigate to "Manage restrictions" node in "Site administration > Plugins > Availability restrictions"
|
||||
|
||||
@@ -28,9 +28,9 @@ Feature: Manage availability conditions
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I am on homepage
|
||||
When I navigate to "Manage restrictions" node in "Site administration > Plugins > Availability restrictions"
|
||||
|
||||
|
||||
@@ -44,13 +44,19 @@ require_once(__DIR__ . '/../../../../lib/behat/lib.php');
|
||||
chdir(__DIR__);
|
||||
$output = null;
|
||||
exec("php util.php --diag", $output, $code);
|
||||
|
||||
// Ensure we have composer installed, before we install or re-install test site.
|
||||
if ($code == TESTING_EXITCODE_COMPOSER || $code == BEHAT_EXITCODE_INSTALL || $code == BEHAT_EXITCODE_REINSTALL) {
|
||||
testing_update_composer_dependencies();
|
||||
chdir(__DIR__);
|
||||
exec("php util.php --diag", $output, $code);
|
||||
}
|
||||
|
||||
if ($code == 0) {
|
||||
echo "Behat test environment already installed\n";
|
||||
|
||||
} else if ($code == BEHAT_EXITCODE_INSTALL) {
|
||||
|
||||
testing_update_composer_dependencies();
|
||||
|
||||
// Behat and dependencies are installed and we need to install the test site.
|
||||
chdir(__DIR__);
|
||||
passthru("php util.php --install", $code);
|
||||
@@ -60,8 +66,6 @@ if ($code == 0) {
|
||||
|
||||
} else if ($code == BEHAT_EXITCODE_REINSTALL) {
|
||||
|
||||
testing_update_composer_dependencies();
|
||||
|
||||
// Test site data is outdated.
|
||||
chdir(__DIR__);
|
||||
passthru("php util.php --drop", $code);
|
||||
@@ -74,18 +78,6 @@ if ($code == 0) {
|
||||
exit($code);
|
||||
}
|
||||
|
||||
} else if ($code == BEHAT_EXITCODE_COMPOSER) {
|
||||
// Missing Behat dependencies.
|
||||
|
||||
testing_update_composer_dependencies();
|
||||
|
||||
// Returning to admin/tool/behat/cli.
|
||||
chdir(__DIR__);
|
||||
passthru("php util.php --install", $code);
|
||||
if ($code != 0) {
|
||||
exit($code);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Generic error, we just output it.
|
||||
echo implode("\n", $output)."\n";
|
||||
|
||||
@@ -165,7 +165,7 @@ class tool_behat_renderer extends plugin_renderer_base {
|
||||
// Info.
|
||||
$installurl = behat_command::DOCS_URL . '#Installation';
|
||||
$installlink = html_writer::tag('a', $installurl, array('href' => $installurl, 'target' => '_blank'));
|
||||
$writetestsurl = behat_command::DOCS_URL . '#Writting_features';
|
||||
$writetestsurl = behat_command::DOCS_URL . '#Writing_features';
|
||||
$writetestslink = html_writer::tag('a', $writetestsurl, array('href' => $writetestsurl, 'target' => '_blank'));
|
||||
$writestepsurl = behat_command::DOCS_URL . '#Adding_steps_definitions';
|
||||
$writestepslink = html_writer::tag('a', $writestepsurl, array('href' => $writestepsurl, 'target' => '_blank'));
|
||||
|
||||
@@ -69,8 +69,8 @@ Feature: Set up contextual data for tests
|
||||
Scenario: Role overrides
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And the following "categories" exist:
|
||||
| name | category | idnumber |
|
||||
| Cat 1 | 0 | CAT1 |
|
||||
@@ -99,7 +99,7 @@ Feature: Set up contextual data for tests
|
||||
Scenario: Add course enrolments
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
@@ -117,11 +117,11 @@ Feature: Set up contextual data for tests
|
||||
| Custom student | custom2 | | |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | User | 1 | user1@moodlemoodle.com |
|
||||
| user2 | User | 2 | user2@moodlemoodle.com |
|
||||
| user3 | User | 3 | user3@moodlemoodle.com |
|
||||
| user4 | User | 4 | user4@moodlemoodle.com |
|
||||
| user5 | User | 5 | user5@moodlemoodle.com |
|
||||
| user1 | User | 1 | user1@example.com |
|
||||
| user2 | User | 2 | user2@example.com |
|
||||
| user3 | User | 3 | user3@example.com |
|
||||
| user4 | User | 4 | user4@example.com |
|
||||
| user5 | User | 5 | user5@example.com |
|
||||
And the following "categories" exist:
|
||||
| name | category | idnumber |
|
||||
| Cat 1 | 0 | CAT1 |
|
||||
@@ -229,8 +229,8 @@ Feature: Set up contextual data for tests
|
||||
Scenario: Add relations between users and groups
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| student2 | Student | 2 | student2@asd.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
| student2 | Student | 2 | student2@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname |
|
||||
| Course 1 | C1 |
|
||||
@@ -269,8 +269,8 @@ Feature: Set up contextual data for tests
|
||||
| Cat 1 | 0 | CAT1 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| student2 | Student | 2 | student2@asd.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
| student2 | Student | 2 | student2@example.com |
|
||||
And the following "cohorts" exist:
|
||||
| name | idnumber |
|
||||
| System cohort A | CHSA |
|
||||
@@ -385,9 +385,9 @@ Feature: Set up contextual data for tests
|
||||
And the following "grade outcomes" exist:
|
||||
| fullname | shortname | course | scale |
|
||||
| Grade outcome 2 | OT2 | C1 | Test Scale 1 |
|
||||
And the following config values are set as admin:
|
||||
| enableoutcomes | 1 |
|
||||
When I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable outcomes | 1 |
|
||||
And I follow "Home"
|
||||
And I follow "Course 1"
|
||||
And I follow "Outcomes"
|
||||
@@ -414,9 +414,9 @@ Feature: Set up contextual data for tests
|
||||
And the following "grade items" exist:
|
||||
| itemname | course | outcome | gradecategory |
|
||||
| Test Outcome Grade Item 1 | C1 | OT1 | Grade category 1 |
|
||||
And the following config values are set as admin:
|
||||
| enableoutcomes | 1 |
|
||||
When I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable outcomes | 1 |
|
||||
And I follow "Home"
|
||||
And I follow "Course 1"
|
||||
And I follow "Grades"
|
||||
|
||||
@@ -7,7 +7,7 @@ Feature: Edit capabilities
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
|
||||
@@ -10,9 +10,9 @@ Feature: Verify that all form fields values can be get and set
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | email | firstname | lastname |
|
||||
| student1 | s1@asd.com | Student | 1 |
|
||||
| student2 | s2@asd.com | Student | 2 |
|
||||
| student3 | s3@asd.com | Student | 3 |
|
||||
| student1 | s1@example.com | Student | 1 |
|
||||
| student2 | s2@example.com | Student | 2 |
|
||||
| student3 | s3@example.com | Student | 3 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
|
||||
@@ -91,19 +91,24 @@ class store implements \tool_log\log\store, \core\log\sql_select_reader {
|
||||
// Replace the query with hardcoded mappings required for core.
|
||||
list($selectwhere, $params, $sort) = self::replace_sql_legacy($selectwhere, $params, $sort);
|
||||
|
||||
$events = array();
|
||||
$records = array();
|
||||
|
||||
try {
|
||||
$records = $DB->get_records_select('log', $selectwhere, $params, $sort, '*', $limitfrom, $limitnum);
|
||||
// A custom report + on the fly SQL rewriting = a possible exception.
|
||||
$records = $DB->get_recordset_select('log', $selectwhere, $params, $sort, '*', $limitfrom, $limitnum);
|
||||
} catch (\moodle_exception $ex) {
|
||||
debugging("error converting legacy event data " . $ex->getMessage() . $ex->debuginfo, DEBUG_DEVELOPER);
|
||||
return array();
|
||||
}
|
||||
|
||||
$events = array();
|
||||
|
||||
foreach ($records as $data) {
|
||||
$events[$data->id] = \logstore_legacy\event\legacy_logged::restore_legacy($data);
|
||||
}
|
||||
|
||||
$records->close();
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,11 +44,26 @@ class cleanup_task extends \core\task\scheduled_task {
|
||||
public function execute() {
|
||||
global $CFG, $DB;
|
||||
|
||||
// Delete old logs to save space (this might need a timer to slow it down...).
|
||||
if (!empty($CFG->loglifetime)) { // Value in days.
|
||||
$loglifetime = time(0) - ($CFG->loglifetime * 3600 * 24);
|
||||
$DB->delete_records_select("log", "time < ?", array($loglifetime));
|
||||
mtrace(" Deleted old legacy log records");
|
||||
if (empty($CFG->loglifetime)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$loglifetime = time() - ($CFG->loglifetime * 3600 * 24); // Value in days.
|
||||
$lifetimep = array($loglifetime);
|
||||
$start = time();
|
||||
|
||||
while ($min = $DB->get_field_select("log", "MIN(time)", "time < ?", $lifetimep)) {
|
||||
// Break this down into chunks to avoid transaction for too long and generally thrashing database.
|
||||
// Experiments suggest deleting one day takes up to a few seconds; probably a reasonable chunk size usually.
|
||||
// If the cleanup has just been enabled, it might take e.g a month to clean the years of logs.
|
||||
$params = array(min($min + 3600 * 24, $loglifetime));
|
||||
$DB->delete_records_select("log", "time < ?", $params);
|
||||
if (time() > $start + 300) {
|
||||
// Do not churn on log deletion for too long each run.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mtrace(" Deleted old legacy log records");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,4 +273,33 @@ class logstore_legacy_store_testcase extends advanced_testcase {
|
||||
$this->assertContains($expectedreport, $reports);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the legacy log cleanup works correctly.
|
||||
*/
|
||||
public function test_cleanup_task() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create some records spread over various days; test multiple iterations in cleanup.
|
||||
$record = (object) array('time' => time());
|
||||
$DB->insert_record('log', $record);
|
||||
$record->time -= 3600 * 24 * 30;
|
||||
$DB->insert_record('log', $record);
|
||||
$record->time -= 3600 * 24 * 30;
|
||||
$DB->insert_record('log', $record);
|
||||
$record->time -= 3600 * 24 * 30;
|
||||
$DB->insert_record('log', $record);
|
||||
$this->assertEquals(4, $DB->count_records('log'));
|
||||
|
||||
// Remove all logs before "today".
|
||||
set_config('loglifetime', 1);
|
||||
|
||||
$this->expectOutputString(" Deleted old legacy log records\n");
|
||||
$clean = new \logstore_legacy\task\cleanup_task();
|
||||
$clean->execute();
|
||||
|
||||
$this->assertEquals(1, $DB->count_records('log'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ class store implements \tool_log\log\writer, \core\log\sql_internal_reader {
|
||||
$sort = self::tweak_sort_by_id($sort);
|
||||
|
||||
$events = array();
|
||||
$records = $DB->get_records_select('logstore_standard_log', $selectwhere, $params, $sort, '*', $limitfrom, $limitnum);
|
||||
$records = $DB->get_recordset_select('logstore_standard_log', $selectwhere, $params, $sort, '*', $limitfrom, $limitnum);
|
||||
|
||||
foreach ($records as $data) {
|
||||
$extra = array('origin' => $data->origin, 'ip' => $data->ip, 'realuserid' => $data->realuserid);
|
||||
@@ -94,6 +94,8 @@ class store implements \tool_log\log\writer, \core\log\sql_internal_reader {
|
||||
}
|
||||
}
|
||||
|
||||
$records->close();
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,12 +43,29 @@ class cleanup_task extends \core\task\scheduled_task {
|
||||
*/
|
||||
public function execute() {
|
||||
global $DB;
|
||||
|
||||
$loglifetime = (int)get_config('logstore_standard', 'loglifetime');
|
||||
|
||||
if ($loglifetime > 0) {
|
||||
$loglifetime = time() - ($loglifetime * 3600 * 24); // Value in days.
|
||||
$DB->delete_records_select("logstore_standard_log", "timecreated < ?", array($loglifetime));
|
||||
mtrace(" Deleted old log records from standard store.");
|
||||
if (empty($loglifetime) || $loglifetime < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$loglifetime = time() - ($loglifetime * 3600 * 24); // Value in days.
|
||||
$lifetimep = array($loglifetime);
|
||||
$start = time();
|
||||
|
||||
while ($min = $DB->get_field_select("logstore_standard_log", "MIN(timecreated)", "timecreated < ?", $lifetimep)) {
|
||||
// Break this down into chunks to avoid transaction for too long and generally thrashing database.
|
||||
// Experiments suggest deleting one day takes up to a few seconds; probably a reasonable chunk size usually.
|
||||
// If the cleanup has just been enabled, it might take e.g a month to clean the years of logs.
|
||||
$params = array(min($min + 3600 * 24, $loglifetime));
|
||||
$DB->delete_records_select("logstore_standard_log", "timecreated < ?", $params);
|
||||
if (time() > $start + 300) {
|
||||
// Do not churn on log deletion for too long each run.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mtrace(" Deleted old log records from standard store.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,4 +218,41 @@ class logstore_standard_store_testcase extends advanced_testcase {
|
||||
$this->assertContains($expectedreport, $reports);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the standard log cleanup works correctly.
|
||||
*/
|
||||
public function test_cleanup_task() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create some records spread over various days; test multiple iterations in cleanup.
|
||||
$ctx = context_course::instance(1);
|
||||
$record = (object) array(
|
||||
'edulevel' => 0,
|
||||
'contextid' => $ctx->id,
|
||||
'contextlevel' => $ctx->contextlevel,
|
||||
'contextinstanceid' => $ctx->instanceid,
|
||||
'userid' => 1,
|
||||
'timecreated' => time(),
|
||||
);
|
||||
$DB->insert_record('logstore_standard_log', $record);
|
||||
$record->timecreated -= 3600 * 24 * 30;
|
||||
$DB->insert_record('logstore_standard_log', $record);
|
||||
$record->timecreated -= 3600 * 24 * 30;
|
||||
$DB->insert_record('logstore_standard_log', $record);
|
||||
$record->timecreated -= 3600 * 24 * 30;
|
||||
$DB->insert_record('logstore_standard_log', $record);
|
||||
$this->assertEquals(4, $DB->count_records('logstore_standard_log'));
|
||||
|
||||
// Remove all logs before "today".
|
||||
set_config('loglifetime', 1, 'logstore_standard');
|
||||
|
||||
$this->expectOutputString(" Deleted old log records from standard store.\n");
|
||||
$clean = new \logstore_standard\task\cleanup_task();
|
||||
$clean->execute();
|
||||
|
||||
$this->assertEquals(1, $DB->count_records('logstore_standard_log'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@ if ($hassiteconfig) {
|
||||
$settings->add(new admin_setting_heading('messageinbound_mailboxconfiguration',
|
||||
new lang_string('mailboxconfiguration', 'tool_messageinbound'),
|
||||
new lang_string('messageinboundmailboxconfiguration_desc', 'tool_messageinbound'), ''));
|
||||
$settings->add(new admin_setting_configtext('messageinbound_mailbox',
|
||||
$settings->add(new admin_setting_configtext_with_maxlength('messageinbound_mailbox',
|
||||
new lang_string('mailbox', 'tool_messageinbound'),
|
||||
null, '', PARAM_RAW));
|
||||
null, '', PARAM_RAW, null, 15));
|
||||
$settings->add(new admin_setting_configtext('messageinbound_domain',
|
||||
new lang_string('domain', 'tool_messageinbound'),
|
||||
null, '', PARAM_RAW));
|
||||
|
||||
@@ -215,7 +215,10 @@ class rules extends \table_sql implements \renderable {
|
||||
return false;
|
||||
}
|
||||
$orderby = 'visible DESC, sortorder ASC';
|
||||
$options = array(0 => get_string('site'));
|
||||
$options = array();
|
||||
if (has_capability('tool/monitor:subscribe', \context_system::instance())) {
|
||||
$options[0] = get_string('site');
|
||||
}
|
||||
if ($courses = get_user_capability_course('tool/monitor:subscribe', null, true, 'fullname', $orderby)) {
|
||||
foreach ($courses as $course) {
|
||||
$options[$course->id] = format_string($course->fullname, true,
|
||||
@@ -223,7 +226,7 @@ class rules extends \table_sql implements \renderable {
|
||||
}
|
||||
}
|
||||
$url = new \moodle_url('/admin/tool/monitor/index.php');
|
||||
$select = new \single_select($url, 'courseid', $options, $this->courseid);
|
||||
$select = new \single_select($url, 'courseid', $options, $this->courseid, array());
|
||||
$select->set_label(get_string('selectacourse', 'tool_monitor'));
|
||||
return $select;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ $confirm = optional_param('confirm', false, PARAM_BOOL);
|
||||
// Validate course id.
|
||||
if (empty($courseid)) {
|
||||
require_login();
|
||||
require_capability('tool/monitor:subscribe', context_system::instance());
|
||||
} else {
|
||||
// They might want to see rules for this course.
|
||||
$course = get_course($courseid);
|
||||
|
||||
@@ -10,7 +10,7 @@ Feature: tool_monitor_rule
|
||||
| Course 1 | C1 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@@ -11,8 +11,8 @@ Feature: tool_monitor_subscriptions
|
||||
| Course 2 | C2 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
| teacher2 | Teacher | 2 | teacher2@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
| teacher2 | Teacher | 2 | teacher2@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
@@ -150,8 +150,6 @@ Feature: tool_monitor_subscriptions
|
||||
And I should see "You can subscribe to rules from the Event monitoring page."
|
||||
And I click on "//a[text()='Event monitoring']" "xpath_element"
|
||||
And the field "courseid" matches value "Course 1"
|
||||
And I set the field "courseid" to "Site"
|
||||
And I should not see "You can manage rules from the Event monitoring rules page."
|
||||
And I log out
|
||||
And I log in as "teacher2"
|
||||
And I follow "Course 1"
|
||||
|
||||
@@ -109,25 +109,29 @@ if ($execute = $options['execute']) {
|
||||
|
||||
$predbqueries = $DB->perf_get_queries();
|
||||
$pretime = microtime(true);
|
||||
|
||||
mtrace("Scheduled task: " . $task->get_name());
|
||||
// NOTE: it would be tricky to move this code to \core\task\manager class,
|
||||
// because we want to do detailed error reporting.
|
||||
$cronlockfactory = \core\lock\lock_config::get_lock_factory('cron');
|
||||
if (!$cronlock = $cronlockfactory->get_lock('core_cron', 10)) {
|
||||
mtrace('Cannot obtain cron lock');
|
||||
exit(129);
|
||||
}
|
||||
if (!$lock = $cronlockfactory->get_lock('\\' . get_class($task), 10)) {
|
||||
$cronlock->release();
|
||||
mtrace('Cannot obtain task lock');
|
||||
exit(130);
|
||||
}
|
||||
|
||||
$task->set_lock($lock);
|
||||
if (!$task->is_blocking()) {
|
||||
$cronlock->release();
|
||||
} else {
|
||||
$task->set_cron_lock($cronlock);
|
||||
}
|
||||
|
||||
try {
|
||||
mtrace("Scheduled task: " . $task->get_name());
|
||||
// NOTE: it would be tricky to move this code to \core\task\manager class,
|
||||
// because we want to do detailed error reporting.
|
||||
$cronlockfactory = \core\lock\lock_config::get_lock_factory('cron');
|
||||
if (!$cronlock = $cronlockfactory->get_lock('core_cron', 10)) {
|
||||
mtrace('Cannot obtain cron lock');
|
||||
exit(129);
|
||||
}
|
||||
if (!$lock = $cronlockfactory->get_lock('\\' . get_class($task), 10)) {
|
||||
mtrace('Cannot obtain task lock');
|
||||
exit(130);
|
||||
}
|
||||
$task->set_lock($lock);
|
||||
if (!$task->is_blocking()) {
|
||||
$cronlock->release();
|
||||
} else {
|
||||
$task->set_cron_lock($cronlock);
|
||||
}
|
||||
get_mailer('buffer');
|
||||
$task->execute();
|
||||
if (isset($predbqueries)) {
|
||||
|
||||
@@ -402,8 +402,13 @@ function uu_pre_process_custom_profile_data($data) {
|
||||
function uu_check_custom_profile_data(&$data) {
|
||||
global $CFG, $DB;
|
||||
$noerror = true;
|
||||
|
||||
// find custom profile fields and check if data needs to converted.
|
||||
$testuserid = null;
|
||||
if (!empty($data['username'])) {
|
||||
if (preg_match('/id=(.*)"/i', $data['username'], $result)) {
|
||||
$testuserid = $result[1];
|
||||
}
|
||||
}
|
||||
// Find custom profile fields and check if data needs to converted.
|
||||
foreach ($data as $key => $value) {
|
||||
if (preg_match('/^profile_field_/', $key)) {
|
||||
$shortname = str_replace('profile_field_', '', $key);
|
||||
@@ -413,13 +418,24 @@ function uu_check_custom_profile_data(&$data) {
|
||||
$newfield = 'profile_field_'.$field->datatype;
|
||||
$formfield = new $newfield($field->id, 0);
|
||||
if (method_exists($formfield, 'convert_external_data') &&
|
||||
is_null($formfield->convert_external_data($value))) {
|
||||
is_null($formfield->convert_external_data($value))) {
|
||||
$data['status'][] = get_string('invaliduserfield', 'error', $shortname);
|
||||
$noerror = false;
|
||||
}
|
||||
// Check for duplicate value.
|
||||
if (method_exists($formfield, 'edit_validate_field') ) {
|
||||
$testuser = new stdClass();
|
||||
$testuser->{$key} = $value;
|
||||
$testuser->id = $testuserid;
|
||||
$err = $formfield->edit_validate_field($testuser);
|
||||
if (!empty($err[$key])) {
|
||||
$data['status'][] = $err[$key].' ('.$key.')';
|
||||
$noerror = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $noerror;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-2
@@ -190,9 +190,14 @@
|
||||
// We don't need to check the fullnamedisplay setting here as the fullname function call further down has
|
||||
// the override parameter set to true.
|
||||
$fullnamesetting = $CFG->alternativefullnameformat;
|
||||
// If we are using language or it is empty, then retrieve all of the user's names.
|
||||
// If we are using language or it is empty, then retrieve the default user names of just 'firstname' and 'lastname'.
|
||||
if ($fullnamesetting == 'language' || empty($fullnamesetting)) {
|
||||
$fullnamesetting = implode(' ', $allusernamefields);
|
||||
// Set $a variables to return 'firstname' and 'lastname'.
|
||||
$a = new stdClass();
|
||||
$a->firstname = 'firstname';
|
||||
$a->lastname = 'lastname';
|
||||
// Getting the fullname display will ensure that the order in the language file is maintained.
|
||||
$fullnamesetting = get_string('fullnamedisplay', null, $a);
|
||||
}
|
||||
|
||||
// Order in string will ensure that the name columns are in the correct order.
|
||||
|
||||
+4
-4
@@ -139,12 +139,12 @@ class auth_plugin_email extends auth_plugin_base {
|
||||
$user = get_complete_user_data('username', $username);
|
||||
|
||||
if (!empty($user)) {
|
||||
if ($user->confirmed) {
|
||||
return AUTH_CONFIRM_ALREADY;
|
||||
|
||||
} else if ($user->auth != $this->authtype) {
|
||||
if ($user->auth != $this->authtype) {
|
||||
return AUTH_CONFIRM_ERROR;
|
||||
|
||||
} else if ($user->secret == $confirmsecret && $user->confirmed) {
|
||||
return AUTH_CONFIRM_ALREADY;
|
||||
|
||||
} else if ($user->secret == $confirmsecret) { // They have provided the secret key to get in
|
||||
$DB->set_field("user", "confirmed", 1, array("id"=>$user->id));
|
||||
if ($user->firstaccess == 0) {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
$string['auth_emaildescription'] = '<p>Email-based self-registration enables a user to create their own account via a \'Create new account\' button on the login page. The user then receives an email containing a secure link to a page where they can confirm their account. Future logins just check the username and password against the stored values in the Moodle database.</p><p>Note: In addition to enabling the plugin, email-based self-registration must also be selected from the self registration drop-down menu on the \'Manage authentication\' page.</p>';
|
||||
$string['auth_emailnoemail'] = 'Tried to send you an email but failed!';
|
||||
$string['auth_emailrecaptcha'] = 'Adds a visual/audio confirmation form element to the signup page for email self-registering users. This protects your site against spammers and contributes to a worthwhile cause. See http://www.google.com/recaptcha/learnmore for more details. <br /><em>PHP cURL extension is required.</em>';
|
||||
$string['auth_emailrecaptcha'] = 'Adds a visual/audio confirmation form element to the sign-up page for email self-registering users. This protects your site against spammers and contributes to a worthwhile cause. See http://www.google.com/recaptcha for more details.';
|
||||
$string['auth_emailrecaptcha_key'] = 'Enable reCAPTCHA element';
|
||||
$string['auth_emailsettings'] = 'Settings';
|
||||
$string['pluginname'] = 'Email-based self-registration';
|
||||
|
||||
+13
-8
@@ -534,6 +534,7 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
*
|
||||
* @param object $user new user object
|
||||
* @param boolean $notify print notice with link and terminate
|
||||
* @return boolean success
|
||||
*/
|
||||
function user_signup($user, $notify=true) {
|
||||
global $CFG, $DB, $PAGE, $OUTPUT;
|
||||
@@ -604,12 +605,12 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
$user = get_complete_user_data('username', $username);
|
||||
|
||||
if (!empty($user)) {
|
||||
if ($user->confirmed) {
|
||||
return AUTH_CONFIRM_ALREADY;
|
||||
|
||||
} else if ($user->auth != $this->authtype) {
|
||||
if ($user->auth != $this->authtype) {
|
||||
return AUTH_CONFIRM_ERROR;
|
||||
|
||||
} else if ($user->secret == $confirmsecret && $user->confirmed) {
|
||||
return AUTH_CONFIRM_ALREADY;
|
||||
|
||||
} else if ($user->secret == $confirmsecret) { // They have provided the secret key to get in
|
||||
if (!$this->user_activate($username)) {
|
||||
return AUTH_CONFIRM_FAIL;
|
||||
@@ -889,7 +890,7 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
|
||||
foreach ($users as $user) {
|
||||
echo "\t"; print_string('auth_dbupdatinguser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id));
|
||||
if (!$this->update_user_record($user->username, $updatekeys)) {
|
||||
if (!$this->update_user_record($user->username, $updatekeys, true)) {
|
||||
echo ' - '.get_string('skipped');
|
||||
}
|
||||
echo "\n";
|
||||
@@ -987,8 +988,11 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
*
|
||||
* @param string $username username
|
||||
* @param boolean $updatekeys true to update the local record with the external LDAP values.
|
||||
* @param bool $triggerevent set false if user_updated event should not be triggered.
|
||||
* This will not affect user_password_updated event triggering.
|
||||
* @return stdClass|bool updated user record or false if there is no new info to update.
|
||||
*/
|
||||
function update_user_record($username, $updatekeys = false) {
|
||||
function update_user_record($username, $updatekeys = false, $triggerevent = false) {
|
||||
global $CFG, $DB;
|
||||
|
||||
// Just in case check text case
|
||||
@@ -1030,7 +1034,7 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
}
|
||||
}
|
||||
}
|
||||
user_update_user($newuser, false, false);
|
||||
user_update_user($newuser, false, $triggerevent);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
@@ -1653,7 +1657,8 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
$_SERVER['HTTP_REFERER'] != $CFG->wwwroot &&
|
||||
$_SERVER['HTTP_REFERER'] != $CFG->wwwroot.'/' &&
|
||||
$_SERVER['HTTP_REFERER'] != $CFG->httpswwwroot.'/login/' &&
|
||||
$_SERVER['HTTP_REFERER'] != $CFG->httpswwwroot.'/login/index.php')
|
||||
$_SERVER['HTTP_REFERER'] != $CFG->httpswwwroot.'/login/index.php' &&
|
||||
clean_param($_SERVER['HTTP_REFERER'], PARAM_LOCALURL) != '')
|
||||
? $_SERVER['HTTP_REFERER'] : NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,9 +136,25 @@ class auth_ldap_plugin_testcase extends advanced_testcase {
|
||||
$auth = get_auth_plugin('ldap');
|
||||
|
||||
ob_start();
|
||||
$sink = $this->redirectEvents();
|
||||
$auth->sync_users(true);
|
||||
$events = $sink->get_events();
|
||||
$sink->close();
|
||||
ob_end_clean();
|
||||
|
||||
// Check events, 5 users created with 2 users having roles.
|
||||
$this->assertCount(7, $events);
|
||||
foreach ($events as $index => $event) {
|
||||
$usercreatedindex = array(0, 2, 4, 5, 6);
|
||||
$roleassignedindex = array (1, 3);
|
||||
if (in_array($index, $usercreatedindex)) {
|
||||
$this->assertInstanceOf('\core\event\user_created', $event);
|
||||
}
|
||||
if (in_array($index, $roleassignedindex)) {
|
||||
$this->assertInstanceOf('\core\event\role_assigned', $event);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
|
||||
$this->assertEquals(2, $DB->count_records('role_assignments'));
|
||||
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id)));
|
||||
@@ -150,9 +166,15 @@ class auth_ldap_plugin_testcase extends advanced_testcase {
|
||||
$this->delete_ldap_user($connection, $topdn, 1);
|
||||
|
||||
ob_start();
|
||||
$sink = $this->redirectEvents();
|
||||
$auth->sync_users(true);
|
||||
$events = $sink->get_events();
|
||||
$sink->close();
|
||||
ob_end_clean();
|
||||
|
||||
// Check events, no new event.
|
||||
$this->assertCount(0, $events);
|
||||
|
||||
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
|
||||
@@ -166,9 +188,17 @@ class auth_ldap_plugin_testcase extends advanced_testcase {
|
||||
$auth = get_auth_plugin('ldap');
|
||||
|
||||
ob_start();
|
||||
$sink = $this->redirectEvents();
|
||||
$auth->sync_users(true);
|
||||
$events = $sink->get_events();
|
||||
$sink->close();
|
||||
ob_end_clean();
|
||||
|
||||
// Check events, 1 user got updated.
|
||||
$this->assertCount(1, $events);
|
||||
$event = reset($events);
|
||||
$this->assertInstanceOf('\core\event\user_updated', $event);
|
||||
|
||||
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('auth'=>'nologin', 'username'=>'username1')));
|
||||
$this->assertEquals(1, $DB->count_records('user', array('auth'=>'ldap', 'suspended'=>'1', 'username'=>'username1')));
|
||||
@@ -179,9 +209,17 @@ class auth_ldap_plugin_testcase extends advanced_testcase {
|
||||
$this->create_ldap_user($connection, $topdn, 1);
|
||||
|
||||
ob_start();
|
||||
$sink = $this->redirectEvents();
|
||||
$auth->sync_users(true);
|
||||
$events = $sink->get_events();
|
||||
$sink->close();
|
||||
ob_end_clean();
|
||||
|
||||
// Check events, 1 user got updated.
|
||||
$this->assertCount(1, $events);
|
||||
$event = reset($events);
|
||||
$this->assertInstanceOf('\core\event\user_updated', $event);
|
||||
|
||||
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
|
||||
@@ -191,9 +229,17 @@ class auth_ldap_plugin_testcase extends advanced_testcase {
|
||||
$DB->set_field('user', 'auth', 'nologin', array('username'=>'username1'));
|
||||
|
||||
ob_start();
|
||||
$sink = $this->redirectEvents();
|
||||
$auth->sync_users(true);
|
||||
$events = $sink->get_events();
|
||||
$sink->close();
|
||||
ob_end_clean();
|
||||
|
||||
// Check events, 1 user got updated.
|
||||
$this->assertCount(1, $events);
|
||||
$event = reset($events);
|
||||
$this->assertInstanceOf('\core\event\user_updated', $event);
|
||||
|
||||
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('deleted'=>1)));
|
||||
@@ -208,9 +254,19 @@ class auth_ldap_plugin_testcase extends advanced_testcase {
|
||||
$this->delete_ldap_user($connection, $topdn, 1);
|
||||
|
||||
ob_start();
|
||||
$sink = $this->redirectEvents();
|
||||
$auth->sync_users(true);
|
||||
$events = $sink->get_events();
|
||||
$sink->close();
|
||||
ob_end_clean();
|
||||
|
||||
// Check events, 2 events role_unassigned and user_deleted.
|
||||
$this->assertCount(2, $events);
|
||||
$event = array_pop($events);
|
||||
$this->assertInstanceOf('\core\event\user_deleted', $event);
|
||||
$event = array_pop($events);
|
||||
$this->assertInstanceOf('\core\event\role_unassigned', $event);
|
||||
|
||||
$this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap')));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('username'=>'username1')));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
|
||||
@@ -221,9 +277,19 @@ class auth_ldap_plugin_testcase extends advanced_testcase {
|
||||
$this->create_ldap_user($connection, $topdn, 1);
|
||||
|
||||
ob_start();
|
||||
$sink = $this->redirectEvents();
|
||||
$auth->sync_users(true);
|
||||
$events = $sink->get_events();
|
||||
$sink->close();
|
||||
ob_end_clean();
|
||||
|
||||
// Check events, 2 events role_assigned and user_created.
|
||||
$this->assertCount(2, $events);
|
||||
$event = array_pop($events);
|
||||
$this->assertInstanceOf('\core\event\role_assigned', $event);
|
||||
$event = array_pop($events);
|
||||
$this->assertInstanceOf('\core\event\user_created', $event);
|
||||
|
||||
$this->assertEquals(6, $DB->count_records('user', array('auth'=>'ldap')));
|
||||
$this->assertEquals(1, $DB->count_records('user', array('username'=>'username1')));
|
||||
$this->assertEquals(0, $DB->count_records('user', array('suspended'=>1)));
|
||||
@@ -296,7 +362,7 @@ class auth_ldap_plugin_testcase extends advanced_testcase {
|
||||
'lastnamephonetic' => '最後のお名前のテスト一号',
|
||||
'firstnamephonetic' => 'お名前のテスト一号',
|
||||
'alternatename' => 'Alternate Name User Test 1',
|
||||
'email' => 'usersignuptest1@email.com',
|
||||
'email' => 'usersignuptest1@example.com',
|
||||
'description' => 'This is a description for user 1',
|
||||
'city' => 'Perth',
|
||||
'country' => 'au',
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
This files describes API changes in the auth_ldap code.
|
||||
=== 2.8.7 ===
|
||||
* auth_plugin_ldap::update_user_record() accepts an additional (optional) param
|
||||
to trigger update event.
|
||||
@@ -16,7 +16,7 @@ Feature: Authentication
|
||||
Scenario: Log in as an existing admin user filling the form
|
||||
Given the following "users" exist:
|
||||
| username | password | firstname | lastname | email |
|
||||
| testuser | testuser | Test | User | moodle@moodlemoodle.com |
|
||||
| testuser | testuser | Test | User | moodle@example.com |
|
||||
And I am on homepage
|
||||
When I follow "Log in"
|
||||
And I set the field "Username" to "testuser"
|
||||
@@ -27,7 +27,7 @@ Feature: Authentication
|
||||
Scenario: Log in as an unexisting user filling the form
|
||||
Given the following "users" exist:
|
||||
| username | password | firstname | lastname | email |
|
||||
| testuser | testuser | Test | User | moodle@moodlemoodle.com |
|
||||
| testuser | testuser | Test | User | moodle@example.com |
|
||||
And I am on homepage
|
||||
When I follow "Log in"
|
||||
And I set the field "Username" to "testuser"
|
||||
|
||||
@@ -53,8 +53,8 @@ class condition extends \core_availability\condition {
|
||||
*/
|
||||
public function __construct($structure) {
|
||||
// Get cmid.
|
||||
if (isset($structure->cm) && is_int($structure->cm)) {
|
||||
$this->cmid = $structure->cm;
|
||||
if (isset($structure->cm) && is_number($structure->cm)) {
|
||||
$this->cmid = (int)$structure->cm;
|
||||
} else {
|
||||
throw new \coding_exception('Missing or invalid ->cm for completion condition');
|
||||
}
|
||||
|
||||
@@ -16,11 +16,9 @@ Feature: availability_completion
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
| Enable completion tracking | 1 |
|
||||
And I log out
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
| enablecompletion | 1 |
|
||||
|
||||
@javascript
|
||||
Scenario: Test condition
|
||||
|
||||
@@ -16,10 +16,8 @@ Feature: availability_date
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I log out
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
|
||||
@javascript
|
||||
Scenario: Test condition
|
||||
|
||||
@@ -10,16 +10,14 @@ Feature: availability_grade
|
||||
| Course 1 | C1 | topics | 1 |
|
||||
And the following "users" exist:
|
||||
| username | email |
|
||||
| teacher1 | t@example.org |
|
||||
| student1 | s@example.org |
|
||||
| teacher1 | t@example.com |
|
||||
| student1 | s@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I log out
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
|
||||
@javascript
|
||||
Scenario: Test condition
|
||||
@@ -60,8 +58,22 @@ Feature: availability_grade
|
||||
And I set the field "Grade" to "A1"
|
||||
And I click on "min" "checkbox" in the ".availability-item" "css_element"
|
||||
And I set the field "Minimum grade percentage (inclusive)" to "50"
|
||||
And I click on "max" "checkbox" in the ".availability-item" "css_element"
|
||||
And I set the field "Maximum grade percentage (exclusive)" to "80"
|
||||
And I press "Save and return to course"
|
||||
|
||||
# Check if disabling a part of the restriction is get saved.
|
||||
And I open "P3" actions menu
|
||||
And I click on "Edit settings" "link" in the "P3" activity
|
||||
And I expand all fieldsets
|
||||
And I click on "max" "checkbox" in the ".availability-item" "css_element"
|
||||
And I press "Save and return to course"
|
||||
And I open "P3" actions menu
|
||||
And I click on "Edit settings" "link" in the "P3" activity
|
||||
And I expand all fieldsets
|
||||
And the field "Maximum grade percentage (exclusive)" matches value ""
|
||||
And I follow "Course 1"
|
||||
|
||||
# Add a Page with a grade condition for 10%.
|
||||
And I add a "Page" to section "4"
|
||||
And I set the following fields to these values:
|
||||
@@ -103,8 +115,8 @@ Feature: availability_grade
|
||||
# Give the assignment 40%.
|
||||
And I follow "A1"
|
||||
And I follow "View/grade all submissions"
|
||||
# Pick the grade link in the row that has s@example.org in it.
|
||||
And I click on "//a[contains(@href, 'action=grade') and ancestor::tr/td[normalize-space(.) = 's@example.org']]/img" "xpath_element"
|
||||
# Pick the grade link in the row that has s@example.com in it.
|
||||
And I click on "//a[contains(@href, 'action=grade') and ancestor::tr/td[normalize-space(.) = 's@example.com']]/img" "xpath_element"
|
||||
And I set the field "Grade out of 100" to "40"
|
||||
And I click on "Save changes" "button"
|
||||
|
||||
|
||||
+1
@@ -95,6 +95,7 @@ M.availability_grade.form.getNode = function(json) {
|
||||
|
||||
root.delegate('click', function() {
|
||||
updateCheckbox(this, true);
|
||||
M.core_availability.form.update();
|
||||
}, '.availability_grade input[type=checkbox]');
|
||||
|
||||
root.delegate('valuechange', function() {
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
YUI.add("moodle-availability_grade-form",function(e,t){M.availability_grade=M.availability_grade||{},M.availability_grade.form=e.Object(M.core_availability.plugin),M.availability_grade.form.grades=null,M.availability_grade.form.initInner=function(e){this.grades=e,this.nodesSoFar=0},M.availability_grade.form.getNode=function(t){this.nodesSoFar++;var n=M.str.availability_grade,r="<label>"+n.title+' <span class="availability-group">'+'<select name="id"><option value="0">'+M.str.moodle.choosedots+"</option>";for(var i=0;i<this.grades.length;i++){var s=this.grades[i];r+='<option value="'+s.id+'">'+s.name+"</option>"}r+='</select></span></label> <span class="availability-group"><label><input type="checkbox" name="min"/>'+n.option_min+'</label> <label><span class="accesshide">'+n.label_min+'</span><input type="text" name="minval" title="'+n.label_min+'"/></label>%</span>'+'<span class="availability-group">'+'<label><input type="checkbox" name="max"/>'+n.option_max+'</label> <label><span class="accesshide">'+n.label_max+'</span><input type="text" name="maxval" title="'+n.label_max+'"/></label>%</span>';var o=e.Node.create("<span>"+r+"</span>");t.id!==undefined&&o.one("select[name=id] > option[value="+t.id+"]")&&o.one("select[name=id]").set("value",""+t.id),t.min!==undefined&&(o.one("input[name=min]").set("checked",!0),o.one("input[name=minval]").set("value",t.min)),t.max!==undefined&&(o.one("input[name=max]").set("checked",!0),o.one("input[name=maxval]").set("value",t.max));var u=function(e,t){var n=e.ancestor("label").next("label").one("input"),r=e.get("checked");return n.set("disabled",!r),t&&r&&n.focus(),r};o.all("input[type=checkbox]").each(u);if(!M.availability_grade.form.addedEvents){M.availability_grade.form.addedEvents=!0;var a=e.one("#fitem_id_availabilityconditionsjson");a.delegate("change",function(){M.core_availability.form.update()},".availability_grade select[name=id]"),a.delegate("click",function(){u(this,!0)},".availability_grade input[type=checkbox]"),a.delegate("valuechange",function(){M.core_availability.form.update()},".availability_grade input[type=text]")}return o},M.availability_grade.form.fillValue=function(e,t){e.id=parseInt(t.one("select[name=id]").get("value"),10),t.one("input[name=min]").get("checked")&&(e.min=this.getValue("minval",t)),t.one("input[name=max]").get("checked")&&(e.max=this.getValue("maxval",t))},M.availability_grade.form.getValue=function(e,t){var n=t.one("input[name="+e+"]").get("value");if(!/^[0-9]+([.,][0-9]+)?$/.test(n))return n;var r=parseFloat(n.replace(",","."));return r<0||r>100?n:r},M.availability_grade.form.fillErrors=function(e,t){var n={};this.fillValue(n,t),n.id===0&&e.push("availability_grade:error_selectgradeid"),n.min!==undefined&&typeof n.min=="string"||n.max!==undefined&&typeof n.max=="string"?e.push("availability_grade:error_invalidnumber"):n.min!==undefined&&n.max!==undefined&&n.min>=n.max&&e.push("availability_grade:error_backwardrange")}},"@VERSION@",{requires:["base","node","event","moodle-core_availability-form"]});
|
||||
YUI.add("moodle-availability_grade-form",function(e,t){M.availability_grade=M.availability_grade||{},M.availability_grade.form=e.Object(M.core_availability.plugin),M.availability_grade.form.grades=null,M.availability_grade.form.initInner=function(e){this.grades=e,this.nodesSoFar=0},M.availability_grade.form.getNode=function(t){this.nodesSoFar++;var n=M.str.availability_grade,r="<label>"+n.title+' <span class="availability-group">'+'<select name="id"><option value="0">'+M.str.moodle.choosedots+"</option>";for(var i=0;i<this.grades.length;i++){var s=this.grades[i];r+='<option value="'+s.id+'">'+s.name+"</option>"}r+='</select></span></label> <span class="availability-group"><label><input type="checkbox" name="min"/>'+n.option_min+'</label> <label><span class="accesshide">'+n.label_min+'</span><input type="text" name="minval" title="'+n.label_min+'"/></label>%</span>'+'<span class="availability-group">'+'<label><input type="checkbox" name="max"/>'+n.option_max+'</label> <label><span class="accesshide">'+n.label_max+'</span><input type="text" name="maxval" title="'+n.label_max+'"/></label>%</span>';var o=e.Node.create("<span>"+r+"</span>");t.id!==undefined&&o.one("select[name=id] > option[value="+t.id+"]")&&o.one("select[name=id]").set("value",""+t.id),t.min!==undefined&&(o.one("input[name=min]").set("checked",!0),o.one("input[name=minval]").set("value",t.min)),t.max!==undefined&&(o.one("input[name=max]").set("checked",!0),o.one("input[name=maxval]").set("value",t.max));var u=function(e,t){var n=e.ancestor("label").next("label").one("input"),r=e.get("checked");return n.set("disabled",!r),t&&r&&n.focus(),r};o.all("input[type=checkbox]").each(u);if(!M.availability_grade.form.addedEvents){M.availability_grade.form.addedEvents=!0;var a=e.one("#fitem_id_availabilityconditionsjson");a.delegate("change",function(){M.core_availability.form.update()},".availability_grade select[name=id]"),a.delegate("click",function(){u(this,!0),M.core_availability.form.update()},".availability_grade input[type=checkbox]"),a.delegate("valuechange",function(){M.core_availability.form.update()},".availability_grade input[type=text]")}return o},M.availability_grade.form.fillValue=function(e,t){e.id=parseInt(t.one("select[name=id]").get("value"),10),t.one("input[name=min]").get("checked")&&(e.min=this.getValue("minval",t)),t.one("input[name=max]").get("checked")&&(e.max=this.getValue("maxval",t))},M.availability_grade.form.getValue=function(e,t){var n=t.one("input[name="+e+"]").get("value");if(!/^[0-9]+([.,][0-9]+)?$/.test(n))return n;var r=parseFloat(n.replace(",","."));return r<0||r>100?n:r},M.availability_grade.form.fillErrors=function(e,t){var n={};this.fillValue(n,t),n.id===0&&e.push("availability_grade:error_selectgradeid"),n.min!==undefined&&typeof n.min=="string"||n.max!==undefined&&typeof n.max=="string"?e.push("availability_grade:error_invalidnumber"):n.min!==undefined&&n.max!==undefined&&n.min>=n.max&&e.push("availability_grade:error_backwardrange")}},"@VERSION@",{requires:["base","node","event","moodle-core_availability-form"]});
|
||||
|
||||
+1
@@ -95,6 +95,7 @@ M.availability_grade.form.getNode = function(json) {
|
||||
|
||||
root.delegate('click', function() {
|
||||
updateCheckbox(this, true);
|
||||
M.core_availability.form.update();
|
||||
}, '.availability_grade input[type=checkbox]');
|
||||
|
||||
root.delegate('valuechange', function() {
|
||||
|
||||
@@ -93,6 +93,7 @@ M.availability_grade.form.getNode = function(json) {
|
||||
|
||||
root.delegate('click', function() {
|
||||
updateCheckbox(this, true);
|
||||
M.core_availability.form.update();
|
||||
}, '.availability_grade input[type=checkbox]');
|
||||
|
||||
root.delegate('valuechange', function() {
|
||||
|
||||
@@ -16,10 +16,8 @@ Feature: availability_group
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I log out
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
|
||||
@javascript
|
||||
Scenario: Test condition
|
||||
|
||||
@@ -22,10 +22,8 @@ Feature: availability_grouping
|
||||
And the following "group members" exist:
|
||||
| user | group |
|
||||
| student1 | GI1 |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I log out
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
|
||||
@javascript
|
||||
Scenario: Test condition
|
||||
|
||||
@@ -10,16 +10,14 @@ Feature: availability_profile
|
||||
| Course 1 | C1 | topics | 1 |
|
||||
And the following "users" exist:
|
||||
| username | email |
|
||||
| teacher1 | t@example.org |
|
||||
| student1 | s@example.org |
|
||||
| teacher1 | t@example.com |
|
||||
| student1 | s@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I log out
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
|
||||
@javascript
|
||||
Scenario: Test condition
|
||||
@@ -38,7 +36,7 @@ Feature: availability_profile
|
||||
And I click on "Add restriction..." "button"
|
||||
And I click on "User profile" "button"
|
||||
And I set the field "User profile field" to "Email address"
|
||||
And I set the field "Value to compare against" to "s@example.org"
|
||||
And I set the field "Value to compare against" to "s@example.com"
|
||||
And I click on ".availability-item .availability-eye img" "css_element"
|
||||
And I click on "Save and return to course" "button"
|
||||
|
||||
@@ -52,7 +50,7 @@ Feature: availability_profile
|
||||
And I click on "Add restriction..." "button"
|
||||
And I click on "User profile" "button"
|
||||
And I set the field "User profile field" to "Email address"
|
||||
And I set the field "Value to compare against" to "q@example.org"
|
||||
And I set the field "Value to compare against" to "q@example.com"
|
||||
And I click on ".availability-item .availability-eye img" "css_element"
|
||||
And I click on "Save and return to course" "button"
|
||||
|
||||
@@ -78,7 +76,7 @@ Feature: availability_profile
|
||||
|
||||
# Set field value for user.
|
||||
And I navigate to "Browse list of users" node in "Site administration > Users > Accounts"
|
||||
And I click on "a[title=Edit]" "css_element" in the "s@example.org" "table_row"
|
||||
And I click on "a[title=Edit]" "css_element" in the "s@example.com" "table_row"
|
||||
And I expand all fieldsets
|
||||
And I set the field "Super field" to "Bananaman"
|
||||
And I click on "Update profile" "button"
|
||||
|
||||
@@ -34,10 +34,8 @@ Feature: display_availability
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I log out
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
|
||||
@javascript
|
||||
Scenario: Activity availability display
|
||||
@@ -76,7 +74,7 @@ Feature: display_availability
|
||||
And I press "Add restriction..."
|
||||
And I click on "User profile" "button" in the "Add restriction..." "dialogue"
|
||||
And I set the field "User profile field" to "Email address"
|
||||
And I set the field "Value to compare against" to "email@example.org"
|
||||
And I set the field "Value to compare against" to "email@example.com"
|
||||
And I set the field "Method of comparison" to "is equal to"
|
||||
And I press "Save and return to course"
|
||||
|
||||
|
||||
@@ -39,15 +39,10 @@ Feature: edit_availability
|
||||
When I edit the section "1"
|
||||
Then "Restrict access" "fieldset" should not exist
|
||||
|
||||
When I log out
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
|
||||
When I log out
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
And I add a "Page" to section "1"
|
||||
Then "Restrict access" "fieldset" should exist
|
||||
|
||||
@@ -58,10 +53,8 @@ Feature: edit_availability
|
||||
@javascript
|
||||
Scenario: Edit availability using settings in activity form
|
||||
# Set up.
|
||||
Given I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I log out
|
||||
Given the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
|
||||
@@ -153,10 +146,8 @@ Feature: edit_availability
|
||||
@javascript
|
||||
Scenario: Edit availability using settings in section form
|
||||
# Set up.
|
||||
Given I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I log out
|
||||
Given the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
@@ -172,3 +163,4 @@ Feature: edit_availability
|
||||
And I should not see "None" in the "Restrict access" "fieldset"
|
||||
And "Restriction type" "select" should be visible
|
||||
And I should see "Date" in the "Restrict access" "fieldset"
|
||||
|
||||
|
||||
+3
-3
@@ -299,7 +299,7 @@
|
||||
<IDNUMBER>891220979</IDNUMBER>
|
||||
<FIRSTNAME>Admin</FIRSTNAME>
|
||||
<LASTNAME>User</LASTNAME>
|
||||
<EMAIL>adamzap@gmail.com</EMAIL>
|
||||
<EMAIL>adamzap@example.com</EMAIL>
|
||||
<EMAILSTOP>0</EMAILSTOP>
|
||||
<ICQ></ICQ>
|
||||
<SKYPE></SKYPE>
|
||||
@@ -368,7 +368,7 @@
|
||||
<IDNUMBER>891111111</IDNUMBER>
|
||||
<FIRSTNAME>Adam</FIRSTNAME>
|
||||
<LASTNAME>Zapletal</LASTNAME>
|
||||
<EMAIL>azaple1@lsu.edu</EMAIL>
|
||||
<EMAIL>azaple1@example.com</EMAIL>
|
||||
<EMAILSTOP>0</EMAILSTOP>
|
||||
<ICQ></ICQ>
|
||||
<SKYPE></SKYPE>
|
||||
@@ -481,7 +481,7 @@
|
||||
<IDNUMBER></IDNUMBER>
|
||||
<FIRSTNAME>Philip</FIRSTNAME>
|
||||
<LASTNAME>Cali</LASTNAME>
|
||||
<EMAIL>pcali1@lsu.edu</EMAIL>
|
||||
<EMAIL>pcali1@example.com</EMAIL>
|
||||
<EMAILSTOP>0</EMAILSTOP>
|
||||
<ICQ></ICQ>
|
||||
<SKYPE></SKYPE>
|
||||
|
||||
@@ -516,7 +516,7 @@ class backup_enrolments_structure_step extends backup_structure_step {
|
||||
|
||||
$enrol = new backup_nested_element('enrol', array('id'), array(
|
||||
'enrol', 'status', 'name', 'enrolperiod', 'enrolstartdate',
|
||||
'enrolenddate', 'expirynotify', 'expirytreshold', 'notifyall',
|
||||
'enrolenddate', 'expirynotify', 'expirythreshold', 'notifyall',
|
||||
'password', 'cost', 'currency', 'roleid',
|
||||
'customint1', 'customint2', 'customint3', 'customint4', 'customint5', 'customint6', 'customint7', 'customint8',
|
||||
'customchar1', 'customchar2', 'customchar3',
|
||||
@@ -926,6 +926,7 @@ class backup_gradebook_structure_step extends backup_structure_step {
|
||||
}
|
||||
|
||||
protected function define_structure() {
|
||||
global $CFG, $DB;
|
||||
|
||||
// are we including user info?
|
||||
$userinfo = $this->get_setting_value('users');
|
||||
@@ -986,6 +987,13 @@ class backup_gradebook_structure_step extends backup_structure_step {
|
||||
$gradebook->add_child($grade_settings);
|
||||
$grade_settings->add_child($grade_setting);
|
||||
|
||||
// Add attribute with gradebook calculation freeze date if needed.
|
||||
$gradebookcalculationfreeze = get_config('core', 'gradebook_calculations_freeze_' . $this->get_courseid());
|
||||
if ($gradebookcalculationfreeze) {
|
||||
$gradebook->add_attributes(array('calculations_freeze'));
|
||||
$gradebook->get_attribute('calculations_freeze')->set_value($gradebookcalculationfreeze);
|
||||
}
|
||||
|
||||
// Define sources
|
||||
|
||||
//Include manual, category and the course grade item
|
||||
@@ -1010,7 +1018,18 @@ class backup_gradebook_structure_step extends backup_structure_step {
|
||||
|
||||
$letter->set_source_table('grade_letters', array('contextid' => backup::VAR_CONTEXTID));
|
||||
|
||||
$grade_setting->set_source_table('grade_settings', array('courseid' => backup::VAR_COURSEID));
|
||||
// Set the grade settings source, forcing the inclusion of minmaxtouse if not present.
|
||||
$settings = array();
|
||||
$rs = $DB->get_recordset('grade_settings', array('courseid' => $this->get_courseid()));
|
||||
foreach ($rs as $record) {
|
||||
$settings[$record->name] = $record;
|
||||
}
|
||||
$rs->close();
|
||||
if (!isset($settings['minmaxtouse'])) {
|
||||
$settings['minmaxtouse'] = (object) array('name' => 'minmaxtouse', 'value' => $CFG->grade_minmaxtouse);
|
||||
}
|
||||
$grade_setting->set_source_array($settings);
|
||||
|
||||
|
||||
// Annotations (both as final as far as they are going to be exported in next steps)
|
||||
$grade_item->annotate_ids('scalefinal', 'scaleid'); // Straight as scalefinal because it's > 0
|
||||
|
||||
@@ -138,6 +138,18 @@ class restore_gradebook_structure_step extends restore_structure_step {
|
||||
}
|
||||
|
||||
protected function process_gradebook($data) {
|
||||
// For non-merge restore types:
|
||||
// Unset 'gradebook_calculations_freeze_' in the course and replace with the one from the backup.
|
||||
$target = $this->get_task()->get_target();
|
||||
if ($target == backup::TARGET_CURRENT_DELETING || $target == backup::TARGET_EXISTING_DELETING) {
|
||||
set_config('gradebook_calculations_freeze_' . $this->get_courseid(), null);
|
||||
}
|
||||
if (!empty($data['calculations_freeze'])) {
|
||||
if ($target == backup::TARGET_NEW_COURSE || $target == backup::TARGET_CURRENT_DELETING ||
|
||||
$target == backup::TARGET_EXISTING_DELETING) {
|
||||
set_config('gradebook_calculations_freeze_' . $this->get_courseid(), $data['calculations_freeze']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function process_grade_item($data) {
|
||||
@@ -319,13 +331,23 @@ class restore_gradebook_structure_step extends restore_structure_step {
|
||||
|
||||
$data->courseid = $this->get_courseid();
|
||||
|
||||
$target = $this->get_task()->get_target();
|
||||
if ($data->name == 'minmaxtouse' &&
|
||||
($target == backup::TARGET_CURRENT_ADDING || $target == backup::TARGET_EXISTING_ADDING)) {
|
||||
// We never restore minmaxtouse during merge.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$DB->record_exists('grade_settings', array('courseid' => $data->courseid, 'name' => $data->name))) {
|
||||
$newitemid = $DB->insert_record('grade_settings', $data);
|
||||
} else {
|
||||
$newitemid = $data->id;
|
||||
}
|
||||
|
||||
$this->set_mapping('grade_setting', $oldid, $newitemid);
|
||||
if (!empty($oldid)) {
|
||||
// In rare cases (minmaxtouse), it is possible that there wasn't any ID associated with the setting.
|
||||
$this->set_mapping('grade_setting', $oldid, $newitemid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,9 +469,101 @@ class restore_gradebook_structure_step extends restore_structure_step {
|
||||
}
|
||||
$rs->close();
|
||||
|
||||
// Check what to do with the minmaxtouse setting.
|
||||
$this->check_minmaxtouse();
|
||||
|
||||
// Freeze gradebook calculations if needed.
|
||||
$this->gradebook_calculation_freeze();
|
||||
|
||||
// Restore marks items as needing update. Update everything now.
|
||||
grade_regrade_final_grades($this->get_courseid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze gradebook calculation if needed.
|
||||
*
|
||||
* This is similar to various upgrade scripts that check if the freeze is needed.
|
||||
*/
|
||||
protected function gradebook_calculation_freeze() {
|
||||
global $CFG;
|
||||
$gradebookcalculationsfreeze = get_config('core', 'gradebook_calculations_freeze_' . $this->get_courseid());
|
||||
preg_match('/(\d{8})/', $this->get_task()->get_info()->moodle_release, $matches);
|
||||
$backupbuild = (int)$matches[1];
|
||||
|
||||
// Extra credits need adjustments only for backups made between 2.8 release (20141110) and the fix release (20150619).
|
||||
if (!$gradebookcalculationsfreeze && $backupbuild >= 20141110 && $backupbuild < 20150619) {
|
||||
require_once($CFG->libdir . '/db/upgradelib.php');
|
||||
upgrade_extra_credit_weightoverride($this->get_courseid());
|
||||
}
|
||||
// Calculated grade items need recalculating for backups made between 2.8 release (20141110) and the fix release (20150627).
|
||||
if (!$gradebookcalculationsfreeze && $backupbuild >= 20141110 && $backupbuild < 20150627) {
|
||||
require_once($CFG->libdir . '/db/upgradelib.php');
|
||||
upgrade_calculated_grade_items($this->get_courseid());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks what should happen with the course grade setting minmaxtouse.
|
||||
*
|
||||
* This is related to the upgrade step at the time the setting was added.
|
||||
*
|
||||
* @see MDL-48618
|
||||
* @return void
|
||||
*/
|
||||
protected function check_minmaxtouse() {
|
||||
global $CFG, $DB;
|
||||
require_once($CFG->libdir . '/gradelib.php');
|
||||
|
||||
$userinfo = $this->task->get_setting_value('users');
|
||||
$settingname = 'minmaxtouse';
|
||||
$courseid = $this->get_courseid();
|
||||
$minmaxtouse = $DB->get_field('grade_settings', 'value', array('courseid' => $courseid, 'name' => $settingname));
|
||||
$version28start = 2014111000.00;
|
||||
$version28last = 2014111006.05;
|
||||
|
||||
$target = $this->get_task()->get_target();
|
||||
if ($minmaxtouse === false &&
|
||||
($target != backup::TARGET_CURRENT_ADDING && $target != backup::TARGET_EXISTING_ADDING)) {
|
||||
// The setting was not found because this setting did not exist at the time the backup was made.
|
||||
// And we are not restoring as merge, in which case we leave the course as it was.
|
||||
$version = $this->get_task()->get_info()->moodle_version;
|
||||
|
||||
if ($version < $version28start) {
|
||||
// We need to set it to use grade_item, but only if the site-wide setting is different. No need to notice them.
|
||||
if ($CFG->grade_minmaxtouse != GRADE_MIN_MAX_FROM_GRADE_ITEM) {
|
||||
grade_set_setting($courseid, $settingname, GRADE_MIN_MAX_FROM_GRADE_ITEM);
|
||||
}
|
||||
|
||||
} else if ($version >= $version28start && $version < $version28last) {
|
||||
// They should be using grade_grade when the course has inconsistencies.
|
||||
|
||||
$sql = "SELECT gi.id
|
||||
FROM {grade_items} gi
|
||||
JOIN {grade_grades} gg
|
||||
ON gg.itemid = gi.id
|
||||
WHERE gi.courseid = ?
|
||||
AND (gi.itemtype != ? AND gi.itemtype != ?)
|
||||
AND (gg.rawgrademax != gi.grademax OR gg.rawgrademin != gi.grademin)";
|
||||
|
||||
// The course can only have inconsistencies when we restore the user info,
|
||||
// we do not need to act on existing grades that were not restored as part of this backup.
|
||||
if ($userinfo && $DB->record_exists_sql($sql, array($courseid, 'course', 'category'))) {
|
||||
|
||||
// Display the notice as we do during upgrade.
|
||||
set_config('show_min_max_grades_changed_' . $courseid, 1);
|
||||
|
||||
if ($CFG->grade_minmaxtouse != GRADE_MIN_MAX_FROM_GRADE_GRADE) {
|
||||
// We need set the setting as their site-wise setting is not GRADE_MIN_MAX_FROM_GRADE_GRADE.
|
||||
// If they are using the site-wide grade_grade setting, we only want to notice them.
|
||||
grade_set_setting($courseid, $settingname, GRADE_MIN_MAX_FROM_GRADE_GRADE);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// This should never happen because from now on minmaxtouse is always saved in backups.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1472,13 +1586,31 @@ class restore_section_structure_step extends restore_structure_step {
|
||||
|
||||
public function process_course_format_options($data) {
|
||||
global $DB;
|
||||
$data = (object)$data;
|
||||
$oldid = $data->id;
|
||||
unset($data->id);
|
||||
$data->sectionid = $this->task->get_sectionid();
|
||||
$data->courseid = $this->get_courseid();
|
||||
$newid = $DB->insert_record('course_format_options', $data);
|
||||
$this->set_mapping('course_format_options', $oldid, $newid);
|
||||
static $courseformats = array();
|
||||
$courseid = $this->get_courseid();
|
||||
if (!array_key_exists($courseid, $courseformats)) {
|
||||
// It is safe to have a static cache of course formats because format can not be changed after this point.
|
||||
$courseformats[$courseid] = $DB->get_field('course', 'format', array('id' => $courseid));
|
||||
}
|
||||
$data = (array)$data;
|
||||
if ($courseformats[$courseid] === $data['format']) {
|
||||
// Import section format options only if both courses (the one that was backed up
|
||||
// and the one we are restoring into) have same formats.
|
||||
$params = array(
|
||||
'courseid' => $this->get_courseid(),
|
||||
'sectionid' => $this->task->get_sectionid(),
|
||||
'format' => $data['format'],
|
||||
'name' => $data['name']
|
||||
);
|
||||
if ($record = $DB->get_record('course_format_options', $params, 'id, value')) {
|
||||
// Do not overwrite existing information.
|
||||
$newid = $record->id;
|
||||
} else {
|
||||
$params['value'] = $data['value'];
|
||||
$newid = $DB->insert_record('course_format_options', $params);
|
||||
}
|
||||
$this->set_mapping('course_format_options', $data['id'], $newid);
|
||||
}
|
||||
}
|
||||
|
||||
protected function after_execute() {
|
||||
@@ -2987,11 +3119,6 @@ class restore_activity_grades_structure_step extends restore_structure_step {
|
||||
$oldparentid = $data->categoryid;
|
||||
$courseid = $this->get_courseid();
|
||||
|
||||
// make sure top course category exists, all grade items will be associated
|
||||
// to it. Later, if restoring the whole gradebook, categories will be introduced
|
||||
$coursecat = grade_category::fetch_course_category($courseid);
|
||||
$coursecatid = $coursecat->id; // Get the categoryid to be used
|
||||
|
||||
$idnumber = null;
|
||||
if (!empty($data->idnumber)) {
|
||||
// Don't get any idnumber from course module. Keep them as they are in grade_item->idnumber
|
||||
@@ -3016,8 +3143,18 @@ class restore_activity_grades_structure_step extends restore_structure_step {
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data->categoryid)) {
|
||||
// If the grade category id of the grade item being restored belongs to this course
|
||||
// then it is a fair assumption that this is the correct grade category for the activity
|
||||
// and we should leave it in place, if not then unset it.
|
||||
// TODO MDL-34790 Gradebook does not import if target course has gradebook categories.
|
||||
$conditions = array('id' => $data->categoryid, 'courseid' => $courseid);
|
||||
if (!$this->task->is_samesite() || !$DB->record_exists('grade_categories', $conditions)) {
|
||||
unset($data->categoryid);
|
||||
}
|
||||
}
|
||||
|
||||
unset($data->id);
|
||||
$data->categoryid = $coursecatid;
|
||||
$data->courseid = $this->get_courseid();
|
||||
$data->iteminstance = $this->task->get_activityid();
|
||||
$data->idnumber = $idnumber;
|
||||
@@ -3836,6 +3973,11 @@ class restore_create_categories_and_questions extends restore_structure_step {
|
||||
|
||||
$data = (object)$data;
|
||||
$newquestion = $this->get_new_parentid('question');
|
||||
$questioncreated = (bool) $this->get_mappingid('question_created', $this->get_old_parentid('question'));
|
||||
if (!$questioncreated) {
|
||||
// This question already exists in the question bank. Nothing for us to do.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($CFG->usetags)) { // if enabled in server
|
||||
// TODO: This is highly inefficient. Each time we add one tag
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tests for Moodle 2 format backup operation.
|
||||
*
|
||||
* @package core_backup
|
||||
* @copyright 2014 Russell Smith
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
|
||||
require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php');
|
||||
require_once($CFG->dirroot . '/course/format/topics/lib.php');
|
||||
require_once($CFG->libdir . '/completionlib.php');
|
||||
|
||||
/**
|
||||
* Tests for Moodle 2 course format section_options backup operation.
|
||||
*
|
||||
* @package core_backup
|
||||
* @copyright 2014 Russell Smith
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_backup_moodle2_course_format_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Tidy up open files that may be left open.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a backup and restore adds the required section option data
|
||||
* when the same course format is used.
|
||||
*/
|
||||
public function test_course_format_options_restore() {
|
||||
global $DB, $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
$this->setAdminUser();
|
||||
$CFG->enableavailability = true;
|
||||
$CFG->enablecompletion = true;
|
||||
|
||||
// Create a course with some availability data set.
|
||||
$generator = $this->getDataGenerator();
|
||||
$course = $generator->create_course(
|
||||
array('format' => 'test_cs_options', 'numsections' => 3,
|
||||
'enablecompletion' => COMPLETION_ENABLED),
|
||||
array('createsections' => true));
|
||||
|
||||
$courseobject = format_base::instance($course->id);
|
||||
$section = $DB->get_record('course_sections',
|
||||
array('course' => $course->id, 'section' => 1), '*', MUST_EXIST);
|
||||
$data = array('id' => $section->id,
|
||||
'numdaystocomplete' => 2);
|
||||
$courseobject->update_section_format_options($data);
|
||||
// Backup and restore it.
|
||||
$this->backup_and_restore($course);
|
||||
|
||||
$sectionoptions = $courseobject->get_format_options(1);
|
||||
$this->assertArrayHasKey('numdaystocomplete', $sectionoptions);
|
||||
$this->assertEquals(2, $sectionoptions['numdaystocomplete']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an import into the same subject successfully
|
||||
* restores the options without error.
|
||||
*/
|
||||
public function test_course_format_options_import_myself() {
|
||||
global $DB, $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
$this->setAdminUser();
|
||||
$CFG->enableavailability = true;
|
||||
$CFG->enablecompletion = true;
|
||||
|
||||
// Create a course with some availability data set.
|
||||
$generator = $this->getDataGenerator();
|
||||
$course = $generator->create_course(
|
||||
array('format' => 'test_cs_options', 'numsections' => 3,
|
||||
'enablecompletion' => COMPLETION_ENABLED),
|
||||
array('createsections' => true));
|
||||
|
||||
$courseobject = format_base::instance($course->id);
|
||||
$section = $DB->get_record('course_sections',
|
||||
array('course' => $course->id, 'section' => 1), '*', MUST_EXIST);
|
||||
$data = array('id' => $section->id,
|
||||
'numdaystocomplete' => 2);
|
||||
$courseobject->update_section_format_options($data);
|
||||
|
||||
$this->backup_and_restore($course, $course);
|
||||
|
||||
$sectionoptions = $courseobject->get_format_options(1);
|
||||
$this->assertArrayHasKey('numdaystocomplete', $sectionoptions);
|
||||
$this->assertArrayNotHasKey('secondparameter', $sectionoptions);
|
||||
$this->assertEquals(2, $sectionoptions['numdaystocomplete']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all section options are copied when the course format is changed.
|
||||
* None of the data is copied.
|
||||
*
|
||||
* It is a future enhancement to copy;
|
||||
* 1. Only the relevant options.
|
||||
* 2. Only the data associated with relevant options.
|
||||
*/
|
||||
public function test_course_format_options_restore_new_format() {
|
||||
global $DB, $CFG;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
$this->setAdminUser();
|
||||
$CFG->enableavailability = true;
|
||||
$CFG->enablecompletion = true;
|
||||
|
||||
// Create a course with some availability data set.
|
||||
$generator = $this->getDataGenerator();
|
||||
$course = $generator->create_course(
|
||||
array('format' => 'test_cs2_options', 'numsections' => 3,
|
||||
'enablecompletion' => COMPLETION_ENABLED),
|
||||
array('createsections' => true));
|
||||
$newcourse = $generator->create_course(
|
||||
array('format' => 'test_cs_options', 'numsections' => 3,
|
||||
'enablecompletion' => COMPLETION_ENABLED),
|
||||
array('createsections' => true));
|
||||
|
||||
$courseobject = format_base::instance($course->id);
|
||||
$section = $DB->get_record('course_sections',
|
||||
array('course' => $course->id, 'section' => 1), '*', MUST_EXIST);
|
||||
|
||||
$data = array('id' => $section->id,
|
||||
'numdaystocomplete' => 2,
|
||||
'secondparameter' => 8);
|
||||
$courseobject->update_section_format_options($data);
|
||||
// Backup and restore it.
|
||||
$this->backup_and_restore($course, $newcourse);
|
||||
|
||||
$newcourseobject = format_base::instance($newcourse->id);
|
||||
$sectionoptions = $newcourseobject->get_format_options(1);
|
||||
$this->assertArrayHasKey('numdaystocomplete', $sectionoptions);
|
||||
$this->assertArrayHasKey('secondparameter', $sectionoptions);
|
||||
$this->assertEquals(0, $sectionoptions['numdaystocomplete']);
|
||||
$this->assertEquals(0, $sectionoptions['secondparameter']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Backs a course up and restores it.
|
||||
*
|
||||
* @param stdClass $srccourse Course object to backup
|
||||
* @param stdClass $dstcourse Course object to restore into
|
||||
* @return int ID of newly restored course
|
||||
*/
|
||||
protected function backup_and_restore($srccourse, $dstcourse = null) {
|
||||
global $USER, $CFG;
|
||||
|
||||
// Turn off file logging, otherwise it can't delete the file (Windows).
|
||||
$CFG->backup_file_logger_level = backup::LOG_NONE;
|
||||
|
||||
// Do backup with default settings. MODE_IMPORT means it will just
|
||||
// create the directory and not zip it.
|
||||
$bc = new backup_controller(backup::TYPE_1COURSE, $srccourse->id,
|
||||
backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_IMPORT,
|
||||
$USER->id);
|
||||
$backupid = $bc->get_backupid();
|
||||
$bc->execute_plan();
|
||||
$bc->destroy();
|
||||
|
||||
// Do restore to new course with default settings.
|
||||
if ($dstcourse !== null) {
|
||||
$newcourseid = $dstcourse->id;
|
||||
} else {
|
||||
$newcourseid = restore_dbops::create_new_course(
|
||||
$srccourse->fullname, $srccourse->shortname . '_2', $srccourse->category);
|
||||
}
|
||||
$rc = new restore_controller($backupid, $newcourseid,
|
||||
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $USER->id,
|
||||
backup::TARGET_NEW_COURSE);
|
||||
|
||||
$this->assertTrue($rc->execute_precheck());
|
||||
$rc->execute_plan();
|
||||
$rc->destroy();
|
||||
|
||||
return $newcourseid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class format_test_cs_options
|
||||
*
|
||||
* Test course format that has 1 option.
|
||||
*/
|
||||
class format_test_cs_options extends format_topics {
|
||||
public function section_format_options($foreditform = false) {
|
||||
return array(
|
||||
'numdaystocomplete' => array(
|
||||
'type' => PARAM_INT,
|
||||
'label' => 'Test days',
|
||||
'element_type' => 'text',
|
||||
'default' => 0,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class format_test_cs2_options
|
||||
*
|
||||
* Test course format that has 2 options, 1 inherited.
|
||||
*/
|
||||
class format_test_cs2_options extends format_test_cs_options {
|
||||
public function section_format_options($foreditform = false) {
|
||||
return array(
|
||||
'secondparameter' => array(
|
||||
'type' => PARAM_INT,
|
||||
'label' => 'Test Parmater',
|
||||
'element_type' => 'text',
|
||||
'default' => 0,
|
||||
),
|
||||
) + parent::section_format_options($foreditform);
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ class course_restore_form extends moodleform {
|
||||
$mform->addElement('hidden', 'contextid', $contextid);
|
||||
$mform->setType('contextid', PARAM_INT);
|
||||
$mform->addElement('filepicker', 'backupfile', get_string('files'));
|
||||
$mform->addRule('backupfile', get_string('required'), 'required');
|
||||
$submit_string = get_string('restore');
|
||||
$this->add_action_buttons(false, $submit_string);
|
||||
}
|
||||
|
||||
@@ -167,4 +167,48 @@ class backup_anonymizer_helper {
|
||||
public static function process_user_imagealt($value) {
|
||||
return ''; // No user imagealt
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymises user's phonetic name field
|
||||
* @param string $value value of the user field
|
||||
* @return string anonymised phonetic name
|
||||
*/
|
||||
public static function process_user_firstnamephonetic($value) {
|
||||
static $counter = 0;
|
||||
$counter++;
|
||||
return 'anonfirstnamephonetic' . $counter; // Just a counter.
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymises user's phonetic last name field
|
||||
* @param string $value value of the user field
|
||||
* @return string anonymised last phonetic name
|
||||
*/
|
||||
public static function process_user_lastnamephonetic($value) {
|
||||
static $counter = 0;
|
||||
$counter++;
|
||||
return 'anonlastnamephonetic' . $counter; // Just a counter.
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymises user's middle name field
|
||||
* @param string $value value of the user field
|
||||
* @return string anonymised middle name
|
||||
*/
|
||||
public static function process_user_middlename($value) {
|
||||
static $counter = 0;
|
||||
$counter++;
|
||||
return 'anonmiddlename' . $counter; // Just a counter.
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymises user's alternate name field
|
||||
* @param string $value value of the user field
|
||||
* @return string anonymised alternate name
|
||||
*/
|
||||
public static function process_user_alternatename($value) {
|
||||
static $counter = 0;
|
||||
$counter++;
|
||||
return 'anonalternatename' . $counter; // Just a counter.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ Feature: Duplicate activities
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@@ -12,7 +12,7 @@ Feature: Import course's contents into another course
|
||||
| Course 2 | C2 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
@@ -43,6 +42,22 @@ abstract class grouped_parser_processor extends simplified_parser_processor {
|
||||
protected $groupedpaths; // Paths we are requesting grouped
|
||||
protected $currentdata; // Where we'll be acummulating data
|
||||
|
||||
// We create a array that stores each of the paths in a tree fashion
|
||||
// like the filesystem. Each element stores all the child elements that are
|
||||
// part of a full path that builds the grouped parent path we are storing.
|
||||
// eg Array keys are stored as follows;
|
||||
// root => a => b
|
||||
// => b
|
||||
// => c => d
|
||||
// => e => f.
|
||||
// Grouped paths here are; /a/b, /b, /c/d, /c/e/f.
|
||||
// There are no nested parent paths, that is an enforced rule so
|
||||
// we store an empty array to designate that the particular XML path element
|
||||
// is in fact a grouped path.
|
||||
// eg; $this->groupedparentprefixtree['a']['b'] = array();
|
||||
/** @var array Search tree storing the grouped paths. */
|
||||
protected $groupedparentprefixtree;
|
||||
|
||||
/**
|
||||
* Keep cache of parent directory paths for XML parsing.
|
||||
* @var array
|
||||
@@ -78,6 +93,18 @@ abstract class grouped_parser_processor extends simplified_parser_processor {
|
||||
throw new progressive_parser_exception('xml_grouped_child_found', $a);
|
||||
}
|
||||
$this->groupedpaths[$path] = true;
|
||||
|
||||
// We check earlier in the function if there is a parent that is above the path
|
||||
// to be added so we can be sure no parent exists in the tree.
|
||||
$patharray = explode('/', $path);
|
||||
$currentpos = &$this->groupedparentprefixtree;
|
||||
foreach ($patharray as $item) {
|
||||
if (!isset($currentpos[$item])) {
|
||||
$currentpos[$item] = array();
|
||||
}
|
||||
// Update the current array position using a reference to allow in-place updates to the array.
|
||||
$currentpos = &$currentpos[$item];
|
||||
}
|
||||
}
|
||||
parent::add_path($path);
|
||||
}
|
||||
@@ -162,13 +189,29 @@ abstract class grouped_parser_processor extends simplified_parser_processor {
|
||||
* false if not
|
||||
*/
|
||||
protected function grouped_parent_exists($path) {
|
||||
$parentpath = $this->get_parent_path($path);
|
||||
|
||||
while ($parentpath != '/') {
|
||||
if ($this->path_is_grouped($parentpath)) {
|
||||
return $parentpath;
|
||||
// Search the tree structure to find out if one of the paths
|
||||
// above the $path is a grouped path.
|
||||
$patharray = explode('/', $this->get_parent_path($path));
|
||||
$groupedpath = '';
|
||||
$currentpos = &$this->groupedparentprefixtree;
|
||||
foreach ($patharray as $item) {
|
||||
// When the item isn't set in the array we know
|
||||
// there is no parent grouped path.
|
||||
if (!isset($currentpos[$item])) {
|
||||
return false;
|
||||
}
|
||||
$parentpath = $this->get_parent_path($parentpath);
|
||||
|
||||
// When we aren't at the start of the path, continue to build
|
||||
// a string representation of the path that is traversed. We will
|
||||
// return the grouped path to the caller if we find one.
|
||||
if ($item != '') {
|
||||
$groupedpath .= '/'.$item;
|
||||
}
|
||||
|
||||
if ($currentpos[$item] == array()) {
|
||||
return $groupedpath;
|
||||
}
|
||||
$currentpos = &$currentpos[$item];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class award_criteria_activity extends award_criteria {
|
||||
if (!$mod) {
|
||||
$str = $OUTPUT->error_text(get_string('error:nosuchmod', 'badges'));
|
||||
} else {
|
||||
$str = html_writer::tag('b', '"' . ucfirst($mod->modname) . ' - ' . $mod->name . '"');
|
||||
$str = html_writer::tag('b', '"' . get_string('modulename', $mod->modname) . ' - ' . $mod->name . '"');
|
||||
if (isset($p['bydate'])) {
|
||||
$str .= get_string('criteria_descr_bydate', 'badges', userdate($p['bydate'], get_string('strftimedate', 'core_langconfig')));
|
||||
}
|
||||
@@ -142,7 +142,7 @@ class award_criteria_activity extends award_criteria {
|
||||
}
|
||||
$param = array('id' => $mod->id,
|
||||
'checked' => $checked,
|
||||
'name' => ucfirst($mod->modname) . ' - ' . $mod->name,
|
||||
'name' => get_string('modulename', $mod->modname) . ' - ' . $mod->name,
|
||||
'error' => false
|
||||
);
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ class award_criteria_courseset extends award_criteria {
|
||||
$param = array(
|
||||
'id' => $course->id,
|
||||
'checked' => true,
|
||||
'name' => ucfirst(format_string($course->fullname, true, array('context' => $coursecontext))),
|
||||
'name' => format_string($course->fullname, true, array('context' => $coursecontext)),
|
||||
'error' => false
|
||||
);
|
||||
|
||||
|
||||
@@ -59,13 +59,15 @@ class OpenBadgesBackpackHandler {
|
||||
break;
|
||||
}
|
||||
|
||||
$curl->setHeader(array('Accept: application/json', 'Expect:'));
|
||||
$options = array(
|
||||
'FRESH_CONNECT' => true,
|
||||
'RETURNTRANSFER' => true,
|
||||
'FORBID_REUSE' => true,
|
||||
'HEADER' => 0,
|
||||
'HTTPHEADER' => array('Expect:'),
|
||||
'CONNECTTIMEOUT' => 3,
|
||||
'FRESH_CONNECT' => true,
|
||||
'RETURNTRANSFER' => true,
|
||||
'FORBID_REUSE' => true,
|
||||
'HEADER' => 0,
|
||||
'CONNECTTIMEOUT' => 3,
|
||||
// Follow redirects with the same type of request when sent 301, or 302 redirects.
|
||||
'CURLOPT_POSTREDIR' => 3
|
||||
);
|
||||
|
||||
if ($action == 'user') {
|
||||
|
||||
@@ -12,10 +12,10 @@ Feature: Add badges to the system
|
||||
Scenario: Setting badges settings
|
||||
Given I navigate to "Badges settings" node in "Site administration > Badges"
|
||||
And I set the field "Default badge issuer name" to "Test Badge Site"
|
||||
And I set the field "Default badge issuer contact details" to "testuser@test-badge-site.com"
|
||||
And I set the field "Default badge issuer contact details" to "testuser@example.com"
|
||||
And I press "Save changes"
|
||||
When I follow "Add a new badge"
|
||||
Then the field "issuercontact" matches value "testuser@test-badge-site.com"
|
||||
Then the field "issuercontact" matches value "testuser@example.com"
|
||||
And the field "issuername" matches value "Test Badge Site"
|
||||
|
||||
@javascript
|
||||
@@ -30,7 +30,7 @@ Feature: Add badges to the system
|
||||
| Name | Test Badge |
|
||||
| Description | Test badge description |
|
||||
| issuername | Test Badge Site |
|
||||
| issuercontact | testuser@test-badge-site.com |
|
||||
| issuercontact | testuser@example.com |
|
||||
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
|
||||
When I press "Create badge"
|
||||
Then I should see "Edit details"
|
||||
|
||||
@@ -12,7 +12,7 @@ Feature: Award badges
|
||||
| Name | Profile Badge |
|
||||
| Description | Test badge description |
|
||||
| issuername | Test Badge Site |
|
||||
| issuercontact | testuser@test-badge-site.com |
|
||||
| issuercontact | testuser@example.com |
|
||||
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
|
||||
And I press "Create badge"
|
||||
And I set the field "type" to "Profile completion"
|
||||
@@ -39,8 +39,8 @@ Feature: Award badges
|
||||
Scenario: Award site badge
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher | teacher | 1 | teacher1@asd.com |
|
||||
| student | student | 1 | student1@asd.com |
|
||||
| teacher | teacher | 1 | teacher1@example.com |
|
||||
| student | student | 1 | student1@example.com |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Add a new badge" node in "Site administration > Badges"
|
||||
And I set the following fields to these values:
|
||||
@@ -56,9 +56,9 @@ Feature: Award badges
|
||||
And I press "Continue"
|
||||
And I follow "Recipients (0)"
|
||||
And I press "Award badge"
|
||||
And I set the field "potentialrecipients[]" to "teacher 1 (teacher1@asd.com)"
|
||||
And I set the field "potentialrecipients[]" to "teacher 1 (teacher1@example.com)"
|
||||
And I press "Award badge"
|
||||
And I set the field "potentialrecipients[]" to "student 1 (student1@asd.com)"
|
||||
And I set the field "potentialrecipients[]" to "student 1 (student1@example.com)"
|
||||
And I press "Award badge"
|
||||
When I follow "Site Badge"
|
||||
Then I should see "Recipients (2)"
|
||||
@@ -71,9 +71,9 @@ Feature: Award badges
|
||||
Scenario: Award course badge
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| student2 | Student | 2 | student2@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
| student2 | Student | 2 | student2@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category | groupmode |
|
||||
| Course 1 | C1 | 0 | 1 |
|
||||
@@ -99,9 +99,9 @@ Feature: Award badges
|
||||
And I press "Continue"
|
||||
And I follow "Recipients (0)"
|
||||
And I press "Award badge"
|
||||
And I set the field "potentialrecipients[]" to "Student 2 (student2@asd.com)"
|
||||
And I set the field "potentialrecipients[]" to "Student 2 (student2@example.com)"
|
||||
And I press "Award badge"
|
||||
And I set the field "potentialrecipients[]" to "Student 1 (student1@asd.com)"
|
||||
And I set the field "potentialrecipients[]" to "Student 1 (student1@example.com)"
|
||||
When I press "Award badge"
|
||||
And I follow "Course Badge"
|
||||
Then I should see "Recipients (2)"
|
||||
@@ -118,16 +118,15 @@ Feature: Award badges
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | Frist | teacher1@asd.com |
|
||||
| student1 | Student | First | student1@asd.com |
|
||||
| teacher1 | Teacher | Frist | teacher1@example.com |
|
||||
| student1 | Student | First | student1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable completion tracking | 1 |
|
||||
And I follow "Home"
|
||||
And the following config values are set as admin:
|
||||
| enablecompletion | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I follow "Edit settings"
|
||||
And I set the following fields to these values:
|
||||
@@ -137,8 +136,6 @@ Feature: Award badges
|
||||
And I add a "Assignment" to section "1" and I fill the form with:
|
||||
| Assignment name | Test assignment name |
|
||||
| Description | Submit your online text |
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I navigate to "Add a new badge" node in "Course administration > Badges"
|
||||
And I follow "Add a new badge"
|
||||
@@ -171,16 +168,15 @@ Feature: Award badges
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | Frist | teacher1@asd.com |
|
||||
| student1 | Student | First | student1@asd.com |
|
||||
| teacher1 | Teacher | Frist | teacher1@example.com |
|
||||
| student1 | Student | First | student1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable completion tracking | 1 |
|
||||
And I follow "Home"
|
||||
And the following config values are set as admin:
|
||||
| enablecompletion | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I follow "Edit settings"
|
||||
And I set the following fields to these values:
|
||||
@@ -194,10 +190,8 @@ Feature: Award badges
|
||||
And I follow "Course completion"
|
||||
And I set the field "id_overall_aggregation" to "2"
|
||||
And I click on "Condition: Activity completion" "link"
|
||||
And I set the field "Assign - Test assignment name" to "1"
|
||||
And I set the field "Assignment - Test assignment name" to "1"
|
||||
And I press "Save changes"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I navigate to "Add a new badge" node in "Course administration > Badges"
|
||||
And I follow "Add a new badge"
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Add a comment to the comments block
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | Frist | teacher1@asd.com |
|
||||
| student1 | Student | First | student1@asd.com |
|
||||
| teacher1 | Teacher | Frist | teacher1@example.com |
|
||||
| student1 | Student | First | student1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@@ -11,8 +11,8 @@ Feature: Delete comment block messages
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | First | teacher1@asd.com |
|
||||
| student1 | Student | First | student1@asd.com |
|
||||
| teacher1 | Teacher | First | teacher1@example.com |
|
||||
| student1 | Student | First | student1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@@ -133,7 +133,7 @@ if (empty($completions)) {
|
||||
echo html_writer::start_tag('tr');
|
||||
echo html_writer::start_tag('td', array('colspan' => '2'));
|
||||
echo html_writer::start_tag('br');
|
||||
echo $OUTPUT->box(get_string('err_nocriteria', 'completion'), 'noticebox');
|
||||
echo $OUTPUT->box(get_string('nocriteriaset', 'completion'), 'noticebox');
|
||||
echo html_writer::end_tag('td');
|
||||
echo html_writer::end_tag('tr');
|
||||
echo html_writer::end_tag('tbody');
|
||||
|
||||
@@ -112,7 +112,7 @@ class block_course_overview extends block_base {
|
||||
* @return array
|
||||
*/
|
||||
public function applicable_formats() {
|
||||
return array('my-index' => true);
|
||||
return array('my' => true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,4 +125,4 @@ class block_course_overview extends block_base {
|
||||
$config = get_config('block_course_overview');
|
||||
return !empty($config->showwelcomearea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Course summary block used in a course
|
||||
| Course 1 | C101 | Proved the course summary block works! |0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Sam | Student | student1@asd.com |
|
||||
| teacher1 | Teacher | One | teacher1@asd.com |
|
||||
| student1 | Sam | Student | student1@example.com |
|
||||
| teacher1 | Teacher | One | teacher1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C101 | student |
|
||||
|
||||
@@ -10,8 +10,8 @@ Feature: Random glossary entry block is used in a course
|
||||
| Course 1 | C1 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Sam1 | Student1 | student1@test.com |
|
||||
| teacher1 | Terry1 | Teacher1 | teacher1@test.com |
|
||||
| student1 | Sam1 | Student1 | student1@example.com |
|
||||
| teacher1 | Terry1 | Teacher1 | teacher1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
|
||||
@@ -7,8 +7,8 @@ Feature: HTML blocks in a course
|
||||
Scenario: Adding HTML block in a course
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Terry1 | Teacher1 | teacher@asd.com |
|
||||
| student1 | Sam1 | Student1 | student1@asd.com |
|
||||
| teacher1 | Terry1 | Teacher1 | teacher@example.com |
|
||||
| student1 | Sam1 | Student1 | student1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname |
|
||||
| Course 1 | C1 |
|
||||
|
||||
@@ -7,7 +7,7 @@ Feature: Login from a block
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | password | firstname | lastname | email |
|
||||
| testuser | testpass | Test | User | student1@asd.com |
|
||||
| testuser | testpass | Test | User | student1@example.com |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Turn editing on" node in "Front page settings"
|
||||
And I add the "Login" block
|
||||
|
||||
@@ -7,8 +7,8 @@ Feature: Expand the courses nodes within the navigation block
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@local.host |
|
||||
| student1 | Student | 1 | student1@local.host |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And the following "categories" exist:
|
||||
| name | category | idnumber | visible |
|
||||
| cat1 | 0 | cat1 | 1 |
|
||||
@@ -34,6 +34,8 @@ Feature: Expand the courses nodes within the navigation block
|
||||
| student1 | c1 | student |
|
||||
| student1 | c2 | student |
|
||||
| student1 | c4 | student |
|
||||
And the following config values are set as admin:
|
||||
| navshowallcourses | 1 |
|
||||
And I log in as "admin"
|
||||
And I follow "Course 2"
|
||||
And I turn editing mode on
|
||||
@@ -187,4 +189,4 @@ Feature: Expand the courses nodes within the navigation block
|
||||
And navigation node "c1" should not be expandable
|
||||
And navigation node "c2" should be expandable
|
||||
And navigation node "c3" should not be expandable
|
||||
And navigation node "c4" should not be expandable
|
||||
And navigation node "c4" should not be expandable
|
||||
|
||||
@@ -6,7 +6,7 @@ Feature: Test expand my courses navigation setting
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And the following "categories" exist:
|
||||
| name | category | idnumber |
|
||||
| cat1 | 0 | cat1 |
|
||||
@@ -29,10 +29,8 @@ Feature: Test expand my courses navigation setting
|
||||
|
||||
@javascript
|
||||
Scenario: The My Courses branch is collapsed when expand my courses is off
|
||||
Given I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Show My courses expanded on My home | 0 |
|
||||
And I log out
|
||||
Given the following config values are set as admin:
|
||||
| navexpandmycourses | 0 |
|
||||
When I log in as "student1"
|
||||
And I click on "My home" "link" in the "Navigation" "block"
|
||||
Then I should not see "c1" in the "Navigation" "block"
|
||||
@@ -41,10 +39,8 @@ Feature: Test expand my courses navigation setting
|
||||
|
||||
@javascript
|
||||
Scenario: My Courses can be expanded on the My Moodle page when expand my courses is off
|
||||
Given I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Show My courses expanded on My home | 0 |
|
||||
And I log out
|
||||
Given the following config values are set as admin:
|
||||
| navexpandmycourses | 0 |
|
||||
When I log in as "student1"
|
||||
And I click on "My home" "link" in the "Navigation" "block"
|
||||
And I should not see "c1" in the "Navigation" "block"
|
||||
|
||||
@@ -7,7 +7,7 @@ Feature: View my courses in navigation block
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And the following "categories" exist:
|
||||
| name | category | idnumber |
|
||||
| cat1 | 0 | cat1 |
|
||||
@@ -29,13 +29,11 @@ Feature: View my courses in navigation block
|
||||
| student1 | c1 | student |
|
||||
| student1 | c31 | student |
|
||||
| student1 | c331 | student |
|
||||
And I log in as "admin"
|
||||
|
||||
@javascript
|
||||
Scenario: The plain list of enrolled courses is shown
|
||||
Given I set the following administration settings values:
|
||||
| Show my course categories | 0 |
|
||||
And I log out
|
||||
Given the following config values are set as admin:
|
||||
| navshowmycoursecategories | 0 |
|
||||
And I log in as "student1"
|
||||
When I click on "My home" "link" in the "Navigation" "block"
|
||||
Then I should not see "cat1" in the "Navigation" "block"
|
||||
@@ -49,9 +47,8 @@ Feature: View my courses in navigation block
|
||||
|
||||
@javascript
|
||||
Scenario: The nested list of enrolled courses is shown
|
||||
Given I set the following administration settings values:
|
||||
| Show my course categories | 1 |
|
||||
And I log out
|
||||
Given the following config values are set as admin:
|
||||
| navshowmycoursecategories | 1 |
|
||||
And I log in as "student1"
|
||||
When I click on "My home" "link" in the "Navigation" "block"
|
||||
Then I should see "cat1" in the "Navigation" "block"
|
||||
@@ -69,10 +66,9 @@ Feature: View my courses in navigation block
|
||||
|
||||
@javascript
|
||||
Scenario: I can expand categories and courses as guest
|
||||
Given I set the following administration settings values:
|
||||
| Show my course categories | 1 |
|
||||
| Show all courses | 1 |
|
||||
And I log out
|
||||
Given the following config values are set as admin:
|
||||
| navshowmycoursecategories | 1 |
|
||||
| navshowallcourses | 1 |
|
||||
And I expand "Courses" node
|
||||
And I should see "cat1" in the "Navigation" "block"
|
||||
And I should see "cat2" in the "Navigation" "block"
|
||||
|
||||
@@ -8,7 +8,7 @@ Feature: Latest news block displays the course latest news
|
||||
Scenario: Latest course news are displayed and can be configured
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And I log in as "admin"
|
||||
And I create a course with:
|
||||
| Course full name | Course 1 |
|
||||
|
||||
@@ -10,7 +10,7 @@ Feature: People Block used in a course
|
||||
| Course 1 | C101 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Sam | Student | student1@asd.com |
|
||||
| student1 | Sam | Student | student1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C101 | student |
|
||||
|
||||
@@ -7,7 +7,7 @@ Feature: People Block used on frontpage
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Sam | Student | student1@asd.com |
|
||||
| student1 | Sam | Student | student1@example.com |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Turn editing on" node in "Front page settings"
|
||||
And I add the "People" block
|
||||
|
||||
@@ -40,7 +40,7 @@ $string['config_show_best'] = 'How many of the highest grades should be shown (0
|
||||
$string['config_show_worst'] = 'How many of the lowest grades should be shown (0 to disable)?';
|
||||
$string['configuredtoshownothing'] = 'This block\'s configuration currently does not allow it to show any results. You may want to either configure it or hide it.';
|
||||
$string['config_use_groups'] = 'Show groups instead of students (only if the quiz supports groups)?';
|
||||
$string['error_emptyquizid'] = 'There is an error right now with this block: you need to select which quiz it should display results from.';
|
||||
$string['error_emptyquizid'] = 'Please configure this block and select which quiz it should display results from.';
|
||||
$string['error_emptyquizrecord'] = 'There is an error right now with this block: the selected quiz does not seem to exist in the database.';
|
||||
$string['error_nogroupsexist'] = 'There is an error right now with this block: it is set to display grades in group mode, but the course has no defined groups.';
|
||||
$string['pluginname'] = 'Quiz results';
|
||||
|
||||
@@ -10,11 +10,11 @@ Feature: View structural changes in recent activity block
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Terry1 | Teacher1 | teacher1@asd.com |
|
||||
| assistant1 | Terry2 | Teacher2 | teacher2@asd.com |
|
||||
| student1 | Sam1 | Student1 | student1@asd.com |
|
||||
| student2 | Sam2 | Student2 | student2@asd.com |
|
||||
| student3 | Sam3 | Student3 | student3@asd.com |
|
||||
| teacher1 | Terry1 | Teacher1 | teacher1@example.com |
|
||||
| assistant1 | Terry2 | Teacher2 | teacher2@example.com |
|
||||
| student1 | Sam1 | Student1 | student1@example.com |
|
||||
| student2 | Sam2 | Student2 | student2@example.com |
|
||||
| student3 | Sam3 | Student3 | student3@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
@@ -46,10 +46,8 @@ Feature: View structural changes in recent activity block
|
||||
| GG3 | G2 |
|
||||
|
||||
Scenario: Check that Added module information is displayed respecting view capability
|
||||
Given I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable conditional access | 1 |
|
||||
And I log out
|
||||
Given the following config values are set as admin:
|
||||
| enableavailability | 1 |
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
|
||||
@@ -7,8 +7,8 @@ Feature: Add blocks
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| student2 | Student | 2 | student2@asd.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
| student2 | Student | 2 | student2@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
|
||||
@@ -10,7 +10,7 @@ Feature: Add and configure blocks throughout the site
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| manager1 | Manager | 1 | manager1@asd.com |
|
||||
| manager1 | Manager | 1 | manager1@example.com |
|
||||
And the following "system role assigns" exist:
|
||||
| user | course | role |
|
||||
| manager1 | Acceptance test site | manager |
|
||||
@@ -36,7 +36,7 @@ Feature: Add and configure blocks throughout the site
|
||||
Scenario: My home does not allow assignation of roles on blocks
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| manager1 | Manager | 1 | manager1@asd.com |
|
||||
| manager1 | Manager | 1 | manager1@example.com |
|
||||
And I log in as "manager1"
|
||||
And I click on "My home" "link" in the "Navigation" "block"
|
||||
When I press "Customise this page"
|
||||
|
||||
@@ -10,7 +10,7 @@ Feature: Block appearances
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | teacher | 1 | teacher1@asd.com |
|
||||
| teacher1 | teacher | 1 | teacher1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
|
||||
@@ -7,7 +7,7 @@ Feature: Allowed blocks controls
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
|
||||
@@ -7,8 +7,8 @@ Feature: Comment on a blog entry
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| testuser | Test | User | moodle@moodlemoodle.com |
|
||||
| testuser2 | Test2 | User2 | moodle2@moodlemoodle.com |
|
||||
| testuser | Test | User | moodle@example.com |
|
||||
| testuser2 | Test2 | User2 | moodle2@example.com |
|
||||
And I log in as "testuser"
|
||||
And I am on homepage
|
||||
And I expand "My profile" node
|
||||
|
||||
Vendored
+2
@@ -318,6 +318,8 @@ class cache_helper {
|
||||
$definitionkey = $definition->get_component().'/'.$definition->get_area();
|
||||
if (isset($inuse[$definitionkey])) {
|
||||
$inuse[$definitionkey]->purge();
|
||||
} else {
|
||||
cache::make($definition->get_component(), $definition->get_area())->purge();
|
||||
}
|
||||
|
||||
// We should only log events for application and session caches.
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ ipaddress:port
|
||||
servername:port:weight
|
||||
</pre>
|
||||
|
||||
If *Enable clustered servers* is enabled below, there must be only one server listed here. This would usually be a name that always resolves to the local manchine, like 127.0.0.1 or localhost.';
|
||||
If *Enable clustered servers* is enabled below, there must be only one server listed here. This would usually be a name that always resolves to the local machine, like 127.0.0.1 or localhost.';
|
||||
$string['serversclusterinvalid'] = 'Exactly one server is required when clustering is enabled.';
|
||||
$string['setservers'] = 'Set Servers';
|
||||
$string['setservers_help'] = 'This is the list of servers that will updated when data is modified in the cache. Generally the fully qualified name of each server in the pool.
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ ipaddress:port
|
||||
servername:port:weight
|
||||
</pre>
|
||||
|
||||
If *Enable clustered servers* is enabled below, there must be only one server listed here. This would usually be a name that always resolves to the local manchine, like 127.0.0.1 or localhost.';
|
||||
If *Enable clustered servers* is enabled below, there must be only one server listed here. This would usually be a name that always resolves to the local machine, like 127.0.0.1 or localhost.';
|
||||
$string['serversclusterinvalid'] = 'Exactly one server is required when clustering is enabled.';
|
||||
$string['setservers'] = 'Set Servers';
|
||||
$string['setservers_help'] = 'This is the list of servers that will updated when data is modified in the cache. Generally the fully qualified name of each server in the pool.
|
||||
|
||||
+2
-2
@@ -2944,7 +2944,7 @@ function calendar_add_icalendar_event($event, $courseid, $subscriptionid, $timez
|
||||
$name = $event->properties['SUMMARY'][0]->value;
|
||||
$name = str_replace('\n', '<br />', $name);
|
||||
$name = str_replace('\\', '', $name);
|
||||
$name = preg_replace('/\s+/', ' ', $name);
|
||||
$name = preg_replace('/\s+/u', ' ', $name);
|
||||
|
||||
$eventrecord = new stdClass;
|
||||
$eventrecord->name = clean_param($name, PARAM_NOTAGS);
|
||||
@@ -2956,7 +2956,7 @@ function calendar_add_icalendar_event($event, $courseid, $subscriptionid, $timez
|
||||
$description = clean_param($description, PARAM_NOTAGS);
|
||||
$description = str_replace('\n', '<br />', $description);
|
||||
$description = str_replace('\\', '', $description);
|
||||
$description = preg_replace('/\s+/', ' ', $description);
|
||||
$description = preg_replace('/\s+/u', ' ', $description);
|
||||
}
|
||||
$eventrecord->description = $description;
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ Feature: Perform basic calendar functionality
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| student2 | Student | 2 | student2@asd.com |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
| student2 | Student | 2 | student2@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
|
||||
@@ -328,6 +328,7 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
|
||||
|
||||
$paramevents = array ('courseids' => array($course->id), 'groupids' => array($group->id));
|
||||
$events = core_calendar_external::get_calendar_events($paramevents, $options);
|
||||
$events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events);
|
||||
$this->assertEquals(4, count($events['events'])); // site, user, group, one course event.
|
||||
$this->assertEquals(0, count($events['warnings']));
|
||||
|
||||
@@ -390,6 +391,7 @@ class core_calendar_externallib_testcase extends externallib_advanced_testcase {
|
||||
array('name' => 'user')
|
||||
);
|
||||
$eventsret = core_calendar_external::create_calendar_events($events);
|
||||
$eventsret = external_api::clean_returnvalue(core_calendar_external::create_calendar_events_returns(), $eventsret);
|
||||
|
||||
// Check to see if things were created properly.
|
||||
$aftercount = $DB->count_records('event');
|
||||
|
||||
+23
-11
@@ -118,6 +118,7 @@ echo $search;
|
||||
echo $OUTPUT->paging_bar($cohorts['totalcohorts'], $page, 25, $baseurl);
|
||||
|
||||
$data = array();
|
||||
$editcolumnisempty = true;
|
||||
foreach($cohorts['cohorts'] as $cohort) {
|
||||
$line = array();
|
||||
$cohortcontext = context::instance_by_id($cohort->contextid);
|
||||
@@ -148,27 +149,29 @@ foreach($cohorts['cohorts'] as $cohort) {
|
||||
|
||||
$urlparams = array('id' => $cohort->id, 'returnurl' => $baseurl->out_as_local_url());
|
||||
$showhideurl = new moodle_url('/cohort/edit.php', $urlparams + array('sesskey' => sesskey()));
|
||||
if ($cohort->visible) {
|
||||
$showhideurl->param('hide', 1);
|
||||
$visibleimg = html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/hide'), 'alt' => get_string('hide'), 'class' => 'iconsmall'));
|
||||
$buttons[] = html_writer::link($showhideurl, $visibleimg, array('title' => get_string('hide')));
|
||||
} else {
|
||||
$showhideurl->param('show', 1);
|
||||
$visibleimg = html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/show'), 'alt' => get_string('show'), 'class' => 'iconsmall'));
|
||||
$buttons[] = html_writer::link($showhideurl, $visibleimg, array('title' => get_string('show')));
|
||||
}
|
||||
if ($cohortmanager) {
|
||||
if ($cohort->visible) {
|
||||
$showhideurl->param('hide', 1);
|
||||
$visibleimg = html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/hide'), 'alt' => get_string('hide'), 'class' => 'iconsmall'));
|
||||
$buttons[] = html_writer::link($showhideurl, $visibleimg, array('title' => get_string('hide')));
|
||||
} else {
|
||||
$showhideurl->param('show', 1);
|
||||
$visibleimg = html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/show'), 'alt' => get_string('show'), 'class' => 'iconsmall'));
|
||||
$buttons[] = html_writer::link($showhideurl, $visibleimg, array('title' => get_string('show')));
|
||||
}
|
||||
$buttons[] = html_writer::link(new moodle_url('/cohort/edit.php', $urlparams + array('delete' => 1)),
|
||||
html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/delete'), 'alt' => get_string('delete'), 'class' => 'iconsmall')),
|
||||
array('title' => get_string('delete')));
|
||||
$buttons[] = html_writer::link(new moodle_url('/cohort/edit.php', $urlparams),
|
||||
html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/edit'), 'alt' => get_string('edit'), 'class' => 'iconsmall')),
|
||||
array('title' => get_string('edit')));
|
||||
$editcolumnisempty = false;
|
||||
}
|
||||
if ($cohortcanassign) {
|
||||
$buttons[] = html_writer::link(new moodle_url('/cohort/assign.php', $urlparams),
|
||||
html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('i/users'), 'alt' => get_string('assign', 'core_cohort'), 'class' => 'iconsmall')),
|
||||
array('title' => get_string('assign', 'core_cohort')));
|
||||
$editcolumnisempty = false;
|
||||
}
|
||||
}
|
||||
$line[] = implode(' ', $buttons);
|
||||
@@ -180,12 +183,21 @@ foreach($cohorts['cohorts'] as $cohort) {
|
||||
}
|
||||
$table = new html_table();
|
||||
$table->head = array(get_string('name', 'cohort'), get_string('idnumber', 'cohort'), get_string('description', 'cohort'),
|
||||
get_string('memberscount', 'cohort'), get_string('component', 'cohort'), get_string('edit'));
|
||||
$table->colclasses = array('leftalign name', 'leftalign id', 'leftalign description', 'leftalign size','centeralign source', 'centeralign action');
|
||||
get_string('memberscount', 'cohort'), get_string('component', 'cohort'));
|
||||
$table->colclasses = array('leftalign name', 'leftalign id', 'leftalign description', 'leftalign size','centeralign source');
|
||||
if ($showall) {
|
||||
array_unshift($table->head, get_string('category'));
|
||||
array_unshift($table->colclasses, 'leftalign category');
|
||||
}
|
||||
if (!$editcolumnisempty) {
|
||||
$table->head[] = get_string('edit');
|
||||
$table->colclasses[] = 'centeralign action';
|
||||
} else {
|
||||
// Remove last column from $data.
|
||||
foreach ($data as $row) {
|
||||
array_pop($row->cells);
|
||||
}
|
||||
}
|
||||
$table->id = 'cohorts';
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$table->data = $data;
|
||||
|
||||
@@ -22,10 +22,10 @@ Feature: Access visible and hidden cohorts
|
||||
| Cohort empty in category 1 | CVE1 | Category | CAT1 | 1 |
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | First | User | first@user.com |
|
||||
| user2 | Second | User | second@user.com |
|
||||
| student | Sam | User | student@user.com |
|
||||
| teacher | Terry | User | teacher@user.com |
|
||||
| user1 | First | User | first@example.com |
|
||||
| user2 | Second | User | second@example.com |
|
||||
| student | Sam | User | student@example.com |
|
||||
| teacher | Terry | User | teacher@example.com |
|
||||
And the following "cohort members" exist:
|
||||
| user | cohort |
|
||||
| student | CV0 |
|
||||
@@ -60,7 +60,7 @@ Feature: Access visible and hidden cohorts
|
||||
And I set the field "Cohort" to "System cohort"
|
||||
And I press "Add method"
|
||||
And I navigate to "Enrolled users" node in "Course administration > Users"
|
||||
And I should see "student@user.com"
|
||||
And I should see "student@example.com"
|
||||
And I navigate to "Groups" node in "Course administration > Users"
|
||||
And I press "Auto-create groups"
|
||||
And the "Select members from cohort" select box should contain "Cohort in category 1"
|
||||
@@ -87,7 +87,7 @@ Feature: Access visible and hidden cohorts
|
||||
And I set the field "Cohort" to "System cohort"
|
||||
And I press "Add method"
|
||||
And I navigate to "Enrolled users" node in "Course administration > Users"
|
||||
And I should see "student@user.com"
|
||||
And I should see "student@example.com"
|
||||
And I navigate to "Groups" node in "Course administration > Users"
|
||||
And I press "Auto-create groups"
|
||||
And the "Select members from cohort" select box should contain "Cohort in category 1"
|
||||
@@ -114,7 +114,7 @@ Feature: Access visible and hidden cohorts
|
||||
And I set the field "Cohort" to "System cohort"
|
||||
And I press "Add method"
|
||||
And I navigate to "Enrolled users" node in "Course administration > Users"
|
||||
And I should see "student@user.com"
|
||||
And I should see "student@example.com"
|
||||
And I navigate to "Groups" node in "Course administration > Users"
|
||||
And I press "Auto-create groups"
|
||||
And the "Select members from cohort" select box should contain "Cohort in category 1"
|
||||
|
||||
@@ -7,10 +7,10 @@ Feature: Add cohorts of users
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| user1 | First | User | first@user.com |
|
||||
| user2 | Second | User | second@user.com |
|
||||
| user3 | Third | User | third@user.com |
|
||||
| user4 | Forth | User | forth@user.com |
|
||||
| user1 | First | User | first@example.com |
|
||||
| user2 | Second | User | second@example.com |
|
||||
| user3 | Third | User | third@example.com |
|
||||
| user4 | Forth | User | forth@example.com |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Cohorts" node in "Site administration > Users > Accounts"
|
||||
And I follow "Add new cohort"
|
||||
@@ -31,13 +31,13 @@ Feature: Add cohorts of users
|
||||
|
||||
@javascript
|
||||
Scenario: Add users to a cohort selecting them from the system users list
|
||||
When I add "First User (first@user.com)" user to "333" cohort members
|
||||
And I add "Second User (second@user.com)" user to "333" cohort members
|
||||
When I add "First User (first@example.com)" user to "333" cohort members
|
||||
And I add "Second User (second@example.com)" user to "333" cohort members
|
||||
Then I should see "2" in the "#cohorts" "css_element"
|
||||
And I follow "Assign"
|
||||
And the "Current users" select box should contain "First User (first@user.com)"
|
||||
And the "Current users" select box should contain "Second User (second@user.com)"
|
||||
And the "Current users" select box should not contain "Forth User (forth@user.com)"
|
||||
And the "Current users" select box should contain "First User (first@example.com)"
|
||||
And the "Current users" select box should contain "Second User (second@example.com)"
|
||||
And the "Current users" select box should not contain "Forth User (forth@example.com)"
|
||||
|
||||
@javascript
|
||||
Scenario: Add users to a cohort using a bulk user action
|
||||
@@ -53,6 +53,6 @@ Feature: Add cohorts of users
|
||||
And I follow "Cohorts"
|
||||
Then I should see "2" in the "#cohorts" "css_element"
|
||||
And I follow "Assign"
|
||||
And the "Current users" select box should contain "Third User (third@user.com)"
|
||||
And the "Current users" select box should contain "Forth User (forth@user.com)"
|
||||
And the "Current users" select box should not contain "First User (first@user.com)"
|
||||
And the "Current users" select box should contain "Third User (third@example.com)"
|
||||
And the "Current users" select box should contain "Forth User (forth@example.com)"
|
||||
And the "Current users" select box should not contain "First User (first@example.com)"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user