Compare commits
477 Commits
v3.4.0-rc1
...
v3.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
| c9236c6860 | |||
| 5dcd9c53e3 | |||
| 758066eda4 | |||
| 6a12f2de83 | |||
| fe8663110a | |||
| 0f6761962a | |||
| bc066df1f6 | |||
| 246b39cba9 | |||
| facd24b4c7 | |||
| b7b3b75b2c | |||
| 98ac97e2a0 | |||
| 9aa6e8bfa4 | |||
| 03a65d8916 | |||
| 5e430e98cb | |||
| 068f22aee0 | |||
| 99d570fef4 | |||
| 4a2bc331fb | |||
| 3fef39fc68 | |||
| 5d434d4d19 | |||
| 440113b457 | |||
| 41ff45a7a7 | |||
| fa4274319d | |||
| 06c5a9e6ff | |||
| ca3605500e | |||
| 6beb56ba1f | |||
| f83fc14e4d | |||
| 844eae52fb | |||
| cf304a8870 | |||
| 8ec36b0fe2 | |||
| 31a9ee8172 | |||
| d0308d8d76 | |||
| 144c240841 | |||
| 434c5f8a56 | |||
| 0ce4a24888 | |||
| bfd1dd07d8 | |||
| 51e05c09c3 | |||
| 02990bd6b9 | |||
| a66195b8b9 | |||
| ae7953ff01 | |||
| e5dc80a10c | |||
| f080964380 | |||
| 2ea79c66cf | |||
| 36b738c185 | |||
| 1a89875c36 | |||
| c29b6e8c15 | |||
| ff710b83c3 | |||
| c619279f5e | |||
| 5772b0fba2 | |||
| c89d473133 | |||
| 0e540897e6 | |||
| 27e2fe6981 | |||
| e35bc644de | |||
| 5d7d6cb52b | |||
| 913abd448b | |||
| dfe9aa213b | |||
| dc24b81fef | |||
| cff1f1943e | |||
| fe5d17b166 | |||
| cdda22dad7 | |||
| 641a281bef | |||
| e70b33b720 | |||
| 8578d28631 | |||
| c7a1ecd9f6 | |||
| 829adb5f21 | |||
| b6e79ab8d8 | |||
| 2ba2d02202 | |||
| 2d117605b8 | |||
| 237e1a85ce | |||
| 5cb64c1faa | |||
| e714f3cee9 | |||
| 16deaa8611 | |||
| ffa36a4bbe | |||
| 5ed65e12e1 | |||
| d1c15a50c9 | |||
| bc121625c3 | |||
| 251a824d8e | |||
| efde049bdf | |||
| 88498220a1 | |||
| dfdadbdbe2 | |||
| fb8b947963 | |||
| b844baf8be | |||
| 0c794fc199 | |||
| 2f4feacac7 | |||
| 7d7edc8820 | |||
| 18c838f586 | |||
| 21c63124ab | |||
| 350cefe41e | |||
| 47c56f3475 | |||
| 4b5ac4ceae | |||
| 8ed193c3ee | |||
| 40e430e634 | |||
| aaf94b8f75 | |||
| 18e6878f5a | |||
| 1041ccaf2e | |||
| fb7b0157c1 | |||
| 8827e7fc3f | |||
| b85ec901dd | |||
| 2faa795209 | |||
| ca5a9de8c5 | |||
| b9287872eb | |||
| 8b448de4b0 | |||
| 06588b2cc0 | |||
| e8e4566aaa | |||
| 94ccf35860 | |||
| cf0386e763 | |||
| a603f86d65 | |||
| 265e374204 | |||
| e62e93aa0d | |||
| d00a6f52b4 | |||
| 0c75121648 | |||
| 5681222a0b | |||
| a45b7aa7ee | |||
| 3093cc28f1 | |||
| 0ff581cece | |||
| b93a787b3e | |||
| 4ab37af070 | |||
| f85f002b37 | |||
| f7bdcf959f | |||
| 64abea941e | |||
| b9bebd0e36 | |||
| de703e70e7 | |||
| b35acd2249 | |||
| a45c466000 | |||
| 3b7f331372 | |||
| 3145f21de1 | |||
| f8550e7982 | |||
| ab0847d328 | |||
| 54339683ac | |||
| 65e260281b | |||
| f29bd28d6a | |||
| 9654f2cd71 | |||
| 2337078a30 | |||
| 29d9535277 | |||
| 4b162c766d | |||
| 606c17e6ef | |||
| daf44482e9 | |||
| 7da0e04ca3 | |||
| 45c42e01a3 | |||
| 74af3b176d | |||
| 7e9f55f138 | |||
| 7354b4ea0e | |||
| 9f6edf2171 | |||
| 511c9addfa | |||
| 8616e10e89 | |||
| 91406c9103 | |||
| aa383f1b47 | |||
| 8bb22c4544 | |||
| ff383cdd57 | |||
| 23e190ead5 | |||
| d997069c62 | |||
| 96cc77d435 | |||
| 1daf3fafc0 | |||
| 7522b6a2e3 | |||
| ece94bb4e2 | |||
| cd44d4e463 | |||
| 395c985759 | |||
| 684d866e20 | |||
| 3b2e8b4a0a | |||
| 816e06e809 | |||
| 6924954471 | |||
| 2875ff2934 | |||
| b1ddacfc8e | |||
| 6d353a7918 | |||
| f9e09bd963 | |||
| 4f657eeed9 | |||
| 60e57b8448 | |||
| 628f99bf45 | |||
| 68e670d8ea | |||
| af9b21a388 | |||
| de08d71fc8 | |||
| 4846674f5c | |||
| ac66136751 | |||
| 5617f26568 | |||
| ad81f22148 | |||
| aabf264460 | |||
| c22d3a30a1 | |||
| 64d3271039 | |||
| c83c2c0f47 | |||
| 5fdb912a82 | |||
| 7a06e15952 | |||
| b64f314662 | |||
| e5994e8c04 | |||
| 1fb4f49cca | |||
| 32b4b57b26 | |||
| fd7e75a8a5 | |||
| abd7d4394b | |||
| e4256cd769 | |||
| 5a6a4cef8b | |||
| 8721afb2c6 | |||
| 0e199a5aec | |||
| 320947908b | |||
| 2e55209603 | |||
| f8979fac97 | |||
| 6a33a850fc | |||
| 9164ab6e39 | |||
| 2af1421e34 | |||
| 5a9fa0fe57 | |||
| c1db07d55b | |||
| c5b7a25ee6 | |||
| 7cc665e9c7 | |||
| 05fd85142e | |||
| e62ea2b803 | |||
| 972142a9af | |||
| b25f3693bb | |||
| 369caa6183 | |||
| 00268741c2 | |||
| 605b0547de | |||
| eea1aff443 | |||
| 1bc5a5abe9 | |||
| be4ea98f29 | |||
| 845215d826 | |||
| 2a9c11965b | |||
| 8c3d8a68f7 | |||
| 969010296d | |||
| 87186b9710 | |||
| 539ad434cb | |||
| af4fa2a55b | |||
| 15aec0b054 | |||
| 7974bbcaf7 | |||
| b4cbad15de | |||
| fe1eb00c0f | |||
| 03df75c0de | |||
| 21c6513a7c | |||
| 8938d826d9 | |||
| e71a526011 | |||
| f3f6960d3e | |||
| 8952d3f100 | |||
| 0bb9e2d8d7 | |||
| 07b6c89868 | |||
| ffba0168b1 | |||
| 26a276cea1 | |||
| 3e2eb62931 | |||
| 62104652c8 | |||
| c950c91696 | |||
| 73e4f14d1b | |||
| 87d3c32f2e | |||
| b8e0488c90 | |||
| 6c23087aa7 | |||
| a6d9966786 | |||
| 1a8167e781 | |||
| 47dd1d85aa | |||
| c29edc7551 | |||
| fdddb80b70 | |||
| 70a804d98e | |||
| c12caea3d4 | |||
| 191a7fd205 | |||
| b0cb0168f4 | |||
| fb762d4e5c | |||
| ed0e988020 | |||
| 20cb5f4086 | |||
| de5d2667ab | |||
| 4a54efd42a | |||
| 5769d5fc86 | |||
| 0225f34969 | |||
| 23c69f1ef0 | |||
| 6e6b38e0b5 | |||
| 2e3892e951 | |||
| abe62e33e6 | |||
| 78731d0b96 | |||
| 56a58d538c | |||
| ef1c918973 | |||
| 3b9fce4e1c | |||
| 7b9e9eb98d | |||
| 0456d880f0 | |||
| 705776211a | |||
| 94b8228ba1 | |||
| 0b7d0d0f79 | |||
| c29501c06d | |||
| c152025706 | |||
| 0444dd2b70 | |||
| 15aded1e2a | |||
| cbff142b8e | |||
| ee16cb39bf | |||
| 7f0eba32de | |||
| 144c9ba7c3 | |||
| b676ff39a4 | |||
| fe709d665d | |||
| d692104051 | |||
| 17ebd603e1 | |||
| b24eb6c565 | |||
| c449504287 | |||
| 8df6b374bb | |||
| e84e1bbff3 | |||
| 3cfc322bdf | |||
| 6da402bf34 | |||
| 126c58ede4 | |||
| 6217d91173 | |||
| d28be61fb5 | |||
| a96ef27857 | |||
| 255541d592 | |||
| 19b4c997e9 | |||
| 93819366a4 | |||
| 7726e2e2d6 | |||
| d95ccdd4ec | |||
| 5698d90e6a | |||
| 44b87b5d95 | |||
| 334412f1cc | |||
| afcb4cd69a | |||
| d8a7c52ee6 | |||
| 05a70bac38 | |||
| 951f10fd3e | |||
| 10a5e2a8de | |||
| 82c32f9a80 | |||
| 17ae93679d | |||
| 27ffa62131 | |||
| 97a4db9c97 | |||
| 6f1a49b8b7 | |||
| 740807d2e3 | |||
| 066b01a788 | |||
| 2ce6578835 | |||
| e7b4c991ee | |||
| 42ee1fc276 | |||
| d56935d66f | |||
| 9e2565d84d | |||
| 73c72b4148 | |||
| 244af9a0da | |||
| 2eb043fb36 | |||
| 2454da368a | |||
| 8e899e949d | |||
| 6b0b697fb8 | |||
| 9a854a2fc9 | |||
| b6f1cf03e3 | |||
| d26cdca687 | |||
| dbeee32b59 | |||
| 0a8663b425 | |||
| 665c3ac59c | |||
| 07c0bb10fb | |||
| cf57ee9285 | |||
| d334aea208 | |||
| 0cf288757d | |||
| 695cd06817 | |||
| ab9936962e | |||
| d39fcc420e | |||
| 08641175b3 | |||
| 66aee746e3 | |||
| f738fc8efd | |||
| 27973b545c | |||
| 3192438075 | |||
| 41b7375c07 | |||
| cb04dcf4ce | |||
| c3925187ed | |||
| 4ceece6ea1 | |||
| cfbc820e1b | |||
| fbbcf45ef2 | |||
| 6e2d8c121b | |||
| 6b2a9a6fb8 | |||
| ae4522ff55 | |||
| fb5bbf1424 | |||
| ce225e1c5e | |||
| 08b7558483 | |||
| 9dead25fd5 | |||
| eac88b955f | |||
| 438c98cc98 | |||
| ba854606e6 | |||
| f5b63fc829 | |||
| 6996fbaa0e | |||
| 20305a8a8f | |||
| 5da020169e | |||
| 2f673d8b6a | |||
| 4bcb0a9a1d | |||
| a4e0b7468c | |||
| 7fdcdc04ff | |||
| bef5a8ca10 | |||
| 246698e779 | |||
| 4f3262fede | |||
| f169f4fd21 | |||
| d48d1ba19a | |||
| 7a571b813a | |||
| 754016ab33 | |||
| 10c17dcc10 | |||
| 5518a32de5 | |||
| 56f05f23c6 | |||
| bb869f05e8 | |||
| 7cf4331a6f | |||
| 762f8dc1db | |||
| a997dc9da5 | |||
| 446b21b512 | |||
| 3968d2ca7e | |||
| 7f83e99e5f | |||
| 68c580c903 | |||
| 0c0d460e8b | |||
| ed0e2cea00 | |||
| 7effd6dd79 | |||
| 29adfbc3c8 | |||
| d00007bc45 | |||
| 4e73acf3cf | |||
| fcafb22c22 | |||
| 6463a047a2 | |||
| ccf7578373 | |||
| 68ba214c65 | |||
| a471bc4971 | |||
| b6319f70bd | |||
| d3882ea4a3 | |||
| e759c9ed83 | |||
| c9f995872f | |||
| 2e36c42625 | |||
| 7a2300fd82 | |||
| f3342e1010 | |||
| ea90412944 | |||
| 8d64443452 | |||
| 4b0facc984 | |||
| abdb8f59a5 | |||
| d6d2cec4a0 | |||
| 57c9b7fc37 | |||
| cae37299f3 | |||
| c835126185 | |||
| 5243e93661 | |||
| b135c42a17 | |||
| ec8f488f30 | |||
| aa30dc8860 | |||
| 76f98c3bd5 | |||
| 7783fd0ec1 | |||
| a6943ebb59 | |||
| eaa43a132c | |||
| 81aa5e196f | |||
| b5b81de3d6 | |||
| f0fc8a194a | |||
| 03561ea899 | |||
| 6688ae2ba2 | |||
| b44bc9bf6c | |||
| 65c52e05d1 | |||
| 1ccc9f1953 | |||
| efe2681894 | |||
| e3a6d44845 | |||
| 8aa01fcf61 | |||
| 8072eb1384 | |||
| b9ae53f86b | |||
| 5616a31987 | |||
| 8926030555 | |||
| 13b19e40cb | |||
| 478b1d194f | |||
| 9aac9f7074 | |||
| 3a0951f027 | |||
| 7d416f9c2c | |||
| 589b602be3 | |||
| 8001199766 | |||
| a56833d49d | |||
| be88f0993d | |||
| 11e60032be | |||
| 401710883b | |||
| 34eb2faa0d | |||
| 8c067bb86d | |||
| 77a4d33755 | |||
| 40f05d2312 | |||
| 3602df58b2 | |||
| f3743b3041 | |||
| e2d635bbaf | |||
| a764855641 | |||
| 9b0f29239b | |||
| 8ce86ebba3 | |||
| 30890c2971 | |||
| 1bd70073c5 | |||
| 9e0884d410 | |||
| af25b8fc7f | |||
| ef29782f31 | |||
| 1ada616c56 | |||
| 8443b88995 | |||
| eb354bdefa | |||
| 4cd3927c4f | |||
| 6a973d261a | |||
| 796e48a58b | |||
| 496b39974f | |||
| 6586118e0f | |||
| 4a145a8ae5 | |||
| da8a0c97f0 | |||
| 20b2565c38 | |||
| 36e84e96fc | |||
| b9fd516407 | |||
| 20a5056df6 | |||
| 6be1923d81 | |||
| 801a372dad | |||
| 1322351b92 | |||
| 0df5c743ad | |||
| 740a9315c3 | |||
| f8c0b9e71f | |||
| 9016f772ce | |||
| 18ae59bea1 |
@@ -1,4 +1,5 @@
|
||||
**/yui/build/** -diff
|
||||
**/amd/build/** -diff
|
||||
lib/dml/oci_native_moodle_package.sql text eol=lf
|
||||
theme/bootstrapbase/style/editor.css -diff
|
||||
theme/bootstrapbase/style/moodle.css -diff
|
||||
|
||||
+13
-10
@@ -13,7 +13,7 @@ language: php
|
||||
|
||||
php:
|
||||
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.0
|
||||
|
||||
addons:
|
||||
@@ -23,14 +23,15 @@ addons:
|
||||
- mysql-client-core-5.6
|
||||
- mysql-client-5.6
|
||||
|
||||
services:
|
||||
- redis-server
|
||||
# Redis tests are currently failing on php 7.2 due to https://bugs.php.net/bug.php?id=75628
|
||||
# services:
|
||||
# - redis-server
|
||||
|
||||
env:
|
||||
# Although we want to run these jobs and see failures as quickly as possible, we also want to get the slowest job to
|
||||
# start first so that the total run time is not too high.
|
||||
#
|
||||
# We only run MySQL on PHP 7.1, so run that first.
|
||||
# We only run MySQL on PHP 7.2, so run that first.
|
||||
# CI Tests should be second-highest in priority as these only take <= 60 seconds to run under normal circumstances.
|
||||
# Postgres is significantly is pretty reasonable in its run-time.
|
||||
|
||||
@@ -54,12 +55,12 @@ matrix:
|
||||
|
||||
include:
|
||||
# Run grunt/npm install on highest version ('node' is an alias for the latest node.js version.)
|
||||
- php: 7.1
|
||||
- php: 7.2
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='8.9'
|
||||
|
||||
exclude:
|
||||
# MySQL - it's just too slow.
|
||||
# Exclude it on all versions except for 7.1
|
||||
# Exclude it on all versions except for 7.2
|
||||
|
||||
- env: DB=mysqli TASK=PHPUNIT
|
||||
php: 7.0
|
||||
@@ -99,8 +100,9 @@ install:
|
||||
fi
|
||||
|
||||
# Enable Redis.
|
||||
echo 'extension="redis.so"' > /tmp/redis.ini
|
||||
phpenv config-add /tmp/redis.ini
|
||||
# Redis tests are currently failing on php 7.2 due to https://bugs.php.net/bug.php?id=75628
|
||||
# echo 'extension="redis.so"' > /tmp/redis.ini
|
||||
# phpenv config-add /tmp/redis.ini
|
||||
|
||||
# Install composer dependencies.
|
||||
# We need --no-interaction in case we hit API limits for composer. This causes it to fall back to a standard clone.
|
||||
@@ -171,10 +173,11 @@ before_script:
|
||||
mkdir -p "$HOME"/roots/phpunit
|
||||
|
||||
# The phpunit dataroot and prefix..
|
||||
# Redis tests are currently failing on php 7.2 due to https://bugs.php.net/bug.php?id=75628
|
||||
# -e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
|
||||
sed -i \
|
||||
-e "/require_once/i \\\$CFG->phpunit_dataroot = '\/home\/travis\/roots\/phpunit';" \
|
||||
-e "/require_once/i \\\$CFG->phpunit_prefix = 'p_';" \
|
||||
-e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
|
||||
config.php ;
|
||||
|
||||
# Initialise PHPUnit for Moodle.
|
||||
@@ -204,7 +207,7 @@ before_script:
|
||||
# We need the official upstream for comparison
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
git fetch upstream master;
|
||||
git fetch upstream MOODLE_34_STABLE;
|
||||
export GIT_PREVIOUS_COMMIT="`git merge-base FETCH_HEAD $TRAVIS_COMMIT`";
|
||||
export GIT_COMMIT="$TRAVIS_COMMIT";
|
||||
export UPSTREAM_FETCH_HEAD=`git rev-parse FETCH_HEAD`
|
||||
|
||||
@@ -165,6 +165,12 @@ function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts,
|
||||
// If custom field then pick name from database.
|
||||
$fieldshortname = str_replace('profile_field_', '', $fieldname);
|
||||
$fieldname = $customfieldname[$fieldshortname]->name;
|
||||
if (core_text::strlen($fieldshortname) > 67) {
|
||||
// If custom profile field name is longer than 67 characters we will not be able to store the setting
|
||||
// such as 'field_updateremote_profile_field_NOTSOSHORTSHORTNAME' in the database because the character
|
||||
// limit for the setting name is 100.
|
||||
continue;
|
||||
}
|
||||
} elseif ($fieldname == 'url') {
|
||||
$fieldname = get_string('webpage');
|
||||
} else {
|
||||
|
||||
+9
-7
@@ -54,14 +54,16 @@ $statusmsg = '';
|
||||
$errormsg = '';
|
||||
|
||||
if ($data = data_submitted() and confirm_sesskey()) {
|
||||
if (admin_write_settings($data)) {
|
||||
$statusmsg = get_string('changessaved');
|
||||
}
|
||||
|
||||
$count = admin_write_settings($data);
|
||||
if (empty($adminroot->errors)) {
|
||||
switch ($return) {
|
||||
case 'site': redirect("$CFG->wwwroot/");
|
||||
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
|
||||
// No errors. Did we change any setting? If so, then indicate success.
|
||||
if ($count) {
|
||||
$statusmsg = get_string('changessaved');
|
||||
} else {
|
||||
switch ($return) {
|
||||
case 'site': redirect("$CFG->wwwroot/");
|
||||
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$errormsg = get_string('errorwithsettings', 'admin');
|
||||
|
||||
@@ -2259,4 +2259,180 @@
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.5" requires="3.1">
|
||||
<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.3" />
|
||||
<VENDOR name="mssql" version="10.0" />
|
||||
<VENDOR name="oracle" version="10.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.0.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="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="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlrpc" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="xmlrpcrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
</PHP_EXTENSIONS>
|
||||
<PHP_SETTINGS>
|
||||
<PHP_SETTING name="memory_limit" value="96M" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="settingmemorylimit" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="file_uploads" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="settingfileuploads" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
<PHP_SETTING name="opcache.enable" value="1" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="opcacherecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_SETTING>
|
||||
</PHP_SETTINGS>
|
||||
<CUSTOM_CHECKS>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbstorageengine" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="quizattemptsupgradedmessage" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="slashargumentswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unsupporteddbtablerowformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="unoconvwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="libcurlwarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfileformat" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddbfilepertable" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unsupporteddblargeprefix" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="ishttpswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="incompleteunicodesupport" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
@@ -29,9 +29,10 @@ require_once($CFG->libdir.'/adminlib.php');
|
||||
$confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
|
||||
|
||||
admin_externalpage_setup('purgecaches');
|
||||
|
||||
// If we have got here as a confirmed aciton, do it.
|
||||
if ($confirm && isloggedin() && confirm_sesskey()) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
if ($confirm && confirm_sesskey()) {
|
||||
|
||||
// Valid request. Purge, and redirect the user back to where they came from.
|
||||
purge_all_caches();
|
||||
@@ -45,8 +46,6 @@ if ($confirm && isloggedin() && confirm_sesskey()) {
|
||||
}
|
||||
|
||||
// Otherwise, show a button to actually purge the caches.
|
||||
admin_externalpage_setup('purgecaches');
|
||||
|
||||
$actionurl = new moodle_url('/admin/purgecaches.php', array('sesskey'=>sesskey(), 'confirm'=>1));
|
||||
if ($returnurl) {
|
||||
$actionurl->param('returnurl', $returnurl);
|
||||
|
||||
@@ -46,6 +46,14 @@ $error = optional_param('error', '', PARAM_ALPHANUM);
|
||||
admin_externalpage_setup('registrationmoodleorg');
|
||||
|
||||
if ($url !== HUB_MOODLEORGHUBURL) {
|
||||
// Allow other plugins to confirm registration on hubs other than moodle.net . Plugins implementing this
|
||||
// callback need to redirect or exit. See https://docs.moodle.org/en/Hub_registration .
|
||||
$callbacks = get_plugins_with_function('hub_registration');
|
||||
foreach ($callbacks as $plugintype => $plugins) {
|
||||
foreach ($plugins as $plugin => $callback) {
|
||||
$callback('confirm');
|
||||
}
|
||||
}
|
||||
throw new moodle_exception('errorotherhubsnotsupported', 'hub');
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,14 @@ $token = optional_param('token', '', PARAM_TEXT);
|
||||
admin_externalpage_setup('registrationmoodleorg');
|
||||
|
||||
if ($url !== HUB_MOODLEORGHUBURL) {
|
||||
// Allow other plugins to renew registration on hubs other than moodle.net . Plugins implementing this
|
||||
// callback need to redirect or exit. See https://docs.moodle.org/en/Hub_registration .
|
||||
$callbacks = get_plugins_with_function('hub_registration');
|
||||
foreach ($callbacks as $plugintype => $plugins) {
|
||||
foreach ($plugins as $plugin => $callback) {
|
||||
$callback('renew');
|
||||
}
|
||||
}
|
||||
throw new moodle_exception('errorotherhubsnotsupported', 'hub');
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -32,15 +32,16 @@ $focus = '';
|
||||
// now we'll deal with the case that the admin has submitted the form with changed settings
|
||||
if ($data = data_submitted() and confirm_sesskey() and isset($data->action) and $data->action == 'save-settings') {
|
||||
require_capability('moodle/site:config', $context);
|
||||
if (admin_write_settings($data)) {
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
$count = admin_write_settings($data);
|
||||
if (!empty($adminroot->errors)) {
|
||||
$errormsg = get_string('errorwithsettings', 'admin');
|
||||
$firsterror = reset($adminroot->errors);
|
||||
$focus = $firsterror->id;
|
||||
} else {
|
||||
// No errors. Did we change any setting? If so, then redirect with success.
|
||||
if ($count) {
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -39,11 +39,15 @@ $statusmsg = '';
|
||||
$errormsg = '';
|
||||
|
||||
if ($data = data_submitted() and confirm_sesskey()) {
|
||||
if (admin_write_settings($data)) {
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
|
||||
$count = admin_write_settings($data);
|
||||
// Regardless of whether any setting change was written (a positive count), check validation errors for those that didn't.
|
||||
if (empty($adminroot->errors)) {
|
||||
// No errors. Did we change any setting? If so, then redirect with success.
|
||||
if ($count) {
|
||||
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
|
||||
}
|
||||
// We didn't change a setting.
|
||||
switch ($return) {
|
||||
case 'site': redirect("$CFG->wwwroot/");
|
||||
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
|
||||
|
||||
@@ -119,6 +119,9 @@ class models_list implements \renderable, \templatable {
|
||||
debugging("The time splitting method '{$modeldata->timesplitting}' should include a '{$identifier}_help'
|
||||
string to describe its purpose.", DEBUG_DEVELOPER);
|
||||
}
|
||||
} else {
|
||||
$helpicon = new \help_icon('timesplittingnotdefined', 'tool_analytics');
|
||||
$modeldata->timesplittinghelp = $helpicon->export_for_template($output);
|
||||
}
|
||||
|
||||
// Has this model generated predictions?.
|
||||
@@ -207,19 +210,22 @@ class models_list implements \renderable, \templatable {
|
||||
}
|
||||
|
||||
// Enable / disable.
|
||||
if ($model->is_enabled()) {
|
||||
$action = 'disable';
|
||||
$text = get_string('disable');
|
||||
$icontype = 't/block';
|
||||
} else {
|
||||
$action = 'enable';
|
||||
$text = get_string('enable');
|
||||
$icontype = 'i/checked';
|
||||
if ($model->is_enabled() || !empty($modeldata->timesplitting)) {
|
||||
// If there is no timesplitting method set, the model can not be enabled.
|
||||
if ($model->is_enabled()) {
|
||||
$action = 'disable';
|
||||
$text = get_string('disable');
|
||||
$icontype = 't/block';
|
||||
} else {
|
||||
$action = 'enable';
|
||||
$text = get_string('enable');
|
||||
$icontype = 'i/checked';
|
||||
}
|
||||
$urlparams['action'] = $action;
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon($icontype, $text), $text);
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
$urlparams['action'] = $action;
|
||||
$url = new \moodle_url('model.php', $urlparams);
|
||||
$icon = new \action_menu_link_secondary($url, new \pix_icon($icontype, $text), $text);
|
||||
$actionsmenu->add($icon);
|
||||
|
||||
// Export training data.
|
||||
if (!$model->is_static() && $model->is_trained()) {
|
||||
@@ -264,8 +270,13 @@ class models_list implements \renderable, \templatable {
|
||||
} else {
|
||||
$url = new \moodle_url('/admin/settings.php', array('section' => 'analyticssettings'),
|
||||
'id_s_analytics_onlycli');
|
||||
|
||||
$langstrid = 'clievaluationandpredictionsnoadmin';
|
||||
if (is_siteadmin()) {
|
||||
$langstrid = 'clievaluationandpredictions';
|
||||
}
|
||||
$data->infos = array(
|
||||
(object)array('message' => get_string('clievaluationandpredictions', 'tool_analytics', $url->out()),
|
||||
(object)array('message' => get_string($langstrid, 'tool_analytics', $url->out()),
|
||||
'closebutton' => true)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -117,12 +117,21 @@ function tool_analytics_calculate_course_dates($course, $options) {
|
||||
|
||||
$notification = $course->shortname . ' (id = ' . $course->id . '): ';
|
||||
|
||||
$originalenddate = null;
|
||||
$guessedstartdate = null;
|
||||
$guessedenddate = null;
|
||||
$samestartdate = null;
|
||||
$lowerenddate = null;
|
||||
|
||||
if ($options['guessstart'] || $options['guessall']) {
|
||||
|
||||
$originalstartdate = $course->startdate;
|
||||
|
||||
$guessedstartdate = $courseman->guess_start();
|
||||
if ($guessedstartdate == $originalstartdate) {
|
||||
$samestartdate = ($guessedstartdate == $originalstartdate);
|
||||
$lowerenddate = ($course->enddate && ($course->enddate < $guessedstartdate));
|
||||
|
||||
if ($samestartdate) {
|
||||
if (!$guessedstartdate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('cantguessstartdate', 'tool_analytics');
|
||||
} else {
|
||||
@@ -131,6 +140,9 @@ function tool_analytics_calculate_course_dates($course, $options) {
|
||||
}
|
||||
} else if (!$guessedstartdate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('cantguessstartdate', 'tool_analytics');
|
||||
} else if ($lowerenddate) {
|
||||
$notification .= PHP_EOL . ' ' . get_string('cantguessstartdate', 'tool_analytics') . ': ' .
|
||||
get_string('enddatebeforestartdate', 'error') . ' - ' . userdate($guessedstartdate);
|
||||
} else {
|
||||
// Update it to something we guess.
|
||||
|
||||
@@ -151,16 +163,21 @@ function tool_analytics_calculate_course_dates($course, $options) {
|
||||
|
||||
if ($options['guessend'] || $options['guessall']) {
|
||||
|
||||
if (!empty($lowerenddate) && !empty($guessedstartdate)) {
|
||||
$course->startdate = $guessedstartdate;
|
||||
}
|
||||
|
||||
$originalenddate = $course->enddate;
|
||||
|
||||
$format = course_get_format($course);
|
||||
$formatoptions = $format->get_format_options();
|
||||
|
||||
if ($course->format === 'weeks' && $formatoptions['automaticenddate']) {
|
||||
// Special treatment for weeks with automatic end date.
|
||||
// Change this for a course formats API level call in MDL-60702.
|
||||
if (method_exists($format, 'update_end_date') && $formatoptions['automaticenddate']) {
|
||||
// Special treatment for weeks-based formats with automatic end date.
|
||||
|
||||
if ($options['update']) {
|
||||
format_weeks::update_end_date($course->id);
|
||||
$format::update_end_date($course->id);
|
||||
$course->enddate = $DB->get_field('course', 'enddate', array('id' => $course->id));
|
||||
$notification .= PHP_EOL . ' ' . get_string('weeksenddateautomaticallyset', 'tool_analytics') . ': ' .
|
||||
userdate($course->enddate);
|
||||
@@ -195,10 +212,8 @@ function tool_analytics_calculate_course_dates($course, $options) {
|
||||
$updateit = true;
|
||||
}
|
||||
|
||||
if ($options['update']) {
|
||||
if ($course->enddate > $course->startdate) {
|
||||
update_course($course);
|
||||
}
|
||||
if ($options['update'] && $updateit) {
|
||||
update_course($course);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ $string['clearpredictions'] = 'Clear predictions';
|
||||
$string['clearmodelpredictions'] = 'Are you sure you want to clear all "{$a}" predictions?';
|
||||
$string['clienablemodel'] = 'You can enable the model by selecting a time-splitting method by its ID. Note that you can also enable it later using the web interface (\'none\' to exit).';
|
||||
$string['clievaluationandpredictions'] = 'A scheduled task iterates through enabled models and gets predictions. Models evaluation via the web interface is disabled. You can allow these processes to be executed manually via the web interface by disabling the <a href="{$a}">\'onlycli\'</a> analytics setting.';
|
||||
$string['clievaluationandpredictionsnoadmin'] = 'A scheduled task iterates through enabled models and gets predictions. Models evaluation via the web interface is disabled. It may be enabled by a site administrator.';
|
||||
$string['editmodel'] = 'Edit "{$a}" model';
|
||||
$string['edittrainedwarning'] = 'This model has already been trained. Note that changing its indicators or its time-splitting method will delete its previous predictions and start generating new predictions.';
|
||||
$string['enabled'] = 'Enabled';
|
||||
@@ -82,6 +83,8 @@ $string['previouspage'] = 'Previous page';
|
||||
$string['samestartdate'] = 'Current start date is good';
|
||||
$string['sameenddate'] = 'Current end date is good';
|
||||
$string['target'] = 'Target';
|
||||
$string['timesplittingnotdefined'] = 'Time splitting is not defined.';
|
||||
$string['timesplittingnotdefined_help'] = 'You need to select a time-splitting method before enabling the model.';
|
||||
$string['trainandpredictmodel'] = 'Training model and calculating predictions';
|
||||
$string['trainingprocessfinished'] = 'Training process finished';
|
||||
$string['trainingresults'] = 'Training results';
|
||||
|
||||
@@ -160,6 +160,9 @@
|
||||
{{/timesplitting}}
|
||||
{{^timesplitting}}
|
||||
{{#str}}notdefined, tool_analytics{{/str}}
|
||||
{{#timesplittinghelp}}
|
||||
{{>core/help_icon}}
|
||||
{{/timesplittinghelp}}
|
||||
{{/timesplitting}}
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_analytics'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_assignmentupgrade';
|
||||
$plugin->dependencies = array('mod_assign' => 2017050500);
|
||||
$plugin->dependencies = array('mod_assign' => 2017110800);
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_availabilityconditions';
|
||||
|
||||
@@ -398,7 +398,7 @@ function print_combined_install_output($processes) {
|
||||
// Show process name in first row.
|
||||
foreach ($processes as $name => $process) {
|
||||
// If we don't have enough space to show full run name then show runX.
|
||||
if ($lengthofprocessline < strlen($name + 2)) {
|
||||
if ($lengthofprocessline < strlen($name) + 2) {
|
||||
$name = substr($name, -5);
|
||||
}
|
||||
// One extra padding as we are adding | separator for rest of the data.
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_cohortroles'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
$plugin->dependencies = array(
|
||||
|
||||
@@ -38,5 +38,8 @@ function xmldb_tool_customlang_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_customlang'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_dbtransfer'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_filetypes';
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_generator';
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_health'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
$plugin->maturity = MATURITY_ALPHA; // this version's maturity level
|
||||
|
||||
@@ -47,12 +47,12 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
"Test image from another site should be replaced" => [
|
||||
"content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', true) . '">',
|
||||
"expectedcontent" => '<img src="' . $this->get_converted_http_link('/test.jpg') . '">',
|
||||
],
|
||||
"Test object from another site should be replaced" => [
|
||||
"content" => '<object data="' . $this->getExternalTestFileUrl('/test.swf', false) . '">',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<object data="' . $this->getExternalTestFileUrl('/test.swf', true) . '">',
|
||||
"expectedcontent" => '<object data="' . $this->get_converted_http_link('/test.swf') . '">',
|
||||
],
|
||||
"Test image from a site with international name should be replaced" => [
|
||||
"content" => '<img src="http://中国互联网络信息中心.中国/logosy/201706/W01.png">',
|
||||
@@ -82,7 +82,7 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
"Search for params should be case insensitive" => [
|
||||
"content" => '<object DATA="' . $this->getExternalTestFileUrl('/test.swf', false) . '">',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<object DATA="' . $this->getExternalTestFileUrl('/test.swf', true) . '">',
|
||||
"expectedcontent" => '<object DATA="' . $this->get_converted_http_link('/test.swf') . '">',
|
||||
],
|
||||
"URL should be case insensitive" => [
|
||||
"content" => '<object data="HTTP://some.site/path?query">',
|
||||
@@ -93,7 +93,7 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
"content" => '<img alt="A picture" src="' . $this->getExternalTestFileUrl('/test.png', false) .
|
||||
'" width="1”><p style="font-size: \'20px\'"></p>',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<img alt="A picture" src="' . $this->getExternalTestFileUrl('/test.png', true) .
|
||||
"expectedcontent" => '<img alt="A picture" src="' . $this->get_converted_http_link('/test.png') .
|
||||
'" width="1”><p style="font-size: \'20px\'"></p>',
|
||||
],
|
||||
"Broken URL should not be changed" => [
|
||||
@@ -113,11 +113,25 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
$this->getExternalTestFileUrl('/test.jpg', false) . '"></a>',
|
||||
"outputregex" => '/UPDATE/',
|
||||
"expectedcontent" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '"><img src="' .
|
||||
$this->getExternalTestFileUrl('/test.jpg', true) . '"></a>',
|
||||
$this->get_converted_http_link('/test.jpg') . '"></a>',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the HTTP external test file URL to use HTTPS.
|
||||
*
|
||||
* Note: We *must not* use getExternalTestFileUrl with the True option
|
||||
* here, becase it is reasonable to have only one of these set due to
|
||||
* issues with SSL certificates.
|
||||
*
|
||||
* @param string $path Path to be rewritten
|
||||
* @return string
|
||||
*/
|
||||
protected function get_converted_http_link($path) {
|
||||
return preg_replace('/^http:/', 'https:', $this->getExternalTestFileUrl($path, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test upgrade_http_links
|
||||
* @param string $content Example content that we'll attempt to replace.
|
||||
@@ -152,7 +166,7 @@ class httpsreplace_test extends \advanced_testcase {
|
||||
// Get the http url, since the default test wwwroot is https.
|
||||
$wwwrootdomain = 'www.example.com';
|
||||
$wwwroothttp = preg_replace('/^https:/', 'http:', $CFG->wwwroot);
|
||||
$testdomain = 'download.moodle.org';
|
||||
$testdomain = $this->get_converted_http_link('');
|
||||
return [
|
||||
"Test image from an available site so shouldn't be reported" => [
|
||||
"content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">',
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017082500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017082400; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_httpsreplace'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_innodb'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->component = 'tool_installaddon';
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->maturity = MATURITY_STABLE;
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_langimport'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -42,5 +42,8 @@ function xmldb_tool_log_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,5 +36,8 @@ function xmldb_logstore_database_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017062600; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'logstore_database'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'logstore_legacy'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -36,5 +36,8 @@ function xmldb_logstore_standard_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'logstore_standard'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_log'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<li>
|
||||
<a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
|
||||
<ul class="dropdown dropdown-menu">
|
||||
{{#canmanage}}
|
||||
<li class="dropdown-item">
|
||||
<a href="#" data-action="edit">
|
||||
{{#pix}}t/edit{{/pix}} {{#str}}edit{{/str}}
|
||||
@@ -89,11 +90,13 @@
|
||||
{{#pix}}t/down{{/pix}} {{#str}}movedown{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
{{/canmanage}}
|
||||
<li class="dropdown-item">
|
||||
<a href="#" data-action="linkedcourses">
|
||||
{{#pix}}t/viewdetails{{/pix}} {{#str}}linkedcourses, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
{{#canmanage}}
|
||||
<li class="dropdown-item">
|
||||
<a href="#" data-action="relatedcompetencies">
|
||||
{{#pix}}t/add{{/pix}} {{#str}}addcrossreferencedcompetency, tool_lp{{/str}}
|
||||
@@ -104,6 +107,7 @@
|
||||
{{#pix}}t/edit{{/pix}} {{#str}}competencyrule, tool_lp{{/str}}
|
||||
</a>
|
||||
</li>
|
||||
{{/canmanage}}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -112,11 +116,11 @@
|
||||
<p data-region="competencyinfo">
|
||||
{{#str}}nocompetencyselected, tool_lp{{/str}}
|
||||
</p>
|
||||
{{#canmanage}}
|
||||
<div data-region="competencyactions">
|
||||
{{#canmanage}}
|
||||
<button class="btn btn-secondary" data-action="add">{{#pix}}t/add{{/pix}} <span data-region="term"></span></button>
|
||||
{{/canmanage}}
|
||||
</div>
|
||||
{{/canmanage}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
$plugin->version = 2017062700; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_lpimportcsv'; // Full name of the plugin (used for diagnostics).
|
||||
$plugin->dependencies = array('tool_lp' => 2017050500);
|
||||
$plugin->dependencies = array('tool_lp' => 2017110800);
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_lpmigrate'; // Full name of the plugin (used for diagnostics).
|
||||
$plugin->dependencies = array(
|
||||
'tool_lp' => ANY_VERSION
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_messageinbound';
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
$plugin->version = 2017051501; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_mobile'; // Full name of the plugin (used for diagnostics).
|
||||
$plugin->dependencies = array(
|
||||
'webservice_rest' => 2017050500
|
||||
'webservice_rest' => 2017110800
|
||||
);
|
||||
|
||||
@@ -76,5 +76,8 @@ function xmldb_tool_monitor_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_monitor'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_multilangupgrade'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
|
||||
@@ -78,6 +78,10 @@ class issuer extends persistent {
|
||||
$mform->addRule('clientsecret', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
|
||||
$mform->addHelpButton('clientsecret', 'issuerclientsecret', 'tool_oauth2');
|
||||
|
||||
// Use basic authentication.
|
||||
$mform->addElement('checkbox', 'basicauth', get_string('usebasicauth', 'tool_oauth2'));
|
||||
$mform->addHelpButton('basicauth', 'usebasicauth', 'tool_oauth2');
|
||||
|
||||
// Login scopes.
|
||||
$mform->addElement('text', 'loginscopes', get_string('issuerloginscopes', 'tool_oauth2'));
|
||||
$mform->addRule('loginscopes', null, 'required', null, 'client');
|
||||
|
||||
@@ -95,6 +95,8 @@ $string['systemaccountconnected_help'] = 'System accounts are used to provide ad
|
||||
$string['systemaccountconnected'] = 'System account connected';
|
||||
$string['systemaccountnotconnected'] = 'System account not connected';
|
||||
$string['systemauthstatus'] = 'System account connected';
|
||||
$string['usebasicauth'] = 'Authenticate token requests via HTTP headers';
|
||||
$string['usebasicauth_help'] = 'Utilise the HTTP Basic authentication scheme when sending client ID and password with a refresh token request. Recommended by the OAuth 2 standard, but may not be available with some issuers.';
|
||||
$string['userfieldexternalfield'] = 'External field name';
|
||||
$string['userfieldexternalfield_help'] = 'Name of the field provided by the external OAuth system.';
|
||||
$string['userfieldinternalfield_help'] = 'Name of the Moodle user field that should be mapped from the external field.';
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_oauth2'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ if ($options['run']) {
|
||||
}
|
||||
}
|
||||
$_SERVER['argv'] = array_values($_SERVER['argv']);
|
||||
PHPUnit_TextUI_Command::main();
|
||||
PHPUnit\TextUI\Command::main();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_phpunit'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_profiling'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -9,6 +9,7 @@ Feature: Basic recycle bin functionality
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher@asd.com |
|
||||
| student1 | Student | 1 | student@asd.com |
|
||||
| student2 | Student | 2 | student2@asd.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname |
|
||||
| Course 1 | C1 |
|
||||
@@ -16,6 +17,23 @@ Feature: Basic recycle bin functionality
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
| teacher1 | C2 | editingteacher |
|
||||
| student1 | C2 | student |
|
||||
| student2 | C2 | student |
|
||||
And the following "groups" exist:
|
||||
| name | course | idnumber |
|
||||
| Group A | C2 | G1 |
|
||||
| Group B | C2 | G2 |
|
||||
| Group C | C2 | G3 |
|
||||
And the following "group members" exist:
|
||||
| user | group |
|
||||
| teacher1 | G1 |
|
||||
| teacher1 | G2 |
|
||||
| student1 | G1 |
|
||||
| student2 | G1 |
|
||||
| student2 | G2 |
|
||||
And the following config values are set as admin:
|
||||
| coursebinenable | 1 | tool_recyclebin |
|
||||
| categorybinenable | 1 | tool_recyclebin |
|
||||
@@ -58,6 +76,12 @@ Feature: Basic recycle bin functionality
|
||||
And I wait to be redirected
|
||||
And I go to the courses management page
|
||||
And I should see "Course 2" in the "#course-listing" "css_element"
|
||||
And I am on "Course 2" course homepage
|
||||
And I navigate to "Groups" node in "Course administration > Users"
|
||||
And I follow "Overview"
|
||||
And "Student 1" "text" should exist in the "Group A" "table_row"
|
||||
And "Student 2" "text" should exist in the "Group A" "table_row"
|
||||
And "Student 2" "text" should exist in the "Group B" "table_row"
|
||||
|
||||
@javascript
|
||||
Scenario: Deleting a single item from the recycle bin
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_recyclebin'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_replace'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
$plugin->maturity = MATURITY_ALPHA; // this version's maturity level
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500;
|
||||
$plugin->requires = 2017050500;
|
||||
$plugin->version = 2017111300;
|
||||
$plugin->requires = 2017110800;
|
||||
$plugin->component = 'tool_spamcleaner'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_task'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_templatelibrary'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_unsuproles'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_uploadcourse'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -358,7 +358,7 @@ if ($formdata = $mform2->is_cancelled()) {
|
||||
|
||||
// add default values for remaining fields
|
||||
$formdefaults = array();
|
||||
if ($updatetype != UU_UPDATE_FILEOVERRIDE && $updatetype != UU_UPDATE_NOCHANGES) {
|
||||
if (!$existinguser || ($updatetype != UU_UPDATE_FILEOVERRIDE && $updatetype != UU_UPDATE_NOCHANGES)) {
|
||||
foreach ($STD_FIELDS as $field) {
|
||||
if (isset($user->$field)) {
|
||||
continue;
|
||||
|
||||
@@ -38,6 +38,31 @@ Feature: Upload users
|
||||
And I set the field "groups" to "Section 1 (1)"
|
||||
And the "members" select box should contain "Tom Jones"
|
||||
|
||||
@javascript
|
||||
Scenario: Upload users enrolling them on courses and groups applying defaults
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Maths | math102 | 0 |
|
||||
And the following "groups" exist:
|
||||
| name | course | idnumber |
|
||||
| Section 1 | math102 | S1 |
|
||||
| Section 3 | math102 | S3 |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Upload users" node in "Site administration > Users > Accounts"
|
||||
When I upload "lib/tests/fixtures/upload_users.csv" file to "File" filemanager
|
||||
And I press "Upload users"
|
||||
And I set the following fields to these values:
|
||||
| City/town | Brighton |
|
||||
| Department | Purchasing |
|
||||
And I press "Upload users"
|
||||
And I press "Continue"
|
||||
And I navigate to "Users > Accounts > Browse list of users" in site administration
|
||||
And I should see "Tom Jones"
|
||||
And I follow "Tom Jones"
|
||||
And I follow "Edit profile"
|
||||
And the field "City/town" matches value "Brighton"
|
||||
And the field "Department" matches value "Purchasing"
|
||||
|
||||
@javascript
|
||||
Scenario: Upload users with custom profile fields
|
||||
# Create user profile field.
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_uploaduser'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -619,26 +619,43 @@ Tour.prototype.addEventHandler = function (eventName, handler) {
|
||||
*/
|
||||
Tour.prototype.processStepListeners = function (stepConfig) {
|
||||
this.listeners.push(
|
||||
// Next/Previous buttons.
|
||||
{
|
||||
node: this.currentStepNode,
|
||||
args: ['click', '[data-role="next"]', $.proxy(this.next, this)]
|
||||
}, {
|
||||
node: this.currentStepNode,
|
||||
args: ['click', '[data-role="previous"]', $.proxy(this.previous, this)]
|
||||
},
|
||||
// Next/Previous buttons.
|
||||
{
|
||||
node: this.currentStepNode,
|
||||
args: ['click', '[data-role="next"]', $.proxy(this.next, this)]
|
||||
}, {
|
||||
node: this.currentStepNode,
|
||||
args: ['click', '[data-role="previous"]', $.proxy(this.previous, this)]
|
||||
},
|
||||
|
||||
// Close and end tour buttons.
|
||||
{
|
||||
node: this.currentStepNode,
|
||||
args: ['click', '[data-role="end"]', $.proxy(this.endTour, this)]
|
||||
},
|
||||
// Close and end tour buttons.
|
||||
{
|
||||
node: this.currentStepNode,
|
||||
args: ['click', '[data-role="end"]', $.proxy(this.endTour, this)]
|
||||
},
|
||||
|
||||
// Keypresses.
|
||||
{
|
||||
node: $('body'),
|
||||
args: ['keydown', $.proxy(this.handleKeyDown, this)]
|
||||
});
|
||||
// Click backdrop and hide tour.
|
||||
{
|
||||
node: $('[data-flexitour="backdrop"]'),
|
||||
args: ['click', $.proxy(this.hide, this)]
|
||||
},
|
||||
|
||||
// Click out and hide tour without backdrop.
|
||||
{
|
||||
node: $('body'),
|
||||
args: ['click', $.proxy(function (e) {
|
||||
// Handle click in or click out tour content,
|
||||
// if click out, hide tour.
|
||||
if (!this.currentStepNode.is(e.target) && $(e.target).closest('[data-role="flexitour-step"]').length === 0) {
|
||||
this.hide();
|
||||
}}, this)]
|
||||
},
|
||||
|
||||
// Keypresses.
|
||||
{
|
||||
node: $('body'),
|
||||
args: ['keydown', $.proxy(this.handleKeyDown, this)]
|
||||
});
|
||||
|
||||
if (stepConfig.moveOnClick) {
|
||||
var targetNode = this.getStepTarget(stepConfig);
|
||||
@@ -904,7 +921,7 @@ Tour.prototype.announceStep = function (stepConfig) {
|
||||
* @param {EventFacade} e
|
||||
*/
|
||||
Tour.prototype.handleKeyDown = function (e) {
|
||||
var tabbableSelector = 'a[href], link[href], [draggable=true], [contenteditable=true], :input:enabled, [tabindex], button';
|
||||
var tabbableSelector = 'a[href], link[href], [draggable=true], [contenteditable=true], :input:enabled, [tabindex], button:enabled';
|
||||
switch (e.keyCode) {
|
||||
case 27:
|
||||
this.endTour();
|
||||
@@ -923,8 +940,17 @@ Tour.prototype.handleKeyDown = function (e) {
|
||||
var activeElement = $(document.activeElement);
|
||||
var stepTarget = this.getStepTarget(this.currentStepConfig);
|
||||
var tabbableNodes = $(tabbableSelector);
|
||||
var dialogContainer = $('span[data-flexitour="container"]');
|
||||
var currentIndex = void 0;
|
||||
tabbableNodes.filter(function (index, element) {
|
||||
// Filter out element which is not belong to target section or dialogue.
|
||||
if (stepTarget) {
|
||||
tabbableNodes = tabbableNodes.filter(function (index, element) {
|
||||
return stepTarget != null && (stepTarget.has(element).length || dialogContainer.has(element).length || stepTarget.is(element) || dialogContainer.is(element));
|
||||
});
|
||||
}
|
||||
|
||||
// Find index of focusing element.
|
||||
tabbableNodes.each(function (index, element) {
|
||||
if (activeElement.is(element)) {
|
||||
currentIndex = index;
|
||||
return false;
|
||||
@@ -934,7 +960,7 @@ Tour.prototype.handleKeyDown = function (e) {
|
||||
var nextIndex = void 0;
|
||||
var nextNode = void 0;
|
||||
var focusRelevant = void 0;
|
||||
if (currentIndex) {
|
||||
if (currentIndex != void 0) {
|
||||
var direction = 1;
|
||||
if (e.shiftKey) {
|
||||
direction = -1;
|
||||
@@ -1090,6 +1116,16 @@ Tour.prototype.hide = function (transition) {
|
||||
$(this).remove();
|
||||
});
|
||||
|
||||
// Remove aria-describedby and tabindex attributes.
|
||||
if (this.currentStepNode && this.currentStepNode.length) {
|
||||
var stepId = this.currentStepNode.attr('id');
|
||||
if (stepId) {
|
||||
var currentStepElement = '[aria-describedby="' + stepId + '-body"]';
|
||||
$(currentStepElement).removeAttr('tabindex');
|
||||
$(currentStepElement).removeAttr('aria-describedby');
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the listeners.
|
||||
this.resetStepListeners();
|
||||
|
||||
|
||||
@@ -48,5 +48,8 @@ function xmldb_tool_usertours_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -157,3 +157,23 @@ Feature: Apply tour filters to a tour
|
||||
When I am on "Course 2" course homepage
|
||||
And I wait until the page is ready
|
||||
Then I should not see "Welcome to your course tour."
|
||||
|
||||
@javascript
|
||||
Scenario: Aria tags should not exist
|
||||
Given I log in as "admin"
|
||||
And I open the User tour settings page
|
||||
# Turn on default tour for boost theme.
|
||||
And I click on "Enable" "link" in the "Boost - administrator" "table_row"
|
||||
And I am on site homepage
|
||||
When I click on "Next" "button"
|
||||
Then "button[aria-describedby^='tour-step-tool_usertours']" "css_element" should exist
|
||||
And "button[tabindex]" "css_element" should exist
|
||||
When I click on "Next" "button"
|
||||
Then "button[aria-describedby^='tour-step-tool_usertours']" "css_element" should not exist
|
||||
And "button[tabindex]" "css_element" should not exist
|
||||
When I click on "Previous" "button"
|
||||
Then "button[aria-describedby^='tour-step-tool_usertours']" "css_element" should exist
|
||||
And "button[tabindex]" "css_element" should exist
|
||||
When I click on "End tour" "button"
|
||||
Then "button[aria-describedby^='tour-step-tool_usertours']" "css_element" should not exist
|
||||
And "button[tabindex]" "css_element" should not exist
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<location>amd/src/tour.js</location>
|
||||
<name>Flexitour</name>
|
||||
<license>GPLv3</license>
|
||||
<version>0.10.0</version>
|
||||
<version>0.12.0</version>
|
||||
<licenseversion>3</licenseversion>
|
||||
</library>
|
||||
<library>
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version.
|
||||
$plugin->version = 2017111300; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_usertours'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'tool_xmldb'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
|
||||
+8
-2
@@ -256,11 +256,17 @@
|
||||
$users[$key]->country = $countries[$user->country];
|
||||
}
|
||||
}
|
||||
if ($sort == "country") { // Need to resort by full country name, not code
|
||||
if ($sort == "country") {
|
||||
// Need to resort by full country name, not code.
|
||||
foreach ($users as $user) {
|
||||
$susers[$user->id] = $user->country;
|
||||
}
|
||||
asort($susers);
|
||||
// Sort by country name, according to $dir.
|
||||
if ($dir === 'DESC') {
|
||||
arsort($susers);
|
||||
} else {
|
||||
asort($susers);
|
||||
}
|
||||
foreach ($susers as $key => $value) {
|
||||
$nusers[] = $users[$key];
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ class course implements \core_analytics\analysable {
|
||||
*
|
||||
* Lazy load of course data, students and teachers.
|
||||
*
|
||||
* @param int|stdClass $course Course id
|
||||
* @param int|\stdClass $course Course id
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($course) {
|
||||
@@ -152,7 +152,7 @@ class course implements \core_analytics\analysable {
|
||||
*
|
||||
* Lazy load of course data, students and teachers.
|
||||
*
|
||||
* @param int|stdClass $course Course object or course id
|
||||
* @param int|\stdClass $course Course object or course id
|
||||
* @return \core_analytics\course
|
||||
*/
|
||||
public static function instance($course) {
|
||||
@@ -184,7 +184,7 @@ class course implements \core_analytics\analysable {
|
||||
/**
|
||||
* Loads the analytics course object.
|
||||
*
|
||||
* @return null
|
||||
* @return void
|
||||
*/
|
||||
protected function load() {
|
||||
|
||||
@@ -356,7 +356,7 @@ class course implements \core_analytics\analysable {
|
||||
$monthsago = time() - (WEEKSECS * 4 * 2);
|
||||
$select = $filterselect . ' AND timeaccess > :timeaccess';
|
||||
$params = $filterparams + array('timeaccess' => $monthsago);
|
||||
$sql = "SELECT timeaccess FROM {user_lastaccess} ula
|
||||
$sql = "SELECT DISTINCT timeaccess FROM {user_lastaccess} ula
|
||||
JOIN {enrol} e ON e.courseid = ula.courseid
|
||||
JOIN {user_enrolments} ue ON e.id = ue.enrolid AND ue.userid = ula.userid
|
||||
WHERE $select";
|
||||
@@ -364,7 +364,7 @@ class course implements \core_analytics\analysable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$sql = "SELECT timeaccess FROM {user_lastaccess} ula
|
||||
$sql = "SELECT DISTINCT timeaccess FROM {user_lastaccess} ula
|
||||
JOIN {enrol} e ON e.courseid = ula.courseid
|
||||
JOIN {user_enrolments} ue ON e.id = ue.enrolid AND ue.userid = ula.userid
|
||||
WHERE $filterselect AND ula.timeaccess != 0
|
||||
@@ -451,7 +451,7 @@ class course implements \core_analytics\analysable {
|
||||
/**
|
||||
* Returns the course students.
|
||||
*
|
||||
* @return stdClass[]
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_students() {
|
||||
|
||||
@@ -547,172 +547,6 @@ class course implements \core_analytics\analysable {
|
||||
return $grades;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses all activities that were available during a period of time.
|
||||
*
|
||||
* @param string $activitytype
|
||||
* @param int $starttime
|
||||
* @param int $endtime
|
||||
* @param \stdClass $student
|
||||
* @return array
|
||||
*/
|
||||
public function get_activities($activitytype, $starttime, $endtime, $student = false) {
|
||||
|
||||
// Var $student may not be available, default to not calculating dynamic data.
|
||||
$studentid = -1;
|
||||
if ($student) {
|
||||
$studentid = $student->id;
|
||||
}
|
||||
$modinfo = get_fast_modinfo($this->get_course_data(), $studentid);
|
||||
$activities = $modinfo->get_instances_of($activitytype);
|
||||
|
||||
$timerangeactivities = array();
|
||||
foreach ($activities as $activity) {
|
||||
if (!$this->completed_by($activity, $starttime, $endtime)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$timerangeactivities[$activity->context->id] = $activity;
|
||||
}
|
||||
|
||||
return $timerangeactivities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was the activity supposed to be completed during the provided time range?.
|
||||
*
|
||||
* @param \cm_info $activity
|
||||
* @param int $starttime
|
||||
* @param int $endtime
|
||||
* @return bool
|
||||
*/
|
||||
protected function completed_by(\cm_info $activity, $starttime, $endtime) {
|
||||
|
||||
// We can't check uservisible because:
|
||||
// - Any activity with available until would not be counted.
|
||||
// - Sites may block student's course view capabilities once the course is closed.
|
||||
|
||||
// Students can not view hidden activities by default, this is not reliable 100% but accurate in most of the cases.
|
||||
if ($activity->visible === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We skip activities that were not yet visible or their 'until' was not in this $starttime - $endtime range.
|
||||
if ($activity->availability) {
|
||||
$info = new \core_availability\info_module($activity);
|
||||
$activityavailability = $this->availability_completed_by($info, $starttime, $endtime);
|
||||
if ($activityavailability === false) {
|
||||
return false;
|
||||
} else if ($activityavailability === true) {
|
||||
// This activity belongs to this time range.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We skip activities in sections that were not yet visible or their 'until' was not in this $starttime - $endtime range.
|
||||
$section = $activity->get_modinfo()->get_section_info($activity->sectionnum);
|
||||
if ($section->availability) {
|
||||
$info = new \core_availability\info_section($section);
|
||||
$sectionavailability = $this->availability_completed_by($info, $starttime, $endtime);
|
||||
if ($sectionavailability === false) {
|
||||
return false;
|
||||
} else if ($sectionavailability === true) {
|
||||
// This activity belongs to this section time range.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// When the course is using format weeks we use the week's end date.
|
||||
$format = course_get_format($activity->get_modinfo()->get_course());
|
||||
if ($this->get_course_data()->format === 'weeks') {
|
||||
$dates = $format->get_section_dates($section);
|
||||
|
||||
// We need to consider the +2 hours added by get_section_dates.
|
||||
// Avoid $starttime <= $dates->end because $starttime may be the start of the next week.
|
||||
if ($starttime < ($dates->end - 7200) && $endtime >= ($dates->end - 7200)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($activity->sectionnum == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->get_end() || !$this->get_start()) {
|
||||
debugging('Activities which due date is in a time range can not be calculated ' .
|
||||
'if the course doesn\'t have start and end date', DEBUG_DEVELOPER);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!course_format_uses_sections($this->get_course_data()->format)) {
|
||||
// If it does not use sections and there are no availability conditions to access it it is available
|
||||
// and we can not magically classify it into any other time range than this one.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Split the course duration in the number of sections and consider the end of each section the due
|
||||
// date of all activities contained in that section.
|
||||
$formatoptions = $format->get_format_options();
|
||||
if (!empty($formatoptions['numsections'])) {
|
||||
$nsections = $formatoptions['numsections'];
|
||||
} else {
|
||||
// There are course format that use sections but without numsections, we fallback to the number
|
||||
// of cached sections in get_section_info_all, not that accurate though.
|
||||
$coursesections = $activity->get_modinfo()->get_section_info_all();
|
||||
$nsections = count($coursesections);
|
||||
if (isset($coursesections[0])) {
|
||||
// We don't count section 0 if it exists.
|
||||
$nsections--;
|
||||
}
|
||||
}
|
||||
|
||||
$courseduration = $this->get_end() - $this->get_start();
|
||||
$sectionduration = round($courseduration / $nsections);
|
||||
$activitysectionenddate = $this->get_start() + ($sectionduration * $activity->sectionnum);
|
||||
if ($activitysectionenddate > $starttime && $activitysectionenddate <= $endtime) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the activity/section should have been completed during the provided period according to its availability rules.
|
||||
*
|
||||
* @param \core_availability\info $info
|
||||
* @param int $starttime
|
||||
* @param int $endtime
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function availability_completed_by(\core_availability\info $info, $starttime, $endtime) {
|
||||
|
||||
$dateconditions = $info->get_availability_tree()->get_all_children('\availability_date\condition');
|
||||
foreach ($dateconditions as $condition) {
|
||||
// Availability API does not allow us to check from / to dates nicely, we need to be naughty.
|
||||
$conditiondata = $condition->save();
|
||||
|
||||
if ($conditiondata->d === \availability_date\condition::DIRECTION_FROM &&
|
||||
$conditiondata->t > $endtime) {
|
||||
// Skip this activity if any 'from' date is later than the end time.
|
||||
return false;
|
||||
|
||||
} else if ($conditiondata->d === \availability_date\condition::DIRECTION_UNTIL &&
|
||||
($conditiondata->t < $starttime || $conditiondata->t > $endtime)) {
|
||||
// Skip activity if any 'until' date is not in $starttime - $endtime range.
|
||||
return false;
|
||||
} else if ($conditiondata->d === \availability_date\condition::DIRECTION_UNTIL &&
|
||||
$conditiondata->t < $endtime && $conditiondata->t > $starttime) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// This can be interpreted as 'the activity was available but we don't know if its expected completion date
|
||||
// was during this period.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by get_user_ids to extract the user id.
|
||||
*
|
||||
@@ -761,7 +595,7 @@ class course implements \core_analytics\analysable {
|
||||
*
|
||||
* Keys are ignored.
|
||||
*
|
||||
* @param int|float $values Sorted array of values
|
||||
* @param int[]|float[] $values Sorted array of values
|
||||
* @return int
|
||||
*/
|
||||
protected function median($values) {
|
||||
@@ -771,7 +605,7 @@ class course implements \core_analytics\analysable {
|
||||
return reset($values);
|
||||
}
|
||||
|
||||
$middlevalue = floor(($count - 1) / 2);
|
||||
$middlevalue = (int)floor(($count - 1) / 2);
|
||||
|
||||
if ($count % 2) {
|
||||
// Odd number, middle is the median.
|
||||
|
||||
@@ -35,6 +35,13 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
abstract class community_of_inquiry_activity extends linear {
|
||||
|
||||
/**
|
||||
* instancedata
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $instancedata = array();
|
||||
|
||||
/**
|
||||
* @var \core_analytics\course
|
||||
*/
|
||||
@@ -478,8 +485,8 @@ abstract class community_of_inquiry_activity extends linear {
|
||||
// Samples are at cm level or below.
|
||||
$useractivities = array(\context_module::instance($cm->id)->id => $cm);
|
||||
} else {
|
||||
// All course activities.
|
||||
$useractivities = $this->course->get_activities($this->get_activity_type(), $starttime, $endtime, $user);
|
||||
// Activities that should be completed during this time period.
|
||||
$useractivities = $this->get_activities($starttime, $endtime, $user);
|
||||
}
|
||||
|
||||
return $useractivities;
|
||||
@@ -741,6 +748,250 @@ abstract class community_of_inquiry_activity extends linear {
|
||||
$this->grades = $course->get_student_grades($courseactivities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guesses all activities that were available during a period of time.
|
||||
*
|
||||
* @param int $starttime
|
||||
* @param int $endtime
|
||||
* @param \stdClass|false $student
|
||||
* @return array
|
||||
*/
|
||||
protected function get_activities($starttime, $endtime, $student = false) {
|
||||
|
||||
$activitytype = $this->get_activity_type();
|
||||
|
||||
// Var $student may not be available, default to not calculating dynamic data.
|
||||
$studentid = -1;
|
||||
if ($student) {
|
||||
$studentid = $student->id;
|
||||
}
|
||||
$modinfo = get_fast_modinfo($this->course->get_course_data(), $studentid);
|
||||
$activities = $modinfo->get_instances_of($activitytype);
|
||||
|
||||
$timerangeactivities = array();
|
||||
foreach ($activities as $activity) {
|
||||
|
||||
if (!$this->activity_completed_by($activity, $starttime, $endtime, $student)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$timerangeactivities[$activity->context->id] = $activity;
|
||||
}
|
||||
|
||||
return $timerangeactivities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was the activity supposed to be completed during the provided time range?.
|
||||
*
|
||||
* @param \cm_info $activity
|
||||
* @param int $starttime
|
||||
* @param int $endtime
|
||||
* @param \stdClass|false $student
|
||||
* @return bool
|
||||
*/
|
||||
protected function activity_completed_by(\cm_info $activity, $starttime, $endtime, $student = false) {
|
||||
|
||||
// We can't check uservisible because:
|
||||
// - Any activity with available until would not be counted.
|
||||
// - Sites may block student's course view capabilities once the course is closed.
|
||||
|
||||
// Students can not view hidden activities by default, this is not reliable 100% but accurate in most of the cases.
|
||||
if ($activity->visible === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Give priority to the different methods activities have to set a "due" date.
|
||||
$return = $this->activity_type_completed_by($activity, $starttime, $endtime, $student);
|
||||
if (!is_null($return)) {
|
||||
// Method activity_type_completed_by returns null if there is no due date method or there is but it is not set.
|
||||
return $return;
|
||||
}
|
||||
|
||||
// We skip activities that were not yet visible or their 'until' was not in this $starttime - $endtime range.
|
||||
if ($activity->availability) {
|
||||
$info = new \core_availability\info_module($activity);
|
||||
$activityavailability = $this->availability_completed_by($info, $starttime, $endtime);
|
||||
if ($activityavailability === false) {
|
||||
return false;
|
||||
} else if ($activityavailability === true) {
|
||||
// This activity belongs to this time range.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We skip activities in sections that were not yet visible or their 'until' was not in this $starttime - $endtime range.
|
||||
$section = $activity->get_modinfo()->get_section_info($activity->sectionnum);
|
||||
if ($section->availability) {
|
||||
$info = new \core_availability\info_section($section);
|
||||
$sectionavailability = $this->availability_completed_by($info, $starttime, $endtime);
|
||||
if ($sectionavailability === false) {
|
||||
return false;
|
||||
} else if ($sectionavailability === true) {
|
||||
// This activity belongs to this section time range.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// When the course is using format weeks we use the week's end date.
|
||||
$format = course_get_format($activity->get_modinfo()->get_course());
|
||||
// We should change this in MDL-60702.
|
||||
if (method_exists($format, 'get_section_dates')) {
|
||||
$dates = $format->get_section_dates($section);
|
||||
|
||||
// We need to consider the +2 hours added by get_section_dates.
|
||||
// Avoid $starttime <= $dates->end because $starttime may be the start of the next week.
|
||||
if ($starttime < ($dates->end - 7200) && $endtime >= ($dates->end - 7200)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($activity->sectionnum == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->course->get_end() || !$this->course->get_start()) {
|
||||
debugging('Activities which due date is in a time range can not be calculated ' .
|
||||
'if the course doesn\'t have start and end date', DEBUG_DEVELOPER);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!course_format_uses_sections($this->course->get_course_data()->format)) {
|
||||
// If it does not use sections and there are no availability conditions to access it it is available
|
||||
// and we can not magically classify it into any other time range than this one.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Split the course duration in the number of sections and consider the end of each section the due
|
||||
// date of all activities contained in that section.
|
||||
$formatoptions = $format->get_format_options();
|
||||
if (!empty($formatoptions['numsections'])) {
|
||||
$nsections = $formatoptions['numsections'];
|
||||
} else {
|
||||
// There are course format that use sections but without numsections, we fallback to the number
|
||||
// of cached sections in get_section_info_all, not that accurate though.
|
||||
$coursesections = $activity->get_modinfo()->get_section_info_all();
|
||||
$nsections = count($coursesections);
|
||||
if (isset($coursesections[0])) {
|
||||
// We don't count section 0 if it exists.
|
||||
$nsections--;
|
||||
}
|
||||
}
|
||||
|
||||
$courseduration = $this->course->get_end() - $this->course->get_start();
|
||||
$sectionduration = round($courseduration / $nsections);
|
||||
$activitysectionenddate = $this->course->get_start() + ($sectionduration * $activity->sectionnum);
|
||||
if ($activitysectionenddate > $starttime && $activitysectionenddate <= $endtime) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the activity is due or it has been closed during this period, false if during another period, null if no due time.
|
||||
*
|
||||
* It can be overwritten by activities that allow teachers to set a due date or a time close separately
|
||||
* from Moodle availability system. Note that in most of the cases overwriting get_timeclose_field should
|
||||
* be enough.
|
||||
*
|
||||
* Returns true or false if the time close date falls into the provided time range. Null otherwise.
|
||||
*
|
||||
* @param \cm_info $activity
|
||||
* @param int $starttime
|
||||
* @param int $endtime
|
||||
* @param \stdClass|false $student
|
||||
* @return null
|
||||
*/
|
||||
protected function activity_type_completed_by(\cm_info $activity, $starttime, $endtime, $student = false) {
|
||||
|
||||
$fieldname = $this->get_timeclose_field();
|
||||
if (!$fieldname) {
|
||||
// This activity type do not have its own availability control.
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->fill_instance_data($activity);
|
||||
$instance = $this->instancedata[$activity->instance];
|
||||
|
||||
if (!$instance->{$fieldname}) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($starttime < $instance->{$fieldname} && $endtime >= $instance->{$fieldname}) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the field that controls activity availability.
|
||||
*
|
||||
* Should be overwritten by activities that allow teachers to set a due date or a time close separately
|
||||
* from Moodle availability system.
|
||||
*
|
||||
* Just 1 field will not be enough for all cases, but for the most simple ones without
|
||||
* overrides and stuff like that.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function get_timeclose_field() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the activity/section should have been completed during the provided period according to its availability rules.
|
||||
*
|
||||
* @param \core_availability\info $info
|
||||
* @param int $starttime
|
||||
* @param int $endtime
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function availability_completed_by(\core_availability\info $info, $starttime, $endtime) {
|
||||
|
||||
$dateconditions = $info->get_availability_tree()->get_all_children('\availability_date\condition');
|
||||
foreach ($dateconditions as $condition) {
|
||||
// Availability API does not allow us to check from / to dates nicely, we need to be naughty.
|
||||
$conditiondata = $condition->save();
|
||||
|
||||
if ($conditiondata->d === \availability_date\condition::DIRECTION_FROM &&
|
||||
$conditiondata->t > $endtime) {
|
||||
// Skip this activity if any 'from' date is later than the end time.
|
||||
return false;
|
||||
|
||||
} else if ($conditiondata->d === \availability_date\condition::DIRECTION_UNTIL &&
|
||||
($conditiondata->t < $starttime || $conditiondata->t > $endtime)) {
|
||||
// Skip activity if any 'until' date is not in $starttime - $endtime range.
|
||||
return false;
|
||||
} else if ($conditiondata->d === \availability_date\condition::DIRECTION_UNTIL &&
|
||||
$conditiondata->t < $endtime && $conditiondata->t > $starttime) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// This can be interpreted as 'the activity was available but we don't know if its expected completion date
|
||||
// was during this period.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills in activity instance data.
|
||||
*
|
||||
* @param \cm_info $cm
|
||||
* @return void
|
||||
*/
|
||||
protected function fill_instance_data(\cm_info $cm) {
|
||||
global $DB;
|
||||
|
||||
if (!isset($this->instancedata[$cm->instance])) {
|
||||
$this->instancedata[$cm->instance] = $DB->get_record($this->get_activity_type(), array('id' => $cm->instance),
|
||||
'*', MUST_EXIST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines indicator type.
|
||||
*
|
||||
|
||||
@@ -1013,6 +1013,10 @@ class model {
|
||||
if (!$this->is_static()) {
|
||||
$this->model->trained = 0;
|
||||
}
|
||||
} else if (empty($this->model->timesplitting)) {
|
||||
// A valid timesplitting method needs to be supplied before a model can be enabled.
|
||||
throw new \moodle_exception('invalidtimesplitting', 'analytics', '', $this->model->id);
|
||||
|
||||
}
|
||||
|
||||
// Purge pages with insights as this may change things.
|
||||
|
||||
+131
-26
@@ -15,7 +15,7 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for course activities.
|
||||
* Unit tests for activities completed by classification.
|
||||
*
|
||||
* @package core_analytics
|
||||
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
|
||||
@@ -25,13 +25,13 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Unit tests for course activities
|
||||
* Unit tests for activities completed by classification.
|
||||
*
|
||||
* @package core_analytics
|
||||
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class core_analytics_course_activities_testcase extends advanced_testcase {
|
||||
class community_of_inquiry_activities_completed_by_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* availability_levels
|
||||
@@ -59,8 +59,6 @@ class core_analytics_course_activities_testcase extends advanced_testcase {
|
||||
// Forum1 is ignored as section 0 does not count.
|
||||
$forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
|
||||
|
||||
$courseman = new \core_analytics\course($course);
|
||||
|
||||
$modinfo = get_fast_modinfo($course, $stu1->id);
|
||||
$cm = $modinfo->get_cm($forum->cmid);
|
||||
|
||||
@@ -93,20 +91,23 @@ class core_analytics_course_activities_testcase extends advanced_testcase {
|
||||
|
||||
$cm = $modinfo->get_cm($forum->cmid);
|
||||
|
||||
$course = new \core_analytics\course($course);
|
||||
list($indicator, $method) = $this->instantiate_indicator('mod_forum', $course);
|
||||
|
||||
// Condition from after provided end time.
|
||||
$this->assertCount(0, $courseman->get_activities('forum', strtotime('2015-10-20 00:00:00 GMT'),
|
||||
$this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-20 00:00:00 GMT'),
|
||||
strtotime('2015-10-21 00:00:00 GMT'), $stu1));
|
||||
|
||||
// Condition until before provided start time
|
||||
$this->assertCount(0, $courseman->get_activities('forum', strtotime('2015-10-25 00:00:00 GMT'),
|
||||
$this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-25 00:00:00 GMT'),
|
||||
strtotime('2015-10-26 00:00:00 GMT'), $stu1));
|
||||
|
||||
// Condition until after provided end time.
|
||||
$this->assertCount(0, $courseman->get_activities('forum', strtotime('2015-10-22 00:00:00 GMT'),
|
||||
$this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-22 00:00:00 GMT'),
|
||||
strtotime('2015-10-23 00:00:00 GMT'), $stu1));
|
||||
|
||||
// Condition until after provided start time and before provided end time.
|
||||
$this->assertCount(1, $courseman->get_activities('forum', strtotime('2015-10-22 00:00:00 GMT'),
|
||||
$this->assertCount(1, $method->invoke($indicator, strtotime('2015-10-22 00:00:00 GMT'),
|
||||
strtotime('2015-10-25 00:00:00 GMT'), $stu1));
|
||||
}
|
||||
|
||||
@@ -138,7 +139,8 @@ class core_analytics_course_activities_testcase extends advanced_testcase {
|
||||
$forum5 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
|
||||
array('section' => 4));
|
||||
|
||||
$courseman = new \core_analytics\course($course);
|
||||
$course = new \core_analytics\course($course);
|
||||
list($indicator, $method) = $this->instantiate_indicator('mod_forum', $course);
|
||||
|
||||
$this->setUser($stu1);
|
||||
|
||||
@@ -146,10 +148,10 @@ class core_analytics_course_activities_testcase extends advanced_testcase {
|
||||
$second = $startdate + WEEKSECS;
|
||||
$third = $startdate + (WEEKSECS * 2);
|
||||
$forth = $startdate + (WEEKSECS * 3);
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $first, $first + WEEKSECS, $stu1));
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $second, $second + WEEKSECS, $stu1));
|
||||
$this->assertCount(0, $courseman->get_activities('forum', $third, $third + WEEKSECS, $stu1));
|
||||
$this->assertCount(2, $courseman->get_activities('forum', $forth, $forth + WEEKSECS, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $first, $first + WEEKSECS, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $second, $second + WEEKSECS, $stu1));
|
||||
$this->assertCount(0, $method->invoke($indicator, $third, $third + WEEKSECS, $stu1));
|
||||
$this->assertCount(2, $method->invoke($indicator, $forth, $forth + WEEKSECS, $stu1));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +191,8 @@ class core_analytics_course_activities_testcase extends advanced_testcase {
|
||||
$forum6 = $this->getDataGenerator()->create_module('forum', array('course' => $course->id),
|
||||
array('section' => 12));
|
||||
|
||||
$courseman = new \core_analytics\course($course);
|
||||
$course = new \core_analytics\course($course);
|
||||
list($indicator, $method) = $this->instantiate_indicator('mod_forum', $course);
|
||||
|
||||
$this->setUser($stu1);
|
||||
|
||||
@@ -199,10 +202,10 @@ class core_analytics_course_activities_testcase extends advanced_testcase {
|
||||
$second = $startdate + $duration;
|
||||
$third = $startdate + ($duration * 2);
|
||||
$forth = $startdate + ($duration * 3);
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $first, $first + $duration, $stu1));
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $second, $second + $duration, $stu1));
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $third, $third + $duration, $stu1));
|
||||
$this->assertCount(2, $courseman->get_activities('forum', $forth, $forth + $duration, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $first, $first + $duration, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $second, $second + $duration, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $third, $third + $duration, $stu1));
|
||||
$this->assertCount(2, $method->invoke($indicator, $forth, $forth + $duration, $stu1));
|
||||
|
||||
// Split the course in as many parts as sections.
|
||||
$duration = ($enddate - $startdate) / $numsections;
|
||||
@@ -210,15 +213,94 @@ class core_analytics_course_activities_testcase extends advanced_testcase {
|
||||
// The -1 because section 1 start represents the course start.
|
||||
$timeranges[$i] = $startdate + ($duration * ($i - 1));
|
||||
}
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $timeranges[1], $timeranges[1] + $duration, $stu1));
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $timeranges[4], $timeranges[4] + $duration, $stu1));
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $timeranges[8], $timeranges[8] + $duration, $stu1));
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $timeranges[10], $timeranges[10] + $duration, $stu1));
|
||||
$this->assertCount(1, $courseman->get_activities('forum', $timeranges[12], $timeranges[12] + $duration, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $timeranges[1], $timeranges[1] + $duration, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $timeranges[4], $timeranges[4] + $duration, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $timeranges[8], $timeranges[8] + $duration, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $timeranges[10], $timeranges[10] + $duration, $stu1));
|
||||
$this->assertCount(1, $method->invoke($indicator, $timeranges[12], $timeranges[12] + $duration, $stu1));
|
||||
|
||||
// Nothing here.
|
||||
$this->assertCount(0, $courseman->get_activities('forum', $timeranges[2], $timeranges[2] + $duration, $stu1));
|
||||
$this->assertCount(0, $courseman->get_activities('forum', $timeranges[3], $timeranges[3] + $duration, $stu1));
|
||||
$this->assertCount(0, $method->invoke($indicator, $timeranges[2], $timeranges[2] + $duration, $stu1));
|
||||
$this->assertCount(0, $method->invoke($indicator, $timeranges[3], $timeranges[3] + $duration, $stu1));
|
||||
}
|
||||
|
||||
/**
|
||||
* test_get_activities_with_specific_restrictions
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_get_activities_with_specific_restrictions() {
|
||||
|
||||
list($course, $stu1) = $this->setup_course();
|
||||
|
||||
$end = strtotime('2015-10-24 00:00:00 GMT');
|
||||
|
||||
// 1 with time close, one without.
|
||||
$params = array('course' => $course->id);
|
||||
$assign1 = $this->getDataGenerator()->create_module('assign', $params);
|
||||
$params['duedate'] = $end;
|
||||
$assign2 = $this->getDataGenerator()->create_module('assign', $params);
|
||||
|
||||
// 1 with time close, one without.
|
||||
$params = array('course' => $course->id);
|
||||
$choice1 = $this->getDataGenerator()->create_module('choice', $params);
|
||||
$params['timeclose'] = $end;
|
||||
$choice1 = $this->getDataGenerator()->create_module('choice', $params);
|
||||
|
||||
// 1 with time close, one without.
|
||||
$params = array('course' => $course->id);
|
||||
$data1 = $this->getDataGenerator()->create_module('data', $params);
|
||||
$params['timeavailableto'] = $end;
|
||||
$data1 = $this->getDataGenerator()->create_module('data', $params);
|
||||
|
||||
// 1 with time close, one without.
|
||||
$params = array('course' => $course->id);
|
||||
$feedback1 = $this->getDataGenerator()->create_module('feedback', $params);
|
||||
$params['timeclose'] = $end;
|
||||
$feedback1 = $this->getDataGenerator()->create_module('feedback', $params);
|
||||
|
||||
// 1 with time close, one without.
|
||||
$params = array('course' => $course->id);
|
||||
$lesson1 = $this->getDataGenerator()->create_module('lesson', $params);
|
||||
$params['deadline'] = $end;
|
||||
$lesson1 = $this->getDataGenerator()->create_module('lesson', $params);
|
||||
|
||||
// 1 with time close, one without.
|
||||
$params = array('course' => $course->id);
|
||||
$quiz1 = $this->getDataGenerator()->create_module('quiz', $params);
|
||||
$params['timeclose'] = $end;
|
||||
$quiz1 = $this->getDataGenerator()->create_module('quiz', $params);
|
||||
|
||||
// 1 with time close, one without.
|
||||
$params = array('course' => $course->id);
|
||||
$scorm1 = $this->getDataGenerator()->create_module('scorm', $params);
|
||||
$params['timeclose'] = $end;
|
||||
$scorm1 = $this->getDataGenerator()->create_module('scorm', $params);
|
||||
|
||||
// 1 with time close, one without.
|
||||
$params = array('course' => $course->id);
|
||||
$workshop1 = $this->getDataGenerator()->create_module('workshop', $params);
|
||||
$params['submissionend'] = $end;
|
||||
$workshop1 = $this->getDataGenerator()->create_module('workshop', $params);
|
||||
|
||||
$course = new \core_analytics\course($course);
|
||||
|
||||
$activitytypes = array('mod_assign', 'mod_choice', 'mod_data', 'mod_feedback', 'mod_lesson',
|
||||
'mod_quiz', 'mod_scorm', 'mod_workshop');
|
||||
foreach ($activitytypes as $activitytype) {
|
||||
|
||||
list($indicator, $method) = $this->instantiate_indicator($activitytype, $course);
|
||||
|
||||
$message = $activitytype . ' activity type returned activities do not match expected size';
|
||||
$this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-20 00:00:00 GMT'),
|
||||
strtotime('2015-10-21 00:00:00 GMT'), $stu1), $message);
|
||||
|
||||
$this->assertCount(0, $method->invoke($indicator, strtotime('2015-10-25 00:00:00 GMT'),
|
||||
strtotime('2015-10-26 00:00:00 GMT'), $stu1), $message);
|
||||
|
||||
$this->assertCount(1, $method->invoke($indicator, strtotime('2015-10-22 00:00:00 GMT'),
|
||||
strtotime('2015-10-25 00:00:00 GMT'), $stu1), $message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,4 +325,27 @@ class core_analytics_course_activities_testcase extends advanced_testcase {
|
||||
return array($course, $stu1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the module cognitive depth indicator and the reflection method.
|
||||
*
|
||||
* @param string $modulename
|
||||
* @param \core_analytics\course $course
|
||||
* @return array
|
||||
*/
|
||||
private function instantiate_indicator($modulename, \core_analytics\course $course) {
|
||||
|
||||
$classname = '\\' . $modulename . '\analytics\indicator\cognitive_depth';
|
||||
$indicator = new $classname();
|
||||
$class = new ReflectionClass($indicator);
|
||||
|
||||
$property = $class->getProperty('course');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($indicator, $course);
|
||||
|
||||
$method = new ReflectionMethod($indicator, 'get_activities');
|
||||
$method->setAccessible(true);
|
||||
|
||||
return array($indicator, $method);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -138,6 +138,7 @@ class dataset_manager_testcase extends advanced_testcase {
|
||||
// Training and prediction files are not mixed up.
|
||||
$trainingfile1 = \core_analytics\dataset_manager::merge_datasets(array($file), $fakemodelid,
|
||||
'\core\analytics\time_splitting\quarters', \core_analytics\dataset_manager::LABELLED_FILEAREA, false);
|
||||
$this->waitForSecond();
|
||||
$trainingfile2 = \core_analytics\dataset_manager::merge_datasets(array($file), $fakemodelid,
|
||||
'\core\analytics\time_splitting\quarters', \core_analytics\dataset_manager::LABELLED_FILEAREA, false);
|
||||
|
||||
|
||||
@@ -226,13 +226,17 @@ class analytics_model_testcase extends advanced_testcase {
|
||||
$this->model->mark_as_trained();
|
||||
$this->assertEquals($originaluniqueid, $this->model->get_unique_id());
|
||||
|
||||
$this->model->enable();
|
||||
$this->assertEquals($originaluniqueid, $this->model->get_unique_id());
|
||||
// Wait for the current timestamp to change.
|
||||
$this->waitForSecond();
|
||||
$this->model->enable('\core\analytics\time_splitting\deciles');
|
||||
$this->assertNotEquals($originaluniqueid, $this->model->get_unique_id());
|
||||
$uniqueid = $this->model->get_unique_id();
|
||||
|
||||
// Wait 1 sec so the timestamp changes.
|
||||
sleep(1);
|
||||
// Wait for the current timestamp to change.
|
||||
$this->waitForSecond();
|
||||
$this->model->enable('\core\analytics\time_splitting\quarters');
|
||||
$this->assertNotEquals($originaluniqueid, $this->model->get_unique_id());
|
||||
$this->assertNotEquals($uniqueid, $this->model->get_unique_id());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,5 +48,8 @@ function xmldb_auth_cas_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'auth_cas'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
$plugin->dependencies = array('auth_ldap' => 2017050500);
|
||||
$plugin->dependencies = array('auth_ldap' => 2017110800);
|
||||
|
||||
@@ -45,5 +45,8 @@ function xmldb_auth_db_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ $string['auth_dbname'] = 'Name of the database itself. Leave empty if using an O
|
||||
$string['auth_dbname_key'] = 'DB name';
|
||||
$string['auth_dbpass'] = 'Password matching the above username';
|
||||
$string['auth_dbpass_key'] = 'Password';
|
||||
$string['auth_dbpasstype'] = '<p>Specify the format that the password field is using. MD5 hashing is useful for connecting to other common web applications like PostNuke.</p> <p>Use \'internal\' if you want the external database to manage usernames and email addresses, but Moodle to manage passwords. If you use \'internal\', you <i>must</i> provide a populated email address field in the external database, and you must execute both admin/cron.php and auth/db/cli/sync_users.php regularly. Moodle will send an email to new users with a temporary password.</p>';
|
||||
$string['auth_dbpasstype'] = '<p>Specify the format that the password field is using.</p> <p>Use \'internal\' if you want the external database to manage usernames and email addresses, but Moodle to manage passwords. If you use \'internal\', you <i>must</i> provide a populated email address field in the external database, and you must execute both admin/cron.php and auth/db/cli/sync_users.php regularly. Moodle will send an email to new users with a temporary password.</p>';
|
||||
$string['auth_dbpasstype_key'] = 'Password format';
|
||||
$string['auth_dbreviveduser'] = 'Revived user {$a->name} id {$a->id}';
|
||||
$string['auth_dbrevivedusererror'] = 'Error reviving user {$a}';
|
||||
|
||||
+2
-2
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'auth_db'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -45,5 +45,8 @@ function xmldb_auth_email_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'auth_email'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
+105
-39
@@ -837,23 +837,7 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
/// User Updates - time-consuming (optional)
|
||||
if ($do_updates) {
|
||||
// Narrow down what fields we need to update
|
||||
$all_keys = array_keys(get_object_vars($this->config));
|
||||
$updatekeys = array();
|
||||
foreach ($all_keys as $key) {
|
||||
if (preg_match('/^field_updatelocal_(.+)$/', $key, $match)) {
|
||||
// If we have a field to update it from
|
||||
// and it must be updated 'onlogin' we
|
||||
// update it on cron
|
||||
if (!empty($this->config->{'field_map_'.$match[1]})
|
||||
and $this->config->{$match[0]} === 'onlogin') {
|
||||
array_push($updatekeys, $match[1]); // the actual key name
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->config->suspended_attribute && $this->config->sync_suspended) {
|
||||
$updatekeys[] = 'suspended';
|
||||
}
|
||||
unset($all_keys); unset($key);
|
||||
$updatekeys = $this->get_profile_keys();
|
||||
|
||||
} else {
|
||||
print_string('noupdatestobedone', 'auth_ldap');
|
||||
@@ -928,14 +912,18 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
|
||||
$id = user_create_user($user, false);
|
||||
echo "\t"; print_string('auth_dbinsertuser', 'auth_db', array('name'=>$user->username, 'id'=>$id)); echo "\n";
|
||||
$user = $DB->get_record('user', array('id' => $id));
|
||||
$euser = $DB->get_record('user', array('id' => $id));
|
||||
|
||||
if (!empty($this->config->forcechangepassword)) {
|
||||
set_user_preference('auth_forcepasswordchange', 1, $id);
|
||||
}
|
||||
|
||||
// Save custom profile fields.
|
||||
$updatekeys = $this->get_profile_keys(true);
|
||||
$this->update_user_record($user->username, $updatekeys, false);
|
||||
|
||||
// Add roles if needed.
|
||||
$this->sync_roles($user);
|
||||
$this->sync_roles($euser);
|
||||
|
||||
}
|
||||
$transaction->allow_commit();
|
||||
@@ -967,6 +955,8 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
function update_user_record($username, $updatekeys = false, $triggerevent = false) {
|
||||
global $CFG, $DB;
|
||||
|
||||
require_once($CFG->dirroot.'/user/profile/lib.php');
|
||||
|
||||
// Just in case check text case
|
||||
$username = trim(core_text::strtolower($username));
|
||||
|
||||
@@ -981,6 +971,8 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
// Protect the userid from being overwritten
|
||||
$userid = $user->id;
|
||||
|
||||
$needsupdate = false;
|
||||
|
||||
if ($newinfo = $this->get_userinfo($username)) {
|
||||
$newinfo = truncate_userinfo($newinfo);
|
||||
|
||||
@@ -993,6 +985,9 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
$newuser->id = $userid;
|
||||
// The cast to int is a workaround for MDL-53959.
|
||||
$newuser->suspended = (int)$this->is_user_suspended((object) $newinfo);
|
||||
// Get all custom fields.
|
||||
$profilefields = (array) profile_user_record($user->id, false);
|
||||
$newprofilefields = [];
|
||||
|
||||
foreach ($updatekeys as $key) {
|
||||
if (isset($newinfo[$key])) {
|
||||
@@ -1002,18 +997,50 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
}
|
||||
|
||||
if (!empty($this->config->{'field_updatelocal_' . $key})) {
|
||||
// Only update if it's changed.
|
||||
if ($user->{$key} != $value) {
|
||||
if (preg_match('/^profile_field_(.*)$/', $key, $match)) {
|
||||
// Custom field.
|
||||
$field = $match[1];
|
||||
$currentvalue = isset($profilefields[$field]) ? $profilefields[$field] : null;
|
||||
$newprofilefields[$field] = $value;
|
||||
} else {
|
||||
// Standard field.
|
||||
$currentvalue = isset($user->$key) ? $user->$key : null;
|
||||
$newuser->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Only update if it's changed.
|
||||
if ($currentvalue !== $value) {
|
||||
$needsupdate = true;
|
||||
}
|
||||
}
|
||||
user_update_user($newuser, false, $triggerevent);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
|
||||
if ($needsupdate) {
|
||||
user_update_user($newuser, false, $triggerevent);
|
||||
|
||||
// Now, save the profile fields if the user has any.
|
||||
if ($fields = $DB->get_records('user_info_field')) {
|
||||
foreach ($fields as $field) {
|
||||
if (isset($newprofilefields[$field->shortname])) {
|
||||
$conditions = array('fieldid' => $field->id, 'userid' => $newuser->id);
|
||||
$id = $DB->get_field('user_info_data', 'id', $conditions);
|
||||
$data = $newprofilefields[$field->shortname];
|
||||
if ($id) {
|
||||
$DB->set_field('user_info_data', 'data', $data, array('id' => $id));
|
||||
} else {
|
||||
$record = array('fieldid' => $field->id, 'userid' => $newuser->id, 'data' => $data);
|
||||
$DB->insert_record('user_info_data', $record);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $DB->get_record('user', array('id' => $userid, 'deleted' => 0));
|
||||
}
|
||||
}
|
||||
return $DB->get_record('user', array('id'=>$userid, 'deleted'=>0));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1201,6 +1228,14 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load old custom fields.
|
||||
$olduserprofilefields = (array) profile_user_record($olduser->id, false);
|
||||
|
||||
$fields = array();
|
||||
foreach (profile_get_custom_fields(false) as $field) {
|
||||
$fields[$field->shortname] = $field;
|
||||
}
|
||||
|
||||
$success = true;
|
||||
$user_info_result = ldap_read($ldapconnection, $user_dn, '(objectClass=*)', $search_attribs);
|
||||
if ($user_info_result) {
|
||||
@@ -1219,19 +1254,24 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
$user_entry = $user_entry[0];
|
||||
|
||||
foreach ($attrmap as $key => $ldapkeys) {
|
||||
$profilefield = '';
|
||||
// Only process if the moodle field ($key) has changed and we
|
||||
// are set to update LDAP with it
|
||||
$customprofilefield = 'profile_field_' . $key;
|
||||
if (isset($olduser->$key) and isset($newuser->$key)
|
||||
and ($olduser->$key !== $newuser->$key)) {
|
||||
$profilefield = $key;
|
||||
} else if (isset($olduser->$customprofilefield) && isset($newuser->$customprofilefield)
|
||||
&& $olduser->$customprofilefield !== $newuser->$customprofilefield) {
|
||||
$profilefield = $customprofilefield;
|
||||
if (preg_match('/^profile_field_(.*)$/', $key, $match)) {
|
||||
// Custom field.
|
||||
$fieldname = $match[1];
|
||||
if (isset($fields[$fieldname])) {
|
||||
$class = 'profile_field_' . $fields[$fieldname]->datatype;
|
||||
$formfield = new $class($fields[$fieldname]->id, $olduser->id);
|
||||
$oldvalue = isset($olduserprofilefields[$fieldname]) ? $olduserprofilefields[$fieldname] : null;
|
||||
} else {
|
||||
$oldvalue = null;
|
||||
}
|
||||
$newvalue = $formfield->edit_save_data_preprocess($newuser->{$formfield->inputname}, new stdClass);
|
||||
} else {
|
||||
// Standard field.
|
||||
$oldvalue = isset($olduser->$key) ? $olduser->$key : null;
|
||||
$newvalue = isset($newuser->$key) ? $newuser->$key : null;
|
||||
}
|
||||
|
||||
if (!empty($profilefield) && !empty($this->config->{'field_updateremote_' . $key})) {
|
||||
if ($newvalue !== null and $newvalue !== $oldvalue and !empty($this->config->{'field_updateremote_' . $key})) {
|
||||
// For ldap values that could be in more than one
|
||||
// ldap key, we will do our best to match
|
||||
// where they came from
|
||||
@@ -1244,9 +1284,9 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
$ambiguous = false;
|
||||
}
|
||||
|
||||
$nuvalue = core_text::convert($newuser->$profilefield, 'utf-8', $this->config->ldapencoding);
|
||||
$nuvalue = core_text::convert($newvalue, 'utf-8', $this->config->ldapencoding);
|
||||
empty($nuvalue) ? $nuvalue = array() : $nuvalue;
|
||||
$ouvalue = core_text::convert($olduser->$profilefield, 'utf-8', $this->config->ldapencoding);
|
||||
$ouvalue = core_text::convert($oldvalue, 'utf-8', $this->config->ldapencoding);
|
||||
|
||||
foreach ($ldapkeys as $ldapkey) {
|
||||
$ldapkey = $ldapkey;
|
||||
@@ -1684,7 +1724,7 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
$sesskey = sesskey();
|
||||
redirect($CFG->wwwroot.'/auth/ldap/ntlmsso_magic.php?sesskey='.$sesskey);
|
||||
} else if ($this->config->ntlmsso_ie_fastpath == AUTH_NTLM_FASTPATH_YESFORM) {
|
||||
redirect($CFG-wwwroot.'/login/index.php?authldap_skipntlmsso=1');
|
||||
redirect($CFG->wwwroot.'/login/index.php?authldap_skipntlmsso=1');
|
||||
}
|
||||
}
|
||||
redirect($CFG->wwwroot.'/auth/ldap/ntlmsso_attempt.php');
|
||||
@@ -2170,4 +2210,30 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
echo $OUTPUT->notification(get_string('ldapnotconfigured', 'auth_ldap'), \core\output\notification::NOTIFY_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of profile fields.
|
||||
*
|
||||
* @param bool $fetchall Fetch all, not just those for update.
|
||||
* @return array
|
||||
*/
|
||||
protected function get_profile_keys($fetchall = false) {
|
||||
$keys = array_keys(get_object_vars($this->config));
|
||||
$updatekeys = [];
|
||||
foreach ($keys as $key) {
|
||||
if (preg_match('/^field_updatelocal_(.+)$/', $key, $match)) {
|
||||
// If we have a field to update it from and it must be updated 'onlogin' we update it on cron.
|
||||
if (!empty($this->config->{'field_map_'.$match[1]})) {
|
||||
if ($fetchall || $this->config->{$match[0]} === 'onlogin') {
|
||||
array_push($updatekeys, $match[1]); // the actual key name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->config->suspended_attribute && $this->config->sync_suspended) {
|
||||
$updatekeys[] = 'suspended';
|
||||
}
|
||||
|
||||
return $updatekeys;
|
||||
}
|
||||
} // End of the class
|
||||
|
||||
@@ -66,5 +66,8 @@ function xmldb_auth_ldap_upgrade($oldversion) {
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ $string['auth_ldapdescription'] = 'This method provides authentication against a
|
||||
entry in its database. This module can read user attributes from LDAP and prefill
|
||||
wanted fields in Moodle. For following logins only the username and
|
||||
password are checked.';
|
||||
$string['auth_ldap_expiration_desc'] = 'Select No to disable expired password checking or LDAP to read passwordexpiration time directly from LDAP';
|
||||
$string['auth_ldap_expiration_key'] = 'Expiration';
|
||||
$string['auth_ldap_expiration_warning_desc'] = 'Number of days before password expiration warning is issued.';
|
||||
$string['auth_ldap_expiration_warning_key'] = 'Expiration warning';
|
||||
$string['auth_ldap_expireattr_desc'] = 'Optional: Overrides the LDAP attribute that stores password expiration time.';
|
||||
$string['auth_ldap_expireattr_key'] = 'Expiration attribute';
|
||||
$string['auth_ldap_expiration_desc'] = 'Select \'{$a->no}\' to disable expired password checking or \'{$a->ldapserver}\' to read the password expiry time directly from the LDAP server.';
|
||||
$string['auth_ldap_expiration_key'] = 'Expiry';
|
||||
$string['auth_ldap_expiration_warning_desc'] = 'Number of days before password expiry warning is issued.';
|
||||
$string['auth_ldap_expiration_warning_key'] = 'Expiry warning';
|
||||
$string['auth_ldap_expireattr_desc'] = 'Optional: Overrides the LDAP attribute that stores password expiry time.';
|
||||
$string['auth_ldap_expireattr_key'] = 'Expiry attribute';
|
||||
$string['auth_ldapextrafields'] = 'These fields are optional. You can choose to pre-fill some Moodle user fields with information from the <b>LDAP fields</b> that you specify here. <p>If you leave these fields blank, then nothing will be transferred from LDAP and Moodle defaults will be used instead.</p><p>In either case, the user will be able to edit all of these fields after they log in.</p>';
|
||||
$string['auth_ldap_graceattr_desc'] = 'Optional: Overrides gracelogin attribute';
|
||||
$string['auth_ldap_gracelogin_key'] = 'Grace login attribute';
|
||||
@@ -75,7 +75,7 @@ $string['auth_ldap_opt_deref'] = 'Determines how aliases are handled during sear
|
||||
$string['auth_ldap_opt_deref_key'] = 'Dereference aliases';
|
||||
$string['auth_ldap_passtype'] = 'Specify the format of new or changed passwords in LDAP server.';
|
||||
$string['auth_ldap_passtype_key'] = 'Password format';
|
||||
$string['auth_ldap_passwdexpire_settings'] = 'LDAP password expiration settings';
|
||||
$string['auth_ldap_passwdexpire_settings'] = 'LDAP password expiry settings';
|
||||
$string['auth_ldap_preventpassindb'] = 'Select yes to prevent passwords from being stored in Moodle\'s DB.';
|
||||
$string['auth_ldap_preventpassindb_key'] = 'Prevent password caching';
|
||||
$string['auth_ldap_rolecontext'] = '{$a->localname} context';
|
||||
@@ -91,7 +91,7 @@ $string['auth_ldap_suspended_attribute'] = 'Optional: When provided this attribu
|
||||
$string['auth_ldap_suspended_attribute_key'] = 'Suspended attribute';
|
||||
$string['auth_ldap_user_exists'] = 'LDAP username already exists.';
|
||||
$string['auth_ldap_user_settings'] = 'User lookup settings';
|
||||
$string['auth_ldap_user_type'] = 'Select how users are stored in LDAP. This setting also specifies how login expiration, grace logins and user creation will work.';
|
||||
$string['auth_ldap_user_type'] = 'Select how users are stored in LDAP. This setting also specifies how login expiry, grace logins and user creation will work.';
|
||||
$string['auth_ldap_user_type_key'] = 'User type';
|
||||
$string['auth_ldap_usertypeundefined'] = 'config.user_type not defined or function ldap_expirationtime2unix does not support selected type!';
|
||||
$string['auth_ldap_usertypeundefined2'] = 'config.user_type not defined or function ldap_unixi2expirationtime does not support selected type!';
|
||||
@@ -121,7 +121,7 @@ $string['didntgetusersfromldap'] = "Did not get any users from LDAP -- error? --
|
||||
$string['gotcountrecordsfromldap'] = "Got {\$a} records from LDAP\n";
|
||||
$string['ldapnotconfigured'] = 'The LDAP host url is currently not configured';
|
||||
$string['morethanoneuser'] = 'Strange! More than one user record found in ldap. Only using the first one.';
|
||||
$string['needbcmath'] = 'You need the BCMath extension to use grace logins with Active Directory';
|
||||
$string['needbcmath'] = 'You need the BCMath extension to use expired password checking with Active Directory.';
|
||||
$string['needmbstring'] = 'You need the mbstring extension to change passwords in Active Directory';
|
||||
$string['nodnforusername'] = 'Error in user_update_password(). No DN for: {$a->username}';
|
||||
$string['noemail'] = 'Tried to send you an email but failed!';
|
||||
@@ -149,7 +149,7 @@ $string['start_tls_key'] = 'Use TLS';
|
||||
$string['updateremfail'] = 'Error updating LDAP record. Error code: {$a->errno}; Error string: {$a->errstring}<br/>Key ({$a->key}) - old moodle value: \'{$a->ouvalue}\' new value: \'{$a->nuvalue}\'';
|
||||
$string['updateremfailamb'] = 'Failed to update LDAP with ambiguous field {$a->key}; old moodle value: \'{$a->ouvalue}\', new value: \'{$a->nuvalue}\'';
|
||||
$string['updatepasserror'] = 'Error in user_update_password(). Error code: {$a->errno}; Error string: {$a->errstring}';
|
||||
$string['updatepasserrorexpire'] = 'Error in user_update_password() when reading password expiration time. Error code: {$a->errno}; Error string: {$a->errstring}';
|
||||
$string['updatepasserrorexpire'] = 'Error in user_update_password() when reading password expiry time. Error code: {$a->errno}; Error string: {$a->errstring}';
|
||||
$string['updatepasserrorexpiregrace'] = 'Error in user_update_password() when modifying expirationtime and/or gracelogins. Error code: {$a->errno}; Error string: {$a->errstring}';
|
||||
$string['updateusernotfound'] = 'Could not find user while updating externally. Details follow: search base: \'{$a->userdn}\'; search filter: \'(objectClass=*)\'; search attributes: {$a->attribs}';
|
||||
$string['user_activatenotsupportusertype'] = 'auth: ldap user_activate() does not support selected usertype: {$a}';
|
||||
|
||||
+15
-3
@@ -185,12 +185,24 @@ if ($ADMIN->fulltree) {
|
||||
new lang_string('auth_ldap_passwdexpire_settings', 'auth_ldap'), ''));
|
||||
|
||||
// Password Expiration.
|
||||
|
||||
// Create the description lang_string object.
|
||||
$strno = get_string('no');
|
||||
$strldapserver = get_string('pluginname', 'auth_ldap');
|
||||
$langobject = new stdClass();
|
||||
$langobject->no = $strno;
|
||||
$langobject->ldapserver = $strldapserver;
|
||||
$description = new lang_string('auth_ldap_expiration_desc', 'auth_ldap', $langobject);
|
||||
|
||||
// Now create the options.
|
||||
$expiration = array();
|
||||
$expiration['0'] = 'no';
|
||||
$expiration['1'] = 'LDAP';
|
||||
$expiration['0'] = $strno;
|
||||
$expiration['1'] = $strldapserver;
|
||||
|
||||
// Add the setting.
|
||||
$settings->add(new admin_setting_configselect('auth_ldap/expiration',
|
||||
new lang_string('auth_ldap_expiration_key', 'auth_ldap'),
|
||||
new lang_string('auth_ldap_expiration_desc', 'auth_ldap'), 0 , $expiration));
|
||||
$description, 0 , $expiration));
|
||||
|
||||
// Password Expiration warning.
|
||||
$settings->add(new admin_setting_configtext('auth_ldap/expiration_warning',
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017080100; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'auth_ldap'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version (3.1).
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version.
|
||||
$plugin->component = 'auth_lti'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -48,5 +48,8 @@ function xmldb_auth_manual_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'auth_manual'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -47,5 +47,8 @@ function xmldb_auth_mnet_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'auth_mnet'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'auth_nologin'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -45,5 +45,8 @@ function xmldb_auth_none_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2017051500; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017050500; // Requires this Moodle version
|
||||
$plugin->version = 2017111300; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2017110800; // Requires this Moodle version
|
||||
$plugin->component = 'auth_none'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -41,5 +41,8 @@ function xmldb_auth_oauth2_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.3.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.4.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user