Compare commits
272 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 00821c744c | |||
| f420af1016 | |||
| 67150560b2 | |||
| 9fac7a8d59 | |||
| e1ca7e93d9 | |||
| 8bd6cfb4c4 | |||
| a3afe546fd | |||
| db30a623bf | |||
| 3afcb70b3d | |||
| 9ca6f8199e | |||
| 4fec7a276d | |||
| b70a1c71e1 | |||
| 90c450839d | |||
| b7a62b4286 | |||
| 33427c7c5d | |||
| 8fa9d159bc | |||
| f8f154236d | |||
| d54cc8fbd7 | |||
| 7e6fc779c7 | |||
| 3467d87c80 | |||
| 855957180a | |||
| 8862b80c56 | |||
| 8b8142d8d9 | |||
| f0260219fa | |||
| be36ead8b0 | |||
| f270bd8c8e | |||
| 357909b23b | |||
| 2c45443ad7 | |||
| 77d7480096 | |||
| b57b9b41cd | |||
| cfa2b28de6 | |||
| e22723680d | |||
| db2a9784ef | |||
| 06d7da192b | |||
| 586a6da356 | |||
| 2ab950039c | |||
| 3b3c246aaa | |||
| b3b476ce3c | |||
| 682ee99293 | |||
| b8069c3372 | |||
| 992d1b29b4 | |||
| ceab4136aa | |||
| 8241aa75d5 | |||
| f186074a54 | |||
| 8585fe1404 | |||
| d4dff59b82 | |||
| af4b97f57a | |||
| c3341dea30 | |||
| 2b0b250162 | |||
| dd17f6b1bf | |||
| 4e1786f27f | |||
| 247437ce25 | |||
| 8d306e640f | |||
| 17d296f1ea | |||
| c9dfaec749 | |||
| 304aaf2b7b | |||
| 34153bcc77 | |||
| 65ef2f90bf | |||
| b12ab80cf5 | |||
| 9ee975f3a9 | |||
| fb02551622 | |||
| 64db9dc75a | |||
| 9d5931b6e2 | |||
| 0369198637 | |||
| 62b9a44045 | |||
| 1251f26d67 | |||
| 77a6c383bf | |||
| 53e81c00fa | |||
| 9480706466 | |||
| bb48ca47ef | |||
| 93b2fe7d38 | |||
| 6ba4712549 | |||
| b192dc7c64 | |||
| 2d9922f388 | |||
| 639f6143e7 | |||
| 0a27966b67 | |||
| 79b89c2d42 | |||
| 591107c208 | |||
| ccfc9f7bc9 | |||
| 06bf0c89d6 | |||
| c25f0087f7 | |||
| 12830e4214 | |||
| 2e1b2cf30e | |||
| 0bfb0a58a0 | |||
| 50ba1375e8 | |||
| 5f57b10712 | |||
| ec6720a836 | |||
| e00b006d51 | |||
| 7ce3918e83 | |||
| aa1c7e0a64 | |||
| cc87756c10 | |||
| e7a53e9410 | |||
| a050d3f41b | |||
| bc103afb53 | |||
| 50d1003bb7 | |||
| 5c899c722c | |||
| 73ad678e73 | |||
| 22a5445346 | |||
| 3ca8535203 | |||
| 7697ac6538 | |||
| c97eb87506 | |||
| 66b3c79275 | |||
| 773db77081 | |||
| a07acd9464 | |||
| 12b20cbf3b | |||
| fa31950c6a | |||
| 6ef5f4ced0 | |||
| c537ed7fed | |||
| f3b2f604e2 | |||
| f987001a61 | |||
| f1ec340cca | |||
| 6998cbfad4 | |||
| 655f4d4f3f | |||
| d9e22f40b4 | |||
| df8a5aeab5 | |||
| 17cc12c381 | |||
| e76c5c764b | |||
| be45f4c47f | |||
| fa7e218546 | |||
| 5c0a5a531d | |||
| 200ec6b6ac | |||
| 0e7dc879de | |||
| 70fe644191 | |||
| 5178b349e8 | |||
| c8e335fbe3 | |||
| 567e587dbb | |||
| 37348f1c2e | |||
| e2feddadd9 | |||
| 0a62138795 | |||
| c24a16a819 | |||
| 8091ab8078 | |||
| 12b9c6051e | |||
| 92e6eb437c | |||
| 32866a1758 | |||
| 9ce415b207 | |||
| ec69ae5929 | |||
| f5545b5c0e | |||
| 7c22b71916 | |||
| b5414af214 | |||
| 686b5beb23 | |||
| af87a57052 | |||
| dec6e261e2 | |||
| 24058ace40 | |||
| d552427f61 | |||
| 0eeb391472 | |||
| 433556de1f | |||
| b24f13eca2 | |||
| 65a9b26791 | |||
| 2cc04e2b29 | |||
| 6be44e7d06 | |||
| 93b3efa5a7 | |||
| 2908ed5405 | |||
| 966c8a37cb | |||
| c8637d645e | |||
| b427f21cca | |||
| 25a0001b9f | |||
| 843cc0ee8d | |||
| 0172d13163 | |||
| 78bddace2c | |||
| 779c1687a4 | |||
| c99a83bc5c | |||
| 0b523e6031 | |||
| 8cd8daa285 | |||
| 1bd007e815 | |||
| 9c35064345 | |||
| 5945a1a926 | |||
| fac91d11d8 | |||
| 9fcd6522ce | |||
| 85673c859e | |||
| 4dba8e8359 | |||
| f03c875cf3 | |||
| 9fcb5ece12 | |||
| b07833ddf4 | |||
| 333f6cb753 | |||
| 1c594e729b | |||
| d8c8f544b3 | |||
| a284ced9a1 | |||
| cb82824f6a | |||
| 613c37d54b | |||
| 53f9417795 | |||
| 407807df6b | |||
| 7c80e15392 | |||
| e95c0a90ac | |||
| 48905f6b75 | |||
| b5b562b7ee | |||
| 4a82e72b00 | |||
| ef95f5262f | |||
| e2d911c07b | |||
| 71bae0da0f | |||
| e7bfbaf7b2 | |||
| 6882d7399b | |||
| 80bf03d583 | |||
| 1039537d83 | |||
| 0214c50b18 | |||
| e29e8373e6 | |||
| 9e11009eb1 | |||
| a01ca7a600 | |||
| 6a662825f7 | |||
| 03e3219884 | |||
| 681b7f4e78 | |||
| f098f28d01 | |||
| bf17d50cf6 | |||
| 8e0f036b29 | |||
| 51c6924206 | |||
| f589a25459 | |||
| dee389dff6 | |||
| a9b83b3c01 | |||
| 0ab0a293a8 | |||
| b76093e90c | |||
| 8f0d40a39c | |||
| 3a2d8a175e | |||
| ff72ca7340 | |||
| 4e346470a5 | |||
| 13c76cc295 | |||
| 2c4426bb10 | |||
| d3a9e2935d | |||
| 2adc010b85 | |||
| c330c9276c | |||
| e9b443b3a1 | |||
| 7bb692666b | |||
| 5e924f295a | |||
| 739cbcf7e9 | |||
| 22df02089a | |||
| be2afb52c1 | |||
| 09520f8e0d | |||
| d661fbfbc1 | |||
| e29069d45b | |||
| f86b5e3545 | |||
| a2dcfd5bf6 | |||
| dd74c34e36 | |||
| 5f3b5fdadf | |||
| 029f061e60 | |||
| 14ea8ed50a | |||
| 28b14d17c2 | |||
| ce69ce2db5 | |||
| 7ca7076c1b | |||
| 4c1fbc320f | |||
| 7b5a1a1967 | |||
| 2a5d1ba26e | |||
| 6e4c5bf0a2 | |||
| e6ebfa4baa | |||
| 5a29867e2d | |||
| bbb83614d2 | |||
| 0ab938d309 | |||
| 6882790684 | |||
| e78929087e | |||
| 10a0ea20ac | |||
| d0b4b6fa2f | |||
| a5dcaee31c | |||
| 05ef5c3c48 | |||
| e803a24401 | |||
| ebe19aa434 | |||
| 4b0988f014 | |||
| 56ec88ca1c | |||
| 849c7704f7 | |||
| 898dd7bf5b | |||
| f5e374c278 | |||
| 4423581f8d | |||
| d0295d8ff2 | |||
| 4aa83d92bf | |||
| 72ad8e6919 | |||
| f6b7ed422a | |||
| 65d419b204 | |||
| 3885c566aa | |||
| ab542b6e98 | |||
| 62530e097b | |||
| 937c7eeef1 | |||
| 7e47aca045 | |||
| c611f94e04 | |||
| ef6f42a825 | |||
| 9597baa6e8 | |||
| 04073c7e31 |
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Template configuraton file for github actions CI/CD.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com}
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
// This cannot be used out from a github actions workflow, so just exit.
|
||||
getenv('GITHUB_WORKFLOW') || die; // phpcs:ignore moodle.Files.MoodleInternal.MoodleInternalGlobalState
|
||||
|
||||
unset($CFG);
|
||||
global $CFG;
|
||||
$CFG = new stdClass();
|
||||
|
||||
$CFG->dbtype = getenv('dbtype');
|
||||
$CFG->dblibrary = 'native';
|
||||
$CFG->dbhost = '127.0.0.1';
|
||||
$CFG->dbname = 'test';
|
||||
$CFG->dbuser = 'test';
|
||||
$CFG->dbpass = 'test';
|
||||
$CFG->prefix = 'm_';
|
||||
$CFG->dboptions = ['dbcollation' => 'utf8mb4_bin'];
|
||||
|
||||
$host = 'localhost';
|
||||
$CFG->wwwroot = "http://{$host}";
|
||||
$CFG->dataroot = realpath(dirname(__DIR__)) . '/moodledata';
|
||||
$CFG->admin = 'admin';
|
||||
$CFG->directorypermissions = 0777;
|
||||
|
||||
// Debug options - possible to be controlled by flag in future.
|
||||
$CFG->debug = (E_ALL | E_STRICT); // DEBUG_DEVELOPER.
|
||||
$CFG->debugdisplay = 1;
|
||||
$CFG->debugstringids = 1; // Add strings=1 to url to get string ids.
|
||||
$CFG->perfdebug = 15;
|
||||
$CFG->debugpageinfo = 1;
|
||||
$CFG->allowthemechangeonurl = 1;
|
||||
$CFG->passwordpolicy = 0;
|
||||
$CFG->cronclionly = 0;
|
||||
$CFG->pathtophp = getenv('pathtophp');
|
||||
|
||||
$CFG->phpunit_dataroot = realpath(dirname(__DIR__)) . '/phpunitdata';
|
||||
$CFG->phpunit_prefix = 't_';
|
||||
|
||||
define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://localhost:8080');
|
||||
define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://localhost:8080');
|
||||
|
||||
define('TEST_SESSION_REDIS_HOST', 'localhost');
|
||||
define('TEST_CACHESTORE_REDIS_TESTSERVERS', 'localhost');
|
||||
|
||||
// TODO: add others (solr, mongodb, memcached, ldap...).
|
||||
|
||||
// Too much for now: define('PHPUNIT_LONGTEST', true); // Only leaves a few tests out and they are run later by CI.
|
||||
|
||||
require_once(__DIR__ . '/lib/setup.php');
|
||||
@@ -0,0 +1,103 @@
|
||||
name: Core
|
||||
|
||||
on: [push]
|
||||
|
||||
env:
|
||||
php: 7.4
|
||||
|
||||
jobs:
|
||||
Grunt:
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
steps:
|
||||
- name: Checking out code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Configuring node & npm
|
||||
shell: bash -l {0}
|
||||
run: nvm install
|
||||
|
||||
- name: Installing node stuff
|
||||
run: npm install
|
||||
|
||||
- name: Running grunt
|
||||
run: npx grunt
|
||||
|
||||
- name: Looking for uncommitted changes
|
||||
# Add all files to the git index and then run diff --cached to see all changes.
|
||||
# This ensures that we get the status of all files, including new files.
|
||||
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
|
||||
run: |
|
||||
git add .
|
||||
git reset -- npm-shrinkwrap.json
|
||||
git diff --cached --exit-code
|
||||
|
||||
PHPUnit:
|
||||
runs-on: ${{ matrix.os }}
|
||||
services:
|
||||
exttests:
|
||||
image: moodlehq/moodle-exttests
|
||||
ports:
|
||||
- 8080:80
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
php: 7.2
|
||||
db: mysqli
|
||||
- os: ubuntu-18.04
|
||||
php: 7.4
|
||||
db: pgsql
|
||||
|
||||
steps:
|
||||
- name: Setting up DB mysql
|
||||
if: ${{ matrix.db == 'mysqli' }}
|
||||
uses: johanmeiring/mysql-action@tmpfs-patch
|
||||
with:
|
||||
collation server: utf8mb4_bin
|
||||
mysql version: 5.7
|
||||
mysql database: test
|
||||
mysql user: test
|
||||
mysql password: test
|
||||
use tmpfs: true
|
||||
|
||||
- name: Setting up DB pgsql
|
||||
if: ${{ matrix.db == 'pgsql' }}
|
||||
uses: m4nu56/postgresql-action@v1
|
||||
with:
|
||||
postgresql version: 9.6
|
||||
postgresql db: test
|
||||
postgresql user: test
|
||||
postgresql password: test
|
||||
|
||||
- name: Configuring git vars
|
||||
uses: rlespinasse/github-slug-action@v3.x
|
||||
|
||||
- name: Setting up PHP ${{ matrix.php }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
coverage: none
|
||||
|
||||
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setting up PHPUnit
|
||||
env:
|
||||
dbtype: ${{ matrix.db }}
|
||||
run: |
|
||||
echo "pathtophp=$(which php)" >> $GITHUB_ENV # Inject installed pathtophp to env. The template config needs it.
|
||||
cp .github/workflows/config-template.php config.php
|
||||
mkdir ../moodledata
|
||||
sudo locale-gen en_AU.UTF-8
|
||||
php admin/tool/phpunit/cli/init.php --no-composer-self-update
|
||||
|
||||
- name: Running PHPUnit tests
|
||||
env:
|
||||
dbtype: ${{ matrix.db }}
|
||||
run: vendor/bin/phpunit -v
|
||||
+29
-71
@@ -16,31 +16,9 @@ services:
|
||||
- mysql
|
||||
- docker
|
||||
|
||||
php:
|
||||
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
|
||||
- 7.4
|
||||
- 7.2
|
||||
|
||||
addons:
|
||||
postgresql: "9.6"
|
||||
|
||||
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.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.
|
||||
|
||||
# Run CI Tests without running PHPUnit.
|
||||
- DB=none TASK=CITEST
|
||||
|
||||
# Run unit tests on Postgres
|
||||
- DB=pgsql TASK=PHPUNIT
|
||||
|
||||
# Perform an upgrade test too.
|
||||
- DB=pgsql TASK=UPGRADE
|
||||
|
||||
jobs:
|
||||
# Enable fast finish.
|
||||
# This will fail the build if a single job fails (except those in allow_failures).
|
||||
@@ -48,12 +26,35 @@ jobs:
|
||||
fast_finish: true
|
||||
|
||||
include:
|
||||
# Run mysql only on highest - it's just too slow
|
||||
- php: 7.4
|
||||
# First all the lowest php ones (7.2)
|
||||
- php: 7.2
|
||||
env: DB=none TASK=CITEST
|
||||
- php: 7.2
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present
|
||||
php: 7.2
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
|
||||
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
|
||||
php: 7.2
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
|
||||
# Then, conditionally, all the highest php ones (7.4)
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 7.4
|
||||
env: DB=none TASK=CITEST
|
||||
- if: env(MOODLE_PHP) = "all"
|
||||
php: 7.4
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
|
||||
|
||||
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present)
|
||||
php: 7.4
|
||||
env: DB=pgsql TASK=PHPUNIT
|
||||
|
||||
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
|
||||
php: 7.4
|
||||
env: DB=mysqli TASK=PHPUNIT
|
||||
# Run grunt/npm install on highest version too ('node' is an alias for the latest node.js version.)
|
||||
- php: 7.4
|
||||
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@@ -113,7 +114,7 @@ install:
|
||||
before_script:
|
||||
- phpenv config-rm xdebug.ini
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' -o "$TASK" = 'UPGRADE' ];
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
then
|
||||
# Copy generic configuration in place.
|
||||
cp config-dist.php config.php ;
|
||||
@@ -224,32 +225,6 @@ before_script:
|
||||
export phpcmd=`which php`;
|
||||
fi
|
||||
|
||||
########################################################################
|
||||
# Upgrade test
|
||||
########################################################################
|
||||
- >
|
||||
if [ "$TASK" = 'UPGRADE' ];
|
||||
then
|
||||
# We need the official upstream.
|
||||
git remote add upstream https://github.com/moodle/moodle.git;
|
||||
|
||||
# Checkout 30 STABLE branch (the first version compatible with PHP 7.x)
|
||||
git fetch upstream MOODLE_30_STABLE;
|
||||
git checkout MOODLE_30_STABLE;
|
||||
|
||||
# Perform the upgrade
|
||||
php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
|
||||
|
||||
# Return to the previous commit
|
||||
git checkout -;
|
||||
|
||||
# Perform the upgrade
|
||||
php admin/cli/upgrade.php --non-interactive --allow-unstable ;
|
||||
|
||||
# The local_ci repository can be used to check upgrade savepoints.
|
||||
git clone https://github.com/moodlehq/moodle-local_ci.git local/ci ;
|
||||
fi
|
||||
|
||||
script:
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
@@ -275,23 +250,6 @@ script:
|
||||
git diff --cached --exit-code ;
|
||||
fi
|
||||
|
||||
########################################################################
|
||||
# Upgrade test
|
||||
########################################################################
|
||||
- >
|
||||
if [ "$TASK" = 'UPGRADE' ];
|
||||
then
|
||||
cp local/ci/check_upgrade_savepoints/check_upgrade_savepoints.php ./check_upgrade_savepoints.php
|
||||
result=`php check_upgrade_savepoints.php`;
|
||||
# Check if there are problems
|
||||
count=`echo "$result" | grep -P "ERROR|WARN" | wc -l` ;
|
||||
if (($count > 0));
|
||||
then
|
||||
echo "$result"
|
||||
exit 1 ;
|
||||
fi
|
||||
fi
|
||||
|
||||
after_script:
|
||||
- >
|
||||
if [ "$TASK" = 'PHPUNIT' ];
|
||||
|
||||
@@ -3344,4 +3344,186 @@
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
<MOODLE version="3.11" requires="3.6">
|
||||
<UNICODE level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="unicoderequired" />
|
||||
</FEEDBACK>
|
||||
</UNICODE>
|
||||
<DATABASE level="required">
|
||||
<VENDOR name="mariadb" version="10.2.29" />
|
||||
<VENDOR name="mysql" version="5.7" />
|
||||
<VENDOR name="postgres" version="9.6" />
|
||||
<VENDOR name="mssql" version="14.0" />
|
||||
<VENDOR name="oracle" version="11.2" />
|
||||
</DATABASE>
|
||||
<PHP version="7.3.0" level="required">
|
||||
</PHP>
|
||||
<PCREUNICODE level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="pcreunicodewarning" />
|
||||
</FEEDBACK>
|
||||
</PCREUNICODE>
|
||||
<PHP_EXTENSIONS>
|
||||
<PHP_EXTENSION name="iconv" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="iconvrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="mbstring" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="mbstringrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="curl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="curlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="openssl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="opensslrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="tokenizer" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="tokenizerrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlrpc" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="xmlrpcrecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="soap" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="soaprecommended" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="ctype" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ctyperequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zip" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="ziprequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="zlib" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="gd" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="gdrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="simplexml" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="simplexmlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="spl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="splrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="pcre" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="dom" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xml" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="xmlreader" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="intl" level="required">
|
||||
<FEEDBACK>
|
||||
<ON_ERROR message="intlrequired" />
|
||||
</FEEDBACK>
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="json" level="required">
|
||||
</PHP_EXTENSION>
|
||||
<PHP_EXTENSION name="hash" level="required"/>
|
||||
<PHP_EXTENSION name="fileinfo" level="required"/>
|
||||
<PHP_EXTENSION name="sodium" level="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_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
|
||||
<FEEDBACK>
|
||||
<ON_CHECK message="sixtyfourbitswarning" />
|
||||
</FEEDBACK>
|
||||
</CUSTOM_CHECK>
|
||||
</CUSTOM_CHECKS>
|
||||
</MOODLE>
|
||||
</COMPATIBILITY_MATRIX>
|
||||
|
||||
@@ -32,6 +32,7 @@ $result = optional_param('result', null, PARAM_INT);
|
||||
|
||||
$pageurl = new \moodle_url('/admin/tasklogs.php');
|
||||
$pageurl->param('filter', $filter);
|
||||
$pageurl->param('result', $result);
|
||||
|
||||
$PAGE->set_url($pageurl);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
@@ -6,14 +6,18 @@ Feature: Edit capabilities
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
| username | firstname | lastname |
|
||||
| teacher1 | Teacher | 1 |
|
||||
| tutor | Teaching | Assistant |
|
||||
| student | Student | One |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
| fullname | shortname |
|
||||
| Course 1 | C1 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| tutor | C1 | teacher |
|
||||
| student | C1 | student |
|
||||
|
||||
Scenario: Default system capabilities modification
|
||||
Given I log in as "admin"
|
||||
@@ -60,3 +64,25 @@ Feature: Edit capabilities
|
||||
Then "mod/forum:deleteanypost" capability has "Prohibit" permission
|
||||
And "mod/forum:editanypost" capability has "Prevent" permission
|
||||
And "mod/forum:addquestion" capability has "Allow" permission
|
||||
|
||||
@javascript
|
||||
Scenario: Edit permissions escapes role names correctly
|
||||
When I am on the "C1" "Course" page logged in as "admin"
|
||||
And I navigate to "Edit settings" in current page administration
|
||||
And I set the following fields to these values:
|
||||
| Your word for 'Teacher' | Teacher >= editing |
|
||||
| Your word for 'Non-editing teacher' | Teacher < "editing" |
|
||||
| Your word for 'Student' | Studier & 'learner' |
|
||||
And I press "Save and display"
|
||||
And I navigate to course participants
|
||||
Then I should see "Teacher >= editing (Teacher)" in the "Teacher 1" "table_row"
|
||||
And I should see "Teacher < \"editing\" (Non-editing teacher)" in the "Teaching Assistant" "table_row"
|
||||
And I should see "Studier & 'learner' (Student)" in the "Student One" "table_row"
|
||||
And I navigate to "Users > Permissions" in current page administration
|
||||
And I should see "Teacher >= editing" in the "mod/forum:replypost" "table_row"
|
||||
And I should see "Teacher < \"editing\"" in the "mod/forum:replypost" "table_row"
|
||||
And I should see "Studier & 'learner'" in the "mod/forum:replypost" "table_row"
|
||||
And I follow "Prohibit"
|
||||
And "Teacher >= editing" "button" in the "Prohibit role" "dialogue" should be visible
|
||||
And "Teacher < \"editing\"" "button" in the "Prohibit role" "dialogue" should be visible
|
||||
And "Studier & 'learner'" "button" in the "Prohibit role" "dialogue" should be visible
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
@tool_behat
|
||||
Feature: Verify that the inplace editable field works as expected
|
||||
In order to use behat step definitions
|
||||
As a test write
|
||||
I need to ensure that the inplace editable works in forms
|
||||
|
||||
Background:
|
||||
Given the following "course" exists:
|
||||
| fullname | Course 1 |
|
||||
| shortname | C1 |
|
||||
And the following "activities" exist:
|
||||
| activity | course | name | idnumber |
|
||||
| forum | C1 | My first forum | forum1 |
|
||||
| assign | C1 | My first assignment | assign1 |
|
||||
| quiz | C1 | My first quiz | quiz1 |
|
||||
And I log in as "admin"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
|
||||
@javascript
|
||||
Scenario: Using an inplace editable updates the name of an activity
|
||||
When I set the field "Edit title" in the "My first assignment" "activity" to "Coursework submission"
|
||||
Then I should see "Coursework submission"
|
||||
And I should not see "My first assignment"
|
||||
But I should see "My first forum"
|
||||
And I should see "My first quiz"
|
||||
And I set the field "Edit title" in the "Coursework submission" "activity" to "My first assignment"
|
||||
And I should not see "Coursework submission"
|
||||
But I should see "My first assignment"
|
||||
And I should see "My first forum"
|
||||
And I should see "My first quiz"
|
||||
@@ -0,0 +1,53 @@
|
||||
@tool_behat
|
||||
Feature: Verify that keyboard steps work as expected
|
||||
In order to use behat step definitions
|
||||
As a test writer
|
||||
I need to verify that the keyboard steps work as expected
|
||||
|
||||
@javascript
|
||||
Scenario: Typing keys into a field causes them to be input
|
||||
Given the following "users" exist:
|
||||
| username | email | firstname | lastname | password |
|
||||
| saffronr | saffron.rutledge@example.com | Saffron | Rutledge | flowerpower |
|
||||
Given I click on "Log in" "link"
|
||||
And I click on "Username" "field"
|
||||
When I type "saffronr"
|
||||
And I press the tab key
|
||||
And I type "flowerpower"
|
||||
And I press enter
|
||||
Then I should see "You are logged in as Saffron Rutledge"
|
||||
|
||||
@javascript
|
||||
Scenario: Using tab changes focus to the next or previous field
|
||||
Given I click on "Log in" "link"
|
||||
And I click on "Username" "field"
|
||||
And the focused element is "Username" "field"
|
||||
When I press the tab key
|
||||
Then the focused element is "Password" "field"
|
||||
|
||||
And I press the shift tab key
|
||||
And the focused element is "Username" "field"
|
||||
|
||||
# TODO: Uncomment the following when MDL-66979 is integrated.
|
||||
# @javascript
|
||||
# Scenario: Using the arrow keys allows me to navigate through menus
|
||||
# Given the following "users" exist:
|
||||
# | username | email | firstname | lastname |
|
||||
# | saffronr | saffron.rutledge@example.com | Saffron | Rutledge |
|
||||
# And I log in as "saffronr"
|
||||
# And I click on "Saffron Rutledge" "link" in the ".usermenu" "css_element"
|
||||
# When I press the up key
|
||||
# Then the focused element is "Log out" "link"
|
||||
|
||||
@javascript
|
||||
Scenario: The escape key can be used to close a dialogue
|
||||
Given the following "course" exists:
|
||||
| fullname | C1|
|
||||
| shortname | C1 |
|
||||
And I log in as "admin"
|
||||
And I am on "C1" course homepage
|
||||
And I navigate to course participants
|
||||
And I press "Enrol users"
|
||||
And "Enrol users" "dialogue" should be visible
|
||||
When I press the escape key
|
||||
Then "Enrol users" "dialogue" should not be visible
|
||||
@@ -44,5 +44,8 @@ function xmldb_tool_cohortroles_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -44,5 +44,8 @@ function xmldb_tool_customlang_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -356,5 +356,8 @@ function xmldb_tool_dataprivacy_upgrade($oldversion) {
|
||||
upgrade_plugin_savepoint(true, 2020061501, 'tool', 'dataprivacy');
|
||||
}
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ Feature: Manage data requests
|
||||
And I open the action menu in "John Doe" "table_row"
|
||||
And I should see "View the request"
|
||||
But I should not see "Mark as complete"
|
||||
And I press key "27" in ".moodle-actionmenu" "css_element"
|
||||
And I press the escape key
|
||||
And I open the action menu in "Jane Doe" "table_row"
|
||||
And I choose "Mark as complete" in the open action menu
|
||||
And I should see "Do you really want to mark this user enquiry as complete?"
|
||||
|
||||
@@ -10,16 +10,12 @@ Feature: Manage data storage purposes
|
||||
And I open the action menu in "region-main" "region"
|
||||
And I choose "Purposes" in the open action menu
|
||||
And I press "Add purpose"
|
||||
And I set the field "Name" to "Purpose 1"
|
||||
And I set the field "Description" to "Purpose 1 description"
|
||||
And I click on ".form-autocomplete-downarrow" "css_element" in the "Lawful bases" "form_row"
|
||||
And I click on "Contract (GDPR Art. 6.1(b))" "list_item"
|
||||
And I click on "Legal obligation (GDPR Art 6.1(c))" "list_item"
|
||||
And I press key "27" in the field "Lawful bases"
|
||||
And I click on ".form-autocomplete-downarrow" "css_element" in the "Sensitive personal data processing reasons" "form_row"
|
||||
And I click on "Explicit consent (GDPR Art. 9.2(a))" "list_item"
|
||||
And I press key "27" in the field "Sensitive personal data processing reasons"
|
||||
And I set the field "retentionperiodnumber" to "2"
|
||||
And I set the following fields to these values:
|
||||
| Name | Purpose 1 |
|
||||
| Description | Purpose 1 description |
|
||||
| Lawful bases | Contract (GDPR Art. 6.1(b)),Legal obligation (GDPR Art 6.1(c)) |
|
||||
| Sensitive personal data processing reasons | Explicit consent (GDPR Art. 9.2(a)) |
|
||||
| retentionperiodnumber | 2 |
|
||||
When I press "Save"
|
||||
Then I should see "Purpose 1" in the "List of data purposes" "table"
|
||||
And I should see "Contract (GDPR Art. 6.1(b))" in the "Purpose 1" "table_row"
|
||||
@@ -31,14 +27,13 @@ Feature: Manage data storage purposes
|
||||
Scenario: Update a data storage purpose
|
||||
Given I open the action menu in "Purpose 1" "table_row"
|
||||
And I choose "Edit" in the open action menu
|
||||
And I set the field "Name" to "Purpose 1 edited"
|
||||
And I set the field "Description" to "Purpose 1 description edited"
|
||||
And I click on "Legal obligation (GDPR Art 6.1(c))" "text" in the ".form-autocomplete-selection" "css_element"
|
||||
And I click on ".form-autocomplete-downarrow" "css_element" in the "Lawful bases" "form_row"
|
||||
And I click on "Vital interests (GDPR Art. 6.1(d))" "list_item"
|
||||
And I press key "27" in the field "Lawful bases"
|
||||
And I set the field "retentionperiodnumber" to "3"
|
||||
And I click on "protected" "checkbox"
|
||||
And I set the following fields to these values:
|
||||
| Name | Purpose 1 edited |
|
||||
| Description | Purpose 1 description edited |
|
||||
| Lawful bases | Contract (GDPR Art. 6.1(b)), Vital interests (GDPR Art. 6.1(d)) |
|
||||
| Sensitive personal data processing reasons | Explicit consent (GDPR Art. 9.2(a)) |
|
||||
| retentionperiodnumber | 3 |
|
||||
| protected | 1 |
|
||||
When I press "Save changes"
|
||||
Then I should see "Purpose 1 edited" in the "List of data purposes" "table"
|
||||
And I should see "Purpose 1 description edited" in the "Purpose 1 edited" "table_row"
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_langimport\output;
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_collator;
|
||||
use moodle_url;
|
||||
use renderable;
|
||||
use renderer_base;
|
||||
@@ -95,6 +95,8 @@ class langimport_page implements renderable, templatable {
|
||||
|
||||
if (!empty($this->availablelanguages)) {
|
||||
$data->toinstalloptions = [];
|
||||
|
||||
core_collator::asort($this->availablelanguages);
|
||||
foreach ($this->availablelanguages as $code => $language) {
|
||||
$option = new stdClass();
|
||||
$option->value = $code;
|
||||
|
||||
@@ -48,5 +48,8 @@ function xmldb_tool_log_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -49,5 +49,8 @@ function xmldb_logstore_database_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -49,5 +49,8 @@ function xmldb_logstore_standard_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -53,11 +53,11 @@ Feature: See the competencies for an activity on the course competencies page.
|
||||
Then I should see "Test-Comp1"
|
||||
And I should see "Test-Comp2"
|
||||
And I set the field "Filter competencies by resource or activity" to "PageName1"
|
||||
And I press key "13" in the field "Filter competencies by resource or activity"
|
||||
And I press the enter key
|
||||
And I should see "Test-Comp1"
|
||||
And I should not see "Test-Comp2"
|
||||
And I set the field "Filter competencies by resource or activity" to "PageName2"
|
||||
And I press key "13" in the field "Filter competencies by resource or activity"
|
||||
And I press the enter key
|
||||
And I should not see "Test-Comp1"
|
||||
And I should not see "Test-Comp2"
|
||||
And I should see "No competencies have been linked to this activity or resource."
|
||||
|
||||
@@ -30,7 +30,7 @@ Feature: Manage plearning plan
|
||||
And I click on ".template-userplans" "css_element" in the "Science template" "table_row"
|
||||
And I open the autocomplete suggestions list
|
||||
And I click on "Admin User" item in the autocomplete list
|
||||
And I press key "27" in the field "Select users to create learning plans for"
|
||||
And I press the escape key
|
||||
When I click on "Create learning plans" "button"
|
||||
Then I should see "A learning plan was created"
|
||||
And I should see "Admin User" in the "Science template" "table_row"
|
||||
@@ -53,9 +53,7 @@ Feature: Manage plearning plan
|
||||
And I follow "Home"
|
||||
And I navigate to "Competencies > Learning plan templates" in site administration
|
||||
And I click on ".template-cohorts" "css_element" in the "Science template cohort" "table_row"
|
||||
And I click on ".form-autocomplete-downarrow" "css_element"
|
||||
And I click on "cohort plan" item in the autocomplete list
|
||||
And I press key "27" in the field "Select cohorts to sync"
|
||||
And I set the field "Select cohorts to sync" to "cohort plan"
|
||||
When I click on "Add cohorts" "button"
|
||||
Then I should see "2 learning plans were created."
|
||||
And I follow "Learning plan templates"
|
||||
|
||||
@@ -51,5 +51,8 @@ function xmldb_tool_mobile_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,5 +48,8 @@ function xmldb_tool_monitor_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -123,5 +123,8 @@ function xmldb_tool_moodlenet_upgrade(int $oldversion) {
|
||||
upgrade_plugin_savepoint(true, 2020090700, 'tool', 'moodlenet');
|
||||
}
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -72,5 +72,8 @@ function xmldb_tool_policy_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
define ("tool_templatelibrary/search",["jquery","core/ajax","core/log","core/notification","core/templates","core/config"],function(a,b,c,d,e,f){var g=function(b){e.render("tool_templatelibrary/search_results",{templates:b}).done(function(b,c){e.replaceNode(a("[data-region=\"searchresults\"]"),b,c)}).fail(d.exception)},h=function(c){var e=a("[data-field=\"component\"]").val(),f=a("[data-region=\"list-templates\"] [data-region=\"input\"]").val();if(""!==f){a("[data-region=\"list-templates\"] [data-action=\"clearsearch\"]").removeClass("d-none")}else{a("[data-region=\"list-templates\"] [data-action=\"clearsearch\"]").addClass("d-none")}document.location.hash=f;b.call([{methodname:"tool_templatelibrary_list_templates",args:{component:e,search:f,themename:c},done:g,fail:d.exception}],!0,!1)},i=null,j=function(a,b){if(null!==i){window.clearTimeout(i)}i=window.setTimeout(function(){a();i=null},b)},k=function(){j(h.bind(this,f.theme),400)};a("[data-region=\"list-templates\"]").on("change","[data-field=\"component\"]",k);a("[data-region=\"list-templates\"]").on("input","[data-region=\"input\"]",k);a("[data-action=\"clearsearch\"]").on("click",function(){a("[data-region=\"input\"]").val("");h(f.theme);a(this).addClass("d-none")});a("[data-region=\"input\"]").val(document.location.hash.replace("#",""));h(f.theme);return{}});
|
||||
define ("tool_templatelibrary/search",["jquery","core/ajax","core/log","core/notification","core/templates","core/config"],function(a,b,c,d,e,f){var g=function(b){e.render("tool_templatelibrary/search_results",{templates:b}).done(function(b,c){e.replaceNode(a("[data-region=\"searchresults\"]"),b,c)}).fail(d.exception)},h=function(c){var e=a("[data-field=\"component\"]").val(),f=a("[data-region=\"list-templates\"] [data-region=\"input\"]").val();if(""!==f){a("[data-region=\"list-templates\"] [data-action=\"clearsearch\"]").removeClass("d-none")}else{a("[data-region=\"list-templates\"] [data-action=\"clearsearch\"]").addClass("d-none")}b.call([{methodname:"tool_templatelibrary_list_templates",args:{component:e,search:f,themename:c},done:g,fail:d.exception}],!0,!1)},i=null,j=function(a,b){if(null!==i){window.clearTimeout(i)}i=window.setTimeout(function(){a();i=null},b)},k=function(){j(h.bind(this,f.theme),400)};a("[data-region=\"list-templates\"]").on("change","[data-field=\"component\"]",k);a("[data-region=\"list-templates\"]").on("input","[data-region=\"input\"]",k);a("[data-action=\"clearsearch\"]").on("click",function(){a("[data-region=\"input\"]").val("");h(f.theme);a(this).addClass("d-none")});h(f.theme);return{}});
|
||||
//# sourceMappingURL=search.min.js.map
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -52,9 +52,8 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
|
||||
} else {
|
||||
$('[data-region="list-templates"] [data-action="clearsearch"]').addClass('d-none');
|
||||
}
|
||||
// Trigger the search.
|
||||
document.location.hash = searchStr;
|
||||
|
||||
// Trigger the search.
|
||||
ajax.call([
|
||||
{methodname: 'tool_templatelibrary_list_templates',
|
||||
args: {component: componentStr, search: searchStr, themename: themename},
|
||||
@@ -96,7 +95,6 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
|
||||
$(this).addClass('d-none');
|
||||
});
|
||||
|
||||
$('[data-region="input"]').val(document.location.hash.replace('#', ''));
|
||||
refreshSearch(config.theme);
|
||||
return {};
|
||||
});
|
||||
|
||||
@@ -38,6 +38,22 @@ use tool_templatelibrary\api;
|
||||
*/
|
||||
class list_templates_page implements renderable, templatable {
|
||||
|
||||
/** @var string $component The currently selected component */
|
||||
protected $component;
|
||||
/** @var string $search The current search */
|
||||
protected $search;
|
||||
|
||||
/**
|
||||
* Template page constructor
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $search
|
||||
*/
|
||||
public function __construct(string $component = '', string $search = '') {
|
||||
$this->component = $component;
|
||||
$this->search = $search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export this data so it can be used as the context for a mustache template.
|
||||
*
|
||||
@@ -46,6 +62,7 @@ class list_templates_page implements renderable, templatable {
|
||||
public function export_for_template(renderer_base $output) {
|
||||
$data = new stdClass();
|
||||
$data->allcomponents = array();
|
||||
$data->search = $this->search;
|
||||
$fulltemplatenames = api::list_templates();
|
||||
$pluginmanager = core_plugin_manager::instance();
|
||||
$components = array();
|
||||
@@ -59,6 +76,7 @@ class list_templates_page implements renderable, templatable {
|
||||
foreach ($components as $component) {
|
||||
$info = new stdClass();
|
||||
$info->component = $component;
|
||||
$info->selected = ($component === $this->component);
|
||||
if (strpos($component, 'core') === 0) {
|
||||
$info->name = get_string('coresubsystem', 'tool_templatelibrary', $component);
|
||||
} else {
|
||||
|
||||
@@ -72,10 +72,10 @@
|
||||
{{/label}}
|
||||
|
||||
{{$element}}
|
||||
<select id="selectcomponent" class="form-control" data-field="component">
|
||||
<select id="selectcomponent" name="component" class="form-control" data-field="component">
|
||||
<option value="">{{#str}}all, tool_templatelibrary{{/str}}</option>
|
||||
{{#allcomponents}}
|
||||
<option value="{{component}}">{{name}}</option>
|
||||
<option value="{{component}}" {{#selected}}selected{{/selected}}>{{name}}</option>
|
||||
{{/allcomponents}}
|
||||
</select>
|
||||
{{/element}}
|
||||
@@ -84,10 +84,10 @@
|
||||
{{< core_form/element-template }}
|
||||
{{$element}}
|
||||
{{< core/search_input_auto }}
|
||||
{{$label}}{{{ searchstring }}}{{/label}}
|
||||
{{$placeholder}}{{#str}}
|
||||
search, core
|
||||
{{/str}}{{/placeholder}}
|
||||
{{$label}}
|
||||
{{#str}} search, tool_templatelibrary {{/str}}
|
||||
{{/label}}
|
||||
{{$value}}{{ search }}{{/value}}
|
||||
{{/ core/search_input_auto }}
|
||||
{{/element}}
|
||||
{{/ core_form/element-template }}
|
||||
|
||||
@@ -79,5 +79,8 @@ function xmldb_tool_usertours_upgrade($oldversion) {
|
||||
upgrade_plugin_savepoint(true, 2020082700, 'tool', 'usertours');
|
||||
}
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -55,10 +55,7 @@ Feature: Manage analytics models
|
||||
And I choose "Create model" in the open action menu
|
||||
And I set the field "Enabled" to "Enable"
|
||||
And I select "__core_course__analytics__target__course_completion" from the "target" singleselect
|
||||
And I open the autocomplete suggestions list
|
||||
And I click on "Read actions amount" item in the autocomplete list
|
||||
And I open the autocomplete suggestions list
|
||||
And I click on "Any write action in the course" item in the autocomplete list
|
||||
And I set the field "Indicators" to "Read actions amount, Any write action in the course"
|
||||
And I select "__core__analytics__time_splitting__single_range" from the "timesplitting" singleselect
|
||||
And I press "Save changes"
|
||||
Then I should see "No predictions available yet" in the "Students at risk of not meeting the course completion conditions" "table_row"
|
||||
|
||||
@@ -55,5 +55,8 @@ function xmldb_auth_cas_upgrade($oldversion) {
|
||||
upgrade_plugin_savepoint(true, 2020081700, 'auth', 'cas');
|
||||
}
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+3
-1
@@ -460,7 +460,7 @@ class auth_plugin_db extends auth_plugin_base {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$id = user_create_user($user, false); // It is truly a new user.
|
||||
$id = user_create_user($user, false, false); // It is truly a new user.
|
||||
$trace->output(get_string('auth_dbinsertuser', 'auth_db', array('name'=>$user->username, 'id'=>$id)), 1);
|
||||
} catch (moodle_exception $e) {
|
||||
$trace->output(get_string('auth_dbinsertusererror', 'auth_db', $user->username), 1);
|
||||
@@ -479,6 +479,8 @@ class auth_plugin_db extends auth_plugin_base {
|
||||
|
||||
// Make sure user context is present.
|
||||
context_user::instance($id);
|
||||
|
||||
\core\event\user_created::create_from_userid($id)->trigger();
|
||||
}
|
||||
unset($add_users);
|
||||
}
|
||||
|
||||
@@ -47,5 +47,8 @@ function xmldb_auth_db_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@ class auth_db_testcase extends advanced_testcase {
|
||||
$table->add_field('email', XMLDB_TYPE_CHAR, '255', null, null, null);
|
||||
$table->add_field('firstname', XMLDB_TYPE_CHAR, '255', null, null, null);
|
||||
$table->add_field('lastname', XMLDB_TYPE_CHAR, '255', null, null, null);
|
||||
$table->add_field('animal', XMLDB_TYPE_CHAR, '255', null, null, null);
|
||||
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
|
||||
if ($dbman->table_exists($table)) {
|
||||
$dbman->drop_table($table);
|
||||
@@ -137,6 +138,15 @@ class auth_db_testcase extends advanced_testcase {
|
||||
set_config('field_updateremote_email', '0', 'auth_db');
|
||||
set_config('field_lock_email', 'unlocked', 'auth_db');
|
||||
|
||||
// Create a user profile field and add mapping to it.
|
||||
$DB->insert_record('user_info_field', ['shortname' => 'pet', 'name' => 'Pet', 'required' => 0,
|
||||
'visible' => 1, 'locked' => 0, 'categoryid' => 1, 'datatype' => 'text']);
|
||||
|
||||
set_config('field_map_profile_field_pet', 'animal', 'auth_db');
|
||||
set_config('field_updatelocal_profile_field_pet', 'oncreate', 'auth_db');
|
||||
set_config('field_updateremote_profile_field_pet', '0', 'auth_db');
|
||||
set_config('field_lock_profile_field_pet', 'unlocked', 'auth_db');
|
||||
|
||||
// Init the rest of settings.
|
||||
set_config('passtype', 'plaintext', 'auth_db');
|
||||
set_config('changepasswordurl', '', 'auth_db');
|
||||
@@ -156,6 +166,7 @@ class auth_db_testcase extends advanced_testcase {
|
||||
|
||||
public function test_plugin() {
|
||||
global $DB, $CFG;
|
||||
require_once($CFG->dirroot . '/user/profile/lib.php');
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
@@ -193,7 +204,7 @@ class auth_db_testcase extends advanced_testcase {
|
||||
|
||||
// Test bulk user account creation.
|
||||
|
||||
$user2 = (object)array('name'=>'u2', 'pass'=>'heslo', 'email'=>'u2@example.com');
|
||||
$user2 = (object)['name' => 'u2', 'pass' => 'heslo', 'email' => 'u2@example.com', 'animal' => 'cat'];
|
||||
$user2->id = $DB->insert_record('auth_db_users', $user2);
|
||||
|
||||
$user3 = (object)array('name'=>'admin', 'pass'=>'heslo', 'email'=>'admin@example.com'); // Should be skipped.
|
||||
@@ -202,13 +213,24 @@ class auth_db_testcase extends advanced_testcase {
|
||||
$this->assertCount(2, $DB->get_records('user'));
|
||||
|
||||
$trace = new null_progress_trace();
|
||||
$auth->sync_users($trace, false);
|
||||
|
||||
// Sync users and make sure that two events user_created werer triggered.
|
||||
$sink = $this->redirectEvents();
|
||||
$auth->sync_users($trace, false);
|
||||
$events = $sink->get_events();
|
||||
$sink->close();
|
||||
$this->assertCount(2, $events);
|
||||
$this->assertTrue($events[0] instanceof \core\event\user_created);
|
||||
$this->assertTrue($events[1] instanceof \core\event\user_created);
|
||||
|
||||
// Assert the two users were created.
|
||||
$this->assertEquals(4, $DB->count_records('user'));
|
||||
$u1 = $DB->get_record('user', array('username'=>$user1->name, 'auth'=>'db'));
|
||||
$this->assertSame($user1->email, $u1->email);
|
||||
$this->assertEmpty(profile_user_record($u1->id)->pet);
|
||||
$u2 = $DB->get_record('user', array('username'=>$user2->name, 'auth'=>'db'));
|
||||
$this->assertSame($user2->email, $u2->email);
|
||||
$this->assertSame($user2->animal, profile_user_record($u2->id)->pet);
|
||||
$admin = $DB->get_record('user', array('username'=>'admin', 'auth'=>'manual'));
|
||||
$this->assertNotEmpty($admin);
|
||||
|
||||
@@ -217,12 +239,14 @@ class auth_db_testcase extends advanced_testcase {
|
||||
|
||||
$user2b = clone($user2);
|
||||
$user2b->email = 'u2b@example.com';
|
||||
$user2b->animal = 'dog';
|
||||
$DB->update_record('auth_db_users', $user2b);
|
||||
|
||||
$auth->sync_users($trace, false);
|
||||
$this->assertEquals(4, $DB->count_records('user'));
|
||||
$u2 = $DB->get_record('user', array('username'=>$user2->name));
|
||||
$this->assertSame($user2->email, $u2->email);
|
||||
$this->assertSame($user2->animal, profile_user_record($u2->id)->pet);
|
||||
|
||||
$auth->sync_users($trace, true);
|
||||
$this->assertEquals(4, $DB->count_records('user'));
|
||||
@@ -231,6 +255,8 @@ class auth_db_testcase extends advanced_testcase {
|
||||
|
||||
set_config('field_updatelocal_email', 'onlogin', 'auth_db');
|
||||
$auth->config->field_updatelocal_email = 'onlogin';
|
||||
set_config('field_updatelocal_profile_field_pet', 'onlogin', 'auth_db');
|
||||
$auth->config->field_updatelocal_profile_field_pet = 'onlogin';
|
||||
|
||||
$auth->sync_users($trace, false);
|
||||
$this->assertEquals(4, $DB->count_records('user'));
|
||||
@@ -241,6 +267,7 @@ class auth_db_testcase extends advanced_testcase {
|
||||
$this->assertEquals(4, $DB->count_records('user'));
|
||||
$u2 = $DB->get_record('user', array('username'=>$user2->name));
|
||||
$this->assertSame($user2b->email, $u2->email);
|
||||
$this->assertSame($user2b->animal, profile_user_record($u2->id)->pet);
|
||||
|
||||
|
||||
// Test sync deletes and suspends.
|
||||
|
||||
@@ -47,5 +47,8 @@ function xmldb_auth_email_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -55,5 +55,8 @@ function xmldb_auth_ldap_upgrade($oldversion) {
|
||||
upgrade_plugin_savepoint(true, 2020081700, 'auth', 'ldap');
|
||||
}
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,5 +47,8 @@ function xmldb_auth_manual_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,5 +47,8 @@ function xmldb_auth_mnet_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,5 +47,8 @@ function xmldb_auth_none_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -84,5 +84,8 @@ function xmldb_auth_oauth2_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ require_once('../../config.php');
|
||||
$issuerid = required_param('id', PARAM_INT);
|
||||
$wantsurl = new moodle_url(optional_param('wantsurl', '', PARAM_URL));
|
||||
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_url(new moodle_url('/auth/oauth2/login.php', ['id' => $issuerid]));
|
||||
|
||||
require_sesskey();
|
||||
|
||||
if (!\auth_oauth2\api::is_enabled()) {
|
||||
|
||||
@@ -182,7 +182,8 @@ How to customize the way the Shibboleth user data is used in Moodle
|
||||
Among the Shibboleth settings in Moodle there is a field that should contain a
|
||||
path to a php file that can be used as data manipulation hook.
|
||||
You can use this if you want to further process the way your Shibboleth
|
||||
attributes are used in Moodle.
|
||||
attributes are used in Moodle. Due to security reasons this file cannot be
|
||||
located within the current site data directory ($CFG->dataroot).
|
||||
|
||||
Example 1: Your Shibboleth federation uses an attribute that specifies the
|
||||
user's preferred language, but the content of this attribute is not
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Special setting for auth_shibboleth convert_data.
|
||||
*
|
||||
* @package auth_shibboleth
|
||||
* @copyright 2020 Mihail Geshoski
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Admin settings class for the convert_data option.
|
||||
*
|
||||
* @package auth_shibboleth
|
||||
* @copyright 2020 Mihail Geshoski
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class auth_shibboleth_admin_setting_convert_data extends admin_setting_configfile {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $visiblename
|
||||
* @param string $description
|
||||
* @param mixed $defaultdirectory
|
||||
*/
|
||||
public function __construct($name, $visiblename, $description, $defaultdirectory) {
|
||||
parent::__construct($name, $visiblename, $description, $defaultdirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the file path (location).
|
||||
*
|
||||
* This method ensures that the file defined as a data modification API exists and is not located in the site
|
||||
* data directory ($CFG->dataroot). We should prohibit using files from the site data directory as this introduces
|
||||
* security vulnerabilities.
|
||||
*
|
||||
* @param string $filepath The path to the file.
|
||||
* @return mixed bool true for success or string:error on failure.
|
||||
*/
|
||||
public function validate($filepath) {
|
||||
global $CFG;
|
||||
|
||||
if (empty($filepath)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fail if the file does not exist or it is not readable by the webserver process.
|
||||
if (!is_readable($filepath)) {
|
||||
return get_string('auth_shib_convert_data_warning', 'auth_shibboleth');
|
||||
}
|
||||
|
||||
// Fail if the absolute file path matches the currently defined dataroot path.
|
||||
if (preg_match('/' . preg_quote($CFG->dataroot, '/') . '/', realpath($filepath))) {
|
||||
return get_string('auth_shib_convert_data_filepath_warning', 'auth_shibboleth');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @return bool result
|
||||
*/
|
||||
function xmldb_auth_shibboleth_upgrade($oldversion) {
|
||||
global $CFG, $DB;
|
||||
global $CFG, $DB, $OUTPUT;
|
||||
|
||||
// Automatically generated Moodle v3.5.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
@@ -47,5 +47,30 @@ function xmldb_auth_shibboleth_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
if ($oldversion < 2020110901) {
|
||||
// The 'Data modification API' setting in the Shibboleth authentication plugin can no longer be configured
|
||||
// to use files located within the site data directory, as it exposes the site to security risks. Therefore,
|
||||
// we need to find every existing case and reset the 'Data modification API' setting to its default value.
|
||||
|
||||
$convertdataconfig = get_config('auth_shibboleth', 'convert_data');
|
||||
|
||||
if (preg_match('/' . preg_quote($CFG->dataroot, '/') . '/', realpath($convertdataconfig))) {
|
||||
set_config('convert_data', '', 'auth_shibboleth');
|
||||
|
||||
$warn = 'Your \'Data modification API\' setting in the Shibboleth authentication plugin is currently
|
||||
configured to use a file located within the current site data directory ($CFG->dataroot). You are no
|
||||
longer able to use files from within this directory for this purpose as it exposes your site to security
|
||||
risks. This setting has been reset to its default value. Please reconfigure it by providing a path
|
||||
to a file which is not located within the site data directory.';
|
||||
|
||||
echo $OUTPUT->notification($warn, 'notifyproblem');
|
||||
}
|
||||
|
||||
upgrade_plugin_savepoint(true, 2020110901, 'auth', 'shibboleth');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ $string['auth_shibboleth_select_organization'] = 'For authentication via Shibbol
|
||||
$string['auth_shib_convert_data'] = 'Data modification API';
|
||||
$string['auth_shib_convert_data_description'] = 'You can use this API to further modify the data provided by Shibboleth. Read the <a href="{$a}">README</a> for further instructions.';
|
||||
$string['auth_shib_convert_data_warning'] = 'The file does not exist or is not readable by the webserver process!';
|
||||
$string['auth_shib_convert_data_filepath_warning'] = 'You cannot use a file that is located within the current site data directory ($CFG->dataroot) as the data modification API.';
|
||||
$string['auth_shib_changepasswordurl'] = 'Password-change URL';
|
||||
$string['auth_shib_idp_list'] = 'Identity providers';
|
||||
$string['auth_shib_idp_list_description'] = 'Provide a list of Identity Provider entityIDs to let the user choose from on the login page.<br />On each line there must be a comma-separated tuple for entityID of the IdP (see the Shibboleth metadata file) and Name of IdP as it shall be displayed in the drop-down list.<br />As an optional third parameter you can add the location of a Shibboleth session initiator that shall be used in case your Moodle installation is part of a multi federation setup.';
|
||||
|
||||
@@ -28,6 +28,7 @@ if ($ADMIN->fulltree) {
|
||||
// We use a couple of custom admin settings since we need to massage the data before it is inserted into the DB.
|
||||
require_once($CFG->dirroot.'/auth/shibboleth/classes/admin_setting_special_wayf_select.php');
|
||||
require_once($CFG->dirroot.'/auth/shibboleth/classes/admin_setting_special_idp_configtextarea.php');
|
||||
require_once($CFG->dirroot.'/auth/shibboleth/classes/admin_setting_special_convert_data_configfile.php');
|
||||
|
||||
// Introductory explanation.
|
||||
$readmeurl = (new moodle_url('/auth/shibboleth/README.txt'))->out();
|
||||
@@ -38,8 +39,8 @@ if ($ADMIN->fulltree) {
|
||||
$settings->add(new admin_setting_configtext('auth_shibboleth/user_attribute', get_string('username'),
|
||||
get_string('auth_shib_username_description', 'auth_shibboleth'), '', PARAM_RAW));
|
||||
|
||||
// COnvert Data configuration file.
|
||||
$settings->add(new admin_setting_configfile('auth_shibboleth/convert_data',
|
||||
// Convert Data configuration file.
|
||||
$settings->add(new auth_shibboleth_admin_setting_convert_data('auth_shibboleth/convert_data',
|
||||
get_string('auth_shib_convert_data', 'auth_shibboleth'),
|
||||
get_string('auth_shib_convert_data_description', 'auth_shibboleth', $readmeurl), ''));
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
This files describes API changes in /auth/shibboleth/*,
|
||||
information provided here is intended especially for developers.
|
||||
|
||||
=== 3.10.1 ===
|
||||
|
||||
* The 'Data modification API' (convert_data) setting can no longer be configured to use files located within the
|
||||
current site data directory ($CFG->dataroot), as it exposes the site to security risks.
|
||||
|
||||
=== 3.5.2 ===
|
||||
|
||||
* Moved the public function unserializesession in auth/shibboleth/logout.php to auth/shibboleth/classes/helper.php and
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->version = 2020110901; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2020110300; // Requires this Moodle version
|
||||
$plugin->component = 'auth_shibboleth'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -82,16 +82,17 @@ class restore_quiz_decode_testcase extends \core_privacy\tests\provider_testcase
|
||||
|
||||
$newcm = duplicate_module($course, get_fast_modinfo($course)->get_cm($quiz->cmid));
|
||||
|
||||
$sql = "SELECT qa.answer
|
||||
$sql = "SELECT qa.id, qa.answer
|
||||
FROM {quiz} q
|
||||
LEFT JOIN {quiz_slots} qs ON qs.quizid = q.id
|
||||
LEFT JOIN {question_answers} qa ON qa.question = qs.questionid
|
||||
WHERE q.id = :quizid";
|
||||
$params = array('quizid' => $newcm->instance);
|
||||
$answers = $DB->get_fieldset_sql($sql, $params);
|
||||
$this->assertEquals($CFG->wwwroot . '/course/view.php?id=' . $course->id, $answers[0]);
|
||||
$this->assertEquals($CFG->wwwroot . '/mod/quiz/view.php?id=' . $quiz->cmid, $answers[1]);
|
||||
$this->assertEquals($CFG->wwwroot . '/grade/report/index.php?id=' . $quiz->cmid, $answers[2]);
|
||||
$this->assertEquals($CFG->wwwroot . '/mod/quiz/index.php?id=' . $quiz->cmid, $answers[3]);
|
||||
$answers = $DB->get_records_sql_menu($sql, $params);
|
||||
|
||||
$this->assertEquals($CFG->wwwroot . '/course/view.php?id=' . $course->id, $answers[$firstanswer->id]);
|
||||
$this->assertEquals($CFG->wwwroot . '/mod/quiz/view.php?id=' . $quiz->cmid, $answers[$secondanswer->id]);
|
||||
$this->assertEquals($CFG->wwwroot . '/grade/report/index.php?id=' . $quiz->cmid, $answers[$thirdanswer->id]);
|
||||
$this->assertEquals($CFG->wwwroot . '/mod/quiz/index.php?id=' . $quiz->cmid, $answers[$fourthanswer->id]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,5 +60,8 @@ function xmldb_block_badges_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -60,5 +60,8 @@ function xmldb_block_calendar_month_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -60,5 +60,8 @@ function xmldb_block_calendar_upcoming_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -92,6 +92,9 @@ class core_block_external extends external_api {
|
||||
private static function get_all_current_page_blocks($includeinvisible = false, $returncontents = false) {
|
||||
global $PAGE, $OUTPUT;
|
||||
|
||||
// Set page URL to a fake URL to avoid errors.
|
||||
$PAGE->set_url(new \moodle_url('/webservice/core_block_external/'));
|
||||
|
||||
// Load the block instances for all the regions.
|
||||
$PAGE->blocks->load_blocks($includeinvisible);
|
||||
$PAGE->blocks->create_all_block_instances();
|
||||
|
||||
@@ -63,5 +63,8 @@ function xmldb_block_completionstatus_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,5 +63,8 @@ function xmldb_block_course_summary_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,5 +48,8 @@ function xmldb_block_html_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -543,11 +543,9 @@ function(
|
||||
|
||||
// Filter out all pagination options which are too large for the amount of courses user is enrolled in.
|
||||
var totalCourseCount = parseInt(root.find(Selectors.courseView.region).attr('data-totalcoursecount'), 10);
|
||||
if (totalCourseCount) {
|
||||
itemsPerPage = itemsPerPage.filter(function(pagingOption) {
|
||||
return pagingOption.value < totalCourseCount;
|
||||
});
|
||||
}
|
||||
itemsPerPage = itemsPerPage.filter(function(pagingOption) {
|
||||
return pagingOption.value < totalCourseCount || pagingOption.value === 0;
|
||||
});
|
||||
|
||||
var filters = getFilterValues(root);
|
||||
var config = $.extend({}, DEFAULT_PAGED_CONTENT_CONFIG);
|
||||
@@ -602,7 +600,8 @@ function(
|
||||
pageCourses = $.merge(loadedPages[currentPage].courses, courses.slice(0, nextPageStart));
|
||||
}
|
||||
} else {
|
||||
nextPageStart = pageData.limit;
|
||||
// When the page limit is zero, there is only one page of courses, no start for next page.
|
||||
nextPageStart = pageData.limit || false;
|
||||
pageCourses = (pageData.limit > 0) ? courses.slice(0, pageData.limit) : courses;
|
||||
}
|
||||
|
||||
@@ -611,8 +610,8 @@ function(
|
||||
courses: pageCourses
|
||||
};
|
||||
|
||||
// Set up the next page
|
||||
var remainingCourses = nextPageStart ? courses.slice(nextPageStart, courses.length) : [];
|
||||
// Set up the next page (if there is more than one page).
|
||||
var remainingCourses = nextPageStart !== false ? courses.slice(nextPageStart, courses.length) : [];
|
||||
if (remainingCourses.length) {
|
||||
loadedPages[currentPage + 1] = {
|
||||
courses: remainingCourses
|
||||
|
||||
@@ -202,8 +202,9 @@ class main implements renderable, templatable {
|
||||
// Check and remember the given view.
|
||||
$this->view = $view ? $view : BLOCK_MYOVERVIEW_VIEW_CARD;
|
||||
|
||||
// Check and remember the given page size.
|
||||
if ($paging == BLOCK_MYOVERVIEW_PAGING_ALL) {
|
||||
// Check and remember the given page size, `null` indicates no page size set
|
||||
// while a `0` indicates a paging size of `All`.
|
||||
if (!is_null($paging) && $paging == BLOCK_MYOVERVIEW_PAGING_ALL) {
|
||||
$this->paging = BLOCK_MYOVERVIEW_PAGING_ALL;
|
||||
} else {
|
||||
$this->paging = $paging ? $paging : BLOCK_MYOVERVIEW_PAGING_12;
|
||||
@@ -370,8 +371,9 @@ class main implements renderable, templatable {
|
||||
$select = "instanceid $csql AND fieldid = :fieldid";
|
||||
$params['fieldid'] = $fieldid;
|
||||
$distinctablevalue = $DB->sql_compare_text('value');
|
||||
$values = $DB->get_records_select_menu('customfield_data', $select, $params, $DB->sql_order_by_text('value'),
|
||||
$values = $DB->get_records_select_menu('customfield_data', $select, $params, '',
|
||||
"DISTINCT $distinctablevalue, $distinctablevalue AS value2");
|
||||
\core_collator::asort($values, \core_collator::SORT_NATURAL);
|
||||
$values = array_filter($values);
|
||||
if (!$values) {
|
||||
return [];
|
||||
|
||||
@@ -81,5 +81,8 @@ function xmldb_block_myoverview_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,30 +7,30 @@ Feature: The my overview block allows users to persistence of their page limits
|
||||
| student1 | Student | X | student1@example.com | S1 |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
| Course 2 | C2 | 0 |
|
||||
| Course 3 | C3 | 0 |
|
||||
| Course 4 | C4 | 0 |
|
||||
| Course 5 | C5 | 0 |
|
||||
| Course 6 | C6 | 0 |
|
||||
| Course 7 | C7 | 0 |
|
||||
| Course 8 | C8 | 0 |
|
||||
| Course 9 | C9 | 0 |
|
||||
| Course 1 | C01 | 0 |
|
||||
| Course 2 | C02 | 0 |
|
||||
| Course 3 | C03 | 0 |
|
||||
| Course 4 | C04 | 0 |
|
||||
| Course 5 | C05 | 0 |
|
||||
| Course 6 | C06 | 0 |
|
||||
| Course 7 | C07 | 0 |
|
||||
| Course 8 | C08 | 0 |
|
||||
| Course 9 | C09 | 0 |
|
||||
| Course 10 | C10 | 0 |
|
||||
| Course 11 | C11 | 0 |
|
||||
| Course 12 | C12 | 0 |
|
||||
| Course 13 | C13 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student1 | C2 | student |
|
||||
| student1 | C3 | student |
|
||||
| student1 | C4 | student |
|
||||
| student1 | C5 | student |
|
||||
| student1 | C6 | student |
|
||||
| student1 | C7 | student |
|
||||
| student1 | C8 | student |
|
||||
| student1 | C9 | student |
|
||||
| student1 | C01 | student |
|
||||
| student1 | C02 | student |
|
||||
| student1 | C03 | student |
|
||||
| student1 | C04 | student |
|
||||
| student1 | C05 | student |
|
||||
| student1 | C06 | student |
|
||||
| student1 | C07 | student |
|
||||
| student1 | C08 | student |
|
||||
| student1 | C09 | student |
|
||||
| student1 | C10 | student |
|
||||
| student1 | C11 | student |
|
||||
| student1 | C12 | student |
|
||||
@@ -38,8 +38,8 @@ Feature: The my overview block allows users to persistence of their page limits
|
||||
|
||||
Scenario: Toggle the page limit between page reloads
|
||||
Given I log in as "student1"
|
||||
When I click on "[data-toggle='dropdown']" "css_element" in the "Course overview" "block"
|
||||
And I click on "All" "link"
|
||||
When I click on "[data-action='limit-toggle']" "css_element" in the "Course overview" "block"
|
||||
And I click on "All" "link" in the ".dropdown-menu.show" "css_element"
|
||||
Then I should see "Course 13"
|
||||
And I reload the page
|
||||
Then I should see "Course 13"
|
||||
@@ -47,8 +47,8 @@ Feature: The my overview block allows users to persistence of their page limits
|
||||
|
||||
Scenario: Toggle the page limit between grouping changes
|
||||
Given I log in as "student1"
|
||||
When I click on "[data-toggle='dropdown']" "css_element" in the "Course overview" "block"
|
||||
And I click on "All" "link"
|
||||
When I click on "[data-action='limit-toggle']" "css_element" in the "Course overview" "block"
|
||||
And I click on "All" "link" in the ".dropdown-menu.show" "css_element"
|
||||
And I click on "All (except removed from view)" "button" in the "Course overview" "block"
|
||||
And I click on "In progress" "link" in the "Course overview" "block"
|
||||
Then I should see "Course 13"
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
@block @block_myoverview @javascript
|
||||
Feature: My overview block pagination
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email | idnumber |
|
||||
| student1 | Student | X | student1@example.com | S1 |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 01 | C1 | 0 |
|
||||
| Course 02 | C2 | 0 |
|
||||
| Course 03 | C3 | 0 |
|
||||
| Course 04 | C4 | 0 |
|
||||
| Course 05 | C5 | 0 |
|
||||
| Course 06 | C6 | 0 |
|
||||
| Course 07 | C7 | 0 |
|
||||
| Course 08 | C8 | 0 |
|
||||
| Course 09 | C9 | 0 |
|
||||
| Course 10 | C10 | 0 |
|
||||
| Course 11 | C11 | 0 |
|
||||
| Course 12 | C12 | 0 |
|
||||
| Course 13 | C13 | 0 |
|
||||
| Course 14 | C14 | 0 |
|
||||
| Course 15 | C15 | 0 |
|
||||
| Course 16 | C16 | 0 |
|
||||
| Course 17 | C17 | 0 |
|
||||
| Course 18 | C18 | 0 |
|
||||
| Course 19 | C19 | 0 |
|
||||
| Course 20 | C20 | 0 |
|
||||
| Course 21 | C21 | 0 |
|
||||
| Course 22 | C22 | 0 |
|
||||
| Course 23 | C23 | 0 |
|
||||
| Course 24 | C24 | 0 |
|
||||
| Course 25 | C25 | 0 |
|
||||
|
||||
Scenario: The pagination controls should be hidden if I am not enrolled in any courses
|
||||
When I log in as "student1"
|
||||
Then I should see "No courses" in the "Course overview" "block"
|
||||
And I should not see "Show" in the "Course overview" "block"
|
||||
And ".block_myoverview .dropdown-menu.show" "css_element" should not be visible
|
||||
And ".block_myoverview [data-control='next']" "css_element" should not be visible
|
||||
And ".block_myoverview [data-control='previous']" "css_element" should not be visible
|
||||
And I log out
|
||||
|
||||
Scenario: The pagination controls should be hidden if I am enrolled in 12 courses or less
|
||||
Given the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student1 | C2 | student |
|
||||
| student1 | C3 | student |
|
||||
| student1 | C4 | student |
|
||||
| student1 | C5 | student |
|
||||
| student1 | C6 | student |
|
||||
| student1 | C7 | student |
|
||||
| student1 | C8 | student |
|
||||
| student1 | C9 | student |
|
||||
| student1 | C10 | student |
|
||||
| student1 | C11 | student |
|
||||
| student1 | C12 | student |
|
||||
When I log in as "student1"
|
||||
Then I should not see "Show" in the "Course overview" "block"
|
||||
And ".block_myoverview .dropdown-menu.show" "css_element" should not be visible
|
||||
And ".block_myoverview [data-control='next']" "css_element" should not be visible
|
||||
And ".block_myoverview [data-control='previous']" "css_element" should not be visible
|
||||
And I log out
|
||||
|
||||
Scenario: The default pagination should be 12 courses
|
||||
Given the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student1 | C2 | student |
|
||||
| student1 | C3 | student |
|
||||
| student1 | C4 | student |
|
||||
| student1 | C5 | student |
|
||||
| student1 | C6 | student |
|
||||
| student1 | C7 | student |
|
||||
| student1 | C8 | student |
|
||||
| student1 | C9 | student |
|
||||
| student1 | C10 | student |
|
||||
| student1 | C11 | student |
|
||||
| student1 | C12 | student |
|
||||
| student1 | C13 | student |
|
||||
When I log in as "student1"
|
||||
Then I should see "12" in the "[data-action='limit-toggle']" "css_element"
|
||||
And I log out
|
||||
|
||||
Scenario: I should only see pagination limit options less than total number of enrolled courses
|
||||
Given the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student1 | C2 | student |
|
||||
| student1 | C3 | student |
|
||||
| student1 | C4 | student |
|
||||
| student1 | C5 | student |
|
||||
| student1 | C6 | student |
|
||||
| student1 | C7 | student |
|
||||
| student1 | C8 | student |
|
||||
| student1 | C9 | student |
|
||||
| student1 | C10 | student |
|
||||
| student1 | C11 | student |
|
||||
| student1 | C12 | student |
|
||||
| student1 | C13 | student |
|
||||
And I log in as "student1"
|
||||
When I click on "[data-action='limit-toggle']" "css_element" in the "Course overview" "block"
|
||||
Then I should see "All" in the ".dropdown-menu.show" "css_element"
|
||||
And I should see "12" in the ".dropdown-menu.show" "css_element"
|
||||
And ".block_myoverview [data-control='next']" "css_element" should be visible
|
||||
And ".block_myoverview [data-control='previous']" "css_element" should be visible
|
||||
But I should not see "24" in the ".block_myoverview .dropdown-menu.show" "css_element"
|
||||
And I log out
|
||||
|
||||
Scenario: Previous page button should be disabled when on the first page of courses
|
||||
Given the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student1 | C2 | student |
|
||||
| student1 | C3 | student |
|
||||
| student1 | C4 | student |
|
||||
| student1 | C5 | student |
|
||||
| student1 | C6 | student |
|
||||
| student1 | C7 | student |
|
||||
| student1 | C8 | student |
|
||||
| student1 | C9 | student |
|
||||
| student1 | C10 | student |
|
||||
| student1 | C11 | student |
|
||||
| student1 | C12 | student |
|
||||
| student1 | C13 | student |
|
||||
When I log in as "student1"
|
||||
Then the "class" attribute of ".block_myoverview [data-control='previous']" "css_element" should contain "disabled"
|
||||
And I log out
|
||||
|
||||
Scenario: Next page button should be disabled when on the last page of courses
|
||||
Given the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student1 | C2 | student |
|
||||
| student1 | C3 | student |
|
||||
| student1 | C4 | student |
|
||||
| student1 | C5 | student |
|
||||
| student1 | C6 | student |
|
||||
| student1 | C7 | student |
|
||||
| student1 | C8 | student |
|
||||
| student1 | C9 | student |
|
||||
| student1 | C10 | student |
|
||||
| student1 | C11 | student |
|
||||
| student1 | C12 | student |
|
||||
| student1 | C13 | student |
|
||||
When I log in as "student1"
|
||||
And I click on "[data-control='next']" "css_element" in the "Course overview" "block"
|
||||
And I wait until ".block_myoverview [data-control='next']" "css_element" exists
|
||||
Then the "class" attribute of ".block_myoverview [data-control='next']" "css_element" should contain "disabled"
|
||||
And I log out
|
||||
|
||||
Scenario: Next and previous page buttons should both be enabled when not on last or first page of courses
|
||||
Given the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student1 | C2 | student |
|
||||
| student1 | C3 | student |
|
||||
| student1 | C4 | student |
|
||||
| student1 | C5 | student |
|
||||
| student1 | C6 | student |
|
||||
| student1 | C7 | student |
|
||||
| student1 | C8 | student |
|
||||
| student1 | C9 | student |
|
||||
| student1 | C10 | student |
|
||||
| student1 | C11 | student |
|
||||
| student1 | C12 | student |
|
||||
| student1 | C13 | student |
|
||||
| student1 | C14 | student |
|
||||
| student1 | C15 | student |
|
||||
| student1 | C16 | student |
|
||||
| student1 | C17 | student |
|
||||
| student1 | C18 | student |
|
||||
| student1 | C19 | student |
|
||||
| student1 | C20 | student |
|
||||
| student1 | C21 | student |
|
||||
| student1 | C22 | student |
|
||||
| student1 | C23 | student |
|
||||
| student1 | C24 | student |
|
||||
| student1 | C25 | student |
|
||||
When I log in as "student1"
|
||||
And I click on "[data-control='next']" "css_element" in the "Course overview" "block"
|
||||
And I wait until ".block_myoverview [data-control='next']" "css_element" exists
|
||||
Then the "class" attribute of ".block_myoverview [data-control='next']" "css_element" should not contain "disabled"
|
||||
And the "class" attribute of ".block_myoverview [data-control='previous']" "css_element" should not contain "disabled"
|
||||
And I should see "Course 13" in the "Course overview" "block"
|
||||
And I should see "Course 24" in the "Course overview" "block"
|
||||
But I should not see "Course 12" in the "Course overview" "block"
|
||||
And I should not see "Course 25" in the "Course overview" "block"
|
||||
And I log out
|
||||
@@ -70,5 +70,8 @@ function xmldb_block_navigation_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -60,5 +60,8 @@ function xmldb_block_quiz_results_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,5 +62,8 @@ function xmldb_block_recent_activity_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,5 +75,8 @@ function xmldb_block_recentlyaccesseditems_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,5 +48,8 @@ function xmldb_block_rss_client_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -64,5 +64,8 @@ function xmldb_block_section_links_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,5 +63,8 @@ function xmldb_block_selfcompletion_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -70,5 +70,8 @@ function xmldb_block_settings_upgrade($oldversion, $block) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -150,4 +150,17 @@ class behat_block_site_main_menu extends behat_base {
|
||||
$xpath = "//*[contains(concat(' ',normalize-space(@class),' '),' block_site_main_menu ')]//li[contains(., $activityname)]";
|
||||
$this->execute('behat_action_menu::i_open_the_action_menu_in', [$xpath, 'xpath_element']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of partial named selectors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_partial_named_selectors(): array {
|
||||
return [
|
||||
new behat_component_named_selector('Activity', [
|
||||
"//*[contains(concat(' ',normalize-space(@class),' '),' block_site_main_menu ')]//li[contains(., %locator%)]"
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,16 @@ Feature: Edit activities in main menu block
|
||||
|
||||
@javascript
|
||||
Scenario: Edit name of acitivity in-place in site main menu block
|
||||
Given I log in as "admin"
|
||||
Given the following "activity" exists:
|
||||
| activity | forum |
|
||||
| course | Acceptance test site |
|
||||
| name | My forum name |
|
||||
| idnumber | forum |
|
||||
And I log in as "admin"
|
||||
And I am on site homepage
|
||||
And I navigate to "Turn editing on" in current page administration
|
||||
And I add the "Main menu" block
|
||||
When I add a "Forum" to section "0" and I fill the form with:
|
||||
| Forum name | My forum name |
|
||||
And I click on "Edit title" "link" in the "My forum name" activity in site main menu block
|
||||
And I set the field "New name for activity My forum name" to "New forum name"
|
||||
And I press key "13" in the field "New name for activity My forum name"
|
||||
When I set the field "Edit title" in the "My forum name" "block_site_main_menu > Activity" to "New forum name"
|
||||
Then I should not see "My forum name"
|
||||
And I should see "New forum name"
|
||||
And I follow "New forum name"
|
||||
|
||||
@@ -158,4 +158,17 @@ class behat_block_social_activities extends behat_base {
|
||||
$xpath = "//*[contains(concat(' ',normalize-space(@class),' '),' block_social_activities ')]//li[contains(., $activityname)]";
|
||||
$this->execute('behat_action_menu::i_open_the_action_menu_in', [$xpath, 'xpath_element']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of partial named selectors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_partial_named_selectors(): array {
|
||||
return [
|
||||
new behat_component_named_selector('Activity', [
|
||||
"//*[contains(concat(' ',normalize-space(@class),' '),' block_social_activities ')]//li[contains(., %locator%)]",
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,7 @@ Feature: Edit activities in social activities block
|
||||
And I click on "Add a new Forum" "link" in the "Add an activity or resource" "dialogue"
|
||||
And I set the field "Forum name" to "My forum name"
|
||||
And I press "Save and return to course"
|
||||
And I click on "Edit title" "link" in the "My forum name" activity in social activities block
|
||||
And I set the field "New name for activity My forum name" to "New forum name"
|
||||
And I press key "13" in the field "New name for activity My forum name"
|
||||
When I set the field "Edit title" in the "My forum name" "block_social_activities > Activity" to "New forum name"
|
||||
Then I should not see "My forum name" in the "Social activities" "block"
|
||||
And I should see "New forum name"
|
||||
And I follow "New forum name"
|
||||
@@ -84,4 +82,3 @@ Feature: Edit activities in social activities block
|
||||
And I should not see "My forum name" in the "Social activities" "block"
|
||||
And I click on "My forum name" "link" in the "Recent activity" "block"
|
||||
And I should see "My forum name" in the ".breadcrumb" "css_element"
|
||||
And I log out
|
||||
|
||||
@@ -51,9 +51,6 @@ class block_tag_youtube extends block_base {
|
||||
|
||||
function specialization() {
|
||||
$this->title = !empty($this->config->title) ? $this->config->title : get_string('pluginname', 'block_tag_youtube');
|
||||
// Convert numeric categories (old YouTube API) to
|
||||
// textual ones (new Google Data API)
|
||||
$this->config->category = !empty($this->config->category) ? $this->category_map_old2new($this->config->category) : '0';
|
||||
}
|
||||
|
||||
function instance_allow_multiple() {
|
||||
@@ -341,62 +338,71 @@ class block_tag_youtube extends block_base {
|
||||
return $text;
|
||||
}
|
||||
|
||||
function get_categories() {
|
||||
// TODO: Right now using sticky categories from
|
||||
// http://gdata.youtube.com/schemas/2007/categories.cat
|
||||
// This should be performed from time to time by the block insead
|
||||
// and cached somewhere, avoiding deprecated ones and observing regions
|
||||
return array (
|
||||
'0' => get_string('anycategory', 'block_tag_youtube'),
|
||||
'Film' => get_string('filmsanimation', 'block_tag_youtube'),
|
||||
'Autos' => get_string('autosvehicles', 'block_tag_youtube'),
|
||||
'Music' => get_string('music', 'block_tag_youtube'),
|
||||
'Animals'=> get_string('petsanimals', 'block_tag_youtube'),
|
||||
'Sports' => get_string('sports', 'block_tag_youtube'),
|
||||
'Travel' => get_string('travel', 'block_tag_youtube'),
|
||||
'Games' => get_string('gadgetsgames', 'block_tag_youtube'),
|
||||
'Comedy' => get_string('comedy', 'block_tag_youtube'),
|
||||
'People' => get_string('peopleblogs', 'block_tag_youtube'),
|
||||
'News' => get_string('newspolitics', 'block_tag_youtube'),
|
||||
'Entertainment' => get_string('entertainment', 'block_tag_youtube'),
|
||||
'Education' => get_string('education', 'block_tag_youtube'),
|
||||
'Howto' => get_string('howtodiy', 'block_tag_youtube'),
|
||||
'Tech' => get_string('scienceandtech', 'block_tag_youtube')
|
||||
);
|
||||
/**
|
||||
* Method that returns an array containing all relevant video categories obtained through an API call, where the
|
||||
* array index represents the category ID and the array value represents the category name.
|
||||
*
|
||||
* @return array The array containing the relevant video categories
|
||||
* @throws moodle_exception If the API key is not set
|
||||
* @throws Google_Service_Exception If an error occurs while obtaining the categories through the API call
|
||||
*/
|
||||
public function get_categories() {
|
||||
// Get the default categories and it's translations.
|
||||
$categorytranslations = $this->category_map_translation();
|
||||
|
||||
if ($service = $this->get_service()) {
|
||||
// Call the API to fetch the youtube video categories.
|
||||
// This API call requires the regionCode parameter which instructs the API to return the list of video
|
||||
// categories available in the specified country. Currently 'us' is hardcoded as the returned categories
|
||||
// for this region correspond to the previously used (legacy) hardcoded list of categories.
|
||||
// TODO: We should improve this in the future and avoid hardcoding this value.
|
||||
$response = $service->videoCategories->listVideoCategories('snippet', ['regionCode' => 'us']);
|
||||
$categoryitems = $response['modelData']['items'];
|
||||
|
||||
// Return an array with the relevant categories.
|
||||
return array_reduce($categoryitems, function($categories, $category) use ($categorytranslations) {
|
||||
$categoryid = $category['id'];
|
||||
$categoryname = $category['snippet']['title'];
|
||||
// Videos can be associated with this category.
|
||||
if ($category['snippet']['assignable']) {
|
||||
// If the category name can be mapped with a translation, add it to the categories array.
|
||||
if (array_key_exists($categoryname, $categorytranslations)) {
|
||||
$categories[$categoryid] = $categorytranslations[$categoryname];
|
||||
} else { // Otherwise, display the untranslated category name and show a debugging message.
|
||||
$categories[$categoryid] = $categoryname;
|
||||
debugging("The category '{$categoryname}' does not have a translatable language string.");
|
||||
}
|
||||
}
|
||||
return $categories;
|
||||
}, []);
|
||||
} else {
|
||||
throw new \moodle_exception('apierror', 'block_tag_youtube');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide conversion from old numeric categories available in youtube API
|
||||
* to the new ones available in the Google API
|
||||
* Method that provides mapping between the video category names and their translations.
|
||||
*
|
||||
* @param int $oldcat old category code
|
||||
* @return mixed new category code or 0 (if no match found)
|
||||
*
|
||||
* TODO: Someday this should be applied on upgrade for all the existing
|
||||
* block instances so we won't need the mapping any more. That would imply
|
||||
* to implement restore handling to perform the conversion of old blocks.
|
||||
* @return array The array that maps the video category names with their translations
|
||||
*/
|
||||
function category_map_old2new($oldcat) {
|
||||
$oldoptions = array (
|
||||
0 => '0',
|
||||
1 => 'Film',
|
||||
2 => 'Autos',
|
||||
23 => 'Comedy',
|
||||
24 => 'Entertainment',
|
||||
10 => 'Music',
|
||||
25 => 'News',
|
||||
22 => 'People',
|
||||
15 => 'Animals',
|
||||
26 => 'Howto',
|
||||
17 => 'Sports',
|
||||
19 => 'Travel',
|
||||
20 => 'Games'
|
||||
);
|
||||
if (array_key_exists($oldcat, $oldoptions)) {
|
||||
return $oldoptions[$oldcat];
|
||||
} else {
|
||||
return $oldcat;
|
||||
}
|
||||
private function category_map_translation() {
|
||||
return [
|
||||
'Film & Animation' => get_string('filmsanimation', 'block_tag_youtube'),
|
||||
'Autos & Vehicles' => get_string('autosvehicles', 'block_tag_youtube'),
|
||||
'Music' => get_string('music', 'block_tag_youtube'),
|
||||
'Pets & Animals' => get_string('petsanimals', 'block_tag_youtube'),
|
||||
'Sports' => get_string('sports', 'block_tag_youtube'),
|
||||
'Travel & Events' => get_string('travel', 'block_tag_youtube'),
|
||||
'Gaming' => get_string('gadgetsgames', 'block_tag_youtube'),
|
||||
'People & Blogs' => get_string('peopleblogs', 'block_tag_youtube'),
|
||||
'Comedy' => get_string('comedy', 'block_tag_youtube'),
|
||||
'Entertainment' => get_string('entertainment', 'block_tag_youtube'),
|
||||
'News & Politics' => get_string('newspolitics', 'block_tag_youtube'),
|
||||
'Howto & Style' => get_string('howtodiy', 'block_tag_youtube'),
|
||||
'Education' => get_string('education', 'block_tag_youtube'),
|
||||
'Science & Technology' => get_string('scienceandtech', 'block_tag_youtube'),
|
||||
'Nonprofits & Activism' => get_string('nonprofitactivism', 'block_tag_youtube'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file keeps track of upgrades to the tag_youtube block
|
||||
*
|
||||
* @package block_tag_youtube
|
||||
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Upgrade code for the Tag Youtube block.
|
||||
*
|
||||
* @param int $oldversion
|
||||
*/
|
||||
function xmldb_block_tag_youtube_upgrade($oldversion) {
|
||||
global $DB, $CFG, $OUTPUT;
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
if ($oldversion < 2020110901) {
|
||||
// We need to fix every tag_youtube block instance that has used a legacy category name as a category config.
|
||||
// The category config needs to store the category ID instead.
|
||||
|
||||
// If tag_youtube block instances exist.
|
||||
if ($blockinstances = $DB->get_records('block_instances', ['blockname' => 'tag_youtube'])) {
|
||||
$categories = [];
|
||||
// The block tag youtube needs to be configured and have a valid API key in order to obtain the video
|
||||
// category list.
|
||||
if ($apikey = get_config('block_tag_youtube', 'apikey')) {
|
||||
require_once($CFG->libdir . '/google/lib.php');
|
||||
$client = get_google_client();
|
||||
$client->setDeveloperKey($apikey);
|
||||
$client->setScopes(array(Google_Service_YouTube::YOUTUBE_READONLY));
|
||||
$service = new Google_Service_YouTube($client);
|
||||
|
||||
try {
|
||||
// Get the video category list.
|
||||
$response = $service->videoCategories->listVideoCategories('snippet', ['regionCode' => 'us']);
|
||||
|
||||
// Return an array of categories, where the key is the category name and the value is the
|
||||
// category ID.
|
||||
$categories = array_reduce($response['modelData']['items'], function ($categories, $category) {
|
||||
$categoryid = $category['id'];
|
||||
$categoryname = $category['snippet']['title'];
|
||||
// If videos can be associated with this category, add it to the categories list.
|
||||
if ($category['snippet']['assignable']) {
|
||||
$categories[$categoryname] = $categoryid;
|
||||
}
|
||||
return $categories;
|
||||
}, []);
|
||||
} catch (Exception $e) {
|
||||
$warn = "Due to the following error the youtube video categories were not obtained through the API:
|
||||
'{$e->getMessage()}'. Therefore, any legacy values used as a category setting in Tag Youtube
|
||||
block instances cannot be properly mapped and updated. All legacy values used as category setting
|
||||
will still be updated and set by default to 'Any category'.";
|
||||
echo $OUTPUT->notification($warn, 'notifyproblem');
|
||||
}
|
||||
} else {
|
||||
$warn = "The API key is missing in the Tag Youtube block configuration. Therefore, the youtube video
|
||||
categories cannot be obtained and mapped with the legacy values used as category setting. All legacy
|
||||
values used as category setting will still be updated and set by default to 'Any category'.";
|
||||
echo $OUTPUT->notification($warn, 'notifyproblem');
|
||||
}
|
||||
|
||||
// Array that maps the old category names to the current category names.
|
||||
$categorynamemap = [
|
||||
'Film' => 'Film & Animation',
|
||||
'Autos' => 'Autos & Vehicles',
|
||||
'Comedy' => 'Comedy',
|
||||
'Entertainment' => 'Entertainment',
|
||||
'Music' => 'Music',
|
||||
'News' => 'News & Politics',
|
||||
'People' => 'People & Blogs',
|
||||
'Animals' => 'Pets & Animals',
|
||||
'Howto' => 'Howto & Style',
|
||||
'Sports' => 'Sports',
|
||||
'Travel' => 'Travel & Events',
|
||||
'Games' => 'Gaming',
|
||||
'Education' => 'Education',
|
||||
'Tech' => 'Tech'
|
||||
];
|
||||
|
||||
// If the block uses a legacy category name, update it to use the current category ID instead.
|
||||
foreach ($blockinstances as $blockinstance) {
|
||||
$blockconfig = unserialize(base64_decode($blockinstance->configdata));
|
||||
$blockcategoryconfig = $blockconfig->category;
|
||||
// The block is using a legacy category name as a category config.
|
||||
if (array_key_exists($blockcategoryconfig, $categorynamemap)) {
|
||||
if (!empty($categories)) { // The categories were successfully obtained through the API call.
|
||||
// Get the current category name.
|
||||
$currentcategoryname = $categorynamemap[$blockcategoryconfig];
|
||||
// Add the category ID as a new category config for this block instance.
|
||||
$blockconfig->category = $categories[$currentcategoryname];
|
||||
} else { // The categories were not obtained through the API call.
|
||||
// If the categories were not obtained through the API call, we are not able to map the
|
||||
// current legacy category name with the category ID. Therefore, we should default the category
|
||||
// config value to 0 ('Any category') to at least enable the block to function properly. The
|
||||
// user can later manually select the desired category and re-save the config through the UI.
|
||||
$blockconfig->category = 0;
|
||||
}
|
||||
|
||||
$blockinstance->configdata = base64_encode(serialize($blockconfig));
|
||||
$DB->update_record('block_instances', $blockinstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
upgrade_block_savepoint(true, 2020110901, 'tag_youtube', false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -30,6 +30,8 @@
|
||||
*/
|
||||
class block_tag_youtube_edit_form extends block_edit_form {
|
||||
protected function specific_definition($mform) {
|
||||
global $OUTPUT;
|
||||
|
||||
$mform->addElement('header', 'configheader', get_string('blocksettings', 'block'));
|
||||
|
||||
$mform->addElement('text', 'config_title', get_string('configtitle', 'block_tag_youtube'));
|
||||
@@ -38,10 +40,26 @@ class block_tag_youtube_edit_form extends block_edit_form {
|
||||
$mform->addElement('text', 'config_numberofvideos', get_string('numberofvideos', 'block_tag_youtube'), array('size' => 5));
|
||||
$mform->setType('config_numberofvideos', PARAM_INT);
|
||||
|
||||
$categorychoices = $this->block->get_categories();
|
||||
$mform->addElement('select', 'config_category', get_string('category', 'block_tag_youtube'), $categorychoices);
|
||||
// Category setting.
|
||||
$categorychoices = ['0' => get_string('anycategory', 'block_tag_youtube')];
|
||||
$categoryerror = '';
|
||||
|
||||
try {
|
||||
// Get all video categories through an API call and add them to the category list.
|
||||
$categorychoices += $this->block->get_categories();
|
||||
} catch (Exception $e) {
|
||||
$categoryerror = $e->getMessage();
|
||||
}
|
||||
$mform->addElement('select', 'config_category', get_string('category', 'block_tag_youtube'),
|
||||
$categorychoices);
|
||||
$mform->setDefault('config_category', 0);
|
||||
|
||||
if ($categoryerror) {
|
||||
$notification = $OUTPUT->notification(get_string('categoryerror', 'block_tag_youtube', $categoryerror),
|
||||
'error');
|
||||
$mform->addElement('static', 'config_category_error', '', $notification);
|
||||
}
|
||||
|
||||
$mform->addElement('text', 'config_playlist', get_string('includeonlyvideosfromplaylist', 'block_tag_youtube'));
|
||||
$mform->setType('config_playlist', PARAM_ALPHANUM);
|
||||
}
|
||||
|
||||
@@ -32,12 +32,14 @@ $string['comedy'] = 'Comedy';
|
||||
$string['configtitle'] = 'YouTube block title';
|
||||
$string['education'] = 'Education';
|
||||
$string['entertainment'] = 'Entertainment';
|
||||
$string['categoryerror'] = 'Failed to obtain the list of categories. <br> {$a}';
|
||||
$string['filmsanimation'] = 'Films & Animation';
|
||||
$string['gadgetsgames'] = 'Gadgets & Games';
|
||||
$string['howtodiy'] = 'How-to & DIY';
|
||||
$string['includeonlyvideosfromplaylist'] = 'Include only videos from the playlist with id';
|
||||
$string['music'] = 'Music';
|
||||
$string['newspolitics'] = 'News & Politics';
|
||||
$string['nonprofitactivism'] = 'Nonprofits & Activism';
|
||||
$string['numberofvideos'] = 'Number of videos';
|
||||
$string['peopleblogs'] = 'People & Blogs';
|
||||
$string['petsanimals'] = 'Pets & Animals';
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
@block @block_tag_youtube
|
||||
Feature: Adding and configuring YouTube block
|
||||
In order to have the YouTube block used
|
||||
As a admin
|
||||
I need to add the YouTube block to the tags site page
|
||||
|
||||
Background:
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
And I click on "Show" "icon" in the "YouTube" "table_row"
|
||||
|
||||
@javascript
|
||||
Scenario: Category options are not available (except default) in the block settings if the YouTube API key is not set.
|
||||
Given the following config values are set as admin:
|
||||
| apikey | | block_tag_youtube |
|
||||
And I follow "Dashboard" in the user menu
|
||||
And I press "Customise this page"
|
||||
# TODO MDL-57120 site "Tags" link not accessible without navigation block.
|
||||
And I add the "Navigation" block if not present
|
||||
And I click on "Site pages" "list_item" in the "Navigation" "block"
|
||||
And I click on "Tags" "link" in the "Navigation" "block"
|
||||
And I add the "YouTube" block
|
||||
When I configure the "YouTube" block
|
||||
Then I should see "Category"
|
||||
And I should see "Failed to obtain the list of categories."
|
||||
And I should see "The YouTube API key is not set. Contact your administrator."
|
||||
And the "Category" select box should contain "Any category"
|
||||
And the "Category" select box should not contain "Films & Animation"
|
||||
And the "Category" select box should not contain "Entertainment"
|
||||
And the "Category" select box should not contain "Education"
|
||||
|
||||
@javascript
|
||||
Scenario: Category options are not available (except default) in the block settings when invalid YouTube API key is set.
|
||||
Given the following config values are set as admin:
|
||||
| apikey | invalidapikeyvalue | block_tag_youtube |
|
||||
And I follow "Dashboard" in the user menu
|
||||
And I press "Customise this page"
|
||||
And I add the "Navigation" block if not present
|
||||
And I click on "Site pages" "list_item" in the "Navigation" "block"
|
||||
And I click on "Tags" "link" in the "Navigation" "block"
|
||||
And I add the "YouTube" block
|
||||
When I configure the "YouTube" block
|
||||
Then I should see "Category"
|
||||
And I should see "Failed to obtain the list of categories."
|
||||
And the "Category" select box should contain "Any category"
|
||||
And the "Category" select box should not contain "Comedy"
|
||||
And the "Category" select box should not contain "Autos & Vehicles"
|
||||
And the "Category" select box should not contain "News & Politics"
|
||||
@@ -1,5 +1,11 @@
|
||||
This files describes API changes in the block tag_youtube code.
|
||||
|
||||
=== 3.10.1 ===
|
||||
|
||||
* The config category now stores the category ID, instead of a string representation of the category name.
|
||||
In YouTube Data API v3, the API call to fetch the videos related to a certain category expects the category ID to be
|
||||
passed to the videoCategoryId parameter, instead of the category name.
|
||||
|
||||
=== 3.0 ===
|
||||
|
||||
* Due to the final YouTube API v2.0 deprecation we needed to adapt the current
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->version = 2020110901; // The current plugin version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2020110300; // Requires this Moodle version
|
||||
$plugin->component = 'block_tag_youtube'; // Full name of the plugin (used for diagnostics)
|
||||
|
||||
@@ -52,9 +52,9 @@
|
||||
<a href="{{url}}"
|
||||
title={{#quote}}{{{name}}}{{/quote}}
|
||||
aria-label='{{#str}} ariaeventlistitem, block_timeline, { "name": {{#quote}}{{{name}}}{{/quote}}, "course": {{#quote}}{{{course.fullnamedisplay}}}{{/quote}}, "date": "{{#userdate}} {{timesort}}, {{#str}} strftimedatetime, core_langconfig {{/str}} {{/userdate}}" } {{/str}}'
|
||||
><h6 class="event-name text-truncate mb-0">{{#quote}}{{{name}}}{{/quote}}</h6></a>
|
||||
><h6 class="event-name text-truncate mb-0">{{{name}}}</h6></a>
|
||||
{{#course.fullnamedisplay}}
|
||||
<small class="text-muted text-truncate mb-0">{{#quote}}{{{course.fullnamedisplay}}}{{/quote}}</small>
|
||||
<small class="text-muted text-truncate mb-0">{{{course.fullnamedisplay}}}</small>
|
||||
{{/course.fullnamedisplay}}
|
||||
{{#action.actionable}}
|
||||
<h6 class="mb-0 pt-2">
|
||||
|
||||
Vendored
+19
-13
@@ -182,22 +182,28 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
|
||||
$server = $serverconf[0];
|
||||
$port = $serverconf[1];
|
||||
}
|
||||
if ($redis->connect($server, $port)) {
|
||||
if (!empty($password)) {
|
||||
$redis->auth($password);
|
||||
|
||||
try {
|
||||
if ($redis->connect($server, $port)) {
|
||||
if (!empty($password)) {
|
||||
$redis->auth($password);
|
||||
}
|
||||
// If using compressor, serialisation will be done at cachestore level, not php-redis.
|
||||
if ($this->compressor == self::COMPRESSOR_NONE) {
|
||||
$redis->setOption(Redis::OPT_SERIALIZER, $this->serializer);
|
||||
}
|
||||
if (!empty($prefix)) {
|
||||
$redis->setOption(Redis::OPT_PREFIX, $prefix);
|
||||
}
|
||||
// Database setting option...
|
||||
$this->isready = $this->ping($redis);
|
||||
} else {
|
||||
$this->isready = false;
|
||||
}
|
||||
// If using compressor, serialisation will be done at cachestore level, not php-redis.
|
||||
if ($this->compressor == self::COMPRESSOR_NONE) {
|
||||
$redis->setOption(Redis::OPT_SERIALIZER, $this->serializer);
|
||||
}
|
||||
if (!empty($prefix)) {
|
||||
$redis->setOption(Redis::OPT_PREFIX, $prefix);
|
||||
}
|
||||
// Database setting option...
|
||||
$this->isready = $this->ping($redis);
|
||||
} else {
|
||||
} catch (\RedisException $e) {
|
||||
$this->isready = false;
|
||||
}
|
||||
|
||||
return $redis;
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -116,7 +116,11 @@ class calendar_event_exporter extends event_exporter_base {
|
||||
$values['islastday'] = false;
|
||||
$today = $this->related['type']->timestamp_to_date_array($this->related['today']);
|
||||
|
||||
$values['popupname'] = $this->event->get_name();
|
||||
if ($hascourse) {
|
||||
$values['popupname'] = external_format_string($this->event->get_name(), \context_course::instance($course->id), true);
|
||||
} else {
|
||||
$values['popupname'] = external_format_string($this->event->get_name(), \context_system::instance(), true);
|
||||
}
|
||||
|
||||
$times = $this->event->get_times();
|
||||
if ($duration = $times->get_duration()) {
|
||||
|
||||
+6
-3
@@ -115,11 +115,14 @@ if (optional_param('remove', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
</td>
|
||||
<td id="buttonscell">
|
||||
<div id="addcontrols">
|
||||
<input name="add" id="add" type="submit" value="<?php echo $OUTPUT->larrow().' '.s(get_string('add')); ?>" title="<?php p(get_string('add')); ?>" /><br />
|
||||
<input class="btn btn-secondary" name="add" id="add" type="submit" value="<?php echo $OUTPUT->larrow() . ' ' .
|
||||
s(get_string('add')); ?>" title="<?php p(get_string('add')); ?>" /><br />
|
||||
</div>
|
||||
|
||||
<div id="removecontrols">
|
||||
<input name="remove" id="remove" type="submit" value="<?php echo s(get_string('remove')).' '.$OUTPUT->rarrow(); ?>" title="<?php p(get_string('remove')); ?>" />
|
||||
<input class="btn btn-secondary" name="remove" id="remove" type="submit"
|
||||
value="<?php echo s(get_string('remove')) . ' ' . $OUTPUT->rarrow(); ?>"
|
||||
title="<?php p(get_string('remove')); ?>" />
|
||||
</div>
|
||||
</td>
|
||||
<td id="potentialcell">
|
||||
@@ -128,7 +131,7 @@ if (optional_param('remove', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td colspan="3" id='backcell'>
|
||||
<input type="submit" name="cancel" value="<?php p(get_string('backtocohorts', 'cohort')); ?>" />
|
||||
<input class="btn btn-secondary" type="submit" name="cancel" value="<?php p(get_string('backtocohorts', 'cohort')); ?>" />
|
||||
</td></tr>
|
||||
</table>
|
||||
</div></form>
|
||||
|
||||
@@ -62,9 +62,7 @@ Feature: Add cohorts of users
|
||||
@javascript
|
||||
Scenario: Edit cohort name in-place
|
||||
When I follow "Cohorts"
|
||||
And I click on "Edit cohort name" "link" in the "Test cohort name" "table_row"
|
||||
And I set the field "New name for cohort Test cohort name" to "Students cohort"
|
||||
And I press key "13" in the field "New name for cohort Test cohort name"
|
||||
And I set the field "Edit cohort name" to "Students cohort"
|
||||
Then I should not see "Test cohort name"
|
||||
And I should see "Students cohort"
|
||||
And I follow "Cohorts"
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,2 +1,2 @@
|
||||
define ("core_course/local/activitychooser/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b=function(a,b){return"[data-".concat(a,"=\"").concat(b,"\"]")},c={regions:{chooser:b("region","chooser-container"),getSectionChooserOptions:function getSectionChooserOptions(a){return"".concat(a," ").concat(b("region","chooser-options-container"))},chooserOption:{container:b("region","chooser-option-container"),actions:b("region","chooser-option-actions-container"),info:b("region","chooser-option-info-container")},chooserSummary:{container:b("region","chooser-option-summary-container"),content:b("region","chooser-option-summary-content-container"),header:b("region","summary-header"),actions:b("region","chooser-option-summary-actions-container")},carousel:b("region","carousel"),help:b("region","help"),modules:b("region","modules"),favouriteTabNav:b("region","favourite-tab-nav"),recommendedTabNav:b("region","recommended-tab-nav"),defaultTabNav:b("region","default-tab-nav"),activityTabNav:b("region","activity-tab-nav"),resourceTabNav:b("region","resources-tab-nav"),favouriteTab:b("region","favourites"),recommendedTab:b("region","recommended"),defaultTab:b("region","default"),activityTab:b("region","activity"),resourceTab:b("region","resources"),getModuleSelector:function getModuleSelector(a){return"[role=\"menuitem\"][data-modname=\"".concat(a,"\"]")},searchResults:b("region","search-results-container"),searchResultItems:b("region","search-result-items-container")},actions:{optionActions:{showSummary:b("action","show-option-summary"),manageFavourite:b("action","manage-module-favourite")},addChooser:b("action","add-chooser-option"),closeOption:b("action","close-chooser-option-summary"),hide:b("action","hide"),search:b("action","search"),clearSearch:b("action","clearsearch")},render:{favourites:b("render","favourites-area")},elements:{section:".section",sectionmodchooser:"button.section-modchooser-link",sitemenu:".block_site_main_menu",sitetopic:"div.sitetopic",tab:"a[data-toggle=\"tab\"]",activetab:"a[data-toggle=\"tab\"][aria-selected=\"true\"]",visibletabs:"a[data-toggle=\"tab\"]:not(.d-none)"}};a.default=c;return a.default});
|
||||
define ("core_course/local/activitychooser/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b=function(a,b){return"[data-".concat(a,"=\"").concat(b,"\"]")},c={regions:{chooser:b("region","chooser-container"),getSectionChooserOptions:function getSectionChooserOptions(a){return"".concat(a," ").concat(b("region","chooser-options-container"))},chooserOption:{container:b("region","chooser-option-container"),actions:b("region","chooser-option-actions-container"),info:b("region","chooser-option-info-container")},chooserSummary:{container:b("region","chooser-option-summary-container"),content:b("region","chooser-option-summary-content-container"),header:b("region","summary-header"),actions:b("region","chooser-option-summary-actions-container")},carousel:b("region","carousel"),help:b("region","help"),modules:b("region","modules"),favouriteTabNav:b("region","favourite-tab-nav"),defaultTabNav:b("region","default-tab-nav"),activityTabNav:b("region","activity-tab-nav"),favouriteTab:b("region","favourites"),recommendedTab:b("region","recommended"),defaultTab:b("region","default"),activityTab:b("region","activity"),resourceTab:b("region","resources"),getModuleSelector:function getModuleSelector(a){return"[role=\"menuitem\"][data-modname=\"".concat(a,"\"]")},searchResults:b("region","search-results-container"),searchResultItems:b("region","search-result-items-container")},actions:{optionActions:{showSummary:b("action","show-option-summary"),manageFavourite:b("action","manage-module-favourite")},addChooser:b("action","add-chooser-option"),closeOption:b("action","close-chooser-option-summary"),hide:b("action","hide"),search:b("action","search"),clearSearch:b("action","clearsearch")},render:{favourites:b("render","favourites-area")},elements:{section:".section",sectionmodchooser:"button.section-modchooser-link",sitemenu:".block_site_main_menu",sitetopic:"div.sitetopic",tab:"a[data-toggle=\"tab\"]",activetab:"a[data-toggle=\"tab\"][aria-selected=\"true\"]",visibletabs:"a[data-toggle=\"tab\"]:not(.d-none)"}};a.default=c;return a.default});
|
||||
//# sourceMappingURL=selectors.min.js.map
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -216,7 +216,6 @@ const registerListenerEvents = (modal, mappedModules, partialFavourite, footerDa
|
||||
const firstChooserOption = sectionChooserOptions.querySelector(selectors.regions.chooserOption.container);
|
||||
|
||||
toggleFocusableChooserOption(firstChooserOption, true);
|
||||
initTabsKeyboardNavigation(body);
|
||||
initChooserOptionsKeyboardNavigation(body, mappedModules, sectionChooserOptions, modal);
|
||||
|
||||
return body;
|
||||
@@ -235,77 +234,6 @@ const registerListenerEvents = (modal, mappedModules, partialFavourite, footerDa
|
||||
.catch();
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise the keyboard navigation controls for the tab list items.
|
||||
*
|
||||
* @method initTabsKeyboardNavigation
|
||||
* @param {HTMLElement} body Our modal that we are working with
|
||||
*/
|
||||
const initTabsKeyboardNavigation = (body) => {
|
||||
// Set up the tab handlers.
|
||||
const favTabNav = body.querySelector(selectors.regions.favouriteTabNav);
|
||||
const recommendedTabNav = body.querySelector(selectors.regions.recommendedTabNav);
|
||||
const defaultTabNav = body.querySelector(selectors.regions.defaultTabNav);
|
||||
const activityTabNav = body.querySelector(selectors.regions.activityTabNav);
|
||||
const resourceTabNav = body.querySelector(selectors.regions.resourceTabNav);
|
||||
const tabNavArray = [favTabNav, recommendedTabNav, defaultTabNav, activityTabNav, resourceTabNav];
|
||||
tabNavArray.forEach((element) => {
|
||||
return element.addEventListener('keydown', (e) => {
|
||||
// The first visible navigation tab link.
|
||||
const firstLink = e.target.parentElement.querySelector(selectors.elements.visibletabs);
|
||||
// The last navigation tab link. It would always be the default activities tab link.
|
||||
const lastLink = e.target.parentElement.lastElementChild;
|
||||
|
||||
if (e.keyCode === arrowRight) {
|
||||
const nextLink = e.target.nextElementSibling;
|
||||
if (nextLink === null) {
|
||||
e.target.tabIndex = -1;
|
||||
firstLink.tabIndex = 0;
|
||||
firstLink.focus();
|
||||
} else if (nextLink.classList.contains('d-none')) {
|
||||
e.target.tabIndex = -1;
|
||||
lastLink.tabIndex = 0;
|
||||
lastLink.focus();
|
||||
} else {
|
||||
e.target.tabIndex = -1;
|
||||
nextLink.tabIndex = 0;
|
||||
nextLink.focus();
|
||||
}
|
||||
}
|
||||
if (e.keyCode === arrowLeft) {
|
||||
const previousLink = e.target.previousElementSibling;
|
||||
if (previousLink === null) {
|
||||
e.target.tabIndex = -1;
|
||||
lastLink.tabIndex = 0;
|
||||
lastLink.focus();
|
||||
} else if (previousLink.classList.contains('d-none')) {
|
||||
e.target.tabIndex = -1;
|
||||
firstLink.tabIndex = 0;
|
||||
firstLink.focus();
|
||||
} else {
|
||||
e.target.tabIndex = -1;
|
||||
previousLink.tabIndex = 0;
|
||||
previousLink.focus();
|
||||
}
|
||||
}
|
||||
if (e.keyCode === home) {
|
||||
e.target.tabIndex = -1;
|
||||
firstLink.tabIndex = 0;
|
||||
firstLink.focus();
|
||||
}
|
||||
if (e.keyCode === end) {
|
||||
e.target.tabIndex = -1;
|
||||
lastLink.tabIndex = 0;
|
||||
lastLink.focus();
|
||||
}
|
||||
if (e.keyCode === space) {
|
||||
e.preventDefault();
|
||||
e.target.click();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise the keyboard navigation controls for the chooser options.
|
||||
*
|
||||
|
||||
@@ -52,10 +52,8 @@ export default {
|
||||
help: getDataSelector('region', 'help'),
|
||||
modules: getDataSelector('region', 'modules'),
|
||||
favouriteTabNav: getDataSelector('region', 'favourite-tab-nav'),
|
||||
recommendedTabNav: getDataSelector('region', 'recommended-tab-nav'),
|
||||
defaultTabNav: getDataSelector('region', 'default-tab-nav'),
|
||||
activityTabNav: getDataSelector('region', 'activity-tab-nav'),
|
||||
resourceTabNav: getDataSelector('region', 'resources-tab-nav'),
|
||||
favouriteTab: getDataSelector('region', 'favourites'),
|
||||
recommendedTab: getDataSelector('region', 'recommended'),
|
||||
defaultTab: getDataSelector('region', 'default'),
|
||||
|
||||
@@ -102,8 +102,13 @@ class course_handler extends \core_customfield\handler {
|
||||
has_capability('moodle/course:changelockedcustomfields', $context));
|
||||
} else {
|
||||
$context = $this->get_parent_context();
|
||||
return (!$field->get_configdata_property('locked') ||
|
||||
guess_if_creator_will_have_course_capability('moodle/course:changelockedcustomfields', $context));
|
||||
if ($context->contextlevel == CONTEXT_SYSTEM) {
|
||||
return (!$field->get_configdata_property('locked') ||
|
||||
has_capability('moodle/course:changelockedcustomfields', $context));
|
||||
} else {
|
||||
return (!$field->get_configdata_property('locked') ||
|
||||
guess_if_creator_will_have_course_capability('moodle/course:changelockedcustomfields', $context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,5 +48,8 @@ function xmldb_format_topics_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -53,9 +53,7 @@ Feature: Sections can be edited and deleted in topics format
|
||||
|
||||
@javascript
|
||||
Scenario: Inline edit section name in topics format
|
||||
When I click on "Edit topic name" "link" in the "li#section-1" "css_element"
|
||||
And I set the field "New name for topic Topic 1" to "Midterm evaluation"
|
||||
And I press key "13" in the field "New name for topic Topic 1"
|
||||
When I set the field "Edit topic name" in the "li#section-1" "css_element" to "Midterm evaluation"
|
||||
Then I should not see "Topic 1" in the "region-main" "region"
|
||||
And "New name for topic" "field" should not exist
|
||||
And I should see "Midterm evaluation" in the "li#section-1" "css_element"
|
||||
|
||||
@@ -48,5 +48,8 @@ function xmldb_format_weeks_upgrade($oldversion) {
|
||||
// Automatically generated Moodle v3.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
// Automatically generated Moodle v3.10.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -54,9 +54,7 @@ Feature: Sections can be edited and deleted in weeks format
|
||||
|
||||
@javascript
|
||||
Scenario: Inline edit section name in weeks format
|
||||
When I click on "Edit week name" "link" in the "li#section-1" "css_element"
|
||||
And I set the field "New name for week 1 May - 7 May" to "Midterm evaluation"
|
||||
And I press key "13" in the field "New name for week 1 May - 7 May"
|
||||
When I set the field "Edit week name" in the "li#section-1" "css_element" to "Midterm evaluation"
|
||||
Then I should not see "1 May - 7 May" in the "region-main" "region"
|
||||
And "New name for week" "field" should not exist
|
||||
And I should see "Midterm evaluation" in the "li#section-1" "css_element"
|
||||
|
||||
+11
-11
@@ -4743,26 +4743,26 @@ function course_get_recent_courses(int $userid = null, int $limit = 0, int $offs
|
||||
JOIN {user_lastaccess} ul
|
||||
ON ul.courseid = c.id
|
||||
$favsql
|
||||
LEFT JOIN {enrol} eg ON eg.courseid = c.id AND eg.status = :statusenrolg AND eg.enrol = :guestenrol
|
||||
WHERE ul.userid = :userid
|
||||
AND c.visible = :visible
|
||||
AND EXISTS (SELECT e.id
|
||||
AND (eg.id IS NOT NULL
|
||||
OR EXISTS (SELECT e.id
|
||||
FROM {enrol} e
|
||||
LEFT JOIN {user_enrolments} ue ON ue.enrolid = e.id
|
||||
JOIN {user_enrolments} ue ON ue.enrolid = e.id
|
||||
WHERE e.courseid = c.id
|
||||
AND e.status = :statusenrol
|
||||
AND ((ue.status = :status
|
||||
AND ue.userid = ul.userid
|
||||
AND ue.timestart < :now1
|
||||
AND (ue.timeend = 0 OR ue.timeend > :now2)
|
||||
)
|
||||
OR e.enrol = :guestenrol
|
||||
)
|
||||
)
|
||||
AND ue.status = :status
|
||||
AND ue.userid = :userid2
|
||||
AND ue.timestart < :now1
|
||||
AND (ue.timeend = 0 OR ue.timeend > :now2)
|
||||
))
|
||||
$orderby";
|
||||
|
||||
$now = round(time(), -2); // Improves db caching.
|
||||
$params = ['userid' => $userid, 'contextlevel' => CONTEXT_COURSE, 'visible' => 1, 'status' => ENROL_USER_ACTIVE,
|
||||
'statusenrol' => ENROL_INSTANCE_ENABLED, 'guestenrol' => 'guest', 'now1' => $now, 'now2' => $now] + $favparams;
|
||||
'statusenrol' => ENROL_INSTANCE_ENABLED, 'guestenrol' => 'guest', 'now1' => $now, 'now2' => $now,
|
||||
'userid2' => $userid, 'statusenrolg' => ENROL_INSTANCE_ENABLED] + $favparams;
|
||||
|
||||
$recentcourses = $DB->get_records_sql($sql, $params, $offset, $limit);
|
||||
|
||||
|
||||
@@ -60,6 +60,15 @@ if (!empty($add)) {
|
||||
// will be the closest match we have.
|
||||
navigation_node::override_active_url(course_get_url($course, $section));
|
||||
|
||||
// MDL-69431 Validate that $section (url param) does not exceed the maximum for this course / format.
|
||||
// If too high (e.g. section *id* not number) non-sequential sections inserted in course_sections table.
|
||||
// Then on import, backup fills 'gap' with empty sections (see restore_rebuild_course_cache). Avoid this.
|
||||
$courseformat = course_get_format($course);
|
||||
$maxsections = $courseformat->get_max_sections();
|
||||
if ($section > $maxsections) {
|
||||
print_error('maxsectionslimit', 'moodle', '', $maxsections);
|
||||
}
|
||||
|
||||
list($module, $context, $cw, $cm, $data) = prepare_new_moduleinfo_data($course, $add, $section);
|
||||
$data->return = 0;
|
||||
$data->sr = $sectionreturn;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user