Compare commits
241 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| becbdd847d | |||
| 6ac3dd457c | |||
| cd97da9c5c | |||
| 759b2670a0 | |||
| 3f90e29e39 | |||
| 257a8126ad | |||
| d32320beac | |||
| 1352a23354 | |||
| 46a8a3bb75 | |||
| 79d1331384 | |||
| cd72578917 | |||
| 72e9f115ab | |||
| 01011e49dd | |||
| fcf7d12a4b | |||
| f44d6ba340 | |||
| 15632be78d | |||
| 53a0fbecd2 | |||
| 832261f49b | |||
| 2378fc0117 | |||
| cd754d3b44 | |||
| 8307ce8f18 | |||
| 4225940caa | |||
| 2ce1ed7247 | |||
| f21c892997 | |||
| 0b8ab4fcef | |||
| 8ec49b09e5 | |||
| fd9ab3efbd | |||
| acdca038df | |||
| dd6f0debcc | |||
| 8f93e88387 | |||
| 17fccfcf64 | |||
| 0cdb9169cb | |||
| a110b34a5a | |||
| 252d0faac1 | |||
| 1802410629 | |||
| 89cba33e91 | |||
| b86162544d | |||
| 2135ff7c19 | |||
| d0e63f5a60 | |||
| ec65857de0 | |||
| d34d35d2b6 | |||
| 0742fb7b44 | |||
| 0e7caf93b5 | |||
| e876654d1f | |||
| a11e590324 | |||
| 5ff8f06f64 | |||
| 8a1c8f8bb3 | |||
| 671849b2db | |||
| 8341244903 | |||
| 02d251294c | |||
| b490d511d6 | |||
| 2d08d7d2c0 | |||
| 016d123034 | |||
| 2e4c5f9c12 | |||
| e7b463af6d | |||
| 314c9671fc | |||
| b8c4c975e0 | |||
| f3952dc29f | |||
| 71841556aa | |||
| 575fabe57a | |||
| 5cf3b78855 | |||
| a84b1f1307 | |||
| c435b7896f | |||
| e740fa9c3b | |||
| 243eb04a85 | |||
| 88c757cef0 | |||
| 8f06e62409 | |||
| 0eda72ec4f | |||
| 68ff5f0ce0 | |||
| deb5150786 | |||
| 15521655a3 | |||
| 3a2703c9f5 | |||
| f48d31f0d4 | |||
| 38da2c3a61 | |||
| 583b655e37 | |||
| 28f06c0f27 | |||
| 4e1e916ca6 | |||
| 0c2426d207 | |||
| 3f17ea00e7 | |||
| 565fe67086 | |||
| 97f67db36d | |||
| e2b085c81b | |||
| 91bb1805d9 | |||
| 4d36e008dd | |||
| e57d9506af | |||
| 779cd5b40c | |||
| 98fd15d75b | |||
| 552ec1b547 | |||
| 977cbaf239 | |||
| a68be3c7fa | |||
| a123645de3 | |||
| 29191eeff2 | |||
| b9701a8bb8 | |||
| 1fe901e1ab | |||
| 24bc7e9a19 | |||
| c352ec94a8 | |||
| 91c7b05b05 | |||
| a9e12e1d84 | |||
| 33eaae5569 | |||
| aaedf21a31 | |||
| 658c7e9ef5 | |||
| 7ef51203c6 | |||
| 6591971e8a | |||
| 58bc68b0bc | |||
| 93c53ea726 | |||
| 73eec5d12d | |||
| ee36b4146f | |||
| 6180b175d4 | |||
| e083dae38e | |||
| 42be9c33eb | |||
| 8ba4d8be17 | |||
| 78910334ff | |||
| 6af53fa8c0 | |||
| d0b8656cb5 | |||
| 9c93fbe3a4 | |||
| a97f8d6720 | |||
| 7ceb1466e9 | |||
| 5d0b1f0ed3 | |||
| 180bf41216 | |||
| 509578453a | |||
| 8be7ac509a | |||
| fcfd012b6a | |||
| a778af133e | |||
| 1ff07992ec | |||
| 8cbcbc094c | |||
| a35c9aab6d | |||
| bef4181788 | |||
| abcbc42139 | |||
| f65577ef3a | |||
| fdc7349577 | |||
| 0ee24af3cd | |||
| 815419ad12 | |||
| b92f5e00aa | |||
| 54263aa1f6 | |||
| 100fad08fe | |||
| 14f87ce4b5 | |||
| b4b650f9cd | |||
| efc6d19ac2 | |||
| a887e577a4 | |||
| 5b9f243378 | |||
| 1900cadd4f | |||
| f55fd1b49c | |||
| 575358c0f0 | |||
| 83a1703746 | |||
| 5c74434dfa | |||
| 72e2a0dfb5 | |||
| 8c30413ba8 | |||
| ce2a901414 | |||
| 811fc31904 | |||
| 25efc9e7aa | |||
| c29ba27942 | |||
| 125065e488 | |||
| 613ba34b07 | |||
| 975ef5c540 | |||
| 1db7e78c8b | |||
| 37fa9f51e9 | |||
| 4eed9bd261 | |||
| ec6c3cd9a0 | |||
| 133b7b700d | |||
| c269c67830 | |||
| 8d09620c14 | |||
| 94327ba15f | |||
| 8e1353f39d | |||
| 342c6367d0 | |||
| fe6c455b51 | |||
| 777025b298 | |||
| 1545abb21d | |||
| d70b73345c | |||
| fbc97ebdcd | |||
| 95b4682d3c | |||
| 27f7c54d58 | |||
| 459da610c6 | |||
| 930a0d2944 | |||
| e881dee5b4 | |||
| f525194ea2 | |||
| d18f60bd3f | |||
| 01643574c5 | |||
| 0268bbd07b | |||
| 4f5d221749 | |||
| 8ca4a0087d | |||
| 357ab40ff4 | |||
| a0518068fb | |||
| 5ef68db33a | |||
| 2914d47171 | |||
| e79b14e2a9 | |||
| b97ed6d75a | |||
| f4d830d7e4 | |||
| 2974880afe | |||
| 4ed21af7df | |||
| e1d80935a3 | |||
| f40424cd25 | |||
| 47f85d5da1 | |||
| ac0444bff4 | |||
| bb7955546c | |||
| 0fd522dd1f | |||
| a09f258f70 | |||
| b193122b29 | |||
| 10d39a1feb | |||
| d51a14792b | |||
| 074307ebba | |||
| aeacebf383 | |||
| 51c22d1e3f | |||
| e5bf98ab9d | |||
| 1b1758caa2 | |||
| a71341c693 | |||
| b21541294a | |||
| 806a667b3a | |||
| 7311810970 | |||
| c8773b698a | |||
| e446e2b6a9 | |||
| 6a6344e268 | |||
| bcdee74ae9 | |||
| dacd86c23c | |||
| bb6c03a252 | |||
| b37a074180 | |||
| 64e570d0ab | |||
| 0a4af5f771 | |||
| d288aea421 | |||
| a9edf3962a | |||
| 6087c2a835 | |||
| 6fd68977ac | |||
| 94f6eefb86 | |||
| d03da85cef | |||
| 3e789e5d6d | |||
| b16eb4c432 | |||
| f533978709 | |||
| 53846820df | |||
| 65c8839157 | |||
| 0561f8c5b5 | |||
| 8684cd6a76 | |||
| fa10357f57 | |||
| d463e0d8f6 | |||
| 9f7d92de62 | |||
| e237e83dfb | |||
| 3498aeaf1e | |||
| e5e8bc4b22 | |||
| 911fafd9a9 | |||
| 739b551fa8 | |||
| f8351de05e | |||
| 2571dcf012 | |||
| 23f0472514 |
@@ -13,14 +13,14 @@ env:
|
||||
|
||||
jobs:
|
||||
Grunt:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checking out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Configuring node & npm
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
@@ -54,11 +54,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
php: 7.3
|
||||
extensions:
|
||||
db: mysqli
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
php: 8.0
|
||||
db: pgsql
|
||||
extensions: xmlrpc-beta
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
postgresql password: test
|
||||
|
||||
- name: Configuring git vars
|
||||
uses: rlespinasse/github-slug-action@v3.x
|
||||
uses: rlespinasse/github-slug-action@v4
|
||||
|
||||
- name: Setting up PHP ${{ matrix.php }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
coverage: none
|
||||
|
||||
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setting up PHPUnit
|
||||
env:
|
||||
|
||||
@@ -52,3 +52,4 @@ moodle-plugin-ci.phar
|
||||
.stylelintignore
|
||||
/jsdoc
|
||||
.phpcs.xml
|
||||
jsconfig.json
|
||||
|
||||
@@ -233,6 +233,7 @@ const getOwningComponentDirectory = checkPath => {
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
fetchComponentData,
|
||||
getAmdSrcGlobList,
|
||||
getComponentFromPath,
|
||||
getComponentPaths,
|
||||
|
||||
@@ -47,6 +47,9 @@ module.exports = grunt => {
|
||||
// Load ESLint.
|
||||
require('./eslint')(grunt);
|
||||
|
||||
// Load jsconfig.
|
||||
require('./jsconfig')(grunt);
|
||||
|
||||
// Load JSDoc.
|
||||
require('./jsdoc')(grunt);
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* jshint node: true, browser: false */
|
||||
/* eslint-env node */
|
||||
|
||||
/**
|
||||
* @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
const configuration = {
|
||||
compilerOptions: {
|
||||
baseUrl: ".",
|
||||
paths: {
|
||||
},
|
||||
target: "es2015",
|
||||
allowSyntheticDefaultImports: false,
|
||||
},
|
||||
exclude: [
|
||||
"node_modules",
|
||||
],
|
||||
include: [],
|
||||
};
|
||||
|
||||
module.exports = (grunt) => {
|
||||
const handler = () => {
|
||||
const jsconfigData = Object.assign({}, configuration);
|
||||
|
||||
const path = require('path');
|
||||
const {fetchComponentData} = require(path.join(process.cwd(), '.grunt', 'components.js'));
|
||||
|
||||
const componentData = fetchComponentData().components;
|
||||
for (const [thisPath, component] of Object.entries(componentData)) {
|
||||
jsconfigData.compilerOptions.paths[`${component}/*`] = [`${thisPath}/amd/src/*`];
|
||||
jsconfigData.include.push(`${thisPath}/amd/src/**/*`);
|
||||
}
|
||||
|
||||
grunt.file.write('jsconfig.json', JSON.stringify(jsconfigData, null, " ") + "\n");
|
||||
};
|
||||
grunt.registerTask('jsconfig', 'Generate a jsconfig configuration compatible with the LSP', handler);
|
||||
};
|
||||
@@ -3781,11 +3781,6 @@
|
||||
<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" />
|
||||
|
||||
@@ -59,9 +59,8 @@ class mnet_simple_host_form extends moodleform {
|
||||
$wwwroot = 'http://'.$wwwroot;
|
||||
}
|
||||
if ($host = $DB->get_record('mnet_host', array('wwwroot' => $wwwroot))) {
|
||||
global $CFG;
|
||||
return array('wwwroot' => get_string('hostexists', 'mnet',
|
||||
new moodle_url('/admin/mnet/peers.php', array('hostid' => $host->id))));
|
||||
$str = get_string('hostexists', 'mnet', (new moodle_url('/admin/mnet/peers.php', ['hostid' => $host->id]))->out());
|
||||
return array('wwwroot' => $str);
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ Useful for uploading custom langstrings to AMOS or importing or syncing them to
|
||||
Options:
|
||||
-l, --lang Comma seperated language ids to export, default: all
|
||||
-c, --components Comma seperated components to export, default: all
|
||||
-t, --target Target to copy the zip files to, default: $CFG->tempdir/customlang
|
||||
-t, --target Target directory to copy the zip files to, default: $CFG->tempdir/customlang
|
||||
-o, --overwrite Overwrite existing files in the target folder.
|
||||
Note: If the target is not set, the files are always overwritten!
|
||||
-h, --help Print out this help
|
||||
@@ -73,9 +73,10 @@ if ($options['help']) {
|
||||
echo $usage;
|
||||
die;
|
||||
}
|
||||
if (!file_exists($options['target'])) {
|
||||
mkdir($options['target'], 0777, true);
|
||||
}
|
||||
|
||||
// Ensure target directory exists.
|
||||
$options['target'] = rtrim($options['target'], '/') . '/';
|
||||
check_dir_exists($options['target']);
|
||||
|
||||
cli_writeln(get_string('cliexportheading', 'tool_customlang'));
|
||||
$langs = [];
|
||||
@@ -90,7 +91,7 @@ foreach ($langs as $lang) {
|
||||
$filename = $options['target'] . get_string('exportzipfilename', 'tool_customlang', ['lang' => $lang]);
|
||||
// If the file exists and we are not using the temp folder it requires an ovewrite.
|
||||
if ($options['target'] != $dafaulttarget && file_exists($filename) && !$options['overwrite']) {
|
||||
cli_problem(get_string('cliexportfileexists', 'tool_customlang', $lang));
|
||||
cli_problem(get_string('cliexportfileexists', 'tool_customlang', ['lang' => $lang]));
|
||||
continue;
|
||||
}
|
||||
cli_heading(get_string('cliexportstartexport', 'tool_customlang', $lang));
|
||||
|
||||
@@ -160,6 +160,16 @@ foreach ($langfiles as $lng => $files) {
|
||||
|
||||
cli_heading(get_string('clifiles', 'tool_customlang', $lng));
|
||||
|
||||
// If we intend to check in any changes, we must first check them out.
|
||||
if ($checkin) {
|
||||
cli_writeln(get_string('checkout', 'tool_customlang'));
|
||||
|
||||
$progressbar = new progress_bar();
|
||||
$progressbar->create();
|
||||
|
||||
tool_customlang_utils::checkout($lng, $progressbar);
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
// Generate a valid stored_file from this file.
|
||||
$record = (object)[
|
||||
|
||||
@@ -50,6 +50,7 @@ $string['customlang:export'] = 'Export local translation';
|
||||
$string['customlang:view'] = 'View local translation';
|
||||
$string['export'] = 'Export custom strings';
|
||||
$string['exportfilter'] = 'Select component(s) to export';
|
||||
$string['exportzipfilename'] = 'customlang-export-{$a->lang}.zip';
|
||||
$string['filter'] = 'Filter strings';
|
||||
$string['filtercomponent'] = 'Show strings of these components';
|
||||
$string['filtercustomized'] = 'Customised only';
|
||||
|
||||
@@ -89,7 +89,9 @@ class tool_customlang_utils {
|
||||
* @param progress_bar $progressbar optionally, the given progress bar can be updated
|
||||
*/
|
||||
public static function checkout($lang, progress_bar $progressbar = null) {
|
||||
global $DB;
|
||||
global $DB, $CFG;
|
||||
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
|
||||
// For behat executions we are going to load only a few components in the
|
||||
// language customisation structures. Using the whole "en" langpack is
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_httpsreplace\tests;
|
||||
|
||||
namespace tool_httpsreplace;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
@@ -124,6 +124,12 @@ class controller {
|
||||
}
|
||||
|
||||
if ($rm1 or $rm2) {
|
||||
// Set the default site language to en if the deleted language pack is the default site language.
|
||||
if ($CFG->lang === $lang) {
|
||||
set_config('lang', 'en');
|
||||
// Fix the user's current language to the default site language.
|
||||
fix_current_language($CFG->lang);
|
||||
}
|
||||
$this->info[] = get_string('langpackremoved', 'tool_langimport', $lang);
|
||||
event\langpack_removed::event_with_langcode($lang)->trigger();
|
||||
return true;
|
||||
|
||||
@@ -77,9 +77,10 @@
|
||||
ucw.registerEvents('[data-region="user-competency-status"]');
|
||||
ucw.on('status-changed', infoReloader.reload.bind(infoReloader));
|
||||
ucw.on('error-occured', infoReloader.reload.bind(infoReloader));
|
||||
|
||||
var inlineGrader = new mod('#rate_{{uniqid}}', '{{competency.scaleid}}', '{{competency.competency.id}}', '{{user.id}}', '{{plan.id}}', '', '{{#str}}chooserating, tool_lp{{/str}}');
|
||||
inlineGrader.on('competencyupdated', infoReloader.reload.bind(infoReloader));
|
||||
{{#cangrade}}
|
||||
var inlineGrader = new mod('#rate_{{uniqid}}', '{{competency.scaleid}}', '{{competency.competency.id}}', '{{user.id}}', '{{plan.id}}', '', '{{#str}}chooserating, tool_lp{{/str}}');
|
||||
inlineGrader.on('competencyupdated', infoReloader.reload.bind(infoReloader));
|
||||
{{/cangrade}}
|
||||
});
|
||||
{{/js}}
|
||||
{{/usercompetency}}
|
||||
|
||||
@@ -95,13 +95,14 @@
|
||||
{{#js}}
|
||||
require(['jquery', 'tool_lp/grade_user_competency_inline', 'tool_lp/user_competency_info'], function($, mod, info) {
|
||||
|
||||
var inlineGrader = new mod('#rate_{{uniqid}}', '{{competency.scaleid}}', '{{competency.competency.id}}', '{{user.id}}', '', '{{course.id}}', '{{#str}}chooserating, tool_lp{{/str}}');
|
||||
var competencyElement = $('[data-region-id="{{uniqid}}"]');
|
||||
|
||||
var displayuser = ('{{displayuser}}' == 'true') ? true : false;
|
||||
var infoReloader = new info(competencyElement, '{{competency.competency.id}}', '{{user.id}}', '', '{{course.id}}', displayuser);
|
||||
|
||||
inlineGrader.on('competencyupdated', infoReloader.reload.bind(infoReloader));
|
||||
{{#cangrade}}
|
||||
var inlineGrader = new mod('#rate_{{uniqid}}', '{{competency.scaleid}}', '{{competency.competency.id}}', '{{user.id}}', '', '{{course.id}}', '{{#str}}chooserating, tool_lp{{/str}}');
|
||||
inlineGrader.on('competencyupdated', infoReloader.reload.bind(infoReloader));
|
||||
{{/cangrade}}
|
||||
});
|
||||
|
||||
{{/js}}
|
||||
|
||||
+6
-11
@@ -14,24 +14,19 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the import_handler_info class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
use tool_moodlenet\local\import_handler_info;
|
||||
use tool_moodlenet\local\import_strategy;
|
||||
use tool_moodlenet\local\import_strategy_file;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_import_handler_info_testcase, providing test cases for the import_handler_info class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_handler_info_test extends \advanced_testcase {
|
||||
|
||||
+6
-11
@@ -14,15 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the import_handler_registry class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
use tool_moodlenet\local\import_handler_registry;
|
||||
use tool_moodlenet\local\import_handler_info;
|
||||
@@ -31,10 +23,13 @@ use tool_moodlenet\local\import_strategy_link;
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_import_handler_registry_testcase, providing test cases for the import_handler_registry class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_handler_registry_test extends \advanced_testcase {
|
||||
|
||||
+6
-11
@@ -14,24 +14,19 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the import_info class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
use tool_moodlenet\local\import_info;
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_import_info_testcase, providing test cases for the import_info class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_info_test extends \advanced_testcase {
|
||||
|
||||
+6
-11
@@ -14,15 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for the import_processor class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
use tool_moodlenet\local\import_handler_registry;
|
||||
use tool_moodlenet\local\import_processor;
|
||||
@@ -31,10 +23,13 @@ use tool_moodlenet\local\import_strategy_link;
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_import_processor_testcase, providing test cases for the import_processor class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class import_processor_test extends \advanced_testcase {
|
||||
|
||||
+6
-11
@@ -14,24 +14,19 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
/**
|
||||
* Unit tests for the remote_resource class.
|
||||
* Class tool_moodlenet_remote_resource_testcase, providing test cases for the remote_resource class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
|
||||
use tool_moodlenet\local\remote_resource;
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_remote_resource_testcase, providing test cases for the remote_resource class.
|
||||
*/
|
||||
class remote_resource_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
+5
-10
@@ -14,23 +14,18 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace tool_moodlenet\local;
|
||||
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
/**
|
||||
* Unit tests for the url class.
|
||||
* Class tool_moodlenet_url_testcase, providing test cases for the url class.
|
||||
*
|
||||
* @package tool_moodlenet
|
||||
* @category test
|
||||
* @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace tool_moodlenet\local\tests;
|
||||
|
||||
use tool_moodlenet\local\url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class tool_moodlenet_url_testcase, providing test cases for the url class.
|
||||
*/
|
||||
class url_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
@@ -134,7 +134,6 @@ Feature: Basic OAuth2 functionality
|
||||
And I set the following fields to these values:
|
||||
| Name | Testing service modified |
|
||||
And I press "Save changes"
|
||||
And I should see "Could not discover service endpoints"
|
||||
And I should see "Testing service modified"
|
||||
And I click on "Delete" "link" in the "Testing service modified" "table_row"
|
||||
And I should see "Are you sure you want to delete the identity issuer \"Testing service modified\"?"
|
||||
@@ -239,13 +238,12 @@ Feature: Basic OAuth2 functionality
|
||||
And I press "Save changes"
|
||||
And "Do not allow login" "icon" should exist in the "Valid custom" "table_row"
|
||||
And "Allow services" "icon" should exist in the "Valid custom" "table_row"
|
||||
And "Service discovery successful" "icon" should exist in the "Valid custom" "table_row"
|
||||
And I should see "-" in the "Valid custom" "table_row"
|
||||
And I click on "Edit" "link" in the "Valid custom service" "table_row"
|
||||
And I set the following fields to these values:
|
||||
| Name | Invalid custom service |
|
||||
| Service base URL | https://dc.imsglobal.org/ |
|
||||
And I press "Save changes"
|
||||
Then I should see "Could not discover end points for identity issuer: Invalid custom service"
|
||||
And I should see "-" in the "Invalid custom service" "table_row"
|
||||
And I click on "Delete" "link" in the "Invalid custom service" "table_row"
|
||||
And I should see "Are you sure you want to delete the identity issuer \"Invalid custom service\"?"
|
||||
@@ -281,13 +279,12 @@ Feature: Basic OAuth2 functionality
|
||||
And I press "Save changes"
|
||||
And "Do not allow login" "icon" should exist in the "Valid custom" "table_row"
|
||||
And "Allow services" "icon" should exist in the "Valid custom" "table_row"
|
||||
And "Service discovery successful" "icon" should exist in the "Valid custom" "table_row"
|
||||
And I should see "-" in the "Valid custom" "table_row"
|
||||
And I click on "Edit" "link" in the "Valid custom service" "table_row"
|
||||
And I set the following fields to these values:
|
||||
| Name | Invalid custom service |
|
||||
| Service base URL | https://dc.imsglobal.org/ |
|
||||
And I press "Save changes"
|
||||
Then I should see "Could not discover end points for identity issuer: Invalid custom service"
|
||||
And I should see "-" in the "Invalid custom service" "table_row"
|
||||
And I click on "Edit" "link" in the "Invalid custom service" "table_row"
|
||||
And I set the following fields to these values:
|
||||
@@ -351,9 +348,12 @@ Feature: Basic OAuth2 functionality
|
||||
And I should see "Custom display name" in the "Empty custom service" "table_row"
|
||||
And "Not configured" "icon" should exist in the "Empty custom service" "table_row"
|
||||
And "Do not allow services" "icon" should exist in the "Empty custom service" "table_row"
|
||||
And I click on "Edit" "link" in the "Empty custom service" "table_row"
|
||||
And I click on "Configure endpoints" "link" in the "Empty custom service" "table_row"
|
||||
And I press "Create new endpoint for issuer \"Empty custom service\""
|
||||
And I set the following fields to these values:
|
||||
| Service base URL | https://accounts.google.com |
|
||||
| Name | userinfo_endpoint |
|
||||
| URL | https://example.com/userinfo |
|
||||
And I press "Save changes"
|
||||
And I navigate to "Server > OAuth 2 services" in site administration
|
||||
And "Allow login" "icon" should exist in the "Empty custom service" "table_row"
|
||||
And "Do not allow services" "icon" should exist in the "Empty custom service" "table_row"
|
||||
|
||||
@@ -49,7 +49,7 @@ class frontend extends \core_availability\frontend {
|
||||
|
||||
protected function get_javascript_strings() {
|
||||
return array('ajaxerror', 'direction_before', 'direction_from', 'direction_until',
|
||||
'direction_label');
|
||||
'direction_label', 'error_dateconflict');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@ $string['direction_from'] = 'from';
|
||||
$string['direction_label'] = 'Direction';
|
||||
$string['direction_until'] = 'until';
|
||||
$string['description'] = 'Prevent access until (or from) a specified date and time.';
|
||||
$string['error_dateconflict'] = 'Conflicts with other date restrictions';
|
||||
$string['full_from'] = 'It is after <strong>{$a}</strong>';
|
||||
$string['full_from_date'] = 'It is on or after <strong>{$a}</strong>';
|
||||
$string['full_until'] = 'It is before <strong>{$a}</strong>';
|
||||
|
||||
+79
@@ -142,5 +142,84 @@ M.availability_date.form.fillValue = function(value, node) {
|
||||
value.t = parseInt(node.getData('time'), 10);
|
||||
};
|
||||
|
||||
/**
|
||||
* List out Date node value in an array node.
|
||||
*
|
||||
* This will go through all array node and list from earlier date node to current date node.
|
||||
*
|
||||
* @method convertTreeDateValue
|
||||
* @param {array} tree Tree node to convert
|
||||
* @param {array} arrayDateNode
|
||||
* @param {array} currentNode current node.
|
||||
*
|
||||
* @return {array} arrayDateNode
|
||||
*/
|
||||
M.availability_date.form.convertTreeDateValue = function(tree, arrayDateNode, currentNode) {
|
||||
var shouldSkip = false;
|
||||
tree.forEach(function(node) {
|
||||
if (shouldSkip) {
|
||||
return;
|
||||
}
|
||||
if (node.type === 'date') {
|
||||
// We go through all tree node, if we meet the current node then return.
|
||||
if (node.t === parseInt(currentNode.getData('time'), 10)
|
||||
&& currentNode.one('select[name=direction]').get('value') == node.d) {
|
||||
shouldSkip = true;
|
||||
return;
|
||||
}
|
||||
arrayDateNode.push(node);
|
||||
} else if (node.type === undefined) {
|
||||
M.availability_date.form.convertTreeDateValue(node.c, arrayDateNode, currentNode);
|
||||
}
|
||||
});
|
||||
return arrayDateNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check current node.
|
||||
*
|
||||
* This will check current date node with all date node in tree node.
|
||||
*
|
||||
* @method checkConditionDate
|
||||
* @param {array} currentNode The curent node.
|
||||
*
|
||||
* @return {boolean} error Return true if the date is conflict.
|
||||
*/
|
||||
M.availability_date.form.checkConditionDate = function(currentNode) {
|
||||
var error = false;
|
||||
if (M.core_availability.form.rootList.getValue().op === '&') {
|
||||
var jsValue = M.core_availability.form.rootList.getValue().c;
|
||||
var arrayDateNode = M.availability_date.form.convertTreeDateValue(jsValue, [], currentNode);
|
||||
var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
|
||||
var currentNodeTime = parseInt(currentNode.getData('time'), 10);
|
||||
arrayDateNode.forEach(function(checkNode) {
|
||||
// Validate if the date is conflict.
|
||||
if (checkNode.d === '<') {
|
||||
if (currentNodeDirection === '>=' && currentNodeTime >= checkNode.t) {
|
||||
error = true;
|
||||
}
|
||||
} else {
|
||||
if (currentNodeDirection === '<' && currentNodeTime <= checkNode.t) {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
});
|
||||
return error;
|
||||
} else {
|
||||
if (currentNode.one('div > .badge-warning')) {
|
||||
currentNode.one('div > .badge-warning').remove();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
M.availability_date.form.fillErrors = function(errors, node) {
|
||||
var error = M.availability_date.form.checkConditionDate(node);
|
||||
if (error) {
|
||||
errors.push('availability_date:error_dateconflict');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}, '@VERSION@', {"requires": ["base", "node", "event", "io", "moodle-core_availability-form"]});
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
YUI.add("moodle-availability_date-form",function(o,e){M.availability_date=M.availability_date||{},M.availability_date.form=o.Object(M.core_availability.plugin),M.availability_date.form.initInner=function(e,a){this.html=e,this.defaultTime=a},M.availability_date.form.getNode=function(e){var t,i,a='<span class="col-form-label pr-3">'+M.util.get_string("direction_before","availability_date")+'</span> <span class="availability-group"><label><span class="accesshide">'+M.util.get_string("direction_label","availability_date")+' </span><select name="direction" class="custom-select"><option value=">=">'+M.util.get_string("direction_from","availability_date")+'</option><option value="<">'+M.util.get_string("direction_until","availability_date")+"</option></select></label></span> "+this.html,n=o.Node.create("<span>"+a+"</span>");return e.t!==undefined?(n.setData("time",e.t),n.all("select:not([name=direction])").each(function(e){e.set("disabled",!0)}),a=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=fromtime&time="+e.t,o.io(a,{on:{success:function(e,a){var t,i,l=o.JSON.parse(a.responseText);for(t in l)(i=n.one("select[name=x\\["+t+"\\]]")).set("value",""+l[t]),i.set("disabled",!1)},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})):n.setData("time",this.defaultTime),e.d!==undefined&&n.one("select[name=direction]").set("value",e.d),M.availability_date.form.addedEvents||(M.availability_date.form.addedEvents=!0,(a=o.one(".availability-field")).delegate("change",function(){M.core_availability.form.update()},".availability_date select[name=direction]"),a.delegate("change",function(){M.availability_date.form.updateTime(this.ancestor("span.availability_date"))},".availability_date select:not([name=direction])")),n.one("a[href=#]")&&(M.form.dateselector.init_single_date_selector(n),t=n.one("select[name=x\\[year\\]]"),i=t.set,t.set=function(e,a){i.call(t,e,a),"selectedIndex"===e&&setTimeout(function(){M.availability_date.form.updateTime(n)},0)}),n},M.availability_date.form.updateTime=function(t){var e=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=totime&year="+t.one("select[name=x\\[year\\]]").get("value")+"&month="+t.one("select[name=x\\[month\\]]").get("value")+"&day="+t.one("select[name=x\\[day\\]]").get("value")+"&hour="+t.one("select[name=x\\[hour\\]]").get("value")+"&minute="+t.one("select[name=x\\[minute\\]]").get("value");o.io(e,{on:{success:function(e,a){t.setData("time",a.responseText),M.core_availability.form.update()},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})},M.availability_date.form.fillValue=function(e,a){e.d=a.one("select[name=direction]").get("value"),e.t=parseInt(a.getData("time"),10)}},"@VERSION@",{requires:["base","node","event","io","moodle-core_availability-form"]});
|
||||
YUI.add("moodle-availability_date-form",function(o,e){M.availability_date=M.availability_date||{},M.availability_date.form=o.Object(M.core_availability.plugin),M.availability_date.form.initInner=function(e,a){this.html=e,this.defaultTime=a},M.availability_date.form.getNode=function(e){var t,i,a='<span class="col-form-label pr-3">'+M.util.get_string("direction_before","availability_date")+'</span> <span class="availability-group"><label><span class="accesshide">'+M.util.get_string("direction_label","availability_date")+' </span><select name="direction" class="custom-select"><option value=">=">'+M.util.get_string("direction_from","availability_date")+'</option><option value="<">'+M.util.get_string("direction_until","availability_date")+"</option></select></label></span> "+this.html,n=o.Node.create("<span>"+a+"</span>");return e.t!==undefined?(n.setData("time",e.t),n.all("select:not([name=direction])").each(function(e){e.set("disabled",!0)}),a=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=fromtime&time="+e.t,o.io(a,{on:{success:function(e,a){var t,i,l=o.JSON.parse(a.responseText);for(t in l)(i=n.one("select[name=x\\["+t+"\\]]")).set("value",""+l[t]),i.set("disabled",!1)},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})):n.setData("time",this.defaultTime),e.d!==undefined&&n.one("select[name=direction]").set("value",e.d),M.availability_date.form.addedEvents||(M.availability_date.form.addedEvents=!0,(a=o.one(".availability-field")).delegate("change",function(){M.core_availability.form.update()},".availability_date select[name=direction]"),a.delegate("change",function(){M.availability_date.form.updateTime(this.ancestor("span.availability_date"))},".availability_date select:not([name=direction])")),n.one("a[href=#]")&&(M.form.dateselector.init_single_date_selector(n),t=n.one("select[name=x\\[year\\]]"),i=t.set,t.set=function(e,a){i.call(t,e,a),"selectedIndex"===e&&setTimeout(function(){M.availability_date.form.updateTime(n)},0)}),n},M.availability_date.form.updateTime=function(t){var e=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=totime&year="+t.one("select[name=x\\[year\\]]").get("value")+"&month="+t.one("select[name=x\\[month\\]]").get("value")+"&day="+t.one("select[name=x\\[day\\]]").get("value")+"&hour="+t.one("select[name=x\\[hour\\]]").get("value")+"&minute="+t.one("select[name=x\\[minute\\]]").get("value");o.io(e,{on:{success:function(e,a){t.setData("time",a.responseText),M.core_availability.form.update()},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})},M.availability_date.form.fillValue=function(e,a){e.d=a.one("select[name=direction]").get("value"),e.t=parseInt(a.getData("time"),10)},M.availability_date.form.convertTreeDateValue=function(e,a,t){var i=!1;return e.forEach(function(e){i||("date"===e.type?e.t!==parseInt(t.getData("time"),10)||t.one("select[name=direction]").get("value")!=e.d?a.push(e):i=!0:e.type===undefined&&M.availability_date.form.convertTreeDateValue(e.c,a,t))}),a},M.availability_date.form.checkConditionDate=function(e){var a,t,i,l=!1;return"&"===M.core_availability.form.rootList.getValue().op?(a=M.core_availability.form.rootList.getValue().c,a=M.availability_date.form.convertTreeDateValue(a,[],e),t=e.one("select[name=direction]").get("value"),i=parseInt(e.getData("time"),10),a.forEach(function(e){return"<"===e.d?">="===t&&i>=e.t&&(l=!0):"<"===t&&i<=e.t&&(l=!0),l})):e.one("div > .badge-warning")&&e.one("div > .badge-warning").remove(),l},M.availability_date.form.fillErrors=function(e,a){M.availability_date.form.checkConditionDate(a)&&e.push("availability_date:error_dateconflict")}},"@VERSION@",{requires:["base","node","event","io","moodle-core_availability-form"]});
|
||||
availability/condition/date/yui/build/moodle-availability_date-form/moodle-availability_date-form.js
Vendored
+79
@@ -142,5 +142,84 @@ M.availability_date.form.fillValue = function(value, node) {
|
||||
value.t = parseInt(node.getData('time'), 10);
|
||||
};
|
||||
|
||||
/**
|
||||
* List out Date node value in an array node.
|
||||
*
|
||||
* This will go through all array node and list from earlier date node to current date node.
|
||||
*
|
||||
* @method convertTreeDateValue
|
||||
* @param {array} tree Tree node to convert
|
||||
* @param {array} arrayDateNode
|
||||
* @param {array} currentNode current node.
|
||||
*
|
||||
* @return {array} arrayDateNode
|
||||
*/
|
||||
M.availability_date.form.convertTreeDateValue = function(tree, arrayDateNode, currentNode) {
|
||||
var shouldSkip = false;
|
||||
tree.forEach(function(node) {
|
||||
if (shouldSkip) {
|
||||
return;
|
||||
}
|
||||
if (node.type === 'date') {
|
||||
// We go through all tree node, if we meet the current node then return.
|
||||
if (node.t === parseInt(currentNode.getData('time'), 10)
|
||||
&& currentNode.one('select[name=direction]').get('value') == node.d) {
|
||||
shouldSkip = true;
|
||||
return;
|
||||
}
|
||||
arrayDateNode.push(node);
|
||||
} else if (node.type === undefined) {
|
||||
M.availability_date.form.convertTreeDateValue(node.c, arrayDateNode, currentNode);
|
||||
}
|
||||
});
|
||||
return arrayDateNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check current node.
|
||||
*
|
||||
* This will check current date node with all date node in tree node.
|
||||
*
|
||||
* @method checkConditionDate
|
||||
* @param {array} currentNode The curent node.
|
||||
*
|
||||
* @return {boolean} error Return true if the date is conflict.
|
||||
*/
|
||||
M.availability_date.form.checkConditionDate = function(currentNode) {
|
||||
var error = false;
|
||||
if (M.core_availability.form.rootList.getValue().op === '&') {
|
||||
var jsValue = M.core_availability.form.rootList.getValue().c;
|
||||
var arrayDateNode = M.availability_date.form.convertTreeDateValue(jsValue, [], currentNode);
|
||||
var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
|
||||
var currentNodeTime = parseInt(currentNode.getData('time'), 10);
|
||||
arrayDateNode.forEach(function(checkNode) {
|
||||
// Validate if the date is conflict.
|
||||
if (checkNode.d === '<') {
|
||||
if (currentNodeDirection === '>=' && currentNodeTime >= checkNode.t) {
|
||||
error = true;
|
||||
}
|
||||
} else {
|
||||
if (currentNodeDirection === '<' && currentNodeTime <= checkNode.t) {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
});
|
||||
return error;
|
||||
} else {
|
||||
if (currentNode.one('div > .badge-warning')) {
|
||||
currentNode.one('div > .badge-warning').remove();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
M.availability_date.form.fillErrors = function(errors, node) {
|
||||
var error = M.availability_date.form.checkConditionDate(node);
|
||||
if (error) {
|
||||
errors.push('availability_date:error_dateconflict');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}, '@VERSION@', {"requires": ["base", "node", "event", "io", "moodle-core_availability-form"]});
|
||||
|
||||
@@ -139,3 +139,82 @@ M.availability_date.form.fillValue = function(value, node) {
|
||||
value.d = node.one('select[name=direction]').get('value');
|
||||
value.t = parseInt(node.getData('time'), 10);
|
||||
};
|
||||
|
||||
/**
|
||||
* List out Date node value in an array node.
|
||||
*
|
||||
* This will go through all array node and list from earlier date node to current date node.
|
||||
*
|
||||
* @method convertTreeDateValue
|
||||
* @param {array} tree Tree node to convert
|
||||
* @param {array} arrayDateNode
|
||||
* @param {array} currentNode current node.
|
||||
*
|
||||
* @return {array} arrayDateNode
|
||||
*/
|
||||
M.availability_date.form.convertTreeDateValue = function(tree, arrayDateNode, currentNode) {
|
||||
var shouldSkip = false;
|
||||
tree.forEach(function(node) {
|
||||
if (shouldSkip) {
|
||||
return;
|
||||
}
|
||||
if (node.type === 'date') {
|
||||
// We go through all tree node, if we meet the current node then return.
|
||||
if (node.t === parseInt(currentNode.getData('time'), 10)
|
||||
&& currentNode.one('select[name=direction]').get('value') == node.d) {
|
||||
shouldSkip = true;
|
||||
return;
|
||||
}
|
||||
arrayDateNode.push(node);
|
||||
} else if (node.type === undefined) {
|
||||
M.availability_date.form.convertTreeDateValue(node.c, arrayDateNode, currentNode);
|
||||
}
|
||||
});
|
||||
return arrayDateNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check current node.
|
||||
*
|
||||
* This will check current date node with all date node in tree node.
|
||||
*
|
||||
* @method checkConditionDate
|
||||
* @param {array} currentNode The curent node.
|
||||
*
|
||||
* @return {boolean} error Return true if the date is conflict.
|
||||
*/
|
||||
M.availability_date.form.checkConditionDate = function(currentNode) {
|
||||
var error = false;
|
||||
if (M.core_availability.form.rootList.getValue().op === '&') {
|
||||
var jsValue = M.core_availability.form.rootList.getValue().c;
|
||||
var arrayDateNode = M.availability_date.form.convertTreeDateValue(jsValue, [], currentNode);
|
||||
var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
|
||||
var currentNodeTime = parseInt(currentNode.getData('time'), 10);
|
||||
arrayDateNode.forEach(function(checkNode) {
|
||||
// Validate if the date is conflict.
|
||||
if (checkNode.d === '<') {
|
||||
if (currentNodeDirection === '>=' && currentNodeTime >= checkNode.t) {
|
||||
error = true;
|
||||
}
|
||||
} else {
|
||||
if (currentNodeDirection === '<' && currentNodeTime <= checkNode.t) {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
});
|
||||
return error;
|
||||
} else {
|
||||
if (currentNode.one('div > .badge-warning')) {
|
||||
currentNode.one('div > .badge-warning').remove();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
M.availability_date.form.fillErrors = function(errors, node) {
|
||||
var error = M.availability_date.form.checkConditionDate(node);
|
||||
if (error) {
|
||||
errors.push('availability_date:error_dateconflict');
|
||||
}
|
||||
};
|
||||
|
||||
Vendored
+15
-1
@@ -971,7 +971,21 @@ M.core_availability.Item.prototype.fillErrors = function(errors) {
|
||||
// If any errors were added, add the marker to this item.
|
||||
var errorLabel = this.node.one('> .badge-warning');
|
||||
if (errors.length !== before && !errorLabel.get('firstChild')) {
|
||||
errorLabel.appendChild(document.createTextNode(M.util.get_string('invalid', 'availability')));
|
||||
var errorString = '';
|
||||
// Fetch the last error code from the array of errors and split using the ':' delimiter.
|
||||
var langString = errors[errors.length - 1].split(':');
|
||||
var component = langString[0];
|
||||
var identifier = langString[1];
|
||||
// If get_string can't find the string, it will return the string in this format.
|
||||
var undefinedString = '[[' + identifier + ',' + component + ']]';
|
||||
// Get the lang string.
|
||||
errorString = M.util.get_string(identifier, component);
|
||||
if (errorString === undefinedString) {
|
||||
// Use a generic invalid input message when the error lang string cannot be loaded.
|
||||
errorString = M.util.get_string('invalid', 'availability');
|
||||
}
|
||||
// Show the error string.
|
||||
errorLabel.appendChild(document.createTextNode(errorString));
|
||||
} else if (errors.length === before && errorLabel.get('firstChild')) {
|
||||
errorLabel.get('firstChild').remove();
|
||||
}
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+15
-1
@@ -971,7 +971,21 @@ M.core_availability.Item.prototype.fillErrors = function(errors) {
|
||||
// If any errors were added, add the marker to this item.
|
||||
var errorLabel = this.node.one('> .badge-warning');
|
||||
if (errors.length !== before && !errorLabel.get('firstChild')) {
|
||||
errorLabel.appendChild(document.createTextNode(M.util.get_string('invalid', 'availability')));
|
||||
var errorString = '';
|
||||
// Fetch the last error code from the array of errors and split using the ':' delimiter.
|
||||
var langString = errors[errors.length - 1].split(':');
|
||||
var component = langString[0];
|
||||
var identifier = langString[1];
|
||||
// If get_string can't find the string, it will return the string in this format.
|
||||
var undefinedString = '[[' + identifier + ',' + component + ']]';
|
||||
// Get the lang string.
|
||||
errorString = M.util.get_string(identifier, component);
|
||||
if (errorString === undefinedString) {
|
||||
// Use a generic invalid input message when the error lang string cannot be loaded.
|
||||
errorString = M.util.get_string('invalid', 'availability');
|
||||
}
|
||||
// Show the error string.
|
||||
errorLabel.appendChild(document.createTextNode(errorString));
|
||||
} else if (errors.length === before && errorLabel.get('firstChild')) {
|
||||
errorLabel.get('firstChild').remove();
|
||||
}
|
||||
|
||||
Vendored
+15
-1
@@ -969,7 +969,21 @@ M.core_availability.Item.prototype.fillErrors = function(errors) {
|
||||
// If any errors were added, add the marker to this item.
|
||||
var errorLabel = this.node.one('> .badge-warning');
|
||||
if (errors.length !== before && !errorLabel.get('firstChild')) {
|
||||
errorLabel.appendChild(document.createTextNode(M.util.get_string('invalid', 'availability')));
|
||||
var errorString = '';
|
||||
// Fetch the last error code from the array of errors and split using the ':' delimiter.
|
||||
var langString = errors[errors.length - 1].split(':');
|
||||
var component = langString[0];
|
||||
var identifier = langString[1];
|
||||
// If get_string can't find the string, it will return the string in this format.
|
||||
var undefinedString = '[[' + identifier + ',' + component + ']]';
|
||||
// Get the lang string.
|
||||
errorString = M.util.get_string(identifier, component);
|
||||
if (errorString === undefinedString) {
|
||||
// Use a generic invalid input message when the error lang string cannot be loaded.
|
||||
errorString = M.util.get_string('invalid', 'availability');
|
||||
}
|
||||
// Show the error string.
|
||||
errorLabel.appendChild(document.createTextNode(errorString));
|
||||
} else if (errors.length === before && errorLabel.get('firstChild')) {
|
||||
errorLabel.get('firstChild').remove();
|
||||
}
|
||||
|
||||
@@ -4239,7 +4239,8 @@ class restore_block_instance_structure_step extends restore_structure_step {
|
||||
|
||||
// Look for the parent contextid
|
||||
if (!$data->parentcontextid = $this->get_mappingid('context', $data->parentcontextid)) {
|
||||
throw new restore_step_exception('restore_block_missing_parent_ctx', $data->parentcontextid);
|
||||
// Parent contextid does not exist, ignore this block.
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: it would be nice to use standard plugin supports instead of this instance_allow_multiple()
|
||||
@@ -4285,14 +4286,17 @@ class restore_block_instance_structure_step extends restore_structure_step {
|
||||
$params['subpagepattern'] = $data->subpagepattern;
|
||||
}
|
||||
|
||||
$exists = $DB->record_exists_sql("SELECT bi.id
|
||||
$existingblock = $DB->get_records_sql("SELECT bi.id
|
||||
FROM {block_instances} bi
|
||||
JOIN {block} b ON b.name = bi.blockname
|
||||
WHERE bi.blockname = :blockname
|
||||
AND $contextsql
|
||||
AND bi.pagetypepattern $pagetypepatternsql
|
||||
AND $subpagepatternsql", $params);
|
||||
if ($exists) {
|
||||
if (!empty($existingblock)) {
|
||||
// Save the context mapping in case something else is linking to this block's context.
|
||||
$newcontext = context_block::instance(reset($existingblock)->id);
|
||||
$this->set_mapping('context', $oldcontextid, $newcontext->id);
|
||||
// There is at least one very similar block visible on the page where we
|
||||
// are trying to restore the block. In these circumstances the block API
|
||||
// would not allow the user to add another instance of the block, so we
|
||||
@@ -4311,6 +4315,9 @@ class restore_block_instance_structure_step extends restore_structure_step {
|
||||
if ($birecs = $DB->get_records('block_instances', $params)) {
|
||||
foreach($birecs as $birec) {
|
||||
if ($birec->configdata == $data->configdata) {
|
||||
// Save the context mapping in case something else is linking to this block's context.
|
||||
$newcontext = context_block::instance($birec->id);
|
||||
$this->set_mapping('context', $oldcontextid, $newcontext->id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -5296,7 +5303,8 @@ class restore_process_file_aliases_queue extends restore_execution_step {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($info->oldfile->repositorytype === 'local' or $info->oldfile->repositorytype === 'coursefiles') {
|
||||
if ($info->oldfile->repositorytype === 'local' || $info->oldfile->repositorytype === 'coursefiles'
|
||||
|| $info->oldfile->repositorytype === 'contentbank') {
|
||||
// Aliases to Server files and Legacy course files may refer to a file
|
||||
// contained in the backup file or to some existing file (if we are on the
|
||||
// same site).
|
||||
@@ -5459,7 +5467,8 @@ class restore_process_file_aliases_queue extends restore_execution_step {
|
||||
|
||||
// Both Server files and Legacy course files repositories have a single
|
||||
// instance at the system context to use. Let us try to find it.
|
||||
if ($info->oldfile->repositorytype === 'local' or $info->oldfile->repositorytype === 'coursefiles') {
|
||||
if ($info->oldfile->repositorytype === 'local' || $info->oldfile->repositorytype === 'coursefiles'
|
||||
|| $info->oldfile->repositorytype === 'contentbank') {
|
||||
$sql = "SELECT ri.id
|
||||
FROM {repository} r
|
||||
JOIN {repository_instances} ri ON ri.typeid = r.id
|
||||
|
||||
@@ -145,9 +145,11 @@ abstract class convert_helper {
|
||||
$firstchars = fread($handle, 200);
|
||||
$status = fclose($handle);
|
||||
|
||||
if (strpos($firstchars,'<?xml version="1.0" encoding="UTF-8"?>') !== false and
|
||||
strpos($firstchars,'<moodle_backup>') !== false and
|
||||
strpos($firstchars,'<information>') !== false) {
|
||||
// Look for expected XML elements (case-insensitive to account for encoding attribute).
|
||||
if (stripos($firstchars, '<?xml version="1.0" encoding="UTF-8"?>') !== false &&
|
||||
strpos($firstchars, '<moodle_backup>') !== false &&
|
||||
strpos($firstchars, '<information>') !== false) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -643,7 +643,7 @@ class backup_ui_stage_complete extends backup_ui_stage_final {
|
||||
}
|
||||
$output .= $renderer->get_samesite_notification();
|
||||
$output .= $renderer->notification(get_string('executionsuccess', 'backup'), 'notifysuccess');
|
||||
$output .= $renderer->continue_button($restorerul);
|
||||
$output .= $renderer->continue_button($restorerul, 'get');
|
||||
$output .= $renderer->box_end();
|
||||
|
||||
return $output;
|
||||
|
||||
@@ -553,7 +553,8 @@ class core_backup_renderer extends plugin_renderer_base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a continue button
|
||||
* Displays a continue button, overriding core renderer method of the same in order
|
||||
* to override submission method of the button form
|
||||
*
|
||||
* @param string|moodle_url $url
|
||||
* @param string $method
|
||||
@@ -566,7 +567,6 @@ class core_backup_renderer extends plugin_renderer_base {
|
||||
if ($method != 'post') {
|
||||
$method = 'get';
|
||||
}
|
||||
$url->param('sesskey', sesskey());
|
||||
$button = new single_button($url, get_string('continue'), $method, true);
|
||||
$button->class = 'continuebutton';
|
||||
return $this->render($button);
|
||||
|
||||
@@ -1161,8 +1161,10 @@ class restore_ui_stage_complete extends restore_ui_stage_process {
|
||||
$html .= $renderer->notification(get_string('restorefileweremissing', 'backup'), 'notifyproblem');
|
||||
}
|
||||
$html .= $renderer->notification(get_string('restoreexecutionsuccess', 'backup'), 'notifysuccess');
|
||||
$html .= $renderer->continue_button(new moodle_url('/course/view.php', array(
|
||||
'id' => $this->get_ui()->get_controller()->get_courseid())), 'get');
|
||||
|
||||
$courseurl = course_get_url($this->get_ui()->get_controller()->get_courseid());
|
||||
$html .= $renderer->continue_button($courseurl, 'get');
|
||||
|
||||
$html .= $renderer->box_end();
|
||||
|
||||
return $html;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace block_accessreview\tests;
|
||||
namespace block_accessreview;
|
||||
|
||||
use ReflectionClass;
|
||||
use advanced_testcase;
|
||||
|
||||
@@ -83,7 +83,8 @@ class content extends \core_search\base_block {
|
||||
|
||||
$context = \context::instance_by_id($document->get('contextid'));
|
||||
|
||||
$files = $fs->get_area_files($context->id, 'block_html', 'content');
|
||||
$files = $fs->get_area_files($context->id, 'block_html', 'content',
|
||||
false, 'itemid, filepath, filename', false);
|
||||
foreach ($files as $file) {
|
||||
$document->add_stored_file($file);
|
||||
}
|
||||
|
||||
@@ -137,11 +137,9 @@ class search_content_test extends \advanced_testcase {
|
||||
$this->assertCount(0, $doc->get_files());
|
||||
$area->attach_files($doc);
|
||||
$files = $doc->get_files();
|
||||
$this->assertCount(2, $files);
|
||||
// The directory entry should NOT be provided for indexing.
|
||||
$this->assertCount(1, $files);
|
||||
foreach ($files as $file) {
|
||||
if ($file->is_directory()) {
|
||||
continue;
|
||||
}
|
||||
$this->assertEquals('file.txt', $file->get_filename());
|
||||
$this->assertEquals('File content', $file->get_content());
|
||||
}
|
||||
|
||||
Vendored
+7
-5
@@ -358,17 +358,19 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i
|
||||
if (!$handle = fopen($file, 'rb')) {
|
||||
return false;
|
||||
}
|
||||
// Lock it up!
|
||||
// We don't care if this succeeds or not, on some systems it will, on some it won't, meah either way.
|
||||
flock($handle, LOCK_SH);
|
||||
|
||||
// Note: There is no need to perform any file locking here.
|
||||
// The cache file is only ever written to in the `write_file` function, where it does so by writing to a temp
|
||||
// file and performing an atomic rename of that file. The target file is never locked, so there is no benefit to
|
||||
// obtaining a lock (shared or exclusive) here.
|
||||
|
||||
$data = '';
|
||||
// Read the data in 1Mb chunks. Small caches will not loop more than once. We don't use filesize as it may
|
||||
// be cached with a different value than what we need to read from the file.
|
||||
do {
|
||||
$data .= fread($handle, 1048576);
|
||||
} while (!feof($handle));
|
||||
// Unlock it.
|
||||
flock($handle, LOCK_UN);
|
||||
|
||||
// Return it unserialised.
|
||||
return $this->prep_data_after_read($data);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ require_once('../config.php');
|
||||
require_once($CFG->dirroot.'/calendar/lib.php');
|
||||
require_once($CFG->libdir.'/bennu/bennu.inc.php');
|
||||
|
||||
raise_memory_limit(MEMORY_HUGE);
|
||||
|
||||
$userid = optional_param('userid', 0, PARAM_INT);
|
||||
$username = optional_param('username', '', PARAM_TEXT);
|
||||
$authtoken = required_param('authtoken', PARAM_ALPHANUM);
|
||||
|
||||
@@ -63,13 +63,13 @@
|
||||
<div class="commands float-sm-right">
|
||||
{{#canedit}}
|
||||
{{#candelete}}
|
||||
<a href="{{deleteurl}}" data-action="delete">
|
||||
{{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}
|
||||
<a href="{{deleteurl}}" data-action="delete" aria-label="{{#str}}delete{{/str}}" title="{{#str}}delete{{/str}}">
|
||||
{{#pix}}t/delete, core{{/pix}}
|
||||
</a>
|
||||
{{/candelete}}
|
||||
{{^isactionevent}}
|
||||
<a href="{{editurl}}" data-action="edit">
|
||||
{{#pix}}t/edit, core, {{#str}}edit{{/str}}{{/pix}}
|
||||
<a href="{{editurl}}" data-action="edit" aria-label="{{#str}}edit{{/str}}" title="{{#str}}edit{{/str}}">
|
||||
{{#pix}}t/edit, core{{/pix}}
|
||||
</a>
|
||||
{{/isactionevent}}
|
||||
{{/canedit}}
|
||||
|
||||
+5
-5
@@ -12,13 +12,13 @@
|
||||
],
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "9.5.*",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"behat/mink": "~1.8",
|
||||
"mikey179/vfsstream": "1.6.*",
|
||||
"behat/mink": "^1.10.0",
|
||||
"friends-of-behat/mink-extension": "dev-master",
|
||||
"behat/mink-goutte-driver": "~1.2",
|
||||
"behat/mink-goutte-driver": "^1.3",
|
||||
"symfony/process": "^4.0 || ^5.0",
|
||||
"behat/behat": "3.10.*",
|
||||
"oleg-andreyev/mink-phpwebdriver": "^1.0"
|
||||
"behat/behat": "3.11.*",
|
||||
"oleg-andreyev/mink-phpwebdriver": "^1.0.1"
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-0": {
|
||||
|
||||
Generated
+413
-657
File diff suppressed because it is too large
Load Diff
@@ -409,6 +409,9 @@ $CFG->admin = 'admin';
|
||||
// Print to footer (works with the default theme)
|
||||
// define('MDL_PERFTOFOOT', true);
|
||||
//
|
||||
// Print additional data to log of included files
|
||||
// define('MDL_PERFINC', true);
|
||||
//
|
||||
// Enable earlier profiling that causes more code to be covered
|
||||
// on every request (db connections, config load, other inits...).
|
||||
// Requires extra configuration to be defined in config.php like:
|
||||
|
||||
Vendored
+1
-1
@@ -5,6 +5,6 @@ define("core_course/repository",["exports","core/ajax"],(function(_exports,_ajax
|
||||
* @module core_course/repository
|
||||
* @copyright 2018 Ryan Wyllie <ryan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};var _default={getEnrolledCoursesByTimelineClassification:function(classification,limit,offset,sort){var args={classification:classification};void 0!==limit&&(args.limit=limit),void 0!==offset&&(args.offset=offset),void 0!==sort&&(args.sort=sort);var request={methodname:"core_course_get_enrolled_courses_by_timeline_classification",args:args};return _ajax.default.call([request])[0]},getLastAccessedCourses:function(userid,limit,offset,sort){var args={};void 0!==userid&&(args.userid=userid),void 0!==limit&&(args.limit=limit),void 0!==offset&&(args.offset=offset),void 0!==sort&&(args.sort=sort);var request={methodname:"core_course_get_recent_courses",args:args};return _ajax.default.call([request])[0]},getUsersFromCourseModuleID:function(cmid,groupID){var request={methodname:"core_course_get_enrolled_users_by_cmid",args:{cmid:cmid,groupid:groupID}};return _ajax.default.call([request])[0]},toggleManualCompletion:function(cmid,completed){var request={methodname:"core_completion_update_activity_completion_status_manually",args:{cmid:cmid,completed:completed}};return _ajax.default.call([request])[0]}};return _exports.default=_default,_exports.default}));
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};var _default={getEnrolledCoursesByTimelineClassification:function(classification,limit,offset,sort){var args={classification:classification};void 0!==limit&&(args.limit=limit),void 0!==offset&&(args.offset=offset),void 0!==sort&&(args.sort=sort);var request={methodname:"core_course_get_enrolled_courses_by_timeline_classification",args:args};return _ajax.default.call([request])[0]},getLastAccessedCourses:function(userid,limit,offset,sort){var args={};void 0!==userid&&(args.userid=userid),void 0!==limit&&(args.limit=limit),void 0!==offset&&(args.offset=offset),void 0!==sort&&(args.sort=sort);var request={methodname:"core_course_get_recent_courses",args:args};return _ajax.default.call([request])[0]},getUsersFromCourseModuleID:function(cmid,groupID){var onlyActive=arguments.length>2&&void 0!==arguments[2]&&arguments[2],request={methodname:"core_course_get_enrolled_users_by_cmid",args:{cmid:cmid,groupid:groupID,onlyactive:onlyActive}};return _ajax.default.call([request])[0]},toggleManualCompletion:function(cmid,completed){var request={methodname:"core_completion_update_activity_completion_status_manually",args:{cmid:cmid,completed:completed}};return _ajax.default.call([request])[0]}};return _exports.default=_default,_exports.default}));
|
||||
|
||||
//# sourceMappingURL=repository.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -100,14 +100,16 @@ const getLastAccessedCourses = (userid, limit, offset, sort) => {
|
||||
*
|
||||
* @param {Number} cmid Course Module from which the users will be obtained
|
||||
* @param {Number} groupID Group ID from which the users will be obtained
|
||||
* @param {Boolean} onlyActive Whether to fetch only the active enrolled users or all enrolled users in the course.
|
||||
* @returns {Promise} Promise containing a list of users
|
||||
*/
|
||||
const getEnrolledUsersFromCourseModuleID = (cmid, groupID) => {
|
||||
const getEnrolledUsersFromCourseModuleID = (cmid, groupID, onlyActive = false) => {
|
||||
var request = {
|
||||
methodname: 'core_course_get_enrolled_users_by_cmid',
|
||||
args: {
|
||||
cmid: cmid,
|
||||
groupid: groupID,
|
||||
onlyactive: onlyActive,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -4103,6 +4103,8 @@ class core_course_external extends external_api {
|
||||
return new external_function_parameters([
|
||||
'cmid' => new external_value(PARAM_INT, 'id of the course module', VALUE_REQUIRED),
|
||||
'groupid' => new external_value(PARAM_INT, 'id of the group', VALUE_DEFAULT, 0),
|
||||
'onlyactive' => new external_value(PARAM_BOOL, 'whether to return only active users or all.',
|
||||
VALUE_DEFAULT, false),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -4111,26 +4113,25 @@ class core_course_external extends external_api {
|
||||
*
|
||||
* @param int $cmid Course Module id from which the users will be obtained
|
||||
* @param int $groupid Group id from which the users will be obtained
|
||||
* @param bool $onlyactive Whether to return only the active enrolled users or all enrolled users in the course.
|
||||
* @return array List of users
|
||||
* @throws invalid_parameter_exception
|
||||
*/
|
||||
public static function get_enrolled_users_by_cmid(int $cmid, int $groupid = 0) {
|
||||
public static function get_enrolled_users_by_cmid(int $cmid, int $groupid = 0, bool $onlyactive = false) {
|
||||
global $PAGE;
|
||||
$warnings = [];
|
||||
|
||||
[
|
||||
'cmid' => $cmid,
|
||||
'groupid' => $groupid,
|
||||
] = self::validate_parameters(self::get_enrolled_users_by_cmid_parameters(), [
|
||||
self::validate_parameters(self::get_enrolled_users_by_cmid_parameters(), [
|
||||
'cmid' => $cmid,
|
||||
'groupid' => $groupid,
|
||||
'onlyactive' => $onlyactive,
|
||||
]);
|
||||
|
||||
list($course, $cm) = get_course_and_cm_from_cmid($cmid);
|
||||
$coursecontext = context_course::instance($course->id);
|
||||
self::validate_context($coursecontext);
|
||||
|
||||
$enrolledusers = get_enrolled_users($coursecontext, '', $groupid);
|
||||
$enrolledusers = get_enrolled_users($coursecontext, '', $groupid, 'u.*', null, 0, 0, $onlyactive);
|
||||
|
||||
$users = array_map(function ($user) use ($PAGE) {
|
||||
$user->fullname = fullname($user);
|
||||
|
||||
@@ -212,6 +212,7 @@ abstract class moodleform_mod extends moodleform {
|
||||
$this->_features->showdescription = plugin_supports('mod', $this->_modname, FEATURE_SHOW_DESCRIPTION, false);
|
||||
$this->_features->gradecat = ($this->_features->outcomes or $this->_features->hasgrades);
|
||||
$this->_features->advancedgrading = plugin_supports('mod', $this->_modname, FEATURE_ADVANCED_GRADING, false);
|
||||
$this->_features->hasnoview = plugin_supports('mod', $this->_modname, FEATURE_NO_VIEW_LINK, false);
|
||||
$this->_features->canrescale = (component_callback_exists('mod_' . $this->_modname, 'rescale_activity_grades') !== false);
|
||||
}
|
||||
|
||||
@@ -386,11 +387,10 @@ abstract class moodleform_mod extends moodleform {
|
||||
// form verification
|
||||
function validation($data, $files) {
|
||||
global $COURSE, $DB, $CFG;
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
$mform =& $this->_form;
|
||||
|
||||
$errors = array();
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
if ($mform->elementExists('name')) {
|
||||
$name = trim($data['name']);
|
||||
@@ -574,7 +574,10 @@ abstract class moodleform_mod extends moodleform {
|
||||
$mform->addElement('header', 'modstandardelshdr', get_string('modstandardels', 'form'));
|
||||
|
||||
$section = get_fast_modinfo($COURSE)->get_section_info($this->_section);
|
||||
$allowstealth = !empty($CFG->allowstealth) && $this->courseformat->allow_stealth_module_visibility($this->_cm, $section);
|
||||
$allowstealth =
|
||||
!empty($CFG->allowstealth) &&
|
||||
$this->courseformat->allow_stealth_module_visibility($this->_cm, $section) &&
|
||||
!$this->_features->hasnoview;
|
||||
if ($allowstealth && $section->visible) {
|
||||
$modvisiblelabel = 'modvisiblewithstealth';
|
||||
} else if ($section->visible) {
|
||||
|
||||
@@ -3500,6 +3500,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
|
||||
|
||||
$user1 = self::getDataGenerator()->create_user();
|
||||
$user2 = self::getDataGenerator()->create_user();
|
||||
$user3 = self::getDataGenerator()->create_user();
|
||||
|
||||
$user1picture = new user_picture($user1);
|
||||
$user1picture->size = 1;
|
||||
@@ -3509,6 +3510,10 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
|
||||
$user2picture->size = 1;
|
||||
$user2->profileimage = $user2picture->get_url($PAGE)->out(false);
|
||||
|
||||
$user3picture = new user_picture($user3);
|
||||
$user3picture->size = 1;
|
||||
$user3->profileimage = $user3picture->get_url($PAGE)->out(false);
|
||||
|
||||
// Set the first created user to the test user.
|
||||
self::setUser($user1);
|
||||
|
||||
@@ -3523,6 +3528,8 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
|
||||
// Following lines enrol and assign default role id to the users.
|
||||
$this->getDataGenerator()->enrol_user($user1->id, $course1->id);
|
||||
$this->getDataGenerator()->enrol_user($user2->id, $course1->id);
|
||||
// Enrol a suspended user in the course.
|
||||
$this->getDataGenerator()->enrol_user($user3->id, $course1->id, null, 'manual', 0, 0, ENROL_USER_SUSPENDED);
|
||||
|
||||
// Create what we expect to be returned when querying the course module.
|
||||
$expectedusers = array(
|
||||
@@ -3544,11 +3551,42 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
|
||||
'lastname' => $user2->lastname,
|
||||
'profileimage' => $user2->profileimage,
|
||||
];
|
||||
$expectedusers['users'][2] = [
|
||||
'id' => $user3->id,
|
||||
'fullname' => fullname($user3),
|
||||
'firstname' => $user3->firstname,
|
||||
'lastname' => $user3->lastname,
|
||||
'profileimage' => $user3->profileimage,
|
||||
];
|
||||
|
||||
// Test getting the users in a given context.
|
||||
$users = core_course_external::get_enrolled_users_by_cmid($forum1->cmid);
|
||||
$users = external_api::clean_returnvalue(core_course_external::get_enrolled_users_by_cmid_returns(), $users);
|
||||
|
||||
$this->assertEquals(3, count($users['users']));
|
||||
$this->assertEquals($expectedusers, $users);
|
||||
|
||||
// Test getting only the active users in a given context.
|
||||
$users = core_course_external::get_enrolled_users_by_cmid($forum1->cmid, 0, true);
|
||||
$users = external_api::clean_returnvalue(core_course_external::get_enrolled_users_by_cmid_returns(), $users);
|
||||
|
||||
$expectedusers['users'] = [
|
||||
[
|
||||
'id' => $user1->id,
|
||||
'fullname' => fullname($user1),
|
||||
'firstname' => $user1->firstname,
|
||||
'lastname' => $user1->lastname,
|
||||
'profileimage' => $user1->profileimage,
|
||||
],
|
||||
[
|
||||
'id' => $user2->id,
|
||||
'fullname' => fullname($user2),
|
||||
'firstname' => $user2->firstname,
|
||||
'lastname' => $user2->lastname,
|
||||
'profileimage' => $user2->profileimage,
|
||||
]
|
||||
];
|
||||
|
||||
$this->assertEquals(2, count($users['users']));
|
||||
$this->assertEquals($expectedusers, $users);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ use core_privacy\local\request\approved_contextlist;
|
||||
use core_privacy\local\request\contextlist;
|
||||
use core_privacy\local\request\writer;
|
||||
use core_privacy\manager;
|
||||
use Horde\Socket\Client\Exception;
|
||||
|
||||
/**
|
||||
* Class provider
|
||||
@@ -196,7 +195,7 @@ class provider implements
|
||||
$field = array_key_exists($record->fieldid, $fields) ? $fields[$record->fieldid] : null;
|
||||
$data = data_controller::create(0, $record, $field);
|
||||
self::export_customfield_data($data, array_merge($subcontext, [$record->id]));
|
||||
} catch (Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
// We store some data that we can not initialise controller for. We still need to export it.
|
||||
self::export_customfield_data_unknown($record, $field, array_merge($subcontext, [$record->id]));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@customfield @customfield_textarea @javascript @_file_upload
|
||||
# This feature has Atto-specific steps. See MDL-75913 for further details.
|
||||
@customfield @customfield_textarea @javascript @_file_upload @editor_atto
|
||||
Feature: Default value for the textarea custom field can contain images
|
||||
In order to see images on custom fields
|
||||
As a manager
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@core @core_course @core_customfield @javascript
|
||||
# This feature has Atto-specific steps. See MDL-75913 for further details.
|
||||
@core @core_course @core_customfield @javascript @editor_atto
|
||||
Feature: Teachers can edit course custom fields
|
||||
In order to have additional data on the course
|
||||
As a teacher
|
||||
|
||||
@@ -344,6 +344,9 @@ class tool_provider extends ToolProvider {
|
||||
if ($userlog->serviceurl != $serviceurl) {
|
||||
$userlog->serviceurl = $serviceurl;
|
||||
}
|
||||
if (empty($userlog->consumersecret)) {
|
||||
$userlog->consumersecret = $this->consumer->secret;
|
||||
}
|
||||
$userlog->lastaccess = time();
|
||||
$DB->update_record('enrol_lti_users', $userlog);
|
||||
} else {
|
||||
@@ -354,7 +357,7 @@ class tool_provider extends ToolProvider {
|
||||
$userlog->serviceurl = $serviceurl;
|
||||
$userlog->sourceid = $sourceid;
|
||||
$userlog->consumerkey = $this->consumer->getKey();
|
||||
$userlog->consumersecret = $tool->secret;
|
||||
$userlog->consumersecret = $this->consumer->secret;
|
||||
$userlog->lastgrade = 0;
|
||||
$userlog->lastaccess = time();
|
||||
$userlog->timecreated = time();
|
||||
|
||||
@@ -69,5 +69,47 @@ function xmldb_enrol_lti_upgrade($oldversion) {
|
||||
upgrade_plugin_savepoint(true, 2021051701, 'enrol', 'lti');
|
||||
}
|
||||
|
||||
if ($oldversion < 2021051702) {
|
||||
// Update lti user information for LTI 2.0 users having the wrong consumer secret recorded.
|
||||
// This applies to any LTI 2.0 user who has launched the tool (i.e. has lastaccess) and fixes a non-functional grade sync
|
||||
// for LTI 2.0 consumers.
|
||||
$sql = "SELECT lu.id, lc.secret
|
||||
FROM {enrol_lti_users} lu
|
||||
JOIN {enrol_lti_lti2_consumer} lc
|
||||
ON (lu.consumerkey = lc.consumerkey256)
|
||||
WHERE lc.ltiversion = :ltiversion
|
||||
AND lu.consumersecret != lc.secret
|
||||
AND lu.lastaccess IS NOT NULL";
|
||||
$affectedltiusersrs = $DB->get_recordset_sql($sql, ['ltiversion' => 'LTI-2p0']);
|
||||
foreach ($affectedltiusersrs as $ltiuser) {
|
||||
$DB->set_field('enrol_lti_users', 'consumersecret', $ltiuser->secret, ['id' => $ltiuser->id]);
|
||||
}
|
||||
$affectedltiusersrs->close();
|
||||
|
||||
// Lti savepoint reached.
|
||||
upgrade_plugin_savepoint(true, 2021051702, 'enrol', 'lti');
|
||||
}
|
||||
|
||||
if ($oldversion < 2021051703) {
|
||||
// Update lti user information for any users missing a consumer secret.
|
||||
// This applies to any user who has launched the tool (i.e. has lastaccess) but who doesn't have a secret recorded.
|
||||
// This fixes a bug where enrol_lti_users records are created first during a member sync, and are missing the secret,
|
||||
// even despite having launched the tool subsequently.
|
||||
$sql = "SELECT lu.id, lc.secret
|
||||
FROM {enrol_lti_users} lu
|
||||
JOIN {enrol_lti_lti2_consumer} lc
|
||||
ON (lu.consumerkey = lc.consumerkey256)
|
||||
WHERE lu.consumersecret IS NULL
|
||||
AND lu.lastaccess IS NOT NULL";
|
||||
$affectedltiusersrs = $DB->get_recordset_sql($sql);
|
||||
foreach ($affectedltiusersrs as $ltiuser) {
|
||||
$DB->set_field('enrol_lti_users', 'consumersecret', $ltiuser->secret, ['id' => $ltiuser->id]);
|
||||
}
|
||||
$affectedltiusersrs->close();
|
||||
|
||||
// Lti savepoint reached.
|
||||
upgrade_plugin_savepoint(true, 2021051703, 'enrol', 'lti');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2021051701; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2021051703; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2021051100; // Requires this Moodle version.
|
||||
$plugin->component = 'enrol_lti'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace core_files\local\archive_writer;
|
||||
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
use ZipStream\Option\File as FileOptions;
|
||||
use core_files\archive_writer;
|
||||
use core_files\local\archive_writer\file_writer_interface as file_writer_interface;
|
||||
use core_files\local\archive_writer\stream_writer_interface as stream_writer_interface;
|
||||
@@ -110,8 +111,12 @@ class zip_writer extends archive_writer implements file_writer_interface, stream
|
||||
}
|
||||
|
||||
public function add_file_from_stored_file(string $name, \stored_file $file): void {
|
||||
$datetime = new \DateTime();
|
||||
$datetime->setTimestamp($file->get_timemodified());
|
||||
$fileoptions = new FileOptions();
|
||||
$fileoptions->setTime($datetime);
|
||||
$filehandle = $file->get_content_file_handle();
|
||||
$this->archive->addFileFromStream($this->sanitise_filepath($name), $filehandle);
|
||||
$this->archive->addFileFromStream($this->sanitise_filepath($name), $filehandle, $fileoptions);
|
||||
fclose($filehandle);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_files\local\archive_writer/zip_archive.
|
||||
*
|
||||
* @package core_files
|
||||
* @category test
|
||||
* @copyright 2020 Mark Nelson <mdjnelson@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
namespace core_files;
|
||||
|
||||
use advanced_testcase;
|
||||
@@ -31,7 +22,11 @@ use core_files\local\archive_writer\zip_writer;
|
||||
/**
|
||||
* Unit tests for \core_files\archive_writer.
|
||||
*
|
||||
* @coversDefaultClass \core_files\archive_writer
|
||||
* @package core_files
|
||||
* @category test
|
||||
* @copyright 2020 Mark Nelson <mdjnelson@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
* @covers \core_files\archive_writer
|
||||
*/
|
||||
class archive_writer_test extends advanced_testcase {
|
||||
|
||||
|
||||
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for \core_files\local\archive_writer\zip_writer.
|
||||
*
|
||||
* @package core_files
|
||||
* @category test
|
||||
* @copyright 2020 Mark Nelson <mdjnelson@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
namespace core_files\local\archive_writer;
|
||||
|
||||
use advanced_testcase;
|
||||
@@ -33,7 +24,11 @@ use ZipArchive;
|
||||
/**
|
||||
* Unit tests for \core_files\local\archive_writer\zip_writer.
|
||||
*
|
||||
* @coversDefaultClass \core_files\local\archive_writer\zip_writer
|
||||
* @package core_files
|
||||
* @category test
|
||||
* @copyright 2020 Mark Nelson <mdjnelson@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
* @covers \core_files\local\archive_writer\zip_writer
|
||||
*/
|
||||
class zip_writer_test extends advanced_testcase {
|
||||
|
||||
|
||||
@@ -49,7 +49,8 @@ Feature: Render H5P content using filters
|
||||
And I wait until the page is ready
|
||||
Then ".h5p-iframe" "css_element" should not exist
|
||||
|
||||
@javascript
|
||||
# This scenario has Atto-specific steps. See MDL-75913 for further details.
|
||||
@javascript @editor_atto
|
||||
Scenario: Render a local H5P file as admin
|
||||
Given I log in as "admin"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
@@ -83,7 +84,8 @@ Feature: Render H5P content using filters
|
||||
And I should not see "you don't have access"
|
||||
And I should see "Lorum ipsum"
|
||||
|
||||
@javascript
|
||||
# This scenario has Atto-specific steps. See MDL-75913 for further details.
|
||||
@javascript @editor_atto
|
||||
Scenario: Render a local H5P file as teacher
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
@@ -107,7 +109,8 @@ Feature: Render H5P content using filters
|
||||
Then I should see "Note that the libraries may exist in the file you uploaded, but you're not allowed to upload new libraries."
|
||||
And I should see "missing-required-library"
|
||||
|
||||
@javascript
|
||||
# This scenario has Atto-specific steps. See MDL-75913 for further details.
|
||||
@javascript @editor_atto
|
||||
Scenario: Render a local H5P file with existing libraries
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
@@ -165,7 +168,8 @@ Feature: Render H5P content using filters
|
||||
Then I should not see "missing-required-library"
|
||||
And I should see "Lorum ipsum"
|
||||
|
||||
@javascript
|
||||
# This scenario has Atto-specific steps. See MDL-75913 for further details.
|
||||
@javascript @editor_atto
|
||||
Scenario: Render local H5P file with a disabled main library
|
||||
Given I log in as "admin"
|
||||
# Upload H5P file to private files.
|
||||
|
||||
+1
-10
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_grades\component_gradeitems;
|
||||
*
|
||||
* @package gradingform_guide
|
||||
* @category test
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace gradingform_guide\grades\grader\gradingpanel\external;
|
||||
@@ -42,7 +33,7 @@ use moodle_exception;
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class grades_grader_gradingpanel_guide_external_fetch_test extends advanced_testcase {
|
||||
class fetch_test extends advanced_testcase {
|
||||
|
||||
public static function setupBeforeClass(): void {
|
||||
global $CFG;
|
||||
+1
-10
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_grades\component_gradeitems;
|
||||
*
|
||||
* @package gradingform_guide
|
||||
* @category test
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace gradingform_guide\grades\grader\gradingpanel\external;
|
||||
@@ -42,7 +33,7 @@ use moodle_exception;
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class grades_grader_gradingpanel_guide_external_store_test extends advanced_testcase {
|
||||
class store_test extends advanced_testcase {
|
||||
|
||||
public static function setupBeforeClass(): void {
|
||||
global $CFG;
|
||||
+1
-10
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_grades\component_gradeitems;
|
||||
*
|
||||
* @package gradingform_rubric
|
||||
* @category test
|
||||
* @copyright 2019 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace gradingform_rubric\grades\grader\gradingpanel\external;
|
||||
@@ -43,7 +34,7 @@ use moodle_exception;
|
||||
* @copyright 2019 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class grades_grader_gradingpanel_rubric_external_fetch_test extends advanced_testcase {
|
||||
class fetch_test extends advanced_testcase {
|
||||
|
||||
public static function setupBeforeClass(): void {
|
||||
global $CFG;
|
||||
+1
-10
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_grades\component_gradeitems;
|
||||
*
|
||||
* @package gradingform_rubric
|
||||
* @category test
|
||||
* @copyright 2019 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace gradingform_rubric\grades\grader\gradingpanel\external;
|
||||
@@ -42,7 +33,7 @@ use moodle_exception;
|
||||
* @copyright 2019 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class grades_grader_gradingpanel_rubric_external_store_test extends advanced_testcase {
|
||||
class store_test extends advanced_testcase {
|
||||
|
||||
public static function setupBeforeClass(): void {
|
||||
global $CFG;
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace tests\core_grades {
|
||||
namespace core_grades {
|
||||
|
||||
use advanced_testcase;
|
||||
use core_grades\component_gradeitems;
|
||||
|
||||
+1
-10
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_grades\component_gradeitems;
|
||||
*
|
||||
* @package core_grades
|
||||
* @category test
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace core_grades\grades\grader\gradingpanel\point\external;
|
||||
@@ -42,7 +33,7 @@ use moodle_exception;
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class grades_grader_gradingpanel_point_external_fetch_test extends advanced_testcase {
|
||||
class fetch_test extends advanced_testcase {
|
||||
|
||||
public static function setupBeforeClass(): void {
|
||||
global $CFG;
|
||||
+1
-10
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_grades\component_gradeitems;
|
||||
*
|
||||
* @package core_grades
|
||||
* @category test
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace core_grades\grades\grader\gradingpanel\point\external;
|
||||
@@ -44,7 +35,7 @@ use grade_item;
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class grades_grader_gradingpanel_point_external_store_test extends advanced_testcase {
|
||||
class store_test extends advanced_testcase {
|
||||
|
||||
public static function setupBeforeClass(): void {
|
||||
global $CFG;
|
||||
+1
-10
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_grades\component_gradeitems;
|
||||
*
|
||||
* @package core_grades
|
||||
* @category test
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace core_grades\grades\grader\gradingpanel\scale\external;
|
||||
@@ -42,7 +33,7 @@ use moodle_exception;
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class grades_grader_gradingpanel_scale_external_fetch_test extends advanced_testcase {
|
||||
class fetch_test extends advanced_testcase {
|
||||
|
||||
public static function setupBeforeClass(): void {
|
||||
global $CFG;
|
||||
+1
-10
@@ -14,15 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Unit tests for core_grades\component_gradeitems;
|
||||
*
|
||||
* @package core_grades
|
||||
* @category test
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace core_grades\grades\grader\gradingpanel\scale\external;
|
||||
@@ -44,7 +35,7 @@ use grade_item;
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class grades_grader_gradingpanel_scale_external_store_test extends advanced_testcase {
|
||||
class store_test extends advanced_testcase {
|
||||
|
||||
public static function setupBeforeClass(): void {
|
||||
global $CFG;
|
||||
@@ -14,16 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Testing the H5P H5PFileStorage interface implementation.
|
||||
*
|
||||
* @package core_h5p
|
||||
* @category test
|
||||
* @copyright 2019 Victor Deniz <victor@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_h5p\local\tests;
|
||||
namespace core_h5p;
|
||||
|
||||
use core_h5p\file_storage;
|
||||
use core_h5p\local\library\autoloader;
|
||||
@@ -38,11 +29,12 @@ use zip_archive;
|
||||
* Test class covering the H5PFileStorage interface implementation.
|
||||
*
|
||||
* @package core_h5p
|
||||
* @category test
|
||||
* @copyright 2019 Victor Deniz <victor@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @runTestsInSeparateProcesses
|
||||
*/
|
||||
class h5p_file_storage_test extends \advanced_testcase {
|
||||
class file_storage_test extends \advanced_testcase {
|
||||
|
||||
/** @var \core_h5p\file_storage H5P file storage instance */
|
||||
protected $h5p_file_storage;
|
||||
@@ -30,4 +30,4 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['thisdirection'] = 'ltr';
|
||||
$string['thislanguage'] = 'Breizh';
|
||||
$string['thislanguage'] = 'Brezhoneg';
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['parentlanguage'] = 'es';
|
||||
$string['thislanguage'] = 'Español - Argentina';
|
||||
@@ -31,4 +31,4 @@ defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['parentlanguage'] = '';
|
||||
$string['thisdirection'] = 'ltr';
|
||||
$string['thislanguage'] = 'Español (México)';
|
||||
$string['thislanguage'] = 'Español - México';
|
||||
|
||||
@@ -39,6 +39,6 @@ $string['cliunknowoption'] = 'Opzioni non riconosciute:
|
||||
{$a}
|
||||
. Per favore utilizza l\'opzione --help.';
|
||||
$string['cliyesnoprompt'] = 'inserisci s (per Si) o n (per No)';
|
||||
$string['environmentrequireinstall'] = 'E\' necessaria l\'installazione e attivazione';
|
||||
$string['environmentrequireinstall'] = 'Installazione e attivazione obbligatoria';
|
||||
$string['environmentrequireversion'] = 'Versione minima necessaria: {$a->needed}. Versione in uso: {$a->current}';
|
||||
$string['upgradekeyset'] = 'Chiave per l\'aggiornamento (lasciare vuoto se non impostata)';
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['cannotcreatedboninstall'] = '<p>Non è possibile creare il database </p> <p>Il database non esiste e l\'utente fornito non è autorizzato a crearlo.</p>
|
||||
<p>E\' necessario che l\'amministratore del sito verifichi la configurazione del database.</p>';
|
||||
<p>È necessario che l\'amministratore del sito verifichi la configurazione del database.</p>';
|
||||
$string['cannotcreatelangdir'] = 'Non è possibile creare la cartella lang';
|
||||
$string['cannotcreatetempdir'] = 'Non è possibile creare la cartella temp';
|
||||
$string['cannotdownloadcomponents'] = 'Non è possibile scaricare componenti.';
|
||||
|
||||
@@ -85,7 +85,7 @@ $string['phpextension'] = '{$a} estensioni PHP';
|
||||
$string['phpversion'] = 'Versione PHP';
|
||||
$string['phpversionhelp'] = '<p>Moodle necessita come minimo della versione 5.6.5 o 7.1del PHP. (La versione 7.0.x ha alcuni limiti nel motore)</p>
|
||||
<p>La versione installata nel sistema è la {$a}</p>
|
||||
<p>E\' necessario aggiornare la versione del PHP oppure spostarsi su un host che abbia una versione più aggiornata del PHP.<br>';
|
||||
<p>È necessario aggiornare la versione del PHP oppure spostarsi su un host che abbia una versione più aggiornata del PHP.<br>';
|
||||
$string['welcomep10'] = '{$a->installername} ({$a->installerversion})';
|
||||
$string['welcomep20'] = 'Se vedi questa pagina hai installato correttamente e lanciato il pacchetto <strong>{$a->packname} {$a->packversion}</strong>. Complimenti!';
|
||||
$string['welcomep30'] = 'La release di <strong>{$a->installername}</strong> include l\'applicazione per creare l\'ambiente necessario a far girare <strong>Moodle</strong>:';
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['cannotcreatedboninstall'] = '<p>データベースを作成できません。</p>
|
||||
<p>指定されたデータベースは存在しません。また、ユーザにはデータベースを作成するためのパーミッションがありません。</p>
|
||||
<p>サイト管理者はデータベース設定を確認してください。</p>';
|
||||
<p>指定されたデータベースは存在しません。また、指定されたユーザにはデータベースを作成するためのパーミッションがありません。</p>
|
||||
<p>サイト管理者はデータベース設定を確認する必要があります。</p>';
|
||||
$string['cannotcreatelangdir'] = 'langディレクトリを作成できません。';
|
||||
$string['cannotcreatetempdir'] = 'tempディレクトリを作成できません。';
|
||||
$string['cannotdownloadcomponents'] = 'コンポーネントをダウンロードできません。';
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['parentlanguage'] = 'lt';
|
||||
$string['thislanguage'] = 'Lietuvių (Workplace)';
|
||||
@@ -34,6 +34,11 @@ $string['cliansweryes'] = 'j';
|
||||
$string['cliincorrectvalueerror'] = 'Kļūda, nepareiza vērtība "{$a->value}" opcijai "{$a->option}"';
|
||||
$string['cliincorrectvalueretry'] = 'Nepareiza vērtība, lūdzu, mēģiniet vēlreiz';
|
||||
$string['clitypevalue'] = 'veida vērtība';
|
||||
$string['clitypevaluedefault'] = 'ierakstiet vērtību, nospiediet taustiņu Enter, lai izmantotu noklusējuma vērtību ({$a})';
|
||||
$string['cliunknowoption'] = 'Neatpazītas opcijas:
|
||||
{$a}
|
||||
Lūdzu, izmantojiet opciju --help.';
|
||||
$string['cliyesnoprompt'] = 'ierakstiet y (nozīmē jā) vai n (nozīmē nē)';
|
||||
$string['environmentrequireinstall'] = 'nepieciešams instalēt/iespējot';
|
||||
$string['environmentrequireversion'] = 'nepieciešama versija {$a->needed}, bet jūs izmantojat versiju {$a->current}';
|
||||
$string['upgradekeyset'] = 'Jaunināšanas atslēga (lai to neiestatītu, atstājiet tukšu)';
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['parentlanguage'] = 'lv';
|
||||
$string['thislanguage'] = 'Latviešu (Workplace)';
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Automatically generated strings for Moodle installer
|
||||
*
|
||||
* Do not edit this file manually! It contains just a subset of strings
|
||||
* needed during the very first steps of installation. This file was
|
||||
* generated automatically by export-installer.php (which is part of AMOS
|
||||
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
|
||||
* list of strings defined in /install/stringnames.txt.
|
||||
*
|
||||
* @package installer
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$string['thislanguage'] = 'Papiamento';
|
||||
+1
-1
@@ -82,7 +82,7 @@ $string['hideremote'] = 'Hide remote users';
|
||||
$string['host'] = 'host';
|
||||
$string['hostcoursenotfound'] = 'Host or course not found';
|
||||
$string['hostdeleted'] = 'Host deleted';
|
||||
$string['hostexists'] = 'A record already exists for a host with that hostname (it may be deleted). <a href="{$a}">click here</a> to edit that record.';
|
||||
$string['hostexists'] = 'A record already exists for a host with that hostname (it may be deleted). <a href="{$a}">Click here</a> to edit that record.';
|
||||
$string['hostlist'] = 'List of networked hosts';
|
||||
$string['hostname'] = 'Hostname';
|
||||
$string['hostnamehelp'] = 'The fully-qualified domain name of the remote host, e.g. www.example.com';
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@ define("core/local/aria/focuslock",["exports","./selectors"],(function(_exports,
|
||||
* @module core/tablock
|
||||
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.untrapFocus=_exports.trapFocus=void 0,_selectors=(obj=_selectors)&&obj.__esModule?obj:{default:obj};var lockRegionStack=[],initialFocusElementStack=[],finalFocusElementStack=[],lastFocus=null,ignoreFocusChanges=!1,isLocked=!1,lockHandler=function(event){if(!ignoreFocusChanges){var lockRegion=getCurrentLockRegion();lockRegion.parentNode||untrapFocus(),lockRegion.contains(event.target)?lastFocus=event.target:(focusFirstDescendant(),lastFocus==document.activeElement&&focusLastDescendant(),lastFocus=document.activeElement)}},focusFirstDescendant=function(){var lockRegion=getCurrentLockRegion(),focusableElements=Array.from(lockRegion.querySelectorAll(_selectors.default.elements.focusable));return focusableElements.unshift(lockRegion),focusableElements.some((function(focusableElement){return attemptFocus(focusableElement)}))},focusLastDescendant=function(){var lockRegion=getCurrentLockRegion(),focusableElements=Array.from(lockRegion.querySelectorAll(_selectors.default.elements.focusable)).reverse();return focusableElements.push(lockRegion),focusableElements.some((function(focusableElement){return attemptFocus(focusableElement)}))},attemptFocus=function(focusTarget){if(!function(focusTarget){if(focusTarget.tabIndex>0||0===focusTarget.tabIndex&&null!==focusTarget.getAttribute("tabIndex"))return!0;if(focusTarget.disabled)return!1;switch(focusTarget.nodeName){case"A":return!!focusTarget.href&&"ignore"!=focusTarget.rel;case"INPUT":return"hidden"!=focusTarget.type&&"file"!=focusTarget.type;case"BUTTON":case"SELECT":case"TEXTAREA":return!0;default:return!1}}(focusTarget))return!1;ignoreFocusChanges=!0;try{focusTarget.focus()}catch(e){}return ignoreFocusChanges=!1,document.activeElement===focusTarget},getCurrentLockRegion=function(){return lockRegionStack[lockRegionStack.length-1]};_exports.trapFocus=function(newLockRegion){if(function(newLockRegion){if(newLockRegion!==getCurrentLockRegion()){lockRegionStack.push(newLockRegion);var currentLockRegion=getCurrentLockRegion(),element=document.createElement("div");element.tabIndex=0,element.style.position="fixed",element.style.top=0,element.style.left=0;var initialNode=element.cloneNode();currentLockRegion.parentNode.insertBefore(initialNode,currentLockRegion),initialFocusElementStack.push(initialNode);var finalNode=element.cloneNode();currentLockRegion.parentNode.insertBefore(finalNode,currentLockRegion.nextSibling),finalFocusElementStack.push(finalNode)}}(newLockRegion),isLocked||document.addEventListener("focus",lockHandler,!0),!focusFirstDescendant()){var currentLockRegion=getCurrentLockRegion(),originalRegionTabIndex=currentLockRegion.tabIndex;currentLockRegion.tabIndex=0,attemptFocus(currentLockRegion),currentLockRegion.tabIndex=originalRegionTabIndex}lastFocus=document.activeElement,isLocked=!0};var untrapFocus=function(){!function(){lockRegionStack.pop();var finalNode=finalFocusElementStack.pop();finalNode&&finalNode.remove();var initialNode=initialFocusElementStack.pop();initialNode&&initialNode.remove()}(),lockRegionStack.length||(document.removeEventListener("focus",lockHandler,!0),lastFocus=null,ignoreFocusChanges=!1,isLocked=!1)};_exports.untrapFocus=untrapFocus}));
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.untrapFocus=_exports.trapFocus=void 0,_selectors=(obj=_selectors)&&obj.__esModule?obj:{default:obj};var lockRegionStack=[],initialFocusElementStack=[],finalFocusElementStack=[],lastFocus=null,ignoreFocusChanges=!1,isLocked=!1,lockHandler=function(event){if(!ignoreFocusChanges){for(var lockRegion=getCurrentLockRegion();lockRegion&&!document.contains(lockRegion);)untrapFocus(),lockRegion=getCurrentLockRegion();lockRegion&&(lockRegion.contains(event.target)?lastFocus=event.target:(focusFirstDescendant(),lastFocus==document.activeElement&&focusLastDescendant(),lastFocus=document.activeElement))}},focusFirstDescendant=function(){var lockRegion=getCurrentLockRegion(),focusableElements=Array.from(lockRegion.querySelectorAll(_selectors.default.elements.focusable));return focusableElements.unshift(lockRegion),focusableElements.some((function(focusableElement){return attemptFocus(focusableElement)}))},focusLastDescendant=function(){var lockRegion=getCurrentLockRegion(),focusableElements=Array.from(lockRegion.querySelectorAll(_selectors.default.elements.focusable)).reverse();return focusableElements.push(lockRegion),focusableElements.some((function(focusableElement){return attemptFocus(focusableElement)}))},attemptFocus=function(focusTarget){if(!function(focusTarget){if(focusTarget.tabIndex>0||0===focusTarget.tabIndex&&null!==focusTarget.getAttribute("tabIndex"))return!0;if(focusTarget.disabled)return!1;switch(focusTarget.nodeName){case"A":return!!focusTarget.href&&"ignore"!=focusTarget.rel;case"INPUT":return"hidden"!=focusTarget.type&&"file"!=focusTarget.type;case"BUTTON":case"SELECT":case"TEXTAREA":return!0;default:return!1}}(focusTarget))return!1;ignoreFocusChanges=!0;try{focusTarget.focus()}catch(e){}return ignoreFocusChanges=!1,document.activeElement===focusTarget},getCurrentLockRegion=function(){return lockRegionStack[lockRegionStack.length-1]};_exports.trapFocus=function(newLockRegion){if(function(newLockRegion){if(newLockRegion!==getCurrentLockRegion()){lockRegionStack.push(newLockRegion);var currentLockRegion=getCurrentLockRegion(),element=document.createElement("div");element.tabIndex=0,element.style.position="fixed",element.style.top=0,element.style.left=0;var initialNode=element.cloneNode();currentLockRegion.parentNode.insertBefore(initialNode,currentLockRegion),initialFocusElementStack.push(initialNode);var finalNode=element.cloneNode();currentLockRegion.parentNode.insertBefore(finalNode,currentLockRegion.nextSibling),finalFocusElementStack.push(finalNode)}}(newLockRegion),isLocked||document.addEventListener("focus",lockHandler,!0),!focusFirstDescendant()){var currentLockRegion=getCurrentLockRegion(),originalRegionTabIndex=currentLockRegion.tabIndex;currentLockRegion.tabIndex=0,attemptFocus(currentLockRegion),currentLockRegion.tabIndex=originalRegionTabIndex}lastFocus=document.activeElement,isLocked=!0};var untrapFocus=function(){!function(){lockRegionStack.pop();var finalNode=finalFocusElementStack.pop();finalNode&&finalNode.remove();var initialNode=initialFocusElementStack.pop();initialNode&&initialNode.remove()}(),lockRegionStack.length||(document.removeEventListener("focus",lockHandler,!0),lastFocus=null,ignoreFocusChanges=!1,isLocked=!1)};_exports.untrapFocus=untrapFocus}));
|
||||
|
||||
//# sourceMappingURL=focuslock.min.js.map
|
||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -6,6 +6,6 @@
|
||||
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define("core/storagewrapper",["core/config"],(function(config){var Wrapper=function(storage){this.storage=storage,this.supported=this.detectSupport(),this.hashSource=config.wwwroot+"/"+config.jsrev,this.hash=this.hashString(this.hashSource),this.prefix=this.hash+"/",this.jsrevPrefix=this.hashString(config.wwwroot)+"/jsrev",this.validateCache()};return Wrapper.prototype.detectSupport=function(){if(-1==config.jsrev)return!1;if(void 0===this.storage)return!1;try{return null!==this.storage&&(this.storage.setItem("test","1"),this.storage.removeItem("test"),!0)}catch(ex){return!1}},Wrapper.prototype.prefixKey=function(key){return this.prefix+key},Wrapper.prototype.validateCache=function(){var cacheVersion=this.storage.getItem(this.jsrevPrefix);null!==cacheVersion?config.jsrev!=cacheVersion&&(this.storage.clear(),this.storage.setItem(this.jsrevPrefix,config.jsrev)):this.storage.setItem(this.jsrevPrefix,config.jsrev)},Wrapper.prototype.hashString=function(source){var i,len,hash=0;if(0===source.length)return hash;for(i=0,len=source.length;i<len;i++)hash=(hash<<5)-hash+source.charCodeAt(i),hash|=0;return hash},Wrapper.prototype.get=function(key){return!!this.supported&&(key=this.prefixKey(key),this.storage.getItem(key))},Wrapper.prototype.set=function(key,value){if(!this.supported)return!1;key=this.prefixKey(key);try{this.storage.setItem(key,value)}catch(e){return!1}return!0},Wrapper}));
|
||||
define("core/storagewrapper",["core/config"],(function(config){var Wrapper=function(storage){this.storage=storage,this.supported=this.detectSupport(),this.hashSource=config.wwwroot+"/"+config.jsrev,this.hash=this.hashString(this.hashSource),this.prefix=this.hash+"/",this.jsrevPrefix=this.hashString(config.wwwroot)+"/jsrev",this.validateCache()};return Wrapper.prototype.detectSupport=function(){if(-1==config.jsrev)return!1;if(void 0===this.storage)return!1;try{return null!==this.storage&&(this.storage.setItem("test","1"),this.storage.removeItem("test"),!0)}catch(ex){return!1}},Wrapper.prototype.prefixKey=function(key){return this.prefix+key},Wrapper.prototype.validateCache=function(){if(this.supported){var cacheVersion=this.storage.getItem(this.jsrevPrefix);if(null!==cacheVersion)config.jsrev!=cacheVersion&&(this.storage.clear(),this.storage.setItem(this.jsrevPrefix,config.jsrev));else this.storage.setItem(this.jsrevPrefix,config.jsrev)}},Wrapper.prototype.hashString=function(source){var i,len,hash=0;if(0===source.length)return hash;for(i=0,len=source.length;i<len;i++)hash=(hash<<5)-hash+source.charCodeAt(i),hash|=0;return hash},Wrapper.prototype.get=function(key){return!!this.supported&&(key=this.prefixKey(key),this.storage.getItem(key))},Wrapper.prototype.set=function(key,value){if(!this.supported)return!1;key=this.prefixKey(key);try{this.storage.setItem(key,value)}catch(e){return!1}return!0},Wrapper}));
|
||||
|
||||
//# sourceMappingURL=storagewrapper.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -55,12 +55,20 @@ const lockHandler = event => {
|
||||
return;
|
||||
}
|
||||
|
||||
const lockRegion = getCurrentLockRegion();
|
||||
// Find the current lock region.
|
||||
let lockRegion = getCurrentLockRegion();
|
||||
while (lockRegion) {
|
||||
if (document.contains(lockRegion)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!lockRegion.parentNode) {
|
||||
// The lock region does not exist.
|
||||
// Perhaps it was removed without being untrapped.
|
||||
untrapFocus();
|
||||
lockRegion = getCurrentLockRegion();
|
||||
}
|
||||
if (!lockRegion) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lockRegion.contains(event.target)) {
|
||||
|
||||
@@ -408,7 +408,7 @@ function(
|
||||
var pageItems = root.find(SELECTORS.PAGE_ITEM);
|
||||
// We want to request all of the strings at once rather than
|
||||
// one at a time.
|
||||
var stringRequests = pageItems.map(function(index, page) {
|
||||
var stringRequests = pageItems.toArray().map(function(index, page) {
|
||||
page = $(page);
|
||||
var pageNumber = getPageNumber(root, page);
|
||||
|
||||
|
||||
@@ -84,6 +84,9 @@ define(['core/config'], function(config) {
|
||||
* @method validateCache
|
||||
*/
|
||||
Wrapper.prototype.validateCache = function() {
|
||||
if (!this.supported) {
|
||||
return;
|
||||
}
|
||||
var cacheVersion = this.storage.getItem(this.jsrevPrefix);
|
||||
if (cacheVersion === null) {
|
||||
this.storage.setItem(this.jsrevPrefix, config.jsrev);
|
||||
|
||||
@@ -333,6 +333,34 @@ class behat_config_util {
|
||||
return $this->get_component_contexts($component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the list of components contexts.
|
||||
*
|
||||
* This ensures that contexts are sorted consistently.
|
||||
* Core hooks defined in the behat_hooks class _must_ be defined first.
|
||||
*
|
||||
* @param array $contexts
|
||||
* @return array The sorted context list
|
||||
*/
|
||||
protected function sort_component_contexts(array $contexts): array {
|
||||
// Ensure that the lib_tests are first as they include the root of all tests, hooks, and more.
|
||||
uksort($contexts, function($a, $b): int {
|
||||
if ($a === 'behat_hooks') {
|
||||
return -1;
|
||||
}
|
||||
if ($b === 'behat_hooks') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($a == $b) {
|
||||
return 0;
|
||||
}
|
||||
return ($a < $b) ? -1 : 1;
|
||||
});
|
||||
|
||||
return $contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Behat config file specifing the main context class,
|
||||
* the required Behat extensions and Moodle test wwwroot.
|
||||
@@ -1537,8 +1565,9 @@ class behat_config_util {
|
||||
}
|
||||
|
||||
// Sort the list of contexts.
|
||||
ksort($contexts);
|
||||
$contexts = $this->sort_component_contexts($contexts);
|
||||
|
||||
// Cache it for subsequent fetches.
|
||||
$this->themecontexts[$theme] = $contexts;
|
||||
|
||||
return $contexts;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
|
||||
|
||||
use Behat\Testwork\Environment\Environment;
|
||||
use Behat\Mink\Exception\DriverException;
|
||||
|
||||
/**
|
||||
* Helper to get behat contexts.
|
||||
@@ -115,6 +116,34 @@ class behat_context_helper {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all Behat contexts which match the specified context class name prefix.
|
||||
*
|
||||
* Moodle uses a consistent class naming scheme for all Behat contexts, whereby the context name is in the format:
|
||||
*
|
||||
* behat_{component}
|
||||
*
|
||||
* This method will return all contexts which match the specified prefix.
|
||||
*
|
||||
* For example, to find all editors, you would pass in 'behat_editor', and this might return:
|
||||
* - behat_editor_atto
|
||||
* - behat_editor_textarea
|
||||
*
|
||||
* @param string $prefix The prefix to search for
|
||||
* @return \Behat\Behat\Context\Context[]
|
||||
*/
|
||||
public static function get_prefixed_contexts(string $prefix): array {
|
||||
if (!is_a(self::$environment, \Behat\Behat\Context\Environment\InitializedContextEnvironment::class)) {
|
||||
throw new DriverException(
|
||||
'Cannot get prefixed contexts - the environment is not an InitializedContextEnvironment'
|
||||
);
|
||||
}
|
||||
|
||||
return array_filter(self::$environment->getContexts(), function($context) use ($prefix): bool {
|
||||
return (strpos(get_class($context), $prefix) === 0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for any theme override of the specified class name.
|
||||
*
|
||||
|
||||
@@ -30,6 +30,7 @@ use Behat\Mink\Exception\ExpectationException;
|
||||
use Behat\Mink\Exception\ElementNotFoundException;
|
||||
use Behat\Mink\Exception\NoSuchWindowException;
|
||||
use Behat\Mink\Session;
|
||||
use Behat\Testwork\Hook\Scope\HookScope;
|
||||
use Facebook\WebDriver\Exception\ScriptTimeoutException;
|
||||
use Facebook\WebDriver\WebDriverBy;
|
||||
use Facebook\WebDriver\WebDriverElement;
|
||||
@@ -223,6 +224,22 @@ trait behat_session_trait {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a description of the selector and locator to use in an exception message.
|
||||
*
|
||||
* @param string $selector The type of locator
|
||||
* @param mixed $locator The locator text
|
||||
* @return string
|
||||
*/
|
||||
protected function get_selector_description(string $selector, $locator): string {
|
||||
if ($selector === 'NodeElement') {
|
||||
$description = $locator->getText();
|
||||
return "'{$description}' {$selector}";
|
||||
}
|
||||
|
||||
return "'{$locator}' {$selector}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Send key presses straight to the currently active element.
|
||||
*
|
||||
@@ -1038,6 +1055,29 @@ EOF;
|
||||
$this->look_for_exceptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a function in a specific behat context.
|
||||
*
|
||||
* For example, to call the 'set_editor_value' function for all editors, you would call:
|
||||
*
|
||||
* behat_base::execute_in_matching_contexts('editor', 'set_editor_value', ['Some value']);
|
||||
*
|
||||
* This would find all behat contexts whose class name starts with 'behat_editor_' and
|
||||
* call the 'set_editor_value' function on that context.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string $method
|
||||
* @param array $params
|
||||
*/
|
||||
public static function execute_in_matching_contexts(string $prefix, string $method, array $params): void {
|
||||
$contexts = behat_context_helper::get_prefixed_contexts("behat_{$prefix}_");
|
||||
foreach ($contexts as $context) {
|
||||
if (method_exists($context, $method) && is_callable([$context, $method])) {
|
||||
call_user_func_array([$context, $method], $params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual user in the behat session (note $USER does not correspond to the behat session's user).
|
||||
* @return mixed
|
||||
@@ -1587,4 +1627,63 @@ EOF;
|
||||
|
||||
return get_fast_modinfo($course)->get_cm($result->cmid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether any of the tags availble to the current scope match using the given callable.
|
||||
*
|
||||
* This function is typically called from within a Behat Hook, such as BeforeFeature, BeforeScenario, AfterStep, etc.
|
||||
*
|
||||
* The callable is used as the second argument to `array_filter()`, and is passed a single string argument for each of the
|
||||
* tags available in the scope.
|
||||
*
|
||||
* The tags passed will include:
|
||||
* - For a FeatureScope, the Feature tags only
|
||||
* - For a ScenarioScope, the Feature and Scenario tags
|
||||
* - For a StepScope, the Feature, Scenario, and Step tags
|
||||
*
|
||||
* An example usage may be:
|
||||
*
|
||||
* // Note: phpDoc beforeStep attribution not shown.
|
||||
* public function before_step(StepScope $scope) {
|
||||
* $callback = function (string $tag): bool {
|
||||
* return $tag === 'editor_atto' || substr($tag, 0, 5) === 'atto_';
|
||||
* };
|
||||
*
|
||||
* if (!self::scope_tags_match($scope, $callback)) {
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* // Do something here.
|
||||
* }
|
||||
*
|
||||
* @param HookScope $scope The scope to check
|
||||
* @param callable $callback The callable to use to check the scope
|
||||
* @return boolean Whether any of the scope tags match
|
||||
*/
|
||||
public static function scope_tags_match(HookScope $scope, callable $callback): bool {
|
||||
$tags = [];
|
||||
|
||||
if (is_subclass_of($scope, \Behat\Behat\Hook\Scope\FeatureScope::class)) {
|
||||
$tags = $scope->getFeature()->getTags();
|
||||
}
|
||||
|
||||
if (is_subclass_of($scope, \Behat\Behat\Hook\Scope\ScenarioScope::class)) {
|
||||
$tags = array_merge(
|
||||
$scope->getFeature()->getTags(),
|
||||
$scope->getScenario()->getTags()
|
||||
);
|
||||
}
|
||||
|
||||
if (is_subclass_of($scope, \Behat\Behat\Hook\Scope\StepScope::class)) {
|
||||
$tags = array_merge(
|
||||
$scope->getFeature()->getTags(),
|
||||
$scope->getScenario()->getTags(),
|
||||
$scope->getStep()->getTags()
|
||||
);
|
||||
}
|
||||
|
||||
$matches = array_filter($tags, $callback);
|
||||
|
||||
return !empty($matches);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user