Compare commits

..

93 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) 8e619076cb Moodle release 3.9.1 2020-07-12 12:13:02 +02:00
AMOS bot 6a17f29147 Automatically generated installer lang files 2020-07-10 19:52:47 +00:00
Eloy Lafuente (stronk7) cafc042bf6 weekly release 3.9+ 2020-07-10 20:22:25 +02:00
Eloy Lafuente (stronk7) d2e303436b Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-07-10 20:22:18 +02:00
Jake Dallimore fb0d5acf4c Merge branch 'MDL-69232-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-10 15:12:29 +08:00
Andrew Nicols 376d34142f MDL-69232 behat: Simplify hooks
The behat hooks were needlessly complicated which made them much harder
to read, and understand, leading to bugs during development.

These have been significantly simplified to favour clarity over
overloading.
2020-07-10 08:40:30 +08:00
Andrew Nicols 8eb7f7e366 MDL-69232 behat: Make selenium start more fault tolerant
The session was previously only started once, but has now been moved to
restart between each test. Because of this the `$session->start()` is
now called more frequently which exposes a pre-existing issue whereby
Selenium will periodically fail to start.

When the session was only started at the beginning of the test, and at
occasional other times, it made sense to always stop the test runner
because it signified an issue with obtaining the session at all.

Since the session is restarted more frequently, and now between every
test, it no longer makes sense to do this. The test should only be
_stopped_ if the first attempt to obtain the Session fails. Once a
Session has been retrieved at least once it no longer makes sense to
assume that the failure was a configuration failure, but a connection
failure. Therefore subsequent tests should be attempted.
2020-07-10 08:40:29 +08:00
Jake Dallimore c3018e9ee7 Merge branch 'MDL-69135-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-09 10:38:21 +08:00
Michael Hawkins 996c94fd08 MDL-68426 theme: Set a limit on paths length in yui_combo
The maximum paths length is now consistent with the YUI loader.
This fix also removes any duplicate paths, so each file is only ever
fetched once.
2020-07-09 10:23:44 +08:00
Andrew Nicols fd7c3c4834 MDL-69232 behat: Add debugging information to Selenium fails 2020-07-09 09:45:32 +08:00
Andrew Nicols c3b7f2f974 MDL-69232 behat: Move suite tests to BeforeSuite hook 2020-07-09 09:45:32 +08:00
Eloy Lafuente (stronk7) 8589fbda8c Merge branch 'MDL-69134-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-08 20:53:22 +02:00
Jake Dallimore f1a681c983 Merge branch 'MDL-69104-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE 2020-07-08 13:07:01 +08:00
Andrew Nicols 8a66849a57 Merge branch 'MDL-68784-39' of https://github.com/Peterburnett/moodle into MOODLE_39_STABLE 2020-07-08 12:37:27 +08:00
Andrew Nicols 20318b8b7d Merge branch 'm39_MDL-66322_Travis_Run_Using_Docker_ExtTests-v2' of https://github.com/scara/moodle into MOODLE_39_STABLE 2020-07-08 12:20:52 +08:00
Peter Burnett d84d6f57a3 MDL-68784: Updated variable for graph report 2020-07-08 14:06:23 +10:00
Juan Leyva 01ec0ee85b MDL-69031 tool_mobile: Add missing features that can be disabled in 3.9 2020-07-08 09:36:44 +08:00
Andrew Nicols 91b23a2caa Merge branch 'MDL-60494-stray_img_end-39' of https://github.com/leonstr/moodle into MOODLE_39_STABLE 2020-07-08 09:24:05 +08:00
Andrew Nicols 053a433d74 MDL-69134 competencies: Behat fails randomly opening dialogues 2020-07-08 09:21:51 +08:00
Marina Glancy b1a2e67326 MDL-69109 theme: try to load icons from the current theme 2020-07-08 08:40:52 +08:00
Marina Glancy 40553ed459 MDL-69109 core: use different cache keys for FA icon maps 2020-07-08 08:40:51 +08:00
Matteo Scaramuccia 9127c17778 MDL-66322 travis: Configure a local copy of 'exttests' 2020-07-07 21:34:06 +02:00
Andrew Nicols 8f28fbee11 MDL-69086 theme_boost: Improve pendingJs checks for bootstrap
Where an element, like an `alert`, is closed it is removed from the DOM
before the event fires (this is a correct behaviour).

This means that the final event confirming that the action happened
(i.e. close => closed) fires, but does not bubble up the DOM to the
document.body.

This change moves the end event listener to only be added after a start
event has been fired, and to attach directly to the HTMLElement where it
will be fired. This means that the Event handler will still be called,
even though it has been removed from the DOM, because it does not need
to bubble up to the body.
2020-07-07 20:01:02 +02:00
Eloy Lafuente (stronk7) be7bda671e Merge branch 'm39_MDL-68588_Hide_Backuptempdir_From_Message_And_Debuginfo' of https://github.com/scara/moodle into MOODLE_39_STABLE 2020-07-07 19:10:41 +02:00
Eloy Lafuente (stronk7) c58101cde3 Merge branch 'MDL-68784-39' of https://github.com/Peterburnett/moodle into MOODLE_39_STABLE 2020-07-07 18:52:27 +02:00
Víctor Déniz Falcón 6e5b0b5c20 MDL-69093 enrol_manual: added check for allowed roles a user can assign 2020-07-07 08:33:08 +02:00
Andrew Nicols c201456f20 Merge branch 'MDL-69106-39' of git.in.moodle.com:cameron/moodle into MOODLE_39_STABLE 2020-07-07 14:15:54 +08:00
Eloy Lafuente (stronk7) 02b3d5aacf Merge branch 'MDL-60827-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-07-07 00:17:26 +02:00
Andrew Nicols dde1ead9fe MDL-69110 table: Remove commented code 2020-07-06 13:26:28 +08:00
Andrew Nicols 3915147b9b Merge branch 'MDL-69110-39' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-07-06 13:26:00 +08:00
Andrew Nicols 55c7fe15a0 Merge branch 'MDL-69158-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-07-06 12:12:12 +08:00
Jake Dallimore 82dba4d510 Merge branch 'MDL-69136-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-06 10:44:34 +08:00
Mihail Geshoski 9ecff3766a MDL-60827 oauth2: Consider requireconfirmation setting on login 2020-07-06 10:05:16 +08:00
Michael Hawkins 4fb85c9c9f MDL-69128 admin: Convert HTML entities when populating tasklogs filter 2020-07-06 10:04:17 +08:00
AMOS bot 6ea5922916 Automatically generated installer lang files 2020-07-06 00:08:30 +00:00
Leon Stringer 287e8f16e6 MDL-60494 mod_lti: Invalid </img>, example context
<img> was followed by an invalid </img>.  Also added example context for
template so it passes CI checks.
2020-07-05 15:57:42 +01:00
Matteo Scaramuccia 846422a90f MDL-68588 Backup: Hide ->backuptempdir in exception info 2020-07-03 21:18:30 +02:00
Jun Pataleta ea6621e00e MDL-69110 core: Unset the correct sort data element 2020-07-04 00:50:21 +08:00
Eloy Lafuente (stronk7) 44ffa8a801 weekly release 3.9+ 2020-07-03 18:41:38 +02:00
Eloy Lafuente (stronk7) a1d5911159 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-07-03 18:41:32 +02:00
Jake Dallimore c38e38d6b4 Merge branch 'MDL-69130-39-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-07-02 12:08:37 +08:00
Jake Dallimore f5b5f97f56 Merge branch 'MDL-69149-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-02 11:57:18 +08:00
Jake Dallimore 5528302282 Merge branch 'MDL-69122-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-07-02 11:49:19 +08:00
AMOS bot 995f0a3a58 Automatically generated installer lang files 2020-07-02 00:08:08 +00:00
Eloy Lafuente (stronk7) 894ebe38a2 Merge branch 'MDL-69072-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-01 23:23:45 +02:00
Andrew Nicols 0609febf16 MDL-69072 behat: Remove restart_browser_after feature
This is no longer required as the Mink session is restarted after every
test regardless.
2020-07-01 23:23:39 +02:00
Luca Bösch 1d6c1cc0ae MDL-68584 core_question: flexbox compatible separator for question types
* the br tag does not work well in a flexbox context, a 100% with div
works in both classic and boost.
2020-07-01 16:42:50 +08:00
Paul Holden d783f12861 MDL-69150 message_airnotifier: correct apps portal link. 2020-07-01 08:39:47 +08:00
Paul Holden f324c2d16c MDL-69151 message_airnotifier: start output before accesskey request.
This allows debugging generated by the request to be shown on the
page.
2020-07-01 08:32:34 +08:00
Huong Nguyen 5486975097 MDL-69104 Questions: Drag and drop question family don't work with iOS
- Drag and Drop marker question type
 - Drag and Drop onto image question type
 - Drag and Drop into text question type
2020-06-30 14:48:47 +07:00
Cameron Ball d4b6b26f4f MDL-69106 assignfeedback_editpdf: Keep files in conversion queue
In some circumstances, a submission waiting to be converted needs to persist
in the conversion queue so that it can be polled on subsequent cron runs.
2020-06-30 13:56:57 +08:00
Peter Burnett 996dd0b0b9 MDL-68784 scorm: Removed limit on allowed scorm users in report 2020-06-30 15:17:51 +10:00
Luca Bösch b44588aaba MDL-69158 block_blog_menu: format search form. 2020-06-29 11:13:55 +02:00
Andrew Nicols 95fbf4d8e5 MDL-69136 behat: Improve reliability of navigation steps 2020-06-29 11:36:36 +08:00
Andrew Nicols 6f78024717 MDL-69136 behat: Support find on a NodeElement 2020-06-29 11:36:30 +08:00
Andrew Nicols 7b2e257157 MDL-69072 mod_scorm: Stop mink reset after tests
This is now done for all scenarios. It is no longer necessary to do so
specifically for mod_scorm.
2020-06-26 21:17:23 +08:00
Andrew Nicols bb344d07e7 MDL-69072 behat: Relaunch browser session between scenarios 2020-06-26 21:17:22 +08:00
Andrew Nicols 959c2cb84e MDL-69149 core_grade: Correct xpath attribute selector 2020-06-26 19:59:56 +08:00
Andrew Nicols ee7b438f61 MDL-69135 core_calendar: PendingJS for event filtering 2020-06-26 07:58:36 +08:00
Helen Foster dc0241306b MDL-69130 lang: Import fixed English strings (en_fix)
Significant string change:

- presentationoraltrequired,atto_image - wording changed to mention
  'decorative only' checkbox
2020-06-25 21:52:35 +02:00
Eloy Lafuente (stronk7) 89ce4db476 weekly release 3.9+ 2020-06-25 18:06:36 +02:00
Eloy Lafuente (stronk7) 55a1405a84 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-06-25 18:06:31 +02:00
Bas Brands 57b920b8b7 MDL-69122 report_competency: fix clearfix
- a misplaced clearfix caused part of the recontrols to be
inaccessible
2020-06-24 09:15:28 +02:00
Nicolas Martignoni bae07c1bfb MDL-68992 Privacy: Update default minimal digital age of consent
Updating default minimal digital age of consent according to current legislation,
that was updated for several countries since 2018.
2020-06-24 10:14:53 +08:00
Peter Dias 4f7016f2da MDL-69065 course: Provide the id for the sr param
* Pass the section return id to the activity chooser
* Additional behat test to cover the case
2020-06-24 10:14:51 +08:00
Andrew Nicols 7af8441403 MDL-66568 behat: Reset theme CSS between scenarios 2020-06-23 18:03:52 +02:00
Andrew Nicols 7ba95339a6 MDL-66568 behat: Support building of themes for behat 2020-06-23 18:03:52 +02:00
Andrew Nicols b6c37f2926 MDL-66568 core_output: Return built theme CSS 2020-06-23 18:03:52 +02:00
AMOS bot b8408c3582 Automatically generated installer lang files 2020-06-23 12:25:17 +00:00
Bas Brands fb625069cf MDL-69021 theme_boost: improve link styles in alerts
- provide default styles for links in alerts if the .alert-link
css class is omitted.
2020-06-23 11:31:23 +08:00
hiendinh d4297993a4 MDL-68841 Modal dialogs: Wrong behavior of popup 2020-06-23 09:45:44 +08:00
Víctor Déniz Falcón 2104324ded Merge branch 'MDL-69099-39-disabledtasks' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-06-22 17:20:10 +01:00
David Mudrák 153b2cb484 MDL-69099 tasks: Do not mark the non-enabled plugin's task as disabled
The `core\plugininfo\base::is_enabled()` uses three-state logic for its
return value. It can return null as a valid value as per its
documentation. We need to test for the explicit false value in this
case.

To make the attached Behat test able to identify the table, the caption
is added. It seems to be helpful for all users so I leave it displayed
without using the accesshide mechanism.
2020-06-22 10:10:15 +02:00
Jake Dallimore c72adaa749 Merge branch 'MDL-69047-39' of git://github.com/aanabit/moodle into MOODLE_39_STABLE 2020-06-22 12:41:28 +08:00
Adrian Greeve 3c2ed1533c Merge branch 'MDL-69077_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-06-22 10:41:47 +08:00
Jun Pataleta b9518bf811 MDL-69008 core: Fix accessibility issues in paged content templates
* Added menuitem role for the "Show x per page" menu.
* Added appropriate aria-labels for the links in the paging bar.
2020-06-19 16:49:03 +02:00
Amaia Anabitarte 4f0f1bd84f MDL-69047 core_contentbank: Hard coding status messages 2020-06-18 18:07:41 +02:00
Sara Arjona e2ef786003 weekly release 3.9+ 2020-06-18 14:14:00 +02:00
Russell Boyatt 5b134b5de5 MDL-66899 quiz: Adding test for regrading quiz event. 2020-06-18 04:52:47 +01:00
Russell Boyatt 62c4da281a MDL-66899 quiz: Log a regrading event when quiz attempt is regraded. 2020-06-18 04:52:47 +01:00
Víctor Déniz Falcón 4c27f858b9 Merge branch 'MDL-69060-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-06-17 23:44:40 +01:00
Tim Hunt 6ced5c26d0 MDL-69077 questions: question tag capabilties are relevant 2020-06-17 13:07:30 +01:00
hiendinh ccd504115d MDL-68890 progressbar: prevent display exist file's progress bar 2020-06-17 19:54:06 +08:00
Jake Dallimore 647e5d8021 Merge branch 'MDL-68215-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-06-17 14:58:35 +08:00
Tim Hunt 6a7042d980 MDL-68971 webservice: errors should give enough info to find the problem 2020-06-17 11:36:46 +08:00
Jun Pataleta 7532b032bb Merge branch 'MDL-67294-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-06-17 10:36:14 +08:00
Jun Pataleta b5c1d17da5 MDL-69049 tool_dataprivacy: Add possibly missing comment format columns
The earlier CONTRIB plugin versions of the tool (<33.2.0, <34.2.0) were
missing the following columns in the data requests table:
* commentsformat
* dpocommentformat
And the upgrade scripts for the merged tool failed in
Moodle 3.3.8+/3.3.0+ failed to add these columns.
So a site which uses the CONTRIB plugin and eventually upgrading to 3.9
will encounter an error during upgrade because of the missing
dpocommentformat column.
2020-06-16 17:59:03 +01:00
Mihail Geshoski 56a7d91066 MDL-67294 assignsubmission_file: Make sure record exists before updating 2020-06-17 00:55:46 +08:00
Tim Hunt 93d636a95b MDL-68436 atto_recordrtc: only works once per page 2020-06-16 14:40:35 +08:00
Víctor Déniz Falcón 7ca771e4ac Merge branch 'MDL-69044_39' of https://github.com/stronk7/moodle into MOODLE_39_STABLE 2020-06-15 17:36:32 +01:00
Luca Bösch 6e7e7e1241 MDL-68215 block_activity_result: Format elements more nicely. 2020-06-15 15:26:13 +02:00
Luca Bösch 8b43f32f8c MDL-69060 core_contentbank: fix contenbank typos. 2020-06-15 13:37:00 +02:00
Eloy Lafuente (stronk7) a30eb7d16c MDL-69044 upgrade: add 3.9.0 separation line to all upgrade scripts 2020-06-14 13:09:13 +02:00
3476 changed files with 29349 additions and 73689 deletions
+1 -4
View File
@@ -19,7 +19,6 @@ lib/editor/tinymce/plugins/spellchecker/rpc.php
lib/editor/tinymce/tiny_mce/
lib/mlbackend/php/phpml/
lib/adodb/
lib/behat/axe/
lib/bennu/
lib/evalmath/
lib/phpspreadsheet/
@@ -67,9 +66,6 @@ lib/babel-polyfill/
lib/polyfills/
lib/emoji-data/
lib/plist/
lib/zipstream/
lib/php-enum/
lib/http-message/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
@@ -92,4 +88,5 @@ theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
-71
View File
@@ -1,71 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Template configuraton file for github actions CI/CD.
*
* @package core
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com}
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This cannot be used out from a github actions workflow, so just exit.
getenv('GITHUB_WORKFLOW') || die; // phpcs:ignore moodle.Files.MoodleInternal.MoodleInternalGlobalState
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->dbtype = getenv('dbtype');
$CFG->dblibrary = 'native';
$CFG->dbhost = '127.0.0.1';
$CFG->dbname = 'test';
$CFG->dbuser = 'test';
$CFG->dbpass = 'test';
$CFG->prefix = 'm_';
$CFG->dboptions = ['dbcollation' => 'utf8mb4_bin'];
$host = 'localhost';
$CFG->wwwroot = "http://{$host}";
$CFG->dataroot = realpath(dirname(__DIR__)) . '/moodledata';
$CFG->admin = 'admin';
$CFG->directorypermissions = 0777;
// Debug options - possible to be controlled by flag in future.
$CFG->debug = (E_ALL | E_STRICT); // DEBUG_DEVELOPER.
$CFG->debugdisplay = 1;
$CFG->debugstringids = 1; // Add strings=1 to url to get string ids.
$CFG->perfdebug = 15;
$CFG->debugpageinfo = 1;
$CFG->allowthemechangeonurl = 1;
$CFG->passwordpolicy = 0;
$CFG->cronclionly = 0;
$CFG->pathtophp = getenv('pathtophp');
$CFG->phpunit_dataroot = realpath(dirname(__DIR__)) . '/phpunitdata';
$CFG->phpunit_prefix = 't_';
define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://localhost:8080');
define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://localhost:8080');
define('TEST_SESSION_REDIS_HOST', 'localhost');
define('TEST_CACHESTORE_REDIS_TESTSERVERS', 'localhost');
// TODO: add others (solr, mongodb, memcached, ldap...).
// Too much for now: define('PHPUNIT_LONGTEST', true); // Only leaves a few tests out and they are run later by CI.
require_once(__DIR__ . '/lib/setup.php');
-103
View File
@@ -1,103 +0,0 @@
name: Core
on: [push]
env:
php: 7.4
jobs:
Grunt:
runs-on: ubuntu-18.04
steps:
- name: Checking out code
uses: actions/checkout@v2
- name: Configuring node & npm
shell: bash -l {0}
run: nvm install
- name: Installing node stuff
run: npm install
- name: Running grunt
run: npx grunt
- name: Looking for uncommitted changes
# Add all files to the git index and then run diff --cached to see all changes.
# This ensures that we get the status of all files, including new files.
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
run: |
git add .
git reset -- npm-shrinkwrap.json
git diff --cached --exit-code
PHPUnit:
runs-on: ${{ matrix.os }}
services:
exttests:
image: moodlehq/moodle-exttests
ports:
- 8080:80
redis:
image: redis
ports:
- 6379:6379
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
php: 7.2
db: mysqli
- os: ubuntu-18.04
php: 7.4
db: pgsql
steps:
- name: Setting up DB mysql
if: ${{ matrix.db == 'mysqli' }}
uses: johanmeiring/mysql-action@tmpfs-patch
with:
collation server: utf8mb4_bin
mysql version: 5.7
mysql database: test
mysql user: test
mysql password: test
use tmpfs: true
- name: Setting up DB pgsql
if: ${{ matrix.db == 'pgsql' }}
uses: m4nu56/postgresql-action@v1
with:
postgresql version: 9.6
postgresql db: test
postgresql user: test
postgresql password: test
- name: Configuring git vars
uses: rlespinasse/github-slug-action@v3.x
- name: Setting up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
uses: actions/checkout@v2
- name: Setting up PHPUnit
env:
dbtype: ${{ matrix.db }}
run: |
echo "pathtophp=$(which php)" >> $GITHUB_ENV # Inject installed pathtophp to env. The template config needs it.
cp .github/workflows/config-template.php config.php
mkdir ../moodledata
sudo locale-gen en_AU.UTF-8
php admin/tool/phpunit/cli/init.php --no-composer-self-update
- name: Running PHPUnit tests
env:
dbtype: ${{ matrix.db }}
run: vendor/bin/phpunit -v
-2
View File
@@ -33,7 +33,6 @@ CVS
/.project
/.buildpath
/.cache
.phpunit.result.cache
phpunit.xml
# Composer support. Do not ignore composer.json, or composer.lock. These should be shipped by us.
composer.phar
@@ -45,4 +44,3 @@ composer.phar
/lib/yuilib/*/*/*-coverage.js
atlassian-ide-plugin.xml
/node_modules/
/.vscode/
+1 -1
View File
@@ -1 +1 @@
v14.15.0
v14.0.0
+1 -4
View File
@@ -20,7 +20,6 @@ lib/editor/tinymce/plugins/spellchecker/rpc.php
lib/editor/tinymce/tiny_mce/
lib/mlbackend/php/phpml/
lib/adodb/
lib/behat/axe/
lib/bennu/
lib/evalmath/
lib/phpspreadsheet/
@@ -68,9 +67,6 @@ lib/babel-polyfill/
lib/polyfills/
lib/emoji-data/
lib/plist/
lib/zipstream/
lib/php-enum/
lib/http-message/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
@@ -93,4 +89,5 @@ theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
+73 -38
View File
@@ -2,9 +2,10 @@
# process (which uses our internal CI system) this file is here for the benefit
# of community developers git clones - see MDL-51458.
# We currently disable Travis notifications entirely until https://github.com/travis-ci/travis-ci/issues/4976
# is fixed.
notifications:
email:
if: env(MOODLE_EMAIL) != no
email: false
language: php
@@ -16,9 +17,31 @@ services:
- mysql
- docker
php:
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
- 7.4
- 7.2
addons:
postgresql: "9.6"
env:
# Although we want to run these jobs and see failures as quickly as possible, we also want to get the slowest job to
# start first so that the total run time is not too high.
#
# We only run MySQL on PHP 7.2, so run that first.
# CI Tests should be second-highest in priority as these only take <= 60 seconds to run under normal circumstances.
# Postgres is significantly is pretty reasonable in its run-time.
# Run CI Tests without running PHPUnit.
- DB=none TASK=CITEST
# Run unit tests on Postgres
- DB=pgsql TASK=PHPUNIT
# Perform an upgrade test too.
- DB=pgsql TASK=UPGRADE
jobs:
# Enable fast finish.
# This will fail the build if a single job fails (except those in allow_failures).
@@ -26,35 +49,12 @@ jobs:
fast_finish: true
include:
# First all the lowest php ones (7.2)
- php: 7.2
env: DB=none TASK=CITEST
- php: 7.2
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
- if: env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present
php: 7.2
env: DB=pgsql TASK=PHPUNIT
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
php: 7.2
env: DB=mysqli TASK=PHPUNIT
# Then, conditionally, all the highest php ones (7.4)
- if: env(MOODLE_PHP) = "all"
php: 7.4
env: DB=none TASK=CITEST
- if: env(MOODLE_PHP) = "all"
php: 7.4
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present)
php: 7.4
env: DB=pgsql TASK=PHPUNIT
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
php: 7.4
# Run mysql only on highest - it's just too slow
- php: 7.4
env: DB=mysqli TASK=PHPUNIT
# Run grunt/npm install on highest version too ('node' is an alias for the latest node.js version.)
- php: 7.4
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
cache:
directories:
@@ -114,7 +114,7 @@ install:
before_script:
- phpenv config-rm xdebug.ini
- >
if [ "$TASK" = 'PHPUNIT' ];
if [ "$TASK" = 'PHPUNIT' -o "$TASK" = 'UPGRADE' ];
then
# Copy generic configuration in place.
cp config-dist.php config.php ;
@@ -174,9 +174,7 @@ before_script:
# Enable test external resources
sed -i \
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://127.0.0.1:8080');" \
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://127.0.0.1:8080');" \
config.php ;
# Redis cache store tests
sed -i \
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
@@ -214,7 +212,7 @@ before_script:
# We need the official upstream for comparison
git remote add upstream https://github.com/moodle/moodle.git;
git fetch upstream MOODLE_310_STABLE;
git fetch upstream MOODLE_39_STABLE;
export GIT_PREVIOUS_COMMIT="`git merge-base FETCH_HEAD $TRAVIS_COMMIT`";
export GIT_COMMIT="$TRAVIS_COMMIT";
export UPSTREAM_FETCH_HEAD=`git rev-parse FETCH_HEAD`
@@ -225,11 +223,39 @@ before_script:
export phpcmd=`which php`;
fi
########################################################################
# Upgrade test
########################################################################
- >
if [ "$TASK" = 'UPGRADE' ];
then
# We need the official upstream.
git remote add upstream https://github.com/moodle/moodle.git;
# Checkout 30 STABLE branch (the first version compatible with PHP 7.x)
git fetch upstream MOODLE_30_STABLE;
git checkout MOODLE_30_STABLE;
# Perform the upgrade
php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
# Return to the previous commit
git checkout -;
# Perform the upgrade
php admin/cli/upgrade.php --non-interactive --allow-unstable ;
# The local_ci repository can be used to check upgrade savepoints.
git clone https://github.com/moodlehq/moodle-local_ci.git local/ci ;
fi
script:
- >
if [ "$TASK" = 'PHPUNIT' ];
then
vendor/bin/phpunit --fail-on-risky --disallow-test-output --verbose;
EXTTESTS_HITS=$(docker logs exttests 2>&1 | grep -Fv -e 'AH00558' -e '[pid 1]' | wc -l)
echo -e "\nTest local resources number of hits: ${EXTTESTS_HITS}.\n"
fi
- >
@@ -250,10 +276,19 @@ script:
git diff --cached --exit-code ;
fi
after_script:
########################################################################
# Upgrade test
########################################################################
- >
if [ "$TASK" = 'PHPUNIT' ];
if [ "$TASK" = 'UPGRADE' ];
then
EXTTESTS_HITS=$(docker logs exttests 2>&1 | grep -Fv -e 'AH00558' -e '[pid 1]' | wc -l)
echo -e "\nTest local resources number of hits: ${EXTTESTS_HITS}.\n"
cp local/ci/check_upgrade_savepoints/check_upgrade_savepoints.php ./check_upgrade_savepoints.php
result=`php check_upgrade_savepoints.php`;
# Check if there are problems
count=`echo "$result" | grep -P "ERROR|WARN" | wc -l` ;
if (($count > 0));
then
echo "$result"
exit 1 ;
fi
fi
@@ -15,41 +15,34 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Clientside filter base.
* Admin settings search form
*
* @package tool_usertours
* @copyright 2020 The Open University
* @package admin
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\clientside_filter;
defined('MOODLE_INTERNAL') || die();
use stdClass;
use tool_usertours\local\filter\base;
use tool_usertours\tour;
require_once $CFG->libdir.'/formslib.php';
/**
* Clientside filter base.
* Admin settings search form
*
* @copyright 2020 The Open University
* @package admin
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class clientside_filter extends base {
/**
* Returns the filter values needed for client side filtering.
*
* @param tour $tour The tour to find the filter values for
* @return stdClass
*/
public static function get_client_side_values(tour $tour): stdClass {
$data = (object) [];
class admin_settings_search_form extends moodleform {
function definition () {
$mform = $this->_form;
if (is_a(static::class, clientside_filter::class, true)) {
$data->filterdata = $tour->get_filter_values(static::get_filter_name());
}
return $data;
//$mform->addElement('header', 'settingsheader', get_string('search', 'admin'));
$elements = [];
$elements[] = $mform->createElement('text', 'query', get_string('query', 'admin'));
$elements[] = $mform->createElement('submit', 'search', get_string('search'));
$mform->addGroup($elements);
$mform->setType('query', PARAM_RAW);
$mform->setDefault('query', optional_param('query', '', PARAM_RAW));
}
}
}
@@ -43,7 +43,7 @@ class testoutgoingmailconf_form extends \moodleform {
$mform = $this->_form;
// Recipient.
$options = ['maxlength' => '100', 'size' => '25', 'autocomplete' => 'email'];
$options = ['maxlength' => '100', 'size' => '25'];
$mform->addElement('text', 'recipient', get_string('testoutgoingmailconf_toemail', 'admin'), $options);
$mform->setType('recipient', PARAM_EMAIL);
$mform->addRule('recipient', get_string('required'), 'required');
@@ -1,71 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* External admin page class that allows a callback to be provided to determine whether page can be accessed
*
* @package core_admin
* @copyright 2019 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\externalpage;
use admin_externalpage;
defined('MOODLE_INTERNAL') || die();
require_once("{$CFG->libdir}/adminlib.php");
/**
* Admin externalpage class
*
* @package core_admin
* @copyright 2019 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class accesscallback extends admin_externalpage {
/** @var callable $accesscheckcallback */
protected $accesscheckcallback;
/**
* Class constructor
*
* @param string $name
* @param string $visiblename
* @param string $url
* @param callable $accesscheckcallback The callback method that will be executed to check whether user has access to
* this page. The setting instance ($this) is passed as an argument to the callback. Should return boolean value
* @param bool $hidden
*/
public function __construct(string $name, string $visiblename, string $url, callable $accesscheckcallback,
bool $hidden = false) {
$this->accesscheckcallback = $accesscheckcallback;
parent::__construct($name, $visiblename, $url, [], $hidden);
}
/**
* Determines if the current user has access to this external page based on access callback
*
* @return bool
*/
public function check_access() {
return ($this->accesscheckcallback)($this);
}
}
@@ -1,206 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Auto complete admin setting.
*
* @package core_admin
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/adminlib.php');
/**
* Auto complete setting class.
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @copyright 2020 The Open University
*/
class autocomplete extends \admin_setting_configmultiselect {
/** @var boolean Should we allow typing new entries to the field? */
protected $tags = false;
/** @var string Name of an AMD module to send/process ajax requests. */
protected $ajax = '';
/** @var string Placeholder text for an empty list. */
protected $placeholder = '';
/** @var bool Whether the search has to be case-sensitive. */
protected $casesensitive = false;
/** @var bool Show suggestions by default - but this can be turned off. */
protected $showsuggestions = true;
/** @var string String that is shown when there are no selections. */
protected $noselectionstring = '';
/** @var string Delimiter to store values in database. */
protected $delimiter = ',';
/** @var string Should be multiple choices? */
protected $multiple = true;
/** @var string The link to manage choices. */
protected $manageurl = true;
/** @var string The text to display in manage link. */
protected $managetext = true;
/**
* Constructor
*
* @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting'
* for ones in config_plugins.
* @param string $visiblename localised
* @param string $description long localised info
* @param array $defaultsetting array of selected items
* @param array $choices options for autocomplete field
* @param array $attributes settings for autocomplete field
*/
public function __construct($name, $visiblename, $description, $defaultsetting, $choices, $attributes = null) {
if ($attributes === null) {
$attributes = [];
}
$this->placeholder = get_string('search');
$this->noselectionstring = get_string('noselection', 'form');
$defaultattributes = [
'tags',
'showsuggestions',
'placeholder',
'noselectionstring',
'ajax',
'casesensitive',
'delimiter',
'multiple',
'manageurl',
'managetext'
];
foreach ($defaultattributes as $attributename) {
if (isset($attributes[$attributename])) {
$this->$attributename = $attributes[$attributename];
}
}
parent::__construct($name, $visiblename, $description, $defaultsetting, $choices);
}
/**
* Returns the select setting(s)
*
* @return mixed null or array. Null if no settings else array of setting(s)
*/
public function get_setting() {
$result = $this->config_read($this->name);
if (is_null($result)) {
return null;
}
if ($result === '') {
return [];
}
return explode($this->delimiter, $result);
}
/**
* Saves setting(s) provided through $data
*
* @param array $data
*/
public function write_setting($data) {
if (!is_array($data)) {
return ''; // Ignore it.
}
if (!$this->load_choices() || empty($this->choices)) {
return '';
}
unset($data['xxxxx']);
$save = [];
foreach ($data as $value) {
if (!array_key_exists($value, $this->choices)) {
continue; // Ignore it.
}
$save[] = $value;
}
return ($this->config_write($this->name, implode($this->delimiter, $save)) ? '' : get_string('errorsetting', 'admin'));
}
/**
* Returns XHTML autocomplete field
*
* @param array $data Array of values to select by default
* @param string $query
* @return string XHTML autocomplete field
*/
public function output_html($data, $query = '') {
global $OUTPUT;
if (!$this->load_choices() or empty($this->choices)) {
return '';
}
$default = $this->get_defaultsetting();
if (empty($default)) {
$default = [];
}
if (is_null($data)) {
$data = [];
}
$context = [
'id' => $this->get_id(),
'name' => $this->get_full_name()
];
$defaults = [];
$options = [];
$template = 'core_admin/local/settings/autocomplete';
foreach ($this->choices as $value => $name) {
if (in_array($value, $default)) {
$defaults[] = $name;
}
$options[] = [
'value' => $value,
'text' => $name,
'selected' => in_array($value, $data),
'disabled' => false
];
}
$context['options'] = $options;
$context['tags'] = $this->tags;
$context['placeholder'] = $this->placeholder;
$context['casesensitive'] = $this->casesensitive;
$context['multiple'] = $this->multiple;
$context['showsuggestions'] = $this->showsuggestions;
$context['manageurl'] = $this->manageurl;
$context['managetext'] = $this->managetext;
if (is_null($default)) {
$defaultinfo = null;
} if (!empty($defaults)) {
$defaultinfo = implode(', ', $defaults);
} else {
$defaultinfo = get_string('none');
}
$element = $OUTPUT->render_from_template($template, $context);
return format_admin_setting($this, $this->visiblename, $element, $this->description, true, '', $defaultinfo, $query);
}
}
@@ -178,7 +178,6 @@ class filesize extends \admin_setting {
'id' => $this->get_id(),
'name' => $this->get_full_name(),
'value' => $data['v'],
'readonly' => $this->is_readonly(),
'options' => array_map(function($unit, $title) use ($data, $defaultunit) {
return [
'value' => $unit,
@@ -1,74 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Payment gateway admin setting.
*
* @package core_admin
* @copyright 2020 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
/**
* Generic class for managing plugins in a table that allows re-ordering and enable/disable of each plugin.
*/
class manage_payment_gateway_plugins extends \admin_setting_manage_plugins {
/**
* Get the admin settings section title (use get_string).
*
* @return string
*/
public function get_section_title() {
return get_string('type_paygw_plural', 'plugin');
}
/**
* Get the type of plugin to manage.
*
* @return string
*/
public function get_plugin_type() {
return 'paygw';
}
/**
* Get the name of the second column.
*
* @return string
*/
public function get_info_column_name() {
return get_string('supportedcurrencies', 'core_payment');
}
/**
* Get the type of plugin to manage.
*
* @param plugininfo The plugin info class.
* @return string
*/
public function get_info_column($plugininfo) {
$codes = $plugininfo->get_supported_currencies();
$currencies = [];
foreach ($codes as $c) {
$currencies[$c] = new \lang_string($c, 'core_currencies');
}
return implode(get_string('listsep', 'langconfig') . ' ', $currencies);
}
}
-3
View File
@@ -57,8 +57,6 @@ class task_log_table extends \table_sql {
'userid' => get_string('user', 'admin'),
'timestart' => get_string('task_starttime', 'admin'),
'duration' => get_string('task_duration', 'admin'),
'hostname' => get_string('hostname', 'tool_task'),
'pid' => get_string('pid', 'tool_task'),
'db' => get_string('task_dbstats', 'admin'),
'result' => get_string('task_result', 'admin'),
'actions' => '',
@@ -134,7 +132,6 @@ class task_log_table extends \table_sql {
$sql = "SELECT
tl.id, tl.type, tl.component, tl.classname, tl.userid, tl.timestart, tl.timeend,
tl.hostname, tl.pid,
tl.dbreads, tl.dbwrites, tl.result,
tl.dbreads + tl.dbwrites AS db,
tl.timeend - tl.timestart AS duration,
-9
View File
@@ -37,13 +37,11 @@ list($options, $unrecognized) = cli_get_params(
'showsql' => false,
'showdebugging' => false,
'ignorelimits' => false,
'force' => false,
], [
'h' => 'help',
'e' => 'execute',
'k' => 'keep-alive',
'i' => 'ignorelimits',
'f' => 'force',
]
);
@@ -63,7 +61,6 @@ Options:
-e, --execute Run all queued adhoc tasks
-k, --keep-alive=N Keep this script alive for N seconds and poll for new adhoc tasks
-i --ignorelimits Ignore task_adhoc_concurrency_limit and task_adhoc_max_runtime limits
-f, --force Run even if cron is disabled
Example:
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
@@ -95,12 +92,6 @@ if (moodle_needs_upgrading()) {
if (empty($options['execute'])) {
exit(0);
}
if (!get_config('core', 'cron_enabled') && !$options['force']) {
mtrace('Cron is disabled. Use --force to override.');
exit(1);
}
if (empty($options['keep-alive'])) {
$options['keep-alive'] = 0;
}
+6 -105
View File
@@ -36,23 +36,14 @@ require_once($CFG->libdir.'/cronlib.php');
// now get cli options
list($options, $unrecognized) = cli_get_params(
[
array(
'help' => false,
'stop' => false,
'list' => false,
'force' => false,
'enable' => false,
'disable' => false,
'disable-wait' => false,
], [
),
array(
'h' => 'help',
's' => 'stop',
'l' => 'list',
'f' => 'force',
'e' => 'enable',
'd' => 'disable',
'w' => 'disable-wait',
]
)
);
if ($unrecognized) {
@@ -65,13 +56,8 @@ if ($options['help']) {
"Execute periodic cron actions.
Options:
-h, --help Print out this help
-s, --stop Notify all other running cron processes to stop after the current task
-l, --list Show the list of currently running tasks and how long they have been running
-f, --force Execute task even if cron is disabled
-e, --enable Enable cron
-d, --disable Disable cron
-w, --disable-wait=600 Disable cron and wait until all tasks finished or fail after N seconds (optional param)
-h, --help Print out this help
-s, --stop Notify all other running cron processes to stop after the current task
Example:
\$sudo -u www-data /usr/bin/php admin/cli/cron.php
@@ -88,91 +74,6 @@ if ($options['stop']) {
die;
}
if ($options['enable']) {
set_config('cron_enabled', 1);
mtrace('Cron has been enabled for the site.');
exit(0);
}
if ($options['disable']) {
set_config('cron_enabled', 0);
\core\task\manager::clear_static_caches();
mtrace('Cron has been disabled for the site.');
exit(0);
}
if ($options['list']) {
$tasks = \core\task\manager::get_running_tasks();
mtrace('The list of currently running tasks:');
$format = "%7s %-12s %-9s %-20s %-52s\n";
printf ($format,
'PID',
'HOST',
'TYPE',
'TIME',
'CLASSNAME'
);
foreach ($tasks as $task) {
printf ($format,
$task->pid,
substr($task->hostname, 0, 12),
$task->type,
format_time(time() - $task->timestarted),
substr($task->classname, 0, 52)
);
}
exit(0);
}
if ($wait = $options['disable-wait']) {
$started = time();
if (true === $wait) {
// Default waiting time.
$waitsec = 600;
} else {
$waitsec = $wait;
$wait = true;
}
set_config('cron_enabled', 0);
\core\task\manager::clear_static_caches();
mtrace('Cron has been disabled for the site.');
mtrace('Allocating '. format_time($waitsec) . ' for the tasks to finish.');
$lastcount = 0;
while ($wait) {
$tasks = \core\task\manager::get_running_tasks();
if (count($tasks) == 0) {
mtrace('');
mtrace('All scheduled and adhoc tasks finished.');
exit(0);
}
if (time() - $started >= $waitsec) {
mtrace('');
mtrace('Wait time ('. format_time($waitsec) . ') elapsed, but ' . count($tasks) . ' task(s) still running.');
mtrace('Exiting with code 1.');
exit(1);
}
if (count($tasks) !== $lastcount) {
mtrace('');
mtrace(count($tasks) . " tasks currently running.", '');
$lastcount = count($tasks);
} else {
mtrace('.', '');
}
sleep(1);
}
}
if (!get_config('core', 'cron_enabled') && !$options['force']) {
mtrace('Cron is disabled. Use --force to override.');
exit(1);
}
\core\local\cli\shutdown::script_supports_graceful_exit();
cron_run();
+97 -107
View File
@@ -215,7 +215,6 @@ define('SITEID', 1);
//Database types
$databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'),
'auroramysql' => moodle_database::get_driver_instance('auroramysql', 'native'),
'mariadb'=> moodle_database::get_driver_instance('mariadb', 'native'),
'pgsql' => moodle_database::get_driver_instance('pgsql', 'native'),
'oci' => moodle_database::get_driver_instance('oci', 'native'),
@@ -267,7 +266,6 @@ list($options, $unrecognized) = cli_get_params(
);
$interactive = empty($options['non-interactive']);
$skipdatabase = $options['skip-database'];
// set up language
$lang = clean_param($options['lang'], PARAM_SAFEDIR);
@@ -639,100 +637,96 @@ do {
}
} while ($hintdatabase !== '');
// If --skip-database option is provided, we do not need to ask for site fullname, shortname, adminuser, adminpass, adminemail.
// These fields will be requested during the database install part.
if (!$skipdatabase) {
// Ask for fullname.
if ($interactive) {
cli_separator();
cli_heading(get_string('fullsitename', 'moodle'));
// ask for fullname
if ($interactive) {
cli_separator();
cli_heading(get_string('fullsitename', 'moodle'));
if ($options['fullname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['fullname'] = cli_input($prompt, $options['fullname']);
} while (empty($options['fullname']));
if ($options['fullname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
} else {
if (empty($options['fullname'])) {
$a = (object)['option' => 'fullname', 'value' => $options['fullname']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for shortname.
if ($interactive) {
cli_separator();
cli_heading(get_string('shortsitename', 'moodle'));
if ($options['shortname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['shortname'] = cli_input($prompt, $options['shortname']);
} while (empty($options['shortname']));
} else {
if (empty($options['shortname'])) {
$a = (object)['option' => 'shortname', 'value' => $options['shortname']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for admin user name.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminusername', 'install'));
if (!empty($options['adminuser'])) {
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
} else {
if ((empty($options['adminuser']) || $options['adminuser'] === 'guest')) {
$a = (object)['option' => 'adminuser', 'value' => $options['adminuser']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for admin user password.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminpassword', 'install'));
$prompt = get_string('clitypevalue', 'admin');
do {
$options['adminpass'] = cli_input($prompt);
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
} else {
if ((empty($options['adminpass']) or $options['adminpass'] === 'admin')) {
$a = (object)['option' => 'adminpass', 'value' => $options['adminpass']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for the admin email address.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
$options['adminemail'] = cli_input($prompt, $options['adminemail']);
}
// Validate that the address provided was an e-mail address.
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
$a = (object)['option' => 'adminemail', 'value' => $options['adminemail']];
do {
$options['fullname'] = cli_input($prompt, $options['fullname']);
} while (empty($options['fullname']));
} else {
if (empty($options['fullname'])) {
$a = (object)array('option'=>'fullname', 'value'=>$options['fullname']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// ask for shortname
if ($interactive) {
cli_separator();
cli_heading(get_string('shortsitename', 'moodle'));
if ($options['shortname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['shortname'] = cli_input($prompt, $options['shortname']);
} while (empty($options['shortname']));
} else {
if (empty($options['shortname'])) {
$a = (object)array('option'=>'shortname', 'value'=>$options['shortname']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// ask for admin user name
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminusername', 'install'));
if (!empty($options['adminuser'])) {
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
} else {
if (empty($options['adminuser']) or $options['adminuser'] === 'guest') {
$a = (object)array('option'=>'adminuser', 'value'=>$options['adminuser']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// ask for admin user password
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminpassword', 'install'));
$prompt = get_string('clitypevalue', 'admin');
do {
$options['adminpass'] = cli_input($prompt);
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
} else {
if (empty($options['adminpass']) or $options['adminpass'] === 'admin') {
$a = (object)array('option'=>'adminpass', 'value'=>$options['adminpass']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for the admin email address.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
$options['adminemail'] = cli_input($prompt, $options['adminemail']);
}
// Validate that the address provided was an e-mail address.
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
$a = (object) array('option' => 'adminemail', 'value' => $options['adminemail']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
// Ask for the upgrade key.
if ($interactive) {
cli_separator();
@@ -751,27 +745,23 @@ if ($options['upgradekey'] !== '') {
$CFG->upgradekey = $options['upgradekey'];
}
// The user does not also need to pass agree-license when --skip-database is provided as the user will need to accept
// the license again in the database install part.
if (!$skipdatabase) {
if ($interactive) {
if (!$options['agree-license']) {
cli_separator();
cli_heading(get_string('copyrightnotice'));
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
echo get_string('gpl3')."\n\n";
echo get_string('doyouagree')."\n";
$prompt = get_string('cliyesnoprompt', 'admin');
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
if ($input == get_string('clianswerno', 'admin')) {
exit(1);
}
}
} else {
if (!$options['agree-license'] && !$skipdatabase) {
cli_error(get_string('climustagreelicense', 'install'));
if ($interactive) {
if (!$options['agree-license']) {
cli_separator();
cli_heading(get_string('copyrightnotice'));
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
echo get_string('gpl3')."\n\n";
echo get_string('doyouagree')."\n";
$prompt = get_string('cliyesnoprompt', 'admin');
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
if ($input == get_string('clianswerno', 'admin')) {
exit(1);
}
}
} else {
if (!$options['agree-license']) {
cli_error(get_string('climustagreelicense', 'install'));
}
}
// Finally we have all info needed for config.php
@@ -819,7 +809,7 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
cli_error(get_string('pluginschecktodo', 'admin'));
}
if (!$skipdatabase) {
if (!$options['skip-database']) {
install_cli_database($options, $interactive);
// This needs to happen at the end to ensure it occurs after all caches
// have been purged for the last time.
-109
View File
@@ -1,109 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This script allows to restore a course from CLI.
*
* @package core
* @subpackage cli
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', 1);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/clilib.php');
require_once($CFG->dirroot . "/backup/util/includes/restore_includes.php");
list($options, $unrecognized) = cli_get_params([
'file' => '',
'categoryid' => '',
'showdebugging' => false,
'help' => false,
], [
'f' => 'file',
'c' => 'categoryid',
's' => 'showdebugging',
'h' => 'help',
]);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help'] || !($options['file']) || !($options['categoryid'])) {
$help = <<<EOL
Restore backup into provided category.
Options:
-f, --file=STRING Path to the backup file.
-c, --categoryid=INT ID of the category to restore too.
-s, --showdebugging Show developer level debugging information
-h, --help Print out this help.
Example:
\$sudo -u www-data /usr/bin/php admin/cli/restore_backup.php --file=/path/to/backup/file.mbz --categoryid=1\n
EOL;
echo $help;
exit(0);
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if (!$admin = get_admin()) {
print_error('noadmins');
}
if (!file_exists($options['file'])) {
print_error('filenotfound');
}
if (!$category = $DB->get_record('course_categories', ['id' => $options['categoryid']], 'id')) {
print_error('invalidcategoryid');
}
$backupdir = "restore_" . uniqid();
$path = $CFG->tempdir . DIRECTORY_SEPARATOR . "backup" . DIRECTORY_SEPARATOR . $backupdir;
cli_heading(get_string('extractingbackupfileto', 'backup', $path));
$fp = get_file_packer('application/vnd.moodle.backup');
$fp->extract_to_pathname($options['file'], $path);
cli_heading(get_string('preprocessingbackupfile'));
try {
list($fullname, $shortname) = restore_dbops::calculate_course_names(0, get_string('restoringcourse', 'backup'),
get_string('restoringcourseshortname', 'backup'));
$courseid = restore_dbops::create_new_course($fullname, $shortname, $category->id);
$rc = new restore_controller($backupdir, $courseid, backup::INTERACTIVE_NO,
backup::MODE_GENERAL, $admin->id, backup::TARGET_NEW_COURSE);
$rc->execute_precheck();
$rc->execute_plan();
$rc->destroy();
} catch (Exception $e) {
cli_heading(get_string('cleaningtempdata'));
fulldelete($path);
print_error('generalexceptionmessage', 'error', '', $e->getMessage());
}
cli_heading(get_string('restoredcourseid', 'backup', $courseid));
exit(0);
+2 -19
View File
@@ -30,17 +30,8 @@ require_once("$CFG->libdir/clilib.php");
require_once("$CFG->libdir/cronlib.php");
list($options, $unrecognized) = cli_get_params(
[
'help' => false,
'list' => false,
'execute' => false,
'showsql' => false,
'showdebugging' => false,
'force' => false,
], [
'h' => 'help',
'f' => 'force',
]
array('help' => false, 'list' => false, 'execute' => false, 'showsql' => false, 'showdebugging' => false),
array('h' => 'help')
);
if ($unrecognized) {
@@ -58,7 +49,6 @@ if ($options['help'] or (!$options['list'] and !$options['execute'])) {
--showsql Show sql queries before they are executed
--showdebugging Show developer level debugging information
-h, --help Print out this help
-f, --force Execute task even if cron is disabled
Example:
\$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
@@ -131,13 +121,6 @@ if ($execute = $options['execute']) {
exit(1);
}
if (!get_config('core', 'cron_enabled') && !$options['force']) {
mtrace('Cron is disabled. Use --force to override.');
exit(1);
}
\core\task\manager::scheduled_task_starting($task);
// Increase memory limit.
raise_memory_limit(MEMORY_EXTRA);
+7 -7
View File
@@ -38,17 +38,17 @@ if ($unrecognized) {
}
// If necessary add files that should be ignored - such as in 3rd party plugins.
$ignorelist = array();
$blacklist = array();
$path = $options['path'];
if (!file_exists($path)) {
cli_error("Invalid path $path");
}
if ($options['ie9fix']) {
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $ignorelist);
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $blacklist);
} else if ($options['noaspectratio']) {
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $ignorelist);
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $blacklist);
} else {
$help =
@@ -153,9 +153,9 @@ function core_admin_svgtool_noaspectratio($file) {
* @param string $base
* @param string $sub
* @param string $filecallback
* @param array $ignorelist List of files to be ignored and skipped.
* @param array $blacklist
*/
function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
function core_admin_recurse_svgs($base, $sub, $filecallback, $blacklist) {
if (is_dir("$base/$sub")) {
$items = new DirectoryIterator("$base/$sub");
foreach ($items as $item) {
@@ -163,7 +163,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
continue;
}
$file = $item->getFilename();
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $ignorelist);
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $blacklist);
}
unset($item);
unset($items);
@@ -174,7 +174,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
return;
}
$file = realpath("$base/$sub");
if (in_array($file, $ignorelist)) {
if (in_array($file, $blacklist)) {
return;
}
$filecallback($file);
+2 -10
View File
@@ -34,7 +34,6 @@ $help = "Command line tool to uninstall plugins.
Options:
-h --help Print this help.
--show-all Displays a list of all installed plugins.
--show-contrib Displays a list of all third-party installed plugins.
--show-missing Displays a list of plugins missing from disk.
--purge-missing Uninstall all missing from disk plugins.
--plugins=<plugin name> A comma separated list of plugins to be uninstalled. E.g. mod_assign,mod_forum
@@ -45,9 +44,6 @@ Examples:
# php uninstall_plugins.php --show-all
Prints tab-separated list of all installed plugins.
# php uninstall_plugins.php --show-contrib
Prints tab-separated list of all third-party installed plugins.
# php uninstall_plugins.php --show-missing
Prints tab-separated list of all missing from disk plugins.
@@ -67,7 +63,6 @@ Examples:
list($options, $unrecognised) = cli_get_params([
'help' => false,
'show-all' => false,
'show-contrib' => false,
'show-missing' => false,
'purge-missing' => false,
'plugins' => false,
@@ -89,15 +84,12 @@ if ($options['help']) {
$pluginman = core_plugin_manager::instance();
$plugininfo = $pluginman->get_plugins();
if ($options['show-all'] || $options['show-missing'] || $options['show-contrib']) {
if ($options['show-all'] || $options['show-missing']) {
foreach ($plugininfo as $type => $plugins) {
foreach ($plugins as $name => $plugin) {
if ($options['show-contrib'] && $plugin->is_standard()) {
continue;
}
$pluginstring = $plugin->component . "\t" . $plugin->displayname;
if ($options['show-all'] || $options['show-contrib']) {
if ($options['show-all']) {
cli_writeln($pluginstring);
} else {
if ($plugin->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
-366
View File
@@ -2815,7 +2815,6 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.1.0" level="required">
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
@@ -2997,7 +2996,6 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.2.0" level="required">
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
@@ -3165,368 +3163,4 @@
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="3.10" requires="3.5">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.2.29" />
<VENDOR name="mysql" version="5.7" />
<VENDOR name="postgres" version="9.6" />
<VENDOR name="mssql" version="11.0" />
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.2.0" level="required">
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlrpc" level="optional">
<FEEDBACK>
<ON_CHECK message="xmlrpcrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="required">
<FEEDBACK>
<ON_ERROR message="intlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
<FEEDBACK>
<ON_CHECK message="sixtyfourbitswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="3.11" requires="3.6">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.2.29" />
<VENDOR name="mysql" version="5.7" />
<VENDOR name="postgres" version="9.6" />
<VENDOR name="mssql" version="14.0" />
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.3.0" level="required">
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlrpc" level="optional">
<FEEDBACK>
<ON_CHECK message="xmlrpcrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="required">
<FEEDBACK>
<ON_ERROR message="intlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
<FEEDBACK>
<ON_CHECK message="sixtyfourbitswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+2 -4
View File
@@ -509,8 +509,7 @@ if (!$cache and $version > $CFG->version) { // upgrade
// Always verify plugin dependencies!
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
array('confirmplugincheck' => 0)));
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
die();
}
unset($failed);
@@ -702,8 +701,7 @@ if (!$cache and moodle_needs_upgrading()) {
$failed = array();
if (!$pluginman->all_plugins_ok($version, $failed, $CFG->branch)) {
$output = $PAGE->get_renderer('core', 'admin');
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
array('confirmplugincheck' => 0)));
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
die();
}
unset($failed);
+2 -4
View File
@@ -49,7 +49,6 @@
array($module->id));
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
redirect(new moodle_url('/admin/modules.php'));
}
if (!empty($show) and confirm_sesskey()) {
@@ -67,7 +66,6 @@
array($module->id));
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
redirect(new moodle_url('/admin/modules.php'));
}
echo $OUTPUT->header();
@@ -123,8 +121,8 @@
$count = -1;
}
if ($count>0) {
$countlink = $OUTPUT->action_link(new moodle_url('/course/search.php', ['modulelist' => $module->name]),
$count, null, ['title' => $strshowmodulecourse]);
$countlink = "<a href=\"{$CFG->wwwroot}/course/search.php?modulelist=$module->name" .
"&amp;sesskey=".sesskey()."\" title=\"$strshowmodulecourse\">$count</a>";
} else if ($count < 0) {
$countlink = get_string('error');
} else {
+1 -1
View File
@@ -53,6 +53,7 @@ $pageurl = new moodle_url('/admin/plugins.php', $pageparams);
$pluginman = core_plugin_manager::instance();
if ($uninstall) {
require_sesskey();
if (!$confirmed) {
admin_externalpage_setup('pluginsoverview', '', $pageparams);
@@ -91,7 +92,6 @@ if ($uninstall) {
exit();
} else {
require_sesskey();
$SESSION->pluginuninstallreturn = $pluginfo->get_return_url_after_uninstall($return);
$progress = new progress_trace_buffer(new text_progress_trace(), false);
$pluginman->uninstall_plugin($pluginfo->component, $progress);
+2 -2
View File
@@ -1110,7 +1110,7 @@ class core_admin_renderer extends plugin_renderer_base {
if (!empty($installabortable[$plugin->component])) {
$status .= $this->output->single_button(
new moodle_url($this->page->url, array('abortinstall' => $plugin->component, 'confirmplugincheck' => 0)),
new moodle_url($this->page->url, array('abortinstall' => $plugin->component)),
get_string('cancelinstallone', 'core_plugin'),
'post',
array('class' => 'actionbutton cancelinstallone d-block mt-1')
@@ -1209,7 +1209,7 @@ class core_admin_renderer extends plugin_renderer_base {
if ($installabortable) {
$out .= $this->output->single_button(
new moodle_url($this->page->url, array('abortinstallx' => 1, 'confirmplugincheck' => 0)),
new moodle_url($this->page->url, array('abortinstallx' => 1)),
get_string('cancelinstallall', 'core_plugin', count($installabortable)),
'post',
array('class' => 'singlebutton cancelinstallall mr-1')
+7 -7
View File
@@ -536,7 +536,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user1->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist2->get_userids());
$this->assertEquals($expected, $userlist2->get_userids(), '', 0.0, 10, true);
// The user list for coursecontext1 should user1, user2 and admin (role creator).
$userlist3 = new \core_privacy\local\request\userlist($coursecontext1, $component);
@@ -547,7 +547,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user2->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist3->get_userids());
$this->assertEquals($expected, $userlist3->get_userids(), '', 0.0, 10, true);
// The user list for coursecatcontext should user2 and admin (role creator).
$userlist4 = new \core_privacy\local\request\userlist($coursecatcontext, $component);
@@ -557,7 +557,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user2->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist4->get_userids());
$this->assertEquals($expected, $userlist4->get_userids(), '', 0.0, 10, true);
// The user list for systemcontext should user1 and admin (role creator).
$userlist6 = new \core_privacy\local\request\userlist($systemcontext, $component);
@@ -567,7 +567,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user1->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist6->get_userids());
$this->assertEquals($expected, $userlist6->get_userids(), '', 0.0, 10, true);
// The user list for cmcontext should user1, user2 and admin (role creator).
$userlist7 = new \core_privacy\local\request\userlist($cmcontext, $component);
@@ -578,7 +578,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user2->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist7->get_userids());
$this->assertEquals($expected, $userlist7->get_userids(), '', 0.0, 10, true);
// The user list for blockcontext should user1 and admin (role creator).
$userlist8 = new \core_privacy\local\request\userlist($blockcontext, $component);
@@ -588,7 +588,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user1->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist8->get_userids());
$this->assertEquals($expected, $userlist8->get_userids(), '', 0.0, 10, true);
}
/**
@@ -744,4 +744,4 @@ class core_role_privacy_testcase extends provider_testcase {
}
return $rolesnames;
}
}
}
+3 -10
View File
@@ -68,16 +68,9 @@ if ($errormsg !== '') {
$showsettingslinks = true;
if ($hassiteconfig) {
$data = [
'action' => new moodle_url('/admin/search.php'),
'btnclass' => 'btn-primary',
'inputname' => 'query',
'searchstring' => get_string('search'),
'query' => $query,
'extraclasses' => 'd-flex justify-content-center'
];
echo $OUTPUT->render_from_template('core/search_input', $data);
require_once("admin_settings_search_form.php");
$form = new admin_settings_search_form();
$form->display();
echo '<hr>';
if ($query) {
echo admin_search_settings_html($query);
+8 -3
View File
@@ -131,10 +131,15 @@ if ($hassiteconfig && \core_analytics\manager::is_analytics_enabled()) {
$timesplittingdefaults, $timesplittingoptions)
);
// Predictions processor output dir - specify default in setting description (used if left blank).
$defaultmodeloutputdir = \core_analytics\model::default_output_dir();
// Predictions processor output dir.
$defaultmodeloutputdir = rtrim($CFG->dataroot, '/') . DIRECTORY_SEPARATOR . 'models';
if (empty(get_config('analytics', 'modeloutputdir')) && !file_exists($defaultmodeloutputdir) &&
is_writable($defaultmodeloutputdir)) {
// Automatically create the dir for them so users don't see the invalid value red cross.
mkdir($defaultmodeloutputdir, $CFG->directorypermissions, true);
}
$settings->add(new admin_setting_configdirectory('analytics/modeloutputdir', new lang_string('modeloutputdir', 'analytics'),
new lang_string('modeloutputdirwithdefaultinfo', 'analytics', $defaultmodeloutputdir), ''));
new lang_string('modeloutputdirinfo', 'analytics'), $defaultmodeloutputdir));
// Disable web interface evaluation and get predictions.
$settings->add(new admin_setting_configcheckbox('analytics/onlycli', new lang_string('onlycli', 'analytics'),
-67
View File
@@ -22,8 +22,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use core_admin\local\settings\filesize;
$capabilities = array(
'moodle/backup:backupcourse',
'moodle/category:manage',
@@ -77,17 +75,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configselect('moodlecourse/visible', new lang_string('visible'), new lang_string('visible_help'),
1, $choices));
// Enable/disable download course content.
$choices = [
DOWNLOAD_COURSE_CONTENT_DISABLED => new lang_string('no'),
DOWNLOAD_COURSE_CONTENT_ENABLED => new lang_string('yes'),
];
$downloadcontentsitedefault = new admin_setting_configselect('moodlecourse/downloadcontentsitedefault',
new lang_string('enabledownloadcoursecontent', 'course'),
new lang_string('downloadcoursecontent_help', 'course'), 0, $choices);
$downloadcontentsitedefault->add_dependent_on('downloadcoursecontentallowed');
$temp->add($downloadcontentsitedefault);
// Course format.
$temp->add(new admin_setting_heading('courseformathdr', new lang_string('type_format', 'plugin'), ''));
@@ -174,21 +161,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$ADMIN->add('courses', $temp);
// Download course content.
$downloadcoursedefaulturl = new moodle_url('/admin/settings.php', ['section' => 'coursesettings']);
$temp = new admin_settingpage('downloadcoursecontent', new lang_string('downloadcoursecontent', 'course'));
$temp->add(new admin_setting_configcheckbox('downloadcoursecontentallowed',
new lang_string('downloadcoursecontentallowed', 'admin'),
new lang_string('downloadcoursecontentallowed_desc', 'admin', $downloadcoursedefaulturl->out()), 0));
// 50MB default maximum size per file when downloading course content.
$defaultmaxdownloadsize = 50 * filesize::UNIT_MB;
$temp->add(new filesize('maxsizeperdownloadcoursefile', new lang_string('maxsizeperdownloadcoursefile', 'admin'),
new lang_string('maxsizeperdownloadcoursefile_desc', 'admin'), $defaultmaxdownloadsize, filesize::UNIT_MB));
$temp->hide_if('maxsizeperdownloadcoursefile', 'downloadcoursecontentallowed');
$ADMIN->add('courses', $temp);
// "courserequests" settingpage.
$temp = new admin_settingpage('courserequest', new lang_string('courserequest'));
$temp->add(new admin_setting_configcheckbox('enablecourserequests',
@@ -212,7 +184,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
// Add a category for the Activity Chooser.
$ADMIN->add('courses', new admin_category('activitychooser', new lang_string('activitychoosercategory', 'course')));
$temp = new admin_settingpage('activitychoosersettings', new lang_string('activitychoosersettings', 'course'));
// Tab mode for the activity chooser.
$temp->add(
new admin_setting_configselect(
'activitychoosertabmode',
@@ -226,31 +197,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
]
)
);
// Build a list of plugins that use the footer callback.
$pluginswithfunction = get_plugins_with_function('custom_chooser_footer', 'lib.php');
$pluginsoptions = [];
$pluginsoptions[COURSE_CHOOSER_FOOTER_NONE] = get_string('activitychooserhidefooter', 'course');
if ($pluginswithfunction) {
foreach ($pluginswithfunction as $plugintype => $plugins) {
foreach ($plugins as $pluginname => $pluginfunction) {
$plugin = $plugintype.'_'.$pluginname;
$pluginsoptions[$plugin] = get_string('pluginname', $plugin);
}
}
}
// Select what plugin to show in the footer.
$temp->add(
new admin_setting_configselect(
'activitychooseractivefooter',
new lang_string('activitychooseractivefooter', 'course'),
new lang_string('activitychooseractivefooter_desc', 'course'),
COURSE_CHOOSER_FOOTER_NONE,
$pluginsoptions
)
);
$ADMIN->add('activitychooser', $temp);
$ADMIN->add('activitychooser',
new admin_externalpage('activitychooserrecommended', new lang_string('activitychooserrecommendations', 'course'),
@@ -313,9 +259,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
['value' => 1, 'locked' => 0])
);
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_legacyfiles',
new lang_string('generallegacyfiles', 'backup'),
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
$ADMIN->add('backups', $temp);
// Create a page for general import configuration and defaults.
@@ -342,9 +285,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
new lang_string('configgeneralcontentbankcontent', 'backup'),
['value' => 1, 'locked' => 0])
);
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_legacyfiles',
new lang_string('generallegacyfiles', 'backup'),
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
$ADMIN->add('backups', $temp);
@@ -471,10 +411,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
1)
);
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_legacyfiles',
new lang_string('generallegacyfiles', 'backup'),
new lang_string('configlegacyfiles', 'backup'), 1));
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_messages', new lang_string('messages', 'message'), new lang_string('backupmessageshelp','message'), 0));
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_blogs', new lang_string('blogs', 'blog'), new lang_string('backupblogshelp','blog'), 0));
@@ -537,9 +473,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_contentbankcontent',
new lang_string('generalcontentbankcontent', 'backup'),
new lang_string('configrestorecontentbankcontent', 'backup'), array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_legacyfiles',
new lang_string('generallegacyfiles', 'backup'),
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
// Restore defaults when merging into another course.
$temp->add(new admin_setting_heading('mergerestoredefaults', new lang_string('mergerestoredefaults', 'backup'), ''));
-7
View File
@@ -41,13 +41,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp->add(new admin_setting_configcheckbox('debugdisplay', new lang_string('debugdisplay', 'admin'), new lang_string('configdebugdisplay', 'admin'), ini_get_bool('display_errors')));
$temp->add(new admin_setting_configcheckbox('perfdebug', new lang_string('perfdebug', 'admin'), new lang_string('configperfdebug', 'admin'), '7', '15', '7'));
$temp->add(new admin_setting_configcheckbox('debugstringids', new lang_string('debugstringids', 'admin'), new lang_string('debugstringids_desc', 'admin'), 0));
$temp->add(new admin_setting_configselect('debugsqltrace',
new lang_string('debugsqltrace', 'admin'),
new lang_string('debugsqltrace_desc', 'admin'), 0, array(
0 => new lang_string('disabled', 'admin'),
1 => new lang_string('debugsqltrace1', 'admin'),
2 => new lang_string('debugsqltrace2', 'admin'),
100 => new lang_string('debugsqltrace100', 'admin'))));
$temp->add(new admin_setting_configcheckbox('debugvalidators', new lang_string('debugvalidators', 'admin'), new lang_string('configdebugvalidators', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('debugpageinfo', new lang_string('debugpageinfo', 'admin'), new lang_string('configdebugpageinfo', 'admin'), 0));
$ADMIN->add('development', $temp);
-2
View File
@@ -8,8 +8,6 @@ if ($hassiteconfig) {
$temp = new admin_settingpage('langsettings', new lang_string('languagesettings', 'admin'));
$temp->add(new admin_setting_configcheckbox('autolang', new lang_string('autolang', 'admin'), new lang_string('configautolang', 'admin'), 1));
$temp->add(new admin_setting_configselect('lang', new lang_string('lang', 'admin'), new lang_string('configlang', 'admin'), current_language(), get_string_manager()->get_list_of_translations())); // $CFG->lang might be set in installer already, default en is in setup.php
$temp->add(new admin_setting_configcheckbox('autolangusercreation', new lang_string('autolangusercreation', 'admin'),
new lang_string('configautolangusercreation', 'admin'), 1));
$temp->add(new admin_setting_configcheckbox('langmenu', new lang_string('langmenu', 'admin'), new lang_string('configlangmenu', 'admin'), 1));
$temp->add(new admin_setting_langlist());
$temp->add(new admin_setting_configcheckbox('langcache', new lang_string('langcache', 'admin'), new lang_string('langcache_desc', 'admin'), 1));
+14 -50
View File
@@ -1,57 +1,21 @@
<?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 <http://www.gnu.org/licenses/>.
/**
* Define administration settings on the Location settings page.
*
* @package core
* @category admin
* @copyright 2006 Martin Dougiamas <martin@moodle.com>
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
defined('MOODLE_INTERNAL') || die();
// "locations" settingpage
$temp = new admin_settingpage('locationsettings', new lang_string('locationsettings', 'admin'));
$temp->add(new admin_setting_servertimezone());
$temp->add(new admin_setting_forcetimezone());
$temp->add(new admin_settings_country_select('country', new lang_string('country', 'admin'), new lang_string('configcountry', 'admin'), 0));
$temp->add(new admin_setting_configtext('defaultcity', new lang_string('defaultcity', 'admin'), new lang_string('defaultcity_help', 'admin'), ''));
if ($hassiteconfig) {
$temp = new admin_settingpage('locationsettings', new lang_string('locationsettings', 'core_admin'));
$temp->add(new admin_setting_heading('iplookup', new lang_string('iplookup', 'admin'), new lang_string('iplookupinfo', 'admin')));
$temp->add(new admin_setting_configfile('geoip2file', new lang_string('geoipfile', 'admin'),
new lang_string('configgeoipfile', 'admin', $CFG->dataroot.'/geoip/'), $CFG->dataroot.'/geoip/GeoLite2-City.mmdb'));
$temp->add(new admin_setting_configtext('googlemapkey3', new lang_string('googlemapkey3', 'admin'), new lang_string('googlemapkey3_help', 'admin'), '', PARAM_RAW, 60));
if ($ADMIN->fulltree) {
$temp->add(new admin_setting_servertimezone());
$temp->add(new admin_setting_forcetimezone());
$temp->add(new admin_settings_country_select('country', new lang_string('country', 'core_admin'),
new lang_string('configcountry', 'core_admin'), 0));
$temp->add(new admin_setting_configtext('defaultcity', new lang_string('defaultcity', 'core_admin'),
new lang_string('defaultcity_help', 'core_admin'), ''));
$temp->add(new admin_setting_heading('iplookup', new lang_string('iplookup', 'core_admin'),
new lang_string('iplookupinfo', 'core_admin')));
$temp->add(new admin_setting_configfile('geoip2file', new lang_string('geoipfile', 'core_admin'),
new lang_string('configgeoipfile', 'core_admin', $CFG->dataroot . '/geoip/'),
$CFG->dataroot . '/geoip/GeoLite2-City.mmdb'));
$temp->add(new admin_setting_configtext('googlemapkey3', new lang_string('googlemapkey3', 'core_admin'),
new lang_string('googlemapkey3_help', 'core_admin'), '', PARAM_RAW, 60));
$temp->add(new admin_setting_countrycodes('allcountrycodes', new lang_string('allcountrycodes', 'core_admin'),
new lang_string('configallcountrycodes', 'core_admin')));
}
$temp->add(new admin_setting_configtext('allcountrycodes', new lang_string('allcountrycodes', 'admin'), new lang_string('configallcountrycodes', 'admin'), '', '/^(?:\w+(?:,\w+)*)?$/'));
$ADMIN->add('location', $temp);
}
} // end of speedup
-29
View File
@@ -1,29 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Adds payments links to the admin tree
*
* @package core
* @copyright 2020 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$ADMIN->add('payment', new admin_externalpage(
'paymentaccounts',
new lang_string('paymentaccounts', 'payment'),
new moodle_url("/payment/accounts.php"),
['moodle/payment:manageaccounts', 'moodle/payment:viewpayments']));
+2 -105
View File
@@ -167,42 +167,6 @@ if ($hassiteconfig) {
$ADMIN->add('modules', new admin_category('antivirussettings', new lang_string('antiviruses', 'antivirus')));
$temp = new admin_settingpage('manageantiviruses', new lang_string('antivirussettings', 'antivirus'));
$temp->add(new admin_setting_manageantiviruses());
// Common settings.
$temp->add(new admin_setting_heading('antiviruscommonsettings', new lang_string('antiviruscommonsettings', 'antivirus'), ''));
// Alert email.
$temp->add(
new admin_setting_configtext(
'antivirus/notifyemail',
new lang_string('notifyemail', 'antivirus'),
new lang_string('notifyemail_help', 'antivirus'),
'',
PARAM_EMAIL
)
);
// Enable quarantine.
$temp->add(
new admin_setting_configcheckbox(
'antivirus/enablequarantine',
new lang_string('enablequarantine', 'antivirus'),
new lang_string('enablequarantine_help', 'antivirus',
\core\antivirus\quarantine::DEFAULT_QUARANTINE_FOLDER),
0
)
);
// Quarantine time.
$temp->add(
new admin_setting_configduration(
'antivirus/quarantinetime',
new lang_string('quarantinetime', 'antivirus'),
new lang_string('quarantinetime_desc', 'antivirus'),
\core\antivirus\quarantine::DEFAULT_QUARANTINE_TIME
)
);
$ADMIN->add('antivirussettings', $temp);
$plugins = core_plugin_manager::instance()->get_plugins_of_type('antivirus');
core_collator::asort_objects_by_property($plugins, 'displayname');
@@ -280,25 +244,6 @@ if ($hassiteconfig) {
$plugin->load_settings($ADMIN, 'mediaplayers', $hassiteconfig);
}
// Payment gateway plugins.
$ADMIN->add('modules', new admin_category('paymentgateways', new lang_string('type_paygw_plural', 'plugin')));
$temp = new admin_settingpage('managepaymentgateways', new lang_string('type_paygwmanage', 'plugin'));
$temp->add(new \core_admin\local\settings\manage_payment_gateway_plugins());
$temp->add(new admin_setting_description(
'managepaymentgatewayspostfix',
'',
new lang_string('gotopaymentaccounts', 'payment',
html_writer::link(new moodle_url('/payment/accounts.php'), get_string('paymentaccounts', 'payment')))
));
$ADMIN->add('paymentgateways', $temp);
$plugins = core_plugin_manager::instance()->get_plugins_of_type('paygw');
core_collator::asort_objects_by_property($plugins, 'displayname');
foreach ($plugins as $plugin) {
/** @var \core\plugininfo\paygw $plugin */
$plugin->load_settings($ADMIN, 'paymentgateways', $hassiteconfig);
}
// Data format settings.
$ADMIN->add('modules', new admin_category('dataformatsettings', new lang_string('dataformats')));
$temp = new admin_settingpage('managedataformats', new lang_string('managedataformats'));
@@ -604,19 +549,8 @@ if ($hassiteconfig) {
// Search engine selection.
$temp->add(new admin_setting_heading('searchengineheading', new lang_string('searchengine', 'admin'), ''));
$searchengineselect = new admin_setting_configselect('searchengine',
new lang_string('selectsearchengine', 'admin'), '', 'simpledb', $engines);
$searchengineselect->set_validate_function(function(string $value): string {
global $CFG;
// Check nobody's setting the indexing and query-only server to the same one.
if (isset($CFG->searchenginequeryonly) && $CFG->searchenginequeryonly === $value) {
return get_string('searchenginequeryonlysame', 'admin');
} else {
return '';
}
});
$temp->add($searchengineselect);
$temp->add(new admin_setting_configselect('searchengine',
new lang_string('selectsearchengine', 'admin'), '', 'simpledb', $engines));
$temp->add(new admin_setting_heading('searchoptionsheading', new lang_string('searchoptions', 'admin'), ''));
$temp->add(new admin_setting_configcheckbox('searchindexwhendisabled',
new lang_string('searchindexwhendisabled', 'admin'), new lang_string('searchindexwhendisabled_desc', 'admin'),
@@ -656,43 +590,6 @@ if ($hassiteconfig) {
new lang_string('searchhideallcategory_desc', 'admin'),
0));
$temp->add(new admin_setting_heading('searchmanagement', new lang_string('searchmanagement', 'admin'),
new lang_string('searchmanagement_desc', 'admin')));
// Get list of search engines including those with alternate settings.
$searchenginequeryonlyselect = new admin_setting_configselect('searchenginequeryonly',
new lang_string('searchenginequeryonly', 'admin'),
new lang_string('searchenginequeryonly_desc', 'admin'), '', function() use($engines) {
$options = ['' => new lang_string('searchenginequeryonly_none', 'admin')];
foreach ($engines as $name => $display) {
$options[$name] = $display;
$classname = '\search_' . $name . '\engine';
$engine = new $classname;
if ($engine->has_alternate_configuration()) {
$options[$name . '-alternate'] =
new lang_string('searchenginealternatesettings', 'admin', $display);
}
}
return $options;
});
$searchenginequeryonlyselect->set_validate_function(function(string $value): string {
global $CFG;
// Check nobody's setting the indexing and query-only server to the same one.
if (isset($CFG->searchengine) && $CFG->searchengine === $value) {
return get_string('searchenginequeryonlysame', 'admin');
} else {
return '';
}
});
$temp->add($searchenginequeryonlyselect);
$temp->add(new admin_setting_configcheckbox('searchbannerenable',
new lang_string('searchbannerenable', 'admin'), new lang_string('searchbannerenable_desc', 'admin'),
0));
$temp->add(new admin_setting_confightmleditor('searchbanner',
new lang_string('searchbanner', 'admin'), '', ''));
$ADMIN->add('searchplugins', $temp);
$ADMIN->add('searchplugins', new admin_externalpage('searchareas', new lang_string('searchareas', 'admin'),
new moodle_url('/admin/searchareas.php')));
-17
View File
@@ -160,23 +160,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp->add(new admin_setting_configportlist('curlsecurityallowedport',
new lang_string('curlsecurityallowedport', 'admin'),
new lang_string('curlsecurityallowedportsyntax', 'admin'), ""));
// HTTP Header referrer policy settings.
$referreroptions = [
'default' => get_string('referrernone', 'admin'),
'no-referrer' => 'no-referrer',
'no-referrer-when-downgrade' => 'no-referrer-when-downgrade',
'origin' => 'origin',
'origin-when-cross-origin' => 'origin-when-cross-origin',
'same-origin' => 'same-origin',
'strict-origin' => 'strict-origin',
'strict-origin-when-cross-origin' => 'strict-origin-when-cross-origin',
'unsafe-url' => 'unsafe-url',
];
$temp->add(new admin_setting_configselect('referrerpolicy',
new lang_string('referrerpolicy', 'admin'),
new lang_string('referrerpolicydesc', 'admin'), 'default', $referreroptions));
$ADMIN->add('security', $temp);
// "notifications" settingpage
+316 -458
View File
@@ -1,225 +1,162 @@
<?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 <http://www.gnu.org/licenses/>.
/**
* Defines settingpages and externalpages under the "server" category.
*
* @package core
* @category admin
* @copyright 2006 Martin Dougiamas
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This file defines settingpages and externalpages under the "server" category
defined('MOODLE_INTERNAL') || die();
if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
if ($hassiteconfig) {
// System paths.
$temp = new admin_settingpage('systempaths', new lang_string('systempaths', 'admin'));
$temp->add(new admin_setting_configexecutable('pathtophp', new lang_string('pathtophp', 'admin'),
new lang_string('configpathtophp', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'),
new lang_string('configpathtodu', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'),
new lang_string('edhelpaspellpath'), ''));
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'),
new lang_string('pathtodot_help', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtogs', new lang_string('pathtogs', 'admin'),
new lang_string('pathtogs_help', 'admin'), '/usr/bin/gs'));
$temp->add(new admin_setting_configexecutable('pathtopython', new lang_string('pathtopython', 'admin'),
new lang_string('pathtopythondesc', 'admin'), ''));
$ADMIN->add('server', $temp);
// "systempaths" settingpage
$temp = new admin_settingpage('systempaths', new lang_string('systempaths','admin'));
$temp->add(new admin_setting_configexecutable('pathtophp', new lang_string('pathtophp', 'admin'),
new lang_string('configpathtophp', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'), new lang_string('configpathtodu', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'), new lang_string('edhelpaspellpath'), ''));
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'), new lang_string('pathtodot_help', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtogs', new lang_string('pathtogs', 'admin'), new lang_string('pathtogs_help', 'admin'), '/usr/bin/gs'));
$temp->add(new admin_setting_configexecutable('pathtopython', new lang_string('pathtopython', 'admin'),
new lang_string('pathtopythondesc', 'admin'), ''));
$ADMIN->add('server', $temp);
// Support contact.
$temp = new admin_settingpage('supportcontact', new lang_string('supportcontact', 'admin'));
$primaryadmin = get_admin();
if ($primaryadmin) {
$primaryadminemail = $primaryadmin->email;
$primaryadminname = fullname($primaryadmin, true);
} else {
// No defaults during installation - admin user must be created first.
$primaryadminemail = null;
$primaryadminname = null;
}
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'),
new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
$setting = new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'),
new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_EMAIL);
$setting->set_force_ltr(true);
$temp->add($setting);
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'),
new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
$ADMIN->add('server', $temp);
// Session handling.
$temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandling', 'admin'));
if (empty($CFG->session_handler_class) and $DB->session_lock_supported()) {
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'),
new lang_string('configdbsessions', 'admin'), 0));
}
$temp->add(new admin_setting_configduration('sessiontimeout', new lang_string('sessiontimeout', 'admin'),
new lang_string('configsessiontimeout', 'admin'), 8 * 60 * 60));
// "supportcontact" settingpage
$temp = new admin_settingpage('supportcontact', new lang_string('supportcontact','admin'));
$primaryadmin = get_admin();
if ($primaryadmin) {
$primaryadminemail = $primaryadmin->email;
$primaryadminname = fullname($primaryadmin, true);
} else {
// no defaults during installation - admin user must be created first
$primaryadminemail = NULL;
$primaryadminname = NULL;
}
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'),
new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
$setting = new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'),
new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_EMAIL);
$setting->set_force_ltr(true);
$temp->add($setting);
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'), new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_configtext('sessioncookie', new lang_string('sessioncookie', 'admin'),
new lang_string('configsessioncookie', 'admin'), '', PARAM_ALPHANUM));
$temp->add(new admin_setting_configtext('sessioncookiepath', new lang_string('sessioncookiepath', 'admin'),
new lang_string('configsessioncookiepath', 'admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtext('sessioncookiedomain', new lang_string('sessioncookiedomain', 'admin'),
new lang_string('configsessioncookiedomain', 'admin'), '', PARAM_RAW, 50));
$ADMIN->add('server', $temp);
// Statistics.
$temp = new admin_settingpage('stats', new lang_string('stats'), 'moodle/site:config', empty($CFG->enablestats));
$temp->add(new admin_setting_configselect('statsfirstrun', new lang_string('statsfirstrun', 'admin'),
new lang_string('configstatsfirstrun', 'admin'), 'none',
[
'none' => new lang_string('none'),
60 * 60 * 24 * 7 => new lang_string('numweeks', 'moodle', 1),
60 * 60 * 24 * 14 => new lang_string('numweeks', 'moodle', 2),
60 * 60 * 24 * 21 => new lang_string('numweeks', 'moodle', 3),
60 * 60 * 24 * 28 => new lang_string('nummonths', 'moodle', 1),
60 * 60 * 24 * 56 => new lang_string('nummonths', 'moodle', 2),
60 * 60 * 24 * 84 => new lang_string('nummonths', 'moodle', 3),
60 * 60 * 24 * 112 => new lang_string('nummonths', 'moodle', 4),
60 * 60 * 24 * 140 => new lang_string('nummonths', 'moodle', 5),
60 * 60 * 24 * 168 => new lang_string('nummonths', 'moodle', 6),
'all' => new lang_string('all')
]
));
$temp->add(new admin_setting_configselect('statsmaxruntime', new lang_string('statsmaxruntime', 'admin'),
new lang_string('configstatsmaxruntime3', 'admin'), 0,
[
0 => new lang_string('untilcomplete'),
60 * 30 => '10 ' . new lang_string('minutes'),
60 * 30 => '30 ' . new lang_string('minutes'),
60 * 60 => '1 ' . new lang_string('hour'),
60 * 60 * 2 => '2 ' . new lang_string('hours'),
60 * 60 * 3 => '3 ' . new lang_string('hours'),
60 * 60 * 4 => '4 ' . new lang_string('hours'),
60 * 60 * 5 => '5 ' . new lang_string('hours'),
60 * 60 * 6 => '6 ' . new lang_string('hours'),
60 * 60 * 7 => '7 ' . new lang_string('hours'),
60 * 60 * 8 => '8 ' . new lang_string('hours'),
]
));
$temp->add(new admin_setting_configtext('statsruntimedays', new lang_string('statsruntimedays', 'admin'),
new lang_string('configstatsruntimedays', 'admin'), 31, PARAM_INT));
$temp->add(new admin_setting_configtext('statsuserthreshold', new lang_string('statsuserthreshold', 'admin'),
new lang_string('configstatsuserthreshold', 'admin'), 0, PARAM_INT));
$ADMIN->add('server', $temp);
// "sessionhandling" settingpage
$temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandling', 'admin'));
if (empty($CFG->session_handler_class) and $DB->session_lock_supported()) {
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'), new lang_string('configdbsessions', 'admin'), 0));
}
// HTTP.
$temp = new admin_settingpage('http', new lang_string('http', 'admin'));
$temp->add(new admin_setting_configcheckbox('slasharguments', new lang_string('slasharguments', 'admin'),
new lang_string('configslasharguments', 'admin'), 1));
$temp->add(new admin_setting_heading('reverseproxy', new lang_string('reverseproxy', 'admin'), '', ''));
$options = [
0 => 'HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR => 'HTTP_CLIENT, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR | GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'REMOTE_ADDR'
];
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'),
new lang_string('configgetremoteaddrconf', 'admin'),
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR | GETREMOTEADDR_SKIP_HTTP_CLIENT_IP, $options));
$temp->add(new admin_setting_configtext('reverseproxyignore', new lang_string('reverseproxyignore', 'admin'),
new lang_string('configreverseproxyignore', 'admin'), ''));
$temp->add(new admin_setting_configduration('sessiontimeout', new lang_string('sessiontimeout', 'admin'),
new lang_string('configsessiontimeout', 'admin'), 8 * 60 * 60));
$temp->add(new admin_setting_heading('webproxy', new lang_string('webproxy', 'admin'),
new lang_string('webproxyinfo', 'admin')));
$temp->add(new admin_setting_configtext('proxyhost', new lang_string('proxyhost', 'admin'),
new lang_string('configproxyhost', 'admin'), '', PARAM_HOST));
$temp->add(new admin_setting_configtext('proxyport', new lang_string('proxyport', 'admin'),
new lang_string('configproxyport', 'admin'), 0, PARAM_INT));
$options = ['HTTP' => 'HTTP'];
if (defined('CURLPROXY_SOCKS5')) {
$options['SOCKS5'] = 'SOCKS5';
}
$temp->add(new admin_setting_configselect('proxytype', new lang_string('proxytype', 'admin'),
new lang_string('configproxytype', 'admin'), 'HTTP', $options));
$temp->add(new admin_setting_configtext('proxyuser', new lang_string('proxyuser', 'admin'),
new lang_string('configproxyuser', 'admin'), ''));
$temp->add(new admin_setting_configpasswordunmask('proxypassword', new lang_string('proxypassword', 'admin'),
new lang_string('configproxypassword', 'admin'), ''));
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'),
new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_configtext('sessioncookie', new lang_string('sessioncookie', 'admin'), new lang_string('configsessioncookie', 'admin'), '', PARAM_ALPHANUM));
$temp->add(new admin_setting_configtext('sessioncookiepath', new lang_string('sessioncookiepath', 'admin'), new lang_string('configsessioncookiepath', 'admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtext('sessioncookiedomain', new lang_string('sessioncookiedomain', 'admin'), new lang_string('configsessioncookiedomain', 'admin'), '', PARAM_RAW, 50));
$ADMIN->add('server', $temp);
$temp = new admin_settingpage('maintenancemode', new lang_string('sitemaintenancemode', 'admin'));
$options = [0 => new lang_string('disable'), 1 => new lang_string('enable')];
$temp->add(new admin_setting_configselect('maintenance_enabled', new lang_string('sitemaintenancemode', 'admin'),
new lang_string('helpsitemaintenance', 'admin'), 0, $options));
$temp->add(new admin_setting_confightmleditor('maintenance_message', new lang_string('optionalmaintenancemessage', 'admin'),
'', ''));
$ADMIN->add('server', $temp);
// Cleanup.
$temp = new admin_settingpage('cleanup', new lang_string('cleanup', 'admin'));
$temp->add(new admin_setting_configselect('deleteunconfirmed', new lang_string('deleteunconfirmed', 'admin'),
new lang_string('configdeleteunconfirmed', 'admin'), 168,
[
0 => new lang_string('never'),
168 => new lang_string('numdays', '', 7),
144 => new lang_string('numdays', '', 6),
120 => new lang_string('numdays', '', 5),
96 => new lang_string('numdays', '', 4),
72 => new lang_string('numdays', '', 3),
48 => new lang_string('numdays', '', 2),
24 => new lang_string('numdays', '', 1),
12 => new lang_string('numhours', '', 12),
6 => new lang_string('numhours', '', 6),
1 => new lang_string('numhours', '', 1),
]
));
// "stats" settingpage
$temp = new admin_settingpage('stats', new lang_string('stats'), 'moodle/site:config', empty($CFG->enablestats));
$temp->add(new admin_setting_configselect('statsfirstrun', new lang_string('statsfirstrun', 'admin'), new lang_string('configstatsfirstrun', 'admin'), 'none', array('none' => new lang_string('none'),
60*60*24*7 => new lang_string('numweeks','moodle',1),
60*60*24*14 => new lang_string('numweeks','moodle',2),
60*60*24*21 => new lang_string('numweeks','moodle',3),
60*60*24*28 => new lang_string('nummonths','moodle',1),
60*60*24*56 => new lang_string('nummonths','moodle',2),
60*60*24*84 => new lang_string('nummonths','moodle',3),
60*60*24*112 => new lang_string('nummonths','moodle',4),
60*60*24*140 => new lang_string('nummonths','moodle',5),
60*60*24*168 => new lang_string('nummonths','moodle',6),
'all' => new lang_string('all') )));
$temp->add(new admin_setting_configselect('statsmaxruntime', new lang_string('statsmaxruntime', 'admin'), new lang_string('configstatsmaxruntime3', 'admin'), 0, array(0 => new lang_string('untilcomplete'),
60*30 => '10 '.new lang_string('minutes'),
60*30 => '30 '.new lang_string('minutes'),
60*60 => '1 '.new lang_string('hour'),
60*60*2 => '2 '.new lang_string('hours'),
60*60*3 => '3 '.new lang_string('hours'),
60*60*4 => '4 '.new lang_string('hours'),
60*60*5 => '5 '.new lang_string('hours'),
60*60*6 => '6 '.new lang_string('hours'),
60*60*7 => '7 '.new lang_string('hours'),
60*60*8 => '8 '.new lang_string('hours') )));
$temp->add(new admin_setting_configtext('statsruntimedays', new lang_string('statsruntimedays', 'admin'), new lang_string('configstatsruntimedays', 'admin'), 31, PARAM_INT));
$temp->add(new admin_setting_configtext('statsuserthreshold', new lang_string('statsuserthreshold', 'admin'), new lang_string('configstatsuserthreshold', 'admin'), 0, PARAM_INT));
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_configselect('deleteincompleteusers', new lang_string('deleteincompleteusers', 'admin'),
new lang_string('configdeleteincompleteusers', 'admin'), 0,
[
0 => new lang_string('never'),
168 => new lang_string('numdays', '', 7),
144 => new lang_string('numdays', '', 6),
120 => new lang_string('numdays', '', 5),
96 => new lang_string('numdays', '', 4),
72 => new lang_string('numdays', '', 3),
48 => new lang_string('numdays', '', 2),
24 => new lang_string('numdays', '', 1),
]
));
$temp->add(new admin_setting_configcheckbox('disablegradehistory', new lang_string('disablegradehistory', 'grades'),
new lang_string('disablegradehistory_help', 'grades'), 0));
// "http" settingpage
$temp = new admin_settingpage('http', new lang_string('http', 'admin'));
$temp->add(new admin_setting_configcheckbox('slasharguments', new lang_string('slasharguments', 'admin'), new lang_string('configslasharguments', 'admin'), 1));
$temp->add(new admin_setting_heading('reverseproxy', new lang_string('reverseproxy', 'admin'), '', ''));
$options = array(
0 => 'HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR => 'HTTP_CLIENT, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR|GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'REMOTE_ADDR');
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'),
new lang_string('configgetremoteaddrconf', 'admin'),
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR|GETREMOTEADDR_SKIP_HTTP_CLIENT_IP, $options));
$temp->add(new admin_setting_configtext('reverseproxyignore', new lang_string('reverseproxyignore', 'admin'), new lang_string('configreverseproxyignore', 'admin'), ''));
$temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_string('gradehistorylifetime', 'grades'),
new lang_string('gradehistorylifetime_help', 'grades'), 0,
[
0 => new lang_string('neverdeletehistory', 'grades'),
1000 => new lang_string('numdays', '', 1000),
365 => new lang_string('numdays', '', 365),
180 => new lang_string('numdays', '', 180),
150 => new lang_string('numdays', '', 150),
120 => new lang_string('numdays', '', 120),
90 => new lang_string('numdays', '', 90),
60 => new lang_string('numdays', '', 60),
30 => new lang_string('numdays', '', 30),
]
));
$temp->add(new admin_setting_heading('webproxy', new lang_string('webproxy', 'admin'), new lang_string('webproxyinfo', 'admin')));
$temp->add(new admin_setting_configtext('proxyhost', new lang_string('proxyhost', 'admin'), new lang_string('configproxyhost', 'admin'), '', PARAM_HOST));
$temp->add(new admin_setting_configtext('proxyport', new lang_string('proxyport', 'admin'), new lang_string('configproxyport', 'admin'), 0, PARAM_INT));
$options = array('HTTP'=>'HTTP');
if (defined('CURLPROXY_SOCKS5')) {
$options['SOCKS5'] = 'SOCKS5';
}
$temp->add(new admin_setting_configselect('proxytype', new lang_string('proxytype', 'admin'), new lang_string('configproxytype','admin'), 'HTTP', $options));
$temp->add(new admin_setting_configtext('proxyuser', new lang_string('proxyuser', 'admin'), new lang_string('configproxyuser', 'admin'), ''));
$temp->add(new admin_setting_configpasswordunmask('proxypassword', new lang_string('proxypassword', 'admin'), new lang_string('configproxypassword', 'admin'), ''));
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'), new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'),
new lang_string('configtempdatafoldercleanup', 'admin'), 168,
[
$temp = new admin_settingpage('maintenancemode', new lang_string('sitemaintenancemode', 'admin'));
$options = array(0=>new lang_string('disable'), 1=>new lang_string('enable'));
$temp->add(new admin_setting_configselect('maintenance_enabled', new lang_string('sitemaintenancemode', 'admin'),
new lang_string('helpsitemaintenance', 'admin'), 0, $options));
$temp->add(new admin_setting_confightmleditor('maintenance_message', new lang_string('optionalmaintenancemessage', 'admin'),
'', ''));
$ADMIN->add('server', $temp);
$temp = new admin_settingpage('cleanup', new lang_string('cleanup', 'admin'));
$temp->add(new admin_setting_configselect('deleteunconfirmed', new lang_string('deleteunconfirmed', 'admin'), new lang_string('configdeleteunconfirmed', 'admin'), 168, array(0 => new lang_string('never'),
168 => new lang_string('numdays', '', 7),
144 => new lang_string('numdays', '', 6),
120 => new lang_string('numdays', '', 5),
96 => new lang_string('numdays', '', 4),
72 => new lang_string('numdays', '', 3),
48 => new lang_string('numdays', '', 2),
24 => new lang_string('numdays', '', 1),
12 => new lang_string('numhours', '', 12),
6 => new lang_string('numhours', '', 6),
1 => new lang_string('numhours', '', 1))));
$temp->add(new admin_setting_configselect('deleteincompleteusers', new lang_string('deleteincompleteusers', 'admin'), new lang_string('configdeleteincompleteusers', 'admin'), 0, array(0 => new lang_string('never'),
168 => new lang_string('numdays', '', 7),
144 => new lang_string('numdays', '', 6),
120 => new lang_string('numdays', '', 5),
96 => new lang_string('numdays', '', 4),
72 => new lang_string('numdays', '', 3),
48 => new lang_string('numdays', '', 2),
24 => new lang_string('numdays', '', 1))));
$temp->add(new admin_setting_configcheckbox('disablegradehistory', new lang_string('disablegradehistory', 'grades'),
new lang_string('disablegradehistory_help', 'grades'), 0));
$temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_string('gradehistorylifetime', 'grades'),
new lang_string('gradehistorylifetime_help', 'grades'), 0, array(0 => new lang_string('neverdeletehistory', 'grades'),
1000 => new lang_string('numdays', '', 1000),
365 => new lang_string('numdays', '', 365),
180 => new lang_string('numdays', '', 180),
150 => new lang_string('numdays', '', 150),
120 => new lang_string('numdays', '', 120),
90 => new lang_string('numdays', '', 90),
60 => new lang_string('numdays', '', 60),
30 => new lang_string('numdays', '', 30))));
$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'),
new lang_string('configtempdatafoldercleanup', 'admin'), 168, array(
1 => new lang_string('numhours', '', 1),
3 => new lang_string('numhours', '', 3),
6 => new lang_string('numhours', '', 6),
@@ -229,303 +166,224 @@ if ($hassiteconfig) {
24 => new lang_string('numhours', '', 24),
48 => new lang_string('numdays', '', 2),
168 => new lang_string('numdays', '', 7),
]
));
)));
$ADMIN->add('server', $temp);
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_configduration('filescleanupperiod',
new lang_string('filescleanupperiod', 'admin'),
new lang_string('filescleanupperiod_help', 'admin'),
86400));
// Environment.
$ADMIN->add('server', new admin_externalpage('environment', new lang_string('environment', 'admin'),
"{$CFG->wwwroot}/{$CFG->admin}/environment.php"));
$ADMIN->add('server', new admin_externalpage('environment', new lang_string('environment','admin'), "$CFG->wwwroot/$CFG->admin/environment.php"));
$ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo'), "$CFG->wwwroot/$CFG->admin/phpinfo.php"));
$ADMIN->add('server', new admin_externalpage('testoutgoingmailconf', new lang_string('testoutgoingmailconf', 'admin'),
new moodle_url("$CFG->wwwroot/$CFG->admin/testoutgoingmailconf.php"), 'moodle/site:config', true));
// PHP info.
$ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo'),
"{$CFG->wwwroot}/{$CFG->admin}/phpinfo.php"));
// Test outgoing mail configuration (hidden, accessed via direct link from the settings page).
$ADMIN->add('server', new admin_externalpage('testoutgoingmailconf', new lang_string('testoutgoingmailconf', 'admin'),
new moodle_url('/admin/testoutgoingmailconf.php'), 'moodle/site:config', true));
// "performance" settingpage
$temp = new admin_settingpage('performance', new lang_string('performance', 'admin'));
// Performance.
$temp = new admin_settingpage('performance', new lang_string('performance', 'admin'));
// Memory limit options for large administration tasks.
$memoryoptions = array(
'64M' => '64M',
'128M' => '128M',
'256M' => '256M',
'512M' => '512M',
'1024M' => '1024M',
'2048M' => '2048M');
// Memory limit options for large administration tasks.
$memoryoptions = [
'64M' => '64M',
'128M' => '128M',
'256M' => '256M',
'512M' => '512M',
'1024M' => '1024M',
'2048M' => '2048M',
];
// Allow larger memory usage for 64-bit sites only.
if (PHP_INT_SIZE === 8) {
$memoryoptions['3072M'] = '3072M';
$memoryoptions['4096M'] = '4096M';
}
// Allow larger memory usage for 64-bit sites only.
if (PHP_INT_SIZE === 8) {
$memoryoptions['3072M'] = '3072M';
$memoryoptions['4096M'] = '4096M';
}
$temp->add(new admin_setting_configselect('extramemorylimit', new lang_string('extramemorylimit', 'admin'),
new lang_string('configextramemorylimit', 'admin'), '512M', $memoryoptions));
$temp->add(new admin_setting_configtext('maxtimelimit', new lang_string('maxtimelimit', 'admin'),
$temp->add(new admin_setting_configselect('extramemorylimit', new lang_string('extramemorylimit', 'admin'),
new lang_string('configextramemorylimit', 'admin'), '512M',
$memoryoptions));
$temp->add(new admin_setting_configtext('maxtimelimit', new lang_string('maxtimelimit', 'admin'),
new lang_string('maxtimelimit_desc', 'admin'), 0, PARAM_INT));
$temp->add(new admin_setting_configtext('curlcache', new lang_string('curlcache', 'admin'),
new lang_string('configcurlcache', 'admin'), 120, PARAM_INT));
$temp->add(new admin_setting_configtext('curlcache', new lang_string('curlcache', 'admin'),
new lang_string('configcurlcache', 'admin'), 120, PARAM_INT));
$temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('curltimeoutkbitrate', 'admin'),
new lang_string('curltimeoutkbitrate_help', 'admin'), 56, PARAM_INT));
$temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('curltimeoutkbitrate', 'admin'),
new lang_string('curltimeoutkbitrate_help', 'admin'), 56, PARAM_INT));
$ADMIN->add('server', $temp);
$ADMIN->add('server', $temp);
// Tasks.
$ADMIN->add('server', new admin_category('taskconfig', new lang_string('taskadmintitle', 'admin')));
// Task processing.
$temp = new admin_settingpage('taskprocessing', new lang_string('taskprocessing', 'admin'));
$ADMIN->add('server', new admin_category('taskconfig', new lang_string('taskadmintitle', 'admin')));
$temp = new admin_settingpage('taskprocessing', new lang_string('taskprocessing','admin'));
$temp->add(
new admin_setting_configtext(
'task_scheduled_concurrency_limit',
new lang_string('task_scheduled_concurrency_limit', 'admin'),
new lang_string('task_scheduled_concurrency_limit_desc', 'admin'),
3,
PARAM_INT
)
);
$setting = new admin_setting_configcheckbox(
'cron_enabled',
new lang_string('cron_enabled', 'admin'),
new lang_string('cron_enabled_desc', 'admin'),
$temp->add(
new admin_setting_configduration(
'task_scheduled_max_runtime',
new lang_string('task_scheduled_max_runtime', 'admin'),
new lang_string('task_scheduled_max_runtime_desc', 'admin'),
30 * MINSECS
)
);
$temp->add(
new admin_setting_configtext(
'task_adhoc_concurrency_limit',
new lang_string('task_adhoc_concurrency_limit', 'admin'),
new lang_string('task_adhoc_concurrency_limit_desc', 'admin'),
3,
PARAM_INT
)
);
$temp->add(
new admin_setting_configduration(
'task_adhoc_max_runtime',
new lang_string('task_adhoc_max_runtime', 'admin'),
new lang_string('task_adhoc_max_runtime_desc', 'admin'),
30 * MINSECS
)
);
$ADMIN->add('taskconfig', $temp);
$temp = new admin_settingpage('tasklogging', new lang_string('tasklogging','admin'));
$temp->add(
new admin_setting_configselect(
'task_logmode',
new lang_string('task_logmode', 'admin'),
new lang_string('task_logmode_desc', 'admin'),
\core\task\logmanager::MODE_ALL,
[
\core\task\logmanager::MODE_ALL => new lang_string('task_logmode_all', 'admin'),
\core\task\logmanager::MODE_FAILONLY => new lang_string('task_logmode_failonly', 'admin'),
\core\task\logmanager::MODE_NONE => new lang_string('task_logmode_none', 'admin'),
]
)
);
$temp->add(
new admin_setting_configcheckbox(
'task_logtostdout',
new lang_string('task_logtostdout', 'admin'),
new lang_string('task_logtostdout_desc', 'admin'),
1
);
$setting->set_updatedcallback('theme_reset_static_caches');
$temp->add($setting);
$temp->add(
new admin_setting_configtext(
'task_scheduled_concurrency_limit',
new lang_string('task_scheduled_concurrency_limit', 'admin'),
new lang_string('task_scheduled_concurrency_limit_desc', 'admin'),
3,
PARAM_INT
)
);
)
);
if (\core\task\logmanager::uses_standard_settings()) {
$temp->add(
new admin_setting_configduration(
'task_scheduled_max_runtime',
new lang_string('task_scheduled_max_runtime', 'admin'),
new lang_string('task_scheduled_max_runtime_desc', 'admin'),
30 * MINSECS
'task_logretention',
new \lang_string('task_logretention', 'admin'),
new \lang_string('task_logretention_desc', 'admin'),
28 * DAYSECS
)
);
$temp->add(
new admin_setting_configtext(
'task_adhoc_concurrency_limit',
new lang_string('task_adhoc_concurrency_limit', 'admin'),
new lang_string('task_adhoc_concurrency_limit_desc', 'admin'),
3,
'task_logretainruns',
new \lang_string('task_logretainruns', 'admin'),
new \lang_string('task_logretainruns_desc', 'admin'),
20,
PARAM_INT
)
);
}
$ADMIN->add('taskconfig', $temp);
$temp->add(
new admin_setting_configduration(
'task_adhoc_max_runtime',
new lang_string('task_adhoc_max_runtime', 'admin'),
new lang_string('task_adhoc_max_runtime_desc', 'admin'),
30 * MINSECS
)
);
$ADMIN->add('taskconfig', $temp);
if (\core\task\logmanager::uses_standard_settings()) {
$ADMIN->add('taskconfig', new admin_externalpage(
'tasklogs',
new lang_string('tasklogs','admin'),
"{$CFG->wwwroot}/{$CFG->admin}/tasklogs.php"
));
}
// Task log configuration.
$temp = new admin_settingpage('tasklogging', new lang_string('tasklogging', 'admin'));
$temp->add(
new admin_setting_configselect(
'task_logmode',
new lang_string('task_logmode', 'admin'),
new lang_string('task_logmode_desc', 'admin'),
\core\task\logmanager::MODE_ALL,
[
\core\task\logmanager::MODE_ALL => new lang_string('task_logmode_all', 'admin'),
\core\task\logmanager::MODE_FAILONLY => new lang_string('task_logmode_failonly', 'admin'),
\core\task\logmanager::MODE_NONE => new lang_string('task_logmode_none', 'admin'),
]
)
);
$temp->add(
new admin_setting_configcheckbox(
'task_logtostdout',
new lang_string('task_logtostdout', 'admin'),
new lang_string('task_logtostdout_desc', 'admin'),
1
)
);
// E-mail settings.
$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
if (\core\task\logmanager::uses_standard_settings()) {
$temp->add(
new admin_setting_configduration(
'task_logretention',
new \lang_string('task_logretention', 'admin'),
new \lang_string('task_logretention_desc', 'admin'),
28 * DAYSECS
)
);
$temp = new admin_settingpage('outgoingmailconfig', new lang_string('outgoingmailconfig', 'admin'));
$temp->add(
new admin_setting_configtext(
'task_logretainruns',
new \lang_string('task_logretainruns', 'admin'),
new \lang_string('task_logretainruns_desc', 'admin'),
20,
PARAM_INT
)
);
}
$ADMIN->add('taskconfig', $temp);
// Task logs.
if (\core\task\logmanager::uses_standard_settings()) {
$ADMIN->add('taskconfig', new admin_externalpage(
'tasklogs',
new lang_string('tasklogs', 'admin'),
"{$CFG->wwwroot}/{$CFG->admin}/tasklogs.php"
));
}
// Email.
$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
// Outgoing mail configuration.
$temp = new admin_settingpage('outgoingmailconfig', new lang_string('outgoingmailconfig', 'admin'));
$temp->add(new admin_setting_heading('smtpheading', new lang_string('smtp', 'admin'),
new lang_string('smtpdetail', 'admin')));
$temp->add(new admin_setting_configtext('smtphosts', new lang_string('smtphosts', 'admin'),
new lang_string('configsmtphosts', 'admin'), '', PARAM_RAW));
$options = [
'' => new lang_string('none', 'admin'),
'ssl' => 'SSL',
'tls' => 'TLS',
];
$temp->add(new admin_setting_configselect('smtpsecure', new lang_string('smtpsecure', 'admin'),
new lang_string('configsmtpsecure', 'admin'), '', $options));
$authtypeoptions = [
'LOGIN' => 'LOGIN',
'PLAIN' => 'PLAIN',
'NTLM' => 'NTLM',
'CRAM-MD5' => 'CRAM-MD5',
];
$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));
$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));
$temp->add(new admin_setting_configpasswordunmask('smtppass', new lang_string('smtppass', 'admin'),
new lang_string('configsmtpuser', 'admin'), ''));
$temp->add(new admin_setting_configtext('smtpmaxbulk', new lang_string('smtpmaxbulk', 'admin'),
new lang_string('configsmtpmaxbulk', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_heading('noreplydomainheading', new lang_string('noreplydomain', 'admin'),
$temp->add(new admin_setting_heading('smtpheading', new lang_string('smtp', 'admin'),
new lang_string('smtpdetail', 'admin')));
$temp->add(new admin_setting_configtext('smtphosts', new lang_string('smtphosts', 'admin'),
new lang_string('configsmtphosts', 'admin'), '', PARAM_RAW));
$options = array('' => new lang_string('none', 'admin'), 'ssl' => 'SSL', 'tls' => 'TLS');
$temp->add(new admin_setting_configselect('smtpsecure', new lang_string('smtpsecure', 'admin'),
new lang_string('configsmtpsecure', 'admin'), '', $options));
$authtypeoptions = array('LOGIN' => 'LOGIN', 'PLAIN' => 'PLAIN', 'NTLM' => 'NTLM', 'CRAM-MD5' => 'CRAM-MD5');
$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));
$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));
$temp->add(new admin_setting_configpasswordunmask('smtppass', new lang_string('smtppass', 'admin'),
new lang_string('configsmtpuser', 'admin'), ''));
$temp->add(new admin_setting_configtext('smtpmaxbulk', new lang_string('smtpmaxbulk', 'admin'),
new lang_string('configsmtpmaxbulk', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_heading('noreplydomainheading', new lang_string('noreplydomain', 'admin'),
new lang_string('noreplydomaindetail', 'admin')));
$temp->add(new admin_setting_configtext('noreplyaddress', new lang_string('noreplyaddress', 'admin'),
new lang_string('confignoreplyaddress', 'admin'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_EMAIL));
$temp->add(new admin_setting_configtextarea('allowedemaildomains',
$temp->add(new admin_setting_configtext('noreplyaddress', new lang_string('noreplyaddress', 'admin'),
new lang_string('confignoreplyaddress', 'admin'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_EMAIL));
$temp->add(new admin_setting_configtextarea('allowedemaildomains',
new lang_string('allowedemaildomains', 'admin'),
new lang_string('configallowedemaildomains', 'admin'),
''));
$temp->add(new admin_setting_heading('divertallemailsheading', new lang_string('divertallemails', 'admin'),
new lang_string('divertallemailsdetail', 'admin')));
$temp->add(new admin_setting_configtext('divertallemailsto',
new lang_string('divertallemailsto', 'admin'),
new lang_string('divertallemailsto_desc', 'admin'),
''));
$temp->add(new admin_setting_configtextarea('divertallemailsexcept',
new lang_string('divertallemailsexcept', 'admin'),
new lang_string('divertallemailsexcept_desc', 'admin'),
'', PARAM_RAW, '50', '4'));
$noreplyaddress = isset($CFG->noreplyaddress) ? $CFG->noreplyaddress : 'noreply@example.com';
$dkimdomain = substr(strrchr($noreplyaddress, "@"), 1);
$dkimselector = empty($CFG->emaildkimselector) ? '[selector]' : $CFG->emaildkimselector;
$pempath = "\$CFG->dataroot/dkim/{$dkimdomain}/{$dkimselector}.private";
$temp->add(new admin_setting_heading('emaildkim', new lang_string('emaildkim', 'admin'),
new lang_string('emaildkiminfo', 'admin', ['path' => $pempath, 'docs' => \get_docs_url('Mail_configuration#DKIM')])));
$temp->add(new admin_setting_configtext('emaildkimselector', new lang_string('emaildkimselector', 'admin'),
new lang_string('configemaildkimselector', 'admin'), '', PARAM_FILE));
$url = new moodle_url('/admin/testoutgoingmailconf.php');
$link = html_writer::link($url, get_string('testoutgoingmailconf', 'admin'));
$temp->add(new admin_setting_heading('testoutgoinmailc', new lang_string('testoutgoingmailconf', 'admin'),
$url = new moodle_url('/admin/testoutgoingmailconf.php');
$link = html_writer::link($url, get_string('testoutgoingmailconf', 'admin'));
$temp->add(new admin_setting_heading('testoutgoinmailc', new lang_string('testoutgoingmailconf', 'admin'),
new lang_string('testoutgoingmaildetail', 'admin', $link)));
$temp->add(new admin_setting_heading('emaildoesnotfit', new lang_string('doesnotfit', 'admin'),
$temp->add(new admin_setting_heading('emaildoesnotfit', new lang_string('doesnotfit', 'admin'),
new lang_string('doesnotfitdetail', 'admin')));
$charsets = get_list_of_charsets();
unset($charsets['UTF-8']); // Not needed here.
$options = array();
$options['0'] = 'UTF-8';
$options = array_merge($options, $charsets);
$temp->add(new admin_setting_configselect('sitemailcharset', new lang_string('sitemailcharset', 'admin'),
new lang_string('configsitemailcharset','admin'), '0', $options));
$temp->add(new admin_setting_configcheckbox('allowusermailcharset', new lang_string('allowusermailcharset', 'admin'),
new lang_string('configallowusermailcharset', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('allowattachments', new lang_string('allowattachments', 'admin'),
new lang_string('configallowattachments', 'admin'), 1));
$options = array('LF' => 'LF', 'CRLF' => 'CRLF');
$temp->add(new admin_setting_configselect('mailnewline', new lang_string('mailnewline', 'admin'),
new lang_string('configmailnewline', 'admin'), 'LF', $options));
$charsets = get_list_of_charsets();
unset($charsets['UTF-8']);
$options = [
'0' => 'UTF-8',
];
$options = array_merge($options, $charsets);
$temp->add(new admin_setting_configselect('sitemailcharset', new lang_string('sitemailcharset', 'admin'),
new lang_string('configsitemailcharset', 'admin'), '0', $options));
$temp->add(new admin_setting_configcheckbox('allowusermailcharset', new lang_string('allowusermailcharset', 'admin'),
new lang_string('configallowusermailcharset', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('allowattachments', new lang_string('allowattachments', 'admin'),
new lang_string('configallowattachments', 'admin'), 1));
$options = [
'LF' => 'LF',
'CRLF' => 'CRLF',
];
$temp->add(new admin_setting_configselect('mailnewline', new lang_string('mailnewline', 'admin'),
new lang_string('configmailnewline', 'admin'), 'LF', $options));
$choices = [
new lang_string('never', 'admin'),
new lang_string('always', 'admin'),
new lang_string('onlynoreply', 'admin'),
];
$temp->add(new admin_setting_configselect('emailfromvia', new lang_string('emailfromvia', 'admin'),
new lang_string('configemailfromvia', 'admin'), 1, $choices));
$choices = array(new lang_string('never', 'admin'),
new lang_string('always', 'admin'),
new lang_string('onlynoreply', 'admin'));
$temp->add(new admin_setting_configselect('emailfromvia', new lang_string('emailfromvia', 'admin'),
new lang_string('configemailfromvia', 'admin'), 1, $choices));
$temp->add(new admin_setting_configtext('emailsubjectprefix', new lang_string('emailsubjectprefix', 'admin'),
new lang_string('configemailsubjectprefix', 'admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtextarea('emailheaders', new lang_string('emailheaders', 'admin'),
new lang_string('configemailheaders', 'admin'), '', PARAM_RAW, '50', '3'));
$ADMIN->add('email', $temp);
$ADMIN->add('email', $temp);
// Update notifications.
if (empty($CFG->disableupdatenotifications)) {
$temp = new admin_settingpage('updatenotifications', new lang_string('updatenotifications', 'core_admin'));
$temp->add(new admin_setting_configcheckbox('updateautocheck', new lang_string('updateautocheck', 'core_admin'),
new lang_string('updateautocheck_desc', 'core_admin'), 1));
$temp->add(new admin_setting_configselect('updateminmaturity', new lang_string('updateminmaturity', 'core_admin'),
new lang_string('updateminmaturity_desc', 'core_admin'), MATURITY_STABLE,
[
MATURITY_ALPHA => new lang_string('maturity'.MATURITY_ALPHA, 'core_admin'),
MATURITY_BETA => new lang_string('maturity'.MATURITY_BETA, 'core_admin'),
MATURITY_RC => new lang_string('maturity'.MATURITY_RC, 'core_admin'),
MATURITY_STABLE => new lang_string('maturity'.MATURITY_STABLE, 'core_admin'),
]
));
$temp->add(new admin_setting_configcheckbox('updatenotifybuilds', new lang_string('updatenotifybuilds', 'core_admin'),
new lang_string('updatenotifybuilds_desc', 'core_admin'), 0));
$ADMIN->add('server', $temp);
}
// "update notifications" settingpage
if (empty($CFG->disableupdatenotifications)) {
$temp = new admin_settingpage('updatenotifications', new lang_string('updatenotifications', 'core_admin'));
$temp->add(new admin_setting_configcheckbox('updateautocheck', new lang_string('updateautocheck', 'core_admin'),
new lang_string('updateautocheck_desc', 'core_admin'), 1));
$temp->add(new admin_setting_configselect('updateminmaturity', new lang_string('updateminmaturity', 'core_admin'),
new lang_string('updateminmaturity_desc', 'core_admin'), MATURITY_STABLE,
array(
MATURITY_ALPHA => new lang_string('maturity'.MATURITY_ALPHA, 'core_admin'),
MATURITY_BETA => new lang_string('maturity'.MATURITY_BETA, 'core_admin'),
MATURITY_RC => new lang_string('maturity'.MATURITY_RC, 'core_admin'),
MATURITY_STABLE => new lang_string('maturity'.MATURITY_STABLE, 'core_admin'),
)));
$temp->add(new admin_setting_configcheckbox('updatenotifybuilds', new lang_string('updatenotifybuilds', 'core_admin'),
new lang_string('updatenotifybuilds_desc', 'core_admin'), 0));
$ADMIN->add('server', $temp);
}
} // end of speedup
-1
View File
@@ -39,7 +39,6 @@ $ADMIN->add('root', new admin_category('license', new lang_string('license')));
$ADMIN->add('root', new admin_category('location', new lang_string('location','admin')));
$ADMIN->add('root', new admin_category('language', new lang_string('language')));
$ADMIN->add('root', new admin_category('messaging', new lang_string('messagingcategory', 'admin')));
$ADMIN->add('root', new admin_category('payment', new lang_string('payments', 'payment')));
$ADMIN->add('root', new admin_category('modules', new lang_string('plugins', 'admin')));
$ADMIN->add('root', new admin_category('security', new lang_string('security','admin')));
$ADMIN->add('root', new admin_category('appearance', new lang_string('appearance','admin')));
-1
View File
@@ -32,7 +32,6 @@ $result = optional_param('result', null, PARAM_INT);
$pageurl = new \moodle_url('/admin/tasklogs.php');
$pageurl->param('filter', $filter);
$pageurl->param('result', $result);
$PAGE->set_url($pageurl);
$PAGE->set_context(context_system::instance());
@@ -1,87 +0,0 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template core_admin\local\settings\autocomplete
Admin setting auto complete.
Context variables required for this template:
* name - element name
* id - element id
* options - choices
* multiple - is multiple choices?
* manageurl - url to manage choices
* managetext - string to display manage url
* tags - Should we allow typing new entries to the field?
* ajax - Name of an AMD module to send/process ajax requests
* placeholder - Placeholder text for an empty list
* casesensitive - Whether the search has to be case-sensitive
* showsuggestions - Show suggestions by default - but this can be turned off
* noselectionstring - String that is shown when there are no selections
Example context (json):
{
"name": "name0",
"id": "id0",
"options": [{
"value": "1",
"text": "option 1",
"selected": true,
"disabled": false
}],
"multiple": true,
"manageurl": "",
"managetext": "",
"tags": false,
"ajax": "",
"placeholder": "",
"casesensitive": false,
"showsuggestions": true,
"noselectionstring": ""
}
}}
{{!
Setting autocomplete.
}}
<div class="form-select defaultsnext">
<input type="hidden" name="{{name}}[xxxxx]" value="_qf__force_multiselect_submission">
<select class="custom-select" name="{{name}}[]"
id="{{id}}"
{{#multiple}}multiple{{/multiple}}>
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{{text}}}</option>
{{/options}}
</select>
{{#manageurl}}
<a href="{{manageurl}}">{{managetext}}</a>
{{/manageurl}}
</div>
<br/>
{{#js}}
require(['core/form-autocomplete'], function(module) {
module.enhance({{#quote}}#{{id}}{{/quote}},
{{tags}},
{{#quote}}{{ajax}}{{/quote}},
{{#quote}}{{placeholder}}{{/quote}},
{{casesensitive}},
{{showsuggestions}},
{{#quote}}{{noselectionstring}}{{/quote}});
});
{{/js}}
@@ -25,7 +25,6 @@
* value - yes value
* id - element id
* checked - boole
* readonly - bool
Example context (json):
{
@@ -33,11 +32,10 @@
"no": "False",
"value": "True",
"id": "test0",
"checked": "checked",
"readonly": false
"checked": "checked"
}
}}
<div class="form-checkbox defaultsnext">
<input type="hidden" name="{{name}}" value="{{no}}">
<input {{#readonly}}disabled{{/readonly}} type="checkbox" name="{{name}}" value="{{value}}" id="{{id}}" {{#checked}}checked{{/checked}}>
<input type="checkbox" name="{{name}}" value="{{value}}" id="{{id}}" {{#checked}}checked{{/checked}}>
</div>
@@ -25,7 +25,6 @@
* id - element id
* value - element value
* haspreviewconfig - show preview of selected color
* readonly - bool
Example context (json):
{
@@ -33,7 +32,6 @@
"name": "name0",
"id": "id0",
"value": "#555655",
"readonly": false,
"haspreviewconfig": false
}
}}
@@ -46,7 +44,7 @@
{{>core/pix_icon}}
{{/icon}}
</div>
<input type="text" name="{{name}}" id="{{id}}" value="{{value}}" size="12" class="form-control text-ltr" {{#readonly}}disabled{{/readonly}}>
<input type="text" name="{{name}}" id="{{id}}" value="{{value}}" size="12" class="form-control text-ltr">
{{#haspreviewconfig}}
<input type="button" id="{{id}}_preview" value={{#quote}}{{#str}}preview{{/str}}{{/quote}} class="admin_colourpicker_preview">
{{/haspreviewconfig}}
@@ -33,7 +33,7 @@
"name": "test",
"value": "/my-super-secret-path/",
"id": "test0",
"readonly": false,
"readonly": true,
"showvalidity": true,
"valid": false
}
@@ -23,7 +23,6 @@
* name - form element name
* options - list of options for units containing name, value, selected
* value - yes
* readonly - bool
* id - element id
Example context (json):
@@ -31,7 +30,6 @@
"name": "test",
"value": "5",
"id": "test0",
"readonly": false,
"options": [ { "name": "Minutes", "value": "mins", "selected": true } ]
}
}}
@@ -40,9 +38,9 @@
}}
<div class="form-duration defaultsnext">
<div class="form-inline">
<input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr" {{#readonly}}disabled{{/readonly}}>
<input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr">
<label class="sr-only" for="{{id}}u">{{#str}}durationunits, admin{{/str}}</label>
<select id="{{id}}u" name="{{name}}[u]" class="form-control custom-select" {{#readonly}}disabled{{/readonly}}>
<select id="{{id}}u" name="{{name}}[u]" class="form-control custom-select">
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -33,7 +33,7 @@
"name": "test",
"value": "/usr/bin/cowsay",
"id": "test0",
"readonly": false,
"readonly": true,
"showvalidity": true,
"valid": false
}
+1 -3
View File
@@ -26,7 +26,6 @@
* readonly - Make the field readonly
* value - value
* showvalidity - Show a green check if the path is readable
* readonly - bool
* valid - True if the path is readable
Example context (json):
@@ -34,9 +33,8 @@
"name": "test",
"value": "/my-super-secret-path/file",
"id": "test0",
"readonly": false,
"readonly": true,
"showvalidity": true,
"readonly": false,
"valid": false
}
}}
@@ -24,14 +24,12 @@
* options - list of options for units containing name, value, selected
* value - yes
* id - element id
* readonly - bool
Example context (json):
{
"name": "test",
"value": "5",
"id": "test0",
"readonly": false,
"options": [ { "name": "KB", "value": "1024", "selected": true } ]
}
}}
@@ -40,9 +38,9 @@
}}
<div class="form-filesize defaultsnext">
<div class="form-inline">
<input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr" {{#readonly}}disabled{{/readonly}}>
<input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr">
<label class="sr-only" for="{{id}}u">{{#str}}filesizeunits, admin{{/str}}</label>
<select id="{{id}}u" name="{{name}}[u]" class="form-control custom-select" {{#readonly}}disabled{{/readonly}}>
<select id="{{id}}u" name="{{name}}[u]" class="form-control custom-select">
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -24,13 +24,11 @@
* id - element id
* size - element size
* options - list of options containing name, value, selected
* readonly - bool
Example context (json):
{
"name": "test",
"id": "test0",
"readonly": false,
"size": "3",
"options": [ { "name": "Option 1", "value": "V", "selected": true },
{ "name": "Option 2", "value": "V", "selected": true } ]
@@ -41,7 +39,7 @@
}}
<div class="form-select">
<input type="hidden" name="{{name}}[xxxxx]" value="1">
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
<select id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -25,13 +25,11 @@
* size - element size
* options - list of options not grouped
* optgroups - list of options grouped containing the group label and for each option: name, value, selected
* readonly - bool
Example context (json):
{
"name": "test",
"id": "test0",
"readonly": false,
"size": "3",
"options": [
{ "name": "Option 1", "value": "V", "selected": false },
@@ -60,7 +58,7 @@
}}
<div class="form-select">
<input type="hidden" name="{{name}}[xxxxx]" value="1">
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
<select id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -24,7 +24,7 @@
* size - form element size
* value - form element value
* id - element id
* readonly - has value been defined in config.php
* forced - has value been defined in config.php
Example context (json):
{
@@ -32,10 +32,10 @@
"id": "test0",
"size": "8",
"value": "secret",
"readonly": false
"forced": false
}
}}
{{#readonly}}
{{#forced}}
<div class="form-password">
<input type="text"
name = "{{ name }}"
@@ -46,8 +46,8 @@
disabled
>
</div>
{{/readonly}}
{{^readonly}}
{{/forced}}
{{^forced}}
<div class="form-password">
<span data-passwordunmask="wrapper" data-passwordunmaskid="{{ id }}">
<span data-passwordunmask="editor">
@@ -76,4 +76,4 @@ require(['core_form/passwordunmask'], function(PasswordUnmask) {
new PasswordUnmask("{{ id }}");
});
{{/js}}
{{/readonly}}
{{/forced}}
@@ -23,13 +23,11 @@
* name - form element name
* id - element id
* options - list of options containing name, value, selected
* readonly - bool
Example context (json):
{
"name": "test",
"id": "test0",
"readonly": false,
"options": [
{ "name": "Option 1", "value": "V", "selected": true },
{ "name": "Option 2", "value": "V", "selected": true }
@@ -40,7 +38,7 @@
Setting configselect.
}}
<div class="form-select defaultsnext">
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}" class="custom-select">
<select id="{{id}}" name="{{name}}" class="custom-select">
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -22,7 +22,6 @@
Context variables required for this template:
* name - form element name
* id - element id
* readonly - bool
* options - list of options (not grouped)
* optgroups - list of options grouped containing the group label and for each option: name, value, selected
@@ -30,7 +29,6 @@
{
"name": "test",
"id": "test0",
"readonly": false,
"options": [
{ "name": "Option 1", "value": "V", "selected": false },
{ "name": "Option 2", "value": "V", "selected": false }
@@ -57,7 +55,7 @@
Setting configselect with optgroup support.
}}
<div class="form-select defaultsnext">
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}" class="custom-select">
<select id="{{id}}" name="{{name}}" class="custom-select">
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
+1 -3
View File
@@ -26,7 +26,6 @@
* size - element size
* forceltr - always display as ltr
* attributes - list of additional attributes containing name, value
* readonly - bool
Example context (json):
{
@@ -35,7 +34,6 @@
"value": "A tall, dark stranger will have more fun than you.",
"size": "21",
"forceltr": false,
"readonly": false,
"attributes": [ { "name": "readonly", "value": "readonly" } ]
}
}}
@@ -43,5 +41,5 @@
Setting configtext.
}}
<div class="form-text defaultsnext">
<input type="text" name="{{name}}" value="{{value}}" size="{{size}}" id="{{id}}" class="form-control {{#forceltr}}text-ltr{{/forceltr}}" {{#readonly}}disabled{{/readonly}}>
<input type="text" name="{{name}}" value="{{value}}" size="{{size}}" id="{{id}}" class="form-control {{#forceltr}}text-ltr{{/forceltr}}">
</div>
@@ -33,7 +33,6 @@
"cols": "30",
"rows": "3",
"value": "Excellent day for putting Slinkies on an escalator.",
"readonly": false,
"id": "test0"
}
}}
@@ -41,5 +40,5 @@
Setting configtextarea.
}}
<div class="form-textarea">
<textarea {{#readonly}}disabled{{/readonly}} rows="{{rows}}" cols="{{cols}}" id="{{id}}" name="{{name}}" spellcheck="true" class="form-control {{#forceltr}}text-ltr{{/forceltr}}">{{value}}</textarea>
<textarea rows="{{rows}}" cols="{{cols}}" id="{{id}}" name="{{name}}" spellcheck="true" class="form-control {{#forceltr}}text-ltr{{/forceltr}}">{{value}}</textarea>
</div>
+2 -4
View File
@@ -24,13 +24,11 @@
* id - element id
* hours - list of valid hour options containing name, value, selected
* minutes - list of valid minute options containing name, value, selected
* readonly - bool
Example context (json):
{
"name": "test",
"id": "test0",
"readonly": false,
"minutes": [
{ "name": "00", "value": "0", "selected": true },
{ "name": "01", "value": "1", "selected": false }
@@ -47,13 +45,13 @@
<div class="form-time defaultsnext">
<div class="form-inline text-ltr">
<label class="sr-only" for="{{id}}h">{{#str}}hours{{/str}}</label>
<select id="{{id}}h" name="{{name}}[h]" class="custom-select" {{#readonly}}disabled{{/readonly}}>
<select id="{{id}}h" name="{{name}}[h]" class="custom-select">
{{#hours}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/hours}}
</select>:
<label class="sr-only" for="{{id}}m">{{#str}}minutes{{/str}}</label>
<select id="{{id}}m" name="{{name}}[m]" class="custom-select" {{#readonly}}disabled{{/readonly}}>
<select id="{{id}}m" name="{{name}}[m]" class="custom-select">
{{#minutes}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/minutes}}
+1 -1
View File
@@ -56,7 +56,7 @@ class behat_admin extends behat_base {
$this->execute('behat_navigation::i_select_from_flat_navigation_drawer', [get_string('administrationsite')]);
// Search by label.
$this->execute('behat_forms::i_set_the_field_to', [get_string('search'), $label]);
$this->execute('behat_forms::i_set_the_field_to', [get_string('query', 'admin'), $label]);
$this->execute("behat_forms::press_button", get_string('search', 'admin'));
// Admin settings does not use the same DOM structure than other moodle forms
@@ -1,29 +0,0 @@
@core @core_admin
Feature: Administrator is warned and when trying to set invalid allcountrycodes value.
In order to avoid misconfiguration of the country selector fields
As an admin
I want to be warned when I try to set an invalid country code in the allcountrycodes field
Scenario: Attempting to set allcountrycodes field with valid country codes
Given I log in as "admin"
And I navigate to "Location > Location settings" in site administration
When I set the following administration settings values:
| All country codes | CZ,BE,GB,ES |
Then I should not see "Invalid country code"
Scenario: Attempting to set allcountrycodes field with invalid country code
Given I log in as "admin"
And I navigate to "Location > Location settings" in site administration
When I set the following administration settings values:
| All country codes | CZ,BE,FOOBAR,GB,ES |
Then I should see "Invalid country code: FOOBAR"
Scenario: Attempting to unset allcountrycodes field
Given I log in as "admin"
And I navigate to "Location > Location settings" in site administration
And I set the following administration settings values:
| All country codes | CZ,BE,GB,ES |
And I navigate to "Location > Location settings" in site administration
When I set the following administration settings values:
| All country codes | |
Then I should not see "Invalid country code"
@@ -1,34 +0,0 @@
@core @core_admin
Feature: Configure language settings for the site
In order to configure language settings for the site
As an admin
I want to set language settings relevant to my site users
Scenario: Set languages on language menu
Given I log in as "admin"
And I navigate to "Language > Language settings" in site administration
When I set the field "Languages on language menu" to "en"
And I press "Save changes"
Then I should not see "Invalid language code"
Scenario: Reset languages on language menu
Given I log in as "admin"
And I navigate to "Language > Language settings" in site administration
When I set the field "Languages on language menu" to ""
And I press "Save changes"
Then I should not see "Invalid language code"
Scenario Outline: Set languages on language menu with invalid language
Given I log in as "admin"
And I navigate to "Language > Language settings" in site administration
When I set the field "Languages on language menu" to "<fieldvalue>"
And I press "Save changes"
Then I should see "Invalid language code: <invalidlang>"
Examples:
| fieldvalue | invalidlang |
| xx | xx |
| xx\|Bad | xx |
| en,qq | qq |
| en,qq\|Bad | qq |
| en$$ | en$$ |
| en$$\|Bad | en$$ |
@@ -64,7 +64,7 @@ class models_list implements \renderable, \templatable {
$data = new \stdClass();
$newmodelmenu = new \action_menu();
$newmodelmenu->set_menu_trigger(get_string('newmodel', 'tool_analytics'), 'btn btn-secondary');
$newmodelmenu->set_menu_trigger(get_string('newmodel', 'tool_analytics'), 'btn btn-default');
$newmodelmenu->set_alignment(\action_menu::TL, \action_menu::BL);
$newmodelmenu->add(new \action_menu_link(
@@ -57,10 +57,10 @@
{{/trainedexternally}}
{{! Hidden by default if #trainedexternally as the default option is trainedmodel in this case.}}
<div id="id-evaluation-timesplitting-container" class="mt-3 {{#trainedexternally}}hidden{{/trainedexternally}}">
<div id="id-evaluation-timesplitting-container" class="m-t-1 {{#trainedexternally}}hidden{{/trainedexternally}}">
{{#str}} selecttimesplittingforevaluation, tool_analytics {{/str}}
<div>
<select id="id-evaluation-timesplitting" name="timesplitting" class="custom-select mt-3">
<select id="id-evaluation-timesplitting" name="timesplitting" class="custom-select m-t-1">
{{#timesplittingmethods}}
<option value="{{id}}">{{text}}</option>
{{/timesplittingmethods}}
@@ -39,7 +39,7 @@
<input class="custom-control-input" type="radio" name="exportoption" id="id-mode-exportmodel" value="exportmodel" checked>
<label class="custom-control-label" for="id-mode-exportmodel">{{#str}} exportmodel, tool_analytics {{/str}}</label>
</div>
<div class="custom-control custom-checkbox ml-5" id="id-includeweights-container">
<div class="custom-control custom-checkbox m-l-2" id="id-includeweights-container">
<input class="custom-control-input" type="checkbox" id="id-includeweights" value="1" checked>
<label class="custom-control-label" for="id-includeweights">{{#str}} exportincludeweights, tool_analytics {{/str}}</label>
</div>
+2 -1
View File
@@ -66,6 +66,8 @@ class tool_analytics_external_testcase extends externallib_advanced_testcase {
/**
* test_potential_contexts description
*
* @expectedException required_capability_exception
*/
public function test_potential_contexts_no_manager() {
$this->resetAfterTest();
@@ -73,7 +75,6 @@ class tool_analytics_external_testcase extends externallib_advanced_testcase {
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$this->expectException(required_capability_exception::class);
$this->assertCount(2, \tool_analytics\external::potential_contexts());
}
}
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2020110300; // Requires this Moodle version.
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2020060900; // Requires this Moodle version.
$plugin->component = 'tool_analytics'; // Full name of the plugin (used for diagnostics).
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2020110900;
$plugin->requires = 2020110300;
$plugin->version = 2020061500;
$plugin->requires = 2020060900;
$plugin->component = 'tool_availabilityconditions';
+11 -43
View File
@@ -49,10 +49,6 @@ list($options, $unrecognized) = cli_get_params(
'torun' => 0,
'optimize-runs' => '',
'add-core-features-to-theme' => false,
'axe' => false,
'disable-composer' => false,
'composer-upgrade' => true,
'composer-self-update' => true,
),
array(
'j' => 'parallel',
@@ -68,36 +64,18 @@ $help = "
Behat utilities to initialise behat tests
Usage:
php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]]
[--axe] [-o | --optimize-runs] [-a | --add-core-features-to-theme]
[--no-composer-self-update] [--no-composer-upgrade]
[--disable-composer]
[--help]
php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]] [--help]
Options:
-j, --parallel Number of parallel behat run to initialise
-m, --maxruns Max parallel processes to be executed at one time
--fromrun Execute run starting from (Used for parallel runs on different vms)
--torun Execute run till (Used for parallel runs on different vms)
--axe Include axe accessibility tests
-j, --parallel Number of parallel behat run to initialise
-m, --maxruns Max parallel processes to be executed at one time.
--fromrun Execute run starting from (Used for parallel runs on different vms)
--torun Execute run till (Used for parallel runs on different vms)
-o, --optimize-runs
Split features with specified tags in all parallel runs.
-o, --optimize-runs Split features with specified tags in all parallel runs.
-a, --add-core-features-to-theme Add all core features to specified theme's
-a, --add-core-features-to-theme
Add all core features to specified theme's
--no-composer-self-update
Prevent upgrade of the composer utility using its self-update command
--no-composer-upgrade
Prevent update development dependencies using composer
--disable-composer
A shortcut to disable composer self-update and dependency update
Note: Installation of composer and/or dependencies will still happen as required
-h, --help Print out this help
-h, --help Print out this help
Example from Moodle root directory:
\$ php admin/tool/behat/cli/init.php --parallel=2
@@ -124,10 +102,7 @@ if ($options['parallel'] && $options['parallel'] > 1) {
}
} else {
// Only sanitize options for single run.
$cmdoptionsforsinglerun = [
'add-core-features-to-theme',
'axe',
];
$cmdoptionsforsinglerun = array('add-core-features-to-theme');
foreach ($cmdoptionsforsinglerun as $option) {
if (!empty($options[$option])) {
@@ -140,15 +115,8 @@ if ($options['parallel'] && $options['parallel'] > 1) {
$cwd = getcwd();
$output = null;
if ($options['disable-composer']) {
// Disable self-update and upgrade easily.
// Note: Installation will still occur regardless of this setting.
$options['composer-self-update'] = false;
$options['composer-upgrade'] = false;
}
// Install and update composer and dependencies as required.
testing_update_composer_dependencies($options['composer-self-update'], $options['composer-upgrade']);
// If behat dependencies not downloaded then do it first, else symfony/process can't be used.
testing_update_composer_dependencies();
// Check whether the behat test environment needs to be updated.
chdir(__DIR__);
+1 -3
View File
@@ -54,7 +54,6 @@ list($options, $unrecognized) = cli_get_params(
'torun' => 0,
'optimize-runs' => '',
'add-core-features-to-theme' => false,
'axe' => false,
),
array(
'h' => 'help',
@@ -70,7 +69,7 @@ $help = "
Behat utilities to manage the test environment
Usage:
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--axe|--help] [--parallel=value [--maxruns=value]]
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--help] [--parallel=value [--maxruns=value]]
Options:
--install Installs the test environment for acceptance tests
@@ -79,7 +78,6 @@ Options:
--disable Disables test environment
--diag Get behat test environment status code
--updatesteps Update feature step file.
--axe Include axe accessibility tests
-j, --parallel Number of parallel behat run operation
-m, --maxruns Max parallel processes to be executed at one time.
+1 -9
View File
@@ -49,7 +49,6 @@ list($options, $unrecognized) = cli_get_params(
'updatesteps' => false,
'optimize-runs' => '',
'add-core-features-to-theme' => false,
'axe' => false,
),
array(
'h' => 'help',
@@ -76,7 +75,6 @@ Options:
--disable Disables test environment
--diag Get behat test environment status code
--updatesteps Update feature step file.
--axe Include axe accessibility tests
-o, --optimize-runs Split features with specified tags in all parallel runs.
-a, --add-core-features-to-theme Add all core features to specified theme's
@@ -183,17 +181,11 @@ if ($options['install']) {
behat_config_manager::set_behat_run_config_value('behatsiteenabled', 1);
}
// Define whether to run Behat with axe tests.
behat_config_manager::set_behat_run_config_value('axe', $options['axe']);
// Enable test mode.
$timestart = microtime(true);
mtrace('Creating Behat configuration ...', '');
behat_util::start_test_mode($options['add-core-features-to-theme'], $options['optimize-runs'], $parallel, $run);
mtrace(' done in ' . round(microtime(true) - $timestart, 2) . ' seconds.');
// Themes are only built in the 'enable' command.
behat_util::build_themes(true);
behat_util::build_themes();
mtrace("Testing environment themes built");
// This is only displayed once for parallel install.
-1
View File
@@ -46,7 +46,6 @@ $string['stepsdefinitionstype'] = 'Type';
$string['theninfo'] = 'Then. Checkings to ensure the outcomes are the expected ones';
$string['unknownexceptioninfo'] = 'There was a problem with Selenium or your browser. Please ensure you are using the latest version of Selenium. Error:';
$string['viewsteps'] = 'Filter';
$string['warndirrootconfigfound'] = 'A configuration file was found at {$a}. This file is not automatically updated and may become stale. We recommend removing this file.';
$string['wheninfo'] = 'When. Action that provokes an event';
$string['wrongbehatsetup'] = 'Something is wrong with the behat setup and so step definitions cannot be listed: <b>{$a->errormsg}</b><br/><br/>Please check:<ul>
<li>$CFG->behat_dataroot, $CFG->behat_prefix and $CFG->behat_wwwroot are set in config.php with different values from $CFG->dataroot, $CFG->prefix and $CFG->wwwroot.</li>
@@ -156,7 +156,7 @@ Feature: Set up contextual data for tests
And I log in as "user5"
And I should see "You are logged in as"
And I am on "Course 1" course homepage
And I should see "You cannot enrol yourself in this course."
And I should see "You can not enrol yourself in this course."
Scenario: Add modules
Given the following "courses" exist:
@@ -6,18 +6,14 @@ Feature: Edit capabilities
Background:
Given the following "users" exist:
| username | firstname | lastname |
| teacher1 | Teacher | 1 |
| tutor | Teaching | Assistant |
| student | Student | One |
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| tutor | C1 | teacher |
| student | C1 | student |
| user | course | role |
| teacher1 | C1 | editingteacher |
Scenario: Default system capabilities modification
Given I log in as "admin"
@@ -64,25 +60,3 @@ Feature: Edit capabilities
Then "mod/forum:deleteanypost" capability has "Prohibit" permission
And "mod/forum:editanypost" capability has "Prevent" permission
And "mod/forum:addquestion" capability has "Allow" permission
@javascript
Scenario: Edit permissions escapes role names correctly
When I am on the "C1" "Course" page logged in as "admin"
And I navigate to "Edit settings" in current page administration
And I set the following fields to these values:
| Your word for 'Teacher' | Teacher >= editing |
| Your word for 'Non-editing teacher' | Teacher < "editing" |
| Your word for 'Student' | Studier & 'learner' |
And I press "Save and display"
And I navigate to course participants
Then I should see "Teacher >= editing (Teacher)" in the "Teacher 1" "table_row"
And I should see "Teacher < \"editing\" (Non-editing teacher)" in the "Teaching Assistant" "table_row"
And I should see "Studier & 'learner' (Student)" in the "Student One" "table_row"
And I navigate to "Users > Permissions" in current page administration
And I should see "Teacher >= editing" in the "mod/forum:replypost" "table_row"
And I should see "Teacher < \"editing\"" in the "mod/forum:replypost" "table_row"
And I should see "Studier & 'learner'" in the "mod/forum:replypost" "table_row"
And I follow "Prohibit"
And "Teacher >= editing" "button" in the "Prohibit role" "dialogue" should be visible
And "Teacher < \"editing\"" "button" in the "Prohibit role" "dialogue" should be visible
And "Studier & 'learner'" "button" in the "Prohibit role" "dialogue" should be visible
@@ -1,30 +0,0 @@
@tool_behat
Feature: Verify that the inplace editable field works as expected
In order to use behat step definitions
As a test write
I need to ensure that the inplace editable works in forms
Background:
Given the following "course" exists:
| fullname | Course 1 |
| shortname | C1 |
And the following "activities" exist:
| activity | course | name | idnumber |
| forum | C1 | My first forum | forum1 |
| assign | C1 | My first assignment | assign1 |
| quiz | C1 | My first quiz | quiz1 |
And I log in as "admin"
And I am on "Course 1" course homepage with editing mode on
@javascript
Scenario: Using an inplace editable updates the name of an activity
When I set the field "Edit title" in the "My first assignment" "activity" to "Coursework submission"
Then I should see "Coursework submission"
And I should not see "My first assignment"
But I should see "My first forum"
And I should see "My first quiz"
And I set the field "Edit title" in the "Coursework submission" "activity" to "My first assignment"
And I should not see "Coursework submission"
But I should see "My first assignment"
And I should see "My first forum"
And I should see "My first quiz"
@@ -1,52 +0,0 @@
@tool_behat
Feature: Verify that keyboard steps work as expected
In order to use behat step definitions
As a test writer
I need to verify that the keyboard steps work as expected
@javascript
Scenario: Typing keys into a field causes them to be input
Given the following "users" exist:
| username | email | firstname | lastname | password |
| saffronr | saffron.rutledge@example.com | Saffron | Rutledge | flowerpower |
Given I click on "Log in" "link"
And I click on "Username" "field"
When I type "saffronr"
And I press the tab key
And I type "flowerpower"
And I press enter
Then I should see "You are logged in as Saffron Rutledge"
@javascript
Scenario: Using tab changes focus to the next or previous field
Given I click on "Log in" "link"
And I click on "Username" "field"
And the focused element is "Username" "field"
When I press the tab key
Then the focused element is "Password" "field"
And I press the shift tab key
And the focused element is "Username" "field"
@javascript
Scenario: Using the arrow keys allows me to navigate through menus
Given the following "users" exist:
| username | email | firstname | lastname |
| saffronr | saffron.rutledge@example.com | Saffron | Rutledge |
And I log in as "saffronr"
And I click on "Saffron Rutledge" "link" in the ".usermenu" "css_element"
When I press the up key
Then the focused element is "Log out" "link"
@javascript
Scenario: The escape key can be used to close a dialogue
Given the following "course" exists:
| fullname | C1|
| shortname | C1 |
And I log in as "admin"
And I am on "C1" course homepage
And I navigate to course participants
And I press "Enrol users"
And "Enrol users" "dialogue" should be visible
When I press the escape key
Then "Enrol users" "dialogue" should not be visible
@@ -14,6 +14,8 @@ Feature: Forms manipulation
Then the field "First name" matches value "Field value"
And the "Select a country" select box should contain "Japan"
And the field "New password" matches value "TestPass"
And I take focus off "Update profile" "button"
And I press "Update profile"
@javascript
Scenario: Expand all fieldsets and advanced elements
+15 -15
View File
@@ -87,7 +87,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
/**
* Setup test.
*/
public function setUp(): void {
public function setup() {
global $CFG;
$this->resetAfterTest();
@@ -165,7 +165,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -219,7 +219,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -264,7 +264,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -295,7 +295,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -324,7 +324,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -368,7 +368,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -399,7 +399,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -428,7 +428,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -532,7 +532,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -611,7 +611,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -646,7 +646,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -662,7 +662,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -678,7 +678,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -693,7 +693,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
}
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2020110300; // Requires this Moodle version
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2020060900; // Requires this Moodle version
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
@@ -60,12 +60,12 @@ class tool_capability_settings_form extends moodleform {
$form->addElement('select', 'roles', get_string('roleslabel', 'tool_capability'), $roles, $attributes);
$form->setType('roles', PARAM_TEXT);
$filters = [];
$filters[] = $form->createElement('checkbox', 'onlydiff', get_string('onlydiff', 'tool_capability'));
$form->addElement('checkbox', 'onlydiff',
get_string('filters', 'tool_capability'),
get_string('onlydiff', 'tool_capability'));
$form->setType('onlydiff', PARAM_BOOL);
$form->addGroup($filters, 'filters', get_string('filters', 'tool_capability'), array('<br>'), false);
$form->addElement('submit', 'submitbutton', get_string('getreport', 'tool_capability'));
}
}
}
+2 -11
View File
@@ -53,12 +53,7 @@ function tool_capability_calculate_role_data($capability, array $roles) {
$sql = 'SELECT DISTINCT con.path, 1
FROM {context} con
JOIN {role_capabilities} rc ON rc.contextid = con.id
WHERE capability = ? ' .
$sqlroletest .
// Context path should never be null, but can happen in old database with
// bad data (e.g. a course_module where the corresponding course no longer exists).
// We need to leave these out of the report to prevent errors.
' AND con.path IS NOT NULL';
WHERE capability = ? '.$sqlroletest;
$relevantpaths = $DB->get_records_sql_menu($sql, $params);
$requiredcontexts = array($systemcontext->id);
foreach ($relevantpaths as $path => $notused) {
@@ -93,10 +88,6 @@ function tool_capability_calculate_role_data($capability, array $roles) {
// Put the role capabilities into the context tree.
foreach ($rolecaps as $rolecap) {
if (!isset($contexts[$rolecap->contextid])) {
// Skip capabilities in orphaned contexts that are not in the tree.
continue;
}
$contexts[$rolecap->contextid]->rolecapabilities[$rolecap->roleid] = $rolecap->permission;
}
@@ -108,4 +99,4 @@ function tool_capability_calculate_role_data($capability, array $roles) {
}
return $contexts;
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ class tool_capability_events_testcase extends advanced_testcase {
/**
* Setup testcase.
*/
public function setUp(): void {
public function setUp() {
$this->setAdminUser();
$this->resetAfterTest();
}
@@ -1,88 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests for the capability overview helper functions.
*
* @package tool_capability
* @copyright 2021 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/capability/locallib.php');
/**
* Tests for the capability overview helper functions.
*/
class tool_capability_locallib_testcase extends advanced_testcase {
/**
* Test the function that gets the data - simple case.
*/
public function test_tool_capability_calculate_role_data() {
global $DB;
$data = tool_capability_calculate_role_data('mod/quiz:attempt', get_all_roles());
$systcontext = context_system::instance();
$studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student']);
$this->assertArrayHasKey($systcontext->id, $data);
$this->assertCount(1, $data);
foreach ($data[$systcontext->id]->rolecapabilities as $roleid => $permission) {
if ($roleid == $studentroleid) {
$this->assertEquals(CAP_ALLOW, $permission);
} else {
$this->assertEquals(CAP_INHERIT, $permission);
}
}
}
/**
* Test the function that gets the data - simple case.
*/
public function test_tool_capability_calculate_role_data_orphan_contexts() {
global $DB;
$this->resetAfterTest();
// This simulates a situation that seems to happen sometimes, where
// we end up with contexts with path = NULL in the database.
$systcontext = context_system::instance();
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$coursecontext = context_course::instance($course->id);
$studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student']);
role_change_permission($studentroleid, $coursecontext, 'mod/quiz:attempt', CAP_PREVENT);
// This is where we simulate the breakage.
$DB->set_field('context', 'path', null, ['id' => $coursecontext->id]);
// Now call the function. We mainly just want to know there is no exception.
$data = tool_capability_calculate_role_data('mod/quiz:attempt', get_all_roles());
$this->assertArrayHasKey($systcontext->id, $data);
$this->assertCount(1, $data);
foreach ($data[$systcontext->id]->rolecapabilities as $roleid => $permission) {
if ($roleid == $studentroleid) {
$this->assertEquals(CAP_ALLOW, $permission);
} else {
$this->assertEquals(CAP_INHERIT, $permission);
}
}
}
}
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2020110300; // Requires this Moodle version.
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2020060900; // Requires this Moodle version.
$plugin->component = 'tool_capability'; // Full name of the plugin (used for diagnostics).
@@ -53,13 +53,6 @@ SEARCH.prototype = {
* @protected
*/
button: null,
/**
* The cancel button for the form.
* @property button
* @type Node
* @protected
*/
cancel: null,
/**
* The last search node if there is one.
* If there is a last search node then the last search term will be persisted between requests.
@@ -83,28 +76,17 @@ SEARCH.prototype = {
this.button = this.form.all('input[type=submit]');
this.lastsearch = this.form.one('input[name=search]');
var div = Y.Node.create('<div id="capabilitysearchui" class="input-group simplesearchform mb-2"' +
'data-fieldtype="text"></div>'),
label = Y.Node.create('<label for="capabilitysearch"><span class="sr-only"' +
this.get('strsearch') + '</span></label>');
this.cancel = Y.Node.create('<a class="btn btn-clear d-none icon-no-margin">' +
'<i class="icon fa fa-times fa-fw " aria-hidden="true"></i>' +
'</a>');
this.input = Y.Node.create('<input type="text" class="form-control withclear" placeholder="' +
this.get('strsearch') + '"id="capabilitysearch" />');
var div = Y.Node.create('<div id="capabilitysearchui" data-fieldtype="text"></div>'),
label = Y.Node.create('<label for="capabilitysearch">' + this.get('strsearch') + '</label>');
this.input = Y.Node.create('<input type="text" id="capabilitysearch" />');
div.append(label).append(this.input).append(this.cancel);
div.append(label).append(this.input);
this.select.insert(div, 'before');
this.input.on('keyup', this.typed, this);
this.select.on('change', this.validate, this);
this.cancel.on('click', function() {
this.input.set('value', '');
this.typed();
}, this);
if (this.lastsearch) {
this.input.set('value', this.lastsearch.get('value'));
this.typed();
@@ -151,11 +133,6 @@ SEARCH.prototype = {
last.set('selected', true);
}
}
if (search !== '') {
this.cancel.removeClass("d-none");
} else {
this.cancel.addClass("d-none");
}
this.validate();
}
};
@@ -1 +1 @@
YUI.add("moodle-tool_capability-search",function(s,t){var e=function(){e.superclass.constructor.apply(this,arguments)};e.prototype={form:null,select:null,selectoptions:{},input:null,button:null,cancel:null,lastsearch:null,initializer:function(){this.form=s.one("#capability-overview-form"),this.select=this.form.one("select[data-search=capability]"),this.select.setStyle("minWidth",this.select.get("offsetWidth")),this.select.get("options").each(function(t){var e=t.get("value");this.selectoptions[e]=t},this),this.button=this.form.all("input[type=submit]"),this.lastsearch=this.form.one("input[name=search]");var t=s.Node.create('<div id="capabilitysearchui" class="input-group simplesearchform mb-2"data-fieldtype="text"></div>'),e=s.Node.create('<label for="capabilitysearch"><span class="sr-only"'+this.get("strsearch")+"</span></label>");this.cancel=s.Node.create('<a class="btn btn-clear d-none icon-no-margin"><i class="icon fa fa-times fa-fw " aria-hidden="true"></i></a>'),this.input=s.Node.create('<input type="text" class="form-control withclear" placeholder="'+this.get("strsearch")+'"id="capabilitysearch" />'),t.append(e).append(this.input).append(this.cancel),this.select.insert(t,"before"),this.input.on("keyup",this.typed,this),this.select.on("change",this.validate,this),this.cancel.on("click",function(){this.input.set("value",""),this.typed()},this),this.lastsearch&&(this.input.set("value",this.lastsearch.get("value")),this.typed(),this.select.one("option[selected]")&&this.select.set("scrollTop",this.select.one("option[selected]").get("getX"))),this.validate()},validate:function(){this.button.set("disabled",""===this.select.get("value"))},typed:function(){var t,e=this.input.get("value"),s=0,i=null;for(t in this.lastsearch&&this.lastsearch.set("value",e),this.select.all("option").remove(),this.selectoptions)0<=t.indexOf(e)&&(s++,i=this.selectoptions[t],this.select.append(this.selectoptions[t]));0===s?this.input.addClass("error"):(this.input.removeClass("error"),1===s&&i.set("selected",!0)),""!==e?this.cancel.removeClass("d-none"):this.cancel.addClass("d-none"),this.validate()}},s.extend(e,s.Base,e.prototype,{NAME:"tool_capability-search",ATTRS:{strsearch:{}}}),M.tool_capability=M.tool_capability||{},M.tool_capability.init_capability_search=function(t){new e(t)}},"@VERSION@",{requires:["base","node"]});
YUI.add("moodle-tool_capability-search",function(i,t){var e=function(){e.superclass.constructor.apply(this,arguments)};e.prototype={form:null,select:null,selectoptions:{},input:null,button:null,lastsearch:null,initializer:function(){this.form=i.one("#capability-overview-form"),this.select=this.form.one("select[data-search=capability]"),this.select.setStyle("minWidth",this.select.get("offsetWidth")),this.select.get("options").each(function(t){var e=t.get("value");this.selectoptions[e]=t},this),this.button=this.form.all("input[type=submit]"),this.lastsearch=this.form.one("input[name=search]");var t=i.Node.create('<div id="capabilitysearchui" data-fieldtype="text"></div>'),e=i.Node.create('<label for="capabilitysearch">'+this.get("strsearch")+"</label>");this.input=i.Node.create('<input type="text" id="capabilitysearch" />'),t.append(e).append(this.input),this.select.insert(t,"before"),this.input.on("keyup",this.typed,this),this.select.on("change",this.validate,this),this.lastsearch&&(this.input.set("value",this.lastsearch.get("value")),this.typed(),this.select.one("option[selected]")&&this.select.set("scrollTop",this.select.one("option[selected]").get("getX"))),this.validate()},validate:function(){this.button.set("disabled",""===this.select.get("value"))},typed:function(){var t,e=this.input.get("value"),i=0,s=null;for(t in this.lastsearch&&this.lastsearch.set("value",e),this.select.all("option").remove(),this.selectoptions)0<=t.indexOf(e)&&(i++,s=this.selectoptions[t],this.select.append(this.selectoptions[t]));0===i?this.input.addClass("error"):(this.input.removeClass("error"),1===i&&s.set("selected",!0)),this.validate()}},i.extend(e,i.Base,e.prototype,{NAME:"tool_capability-search",ATTRS:{strsearch:{}}}),M.tool_capability=M.tool_capability||{},M.tool_capability.init_capability_search=function(t){new e(t)}},"@VERSION@",{requires:["base","node"]});
@@ -53,13 +53,6 @@ SEARCH.prototype = {
* @protected
*/
button: null,
/**
* The cancel button for the form.
* @property button
* @type Node
* @protected
*/
cancel: null,
/**
* The last search node if there is one.
* If there is a last search node then the last search term will be persisted between requests.
@@ -83,28 +76,17 @@ SEARCH.prototype = {
this.button = this.form.all('input[type=submit]');
this.lastsearch = this.form.one('input[name=search]');
var div = Y.Node.create('<div id="capabilitysearchui" class="input-group simplesearchform mb-2"' +
'data-fieldtype="text"></div>'),
label = Y.Node.create('<label for="capabilitysearch"><span class="sr-only"' +
this.get('strsearch') + '</span></label>');
this.cancel = Y.Node.create('<a class="btn btn-clear d-none icon-no-margin">' +
'<i class="icon fa fa-times fa-fw " aria-hidden="true"></i>' +
'</a>');
this.input = Y.Node.create('<input type="text" class="form-control withclear" placeholder="' +
this.get('strsearch') + '"id="capabilitysearch" />');
var div = Y.Node.create('<div id="capabilitysearchui" data-fieldtype="text"></div>'),
label = Y.Node.create('<label for="capabilitysearch">' + this.get('strsearch') + '</label>');
this.input = Y.Node.create('<input type="text" id="capabilitysearch" />');
div.append(label).append(this.input).append(this.cancel);
div.append(label).append(this.input);
this.select.insert(div, 'before');
this.input.on('keyup', this.typed, this);
this.select.on('change', this.validate, this);
this.cancel.on('click', function() {
this.input.set('value', '');
this.typed();
}, this);
if (this.lastsearch) {
this.input.set('value', this.lastsearch.get('value'));
this.typed();
@@ -151,11 +133,6 @@ SEARCH.prototype = {
last.set('selected', true);
}
}
if (search !== '') {
this.cancel.removeClass("d-none");
} else {
this.cancel.addClass("d-none");
}
this.validate();
}
};
+4 -27
View File
@@ -51,13 +51,6 @@ SEARCH.prototype = {
* @protected
*/
button: null,
/**
* The cancel button for the form.
* @property button
* @type Node
* @protected
*/
cancel: null,
/**
* The last search node if there is one.
* If there is a last search node then the last search term will be persisted between requests.
@@ -81,28 +74,17 @@ SEARCH.prototype = {
this.button = this.form.all('input[type=submit]');
this.lastsearch = this.form.one('input[name=search]');
var div = Y.Node.create('<div id="capabilitysearchui" class="input-group simplesearchform mb-2"' +
'data-fieldtype="text"></div>'),
label = Y.Node.create('<label for="capabilitysearch"><span class="sr-only"' +
this.get('strsearch') + '</span></label>');
this.cancel = Y.Node.create('<a class="btn btn-clear d-none icon-no-margin">' +
'<i class="icon fa fa-times fa-fw " aria-hidden="true"></i>' +
'</a>');
this.input = Y.Node.create('<input type="text" class="form-control withclear" placeholder="' +
this.get('strsearch') + '"id="capabilitysearch" />');
var div = Y.Node.create('<div id="capabilitysearchui" data-fieldtype="text"></div>'),
label = Y.Node.create('<label for="capabilitysearch">' + this.get('strsearch') + '</label>');
this.input = Y.Node.create('<input type="text" id="capabilitysearch" />');
div.append(label).append(this.input).append(this.cancel);
div.append(label).append(this.input);
this.select.insert(div, 'before');
this.input.on('keyup', this.typed, this);
this.select.on('change', this.validate, this);
this.cancel.on('click', function() {
this.input.set('value', '');
this.typed();
}, this);
if (this.lastsearch) {
this.input.set('value', this.lastsearch.get('value'));
this.typed();
@@ -149,11 +131,6 @@ SEARCH.prototype = {
last.set('selected', true);
}
}
if (search !== '') {
this.cancel.removeClass("d-none");
} else {
this.cancel.addClass("d-none");
}
this.validate();
}
};
-3
View File
@@ -44,8 +44,5 @@ function xmldb_tool_cohortroles_upgrade($oldversion) {
// Automatically generated Moodle v3.9.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v3.10.0 release upgrade line.
// Put any upgrade step following this.
return true;
}
+13 -5
View File
@@ -49,7 +49,7 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
/**
* Setup function- we will create a course and add an assign instance to it.
*/
protected function setUp(): void {
protected function setUp() {
$this->resetAfterTest(true);
// Create some users.
@@ -60,6 +60,9 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
cohort_add_member($this->cohort->id, $this->userassignover->id);
}
/**
* @expectedException required_capability_exception
*/
public function test_create_cohort_role_assignment_without_permission() {
$this->setUser($this->userassignto);
$params = (object) array(
@@ -67,10 +70,12 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
'roleid' => $this->roleid,
'cohortid' => $this->cohort->id
);
$this->expectException(required_capability_exception::class);
api::create_cohort_role_assignment($params);
}
/**
* @expectedException core_competency\invalid_persistent_exception
*/
public function test_create_cohort_role_assignment_with_invalid_data() {
$this->setAdminUser();
$params = (object) array(
@@ -78,7 +83,6 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
'roleid' => -8,
'cohortid' => $this->cohort->id
);
$this->expectException(\core_competency\invalid_persistent_exception::class);
api::create_cohort_role_assignment($params);
}
@@ -96,6 +100,9 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
$this->assertEquals($result->get('cohortid'), $this->cohort->id);
}
/**
* @expectedException required_capability_exception
*/
public function test_delete_cohort_role_assignment_without_permission() {
$this->setAdminUser();
$params = (object) array(
@@ -105,10 +112,12 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
);
$result = api::create_cohort_role_assignment($params);
$this->setUser($this->userassignto);
$this->expectException(required_capability_exception::class);
api::delete_cohort_role_assignment($result->get('id'));
}
/**
* @expectedException dml_missing_record_exception
*/
public function test_delete_cohort_role_assignment_with_invalid_data() {
$this->setAdminUser();
$params = (object) array(
@@ -117,7 +126,6 @@ class tool_cohortroles_api_testcase extends advanced_testcase {
'cohortid' => $this->cohort->id
);
$result = api::create_cohort_role_assignment($params);
$this->expectException(dml_missing_record_exception::class);
api::delete_cohort_role_assignment($result->get('id') + 1);
}
@@ -43,7 +43,7 @@ class tool_cohortroles_privacy_testcase extends \core_privacy\tests\provider_tes
/**
* Overriding setUp() function to always reset after tests.
*/
public function setUp(): void {
public function setUp() {
$this->resetAfterTest(true);
}
@@ -87,7 +87,7 @@ class tool_cohortroles_privacy_testcase extends \core_privacy\tests\provider_tes
CONTEXT_COURSECAT
];
// Test the User's contexts equal the system and course category context.
$this->assertEqualsCanonicalizing($expected, $contextlevels);
$this->assertEquals($expected, $contextlevels, '', 0, 10, true);
}
/**
+2 -2
View File
@@ -25,8 +25,8 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2020110900; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2020110300; // Requires this Moodle version.
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2020060900; // Requires this Moodle version.
$plugin->component = 'tool_cohortroles'; // Full name of the plugin (used for diagnostics).
$plugin->dependencies = array(
@@ -1,68 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Creates Formular for customlang file export
*
* @package tool_customlang
* @copyright 2020 Thomas Wedekind <Thomas.Wedekind@univie.ac.at>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_customlang\form;
use tool_customlang_utils;
/**
* Formular for customlang file export
*
* @copyright 2020 Thomas Wedekind <Thomas.Wedekind@univie.ac.at>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class export extends \moodleform {
/**
* Add elements to form
*/
public function definition() {
$lng = $this->_customdata['lng'];
$mform = $this->_form;
$langdir = tool_customlang_utils::get_localpack_location($lng);
// The export button only appears if a local lang is present.
if (!check_dir_exists($langdir) || !count(glob("$langdir/*"))) {
print_error('nolocallang', 'tool_customlang');
}
$langfiles = scandir($langdir);
$fileoptions = [];
foreach ($langfiles as $file) {
if (substr($file, 0, 1) != '.') {
$fileoptions[$file] = $file;
}
}
$mform->addElement('hidden', 'lng', $lng);
$mform->setType('lng', PARAM_LANG);
$select = $mform->addElement('select', 'files', get_string('exportfilter', 'tool_customlang'), $fileoptions);
$select->setMultiple(true);
$mform->addRule('files', get_string('required'), 'required', null, 'client');
$mform->setDefault('files', $fileoptions);
$this->add_action_buttons(true, get_string('export', 'tool_customlang'));
}
}
@@ -1,68 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Upload a zip of custom lang php files.
*
* @package tool_customlang
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_customlang\form;
use tool_customlang\local\importer;
/**
* Upload a zip/php of custom lang php files.
*
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class import extends \moodleform {
/**
* Form definition.
*/
public function definition() {
$mform = $this->_form;
$mform->addElement('header', 'settingsheader', get_string('import', 'tool_customlang'));
$mform->addElement('hidden', 'lng');
$mform->setType('lng', PARAM_LANG);
$mform->setDefault('lng', $this->_customdata['lng']);
$filemanageroptions = array(
'accepted_types' => array('.php', '.zip'),
'maxbytes' => 0,
'maxfiles' => 1,
'subdirs' => 0
);
$mform->addElement('filepicker', 'pack', get_string('langpack', 'tool_customlang'),
null, $filemanageroptions);
$mform->addRule('pack', null, 'required');
$modes = [
importer::IMPORTALL => get_string('import_all', 'tool_customlang'),
importer::IMPORTUPDATE => get_string('import_update', 'tool_customlang'),
importer::IMPORTNEW => get_string('import_new', 'tool_customlang'),
];
$mform->addElement('select', 'importmode', get_string('import_mode', 'tool_customlang'), $modes);
$mform->addElement('submit', 'importcustomstrings', get_string('importfile', 'tool_customlang'));
}
}
@@ -1,268 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Custom lang importer.
*
* @package tool_customlang
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_customlang\local;
use tool_customlang\local\mlang\phpparser;
use tool_customlang\local\mlang\logstatus;
use tool_customlang\local\mlang\langstring;
use core\output\notification;
use stored_file;
use coding_exception;
use moodle_exception;
use core_component;
use stdClass;
/**
* Class containing tha custom lang importer
*
* @package tool_customlang
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class importer {
/** @var int imports will only create new customizations */
public const IMPORTNEW = 1;
/** @var int imports will only update the current customizations */
public const IMPORTUPDATE = 2;
/** @var int imports all strings */
public const IMPORTALL = 3;
/**
* @var string the language name
*/
protected $lng;
/**
* @var int the importation mode (new, update, all)
*/
protected $importmode;
/**
* @var string request folder path
*/
private $folder;
/**
* @var array import log messages
*/
private $log;
/**
* Constructor for the importer class.
*
* @param string $lng the current language to import.
* @param int $importmode the import method (IMPORTALL, IMPORTNEW, IMPORTUPDATE).
*/
public function __construct(string $lng, int $importmode = self::IMPORTALL) {
$this->lng = $lng;
$this->importmode = $importmode;
$this->log = [];
}
/**
* Returns the last parse log.
*
* @return logstatus[] mlang logstatus with the messages
*/
public function get_log(): array {
return $this->log;
}
/**
* Import customlang files.
*
* @param stored_file[] $files array of files to import
*/
public function import(array $files): void {
// Create a temporal folder to store the files.
$this->folder = make_request_directory(false);
$langfiles = $this->deploy_files($files);
$this->process_files($langfiles);
}
/**
* Deploy all files into a request folder.
*
* @param stored_file[] $files array of files to deploy
* @return string[] of file paths
*/
private function deploy_files(array $files): array {
$result = [];
// Desploy all files.
foreach ($files as $file) {
if ($file->get_mimetype() == 'application/zip') {
$result = array_merge($result, $this->unzip_file($file));
} else {
$path = $this->folder.'/'.$file->get_filename();
$file->copy_content_to($path);
$result = array_merge($result, [$path]);
}
}
return $result;
}
/**
* Unzip a file into the request folder.
*
* @param stored_file $file the zip file to unzip
* @return string[] of zip content paths
*/
private function unzip_file(stored_file $file): array {
$fp = get_file_packer('application/zip');
$zipcontents = $fp->extract_to_pathname($file, $this->folder);
if (!$zipcontents) {
throw new moodle_exception("Error Unzipping file", 1);
}
$result = [];
foreach ($zipcontents as $contentname => $success) {
if ($success) {
$result[] = $this->folder.'/'.$contentname;
}
}
return $result;
}
/**
* Import strings from a list of langfiles.
*
* @param string[] $langfiles an array with file paths
*/
private function process_files(array $langfiles): void {
$parser = phpparser::get_instance();
foreach ($langfiles as $filepath) {
$component = $this->component_from_filepath($filepath);
if ($component) {
$strings = $parser->parse(file_get_contents($filepath));
$this->import_strings($strings, $component);
}
}
}
/**
* Try to get the component from a filepath.
*
* @param string $filepath the filepath
* @return stdCalss|null the DB record of that component
*/
private function component_from_filepath(string $filepath) {
global $DB;
// Get component from filename.
$pathparts = pathinfo($filepath);
if (empty($pathparts['filename'])) {
throw new coding_exception("Cannot get filename from $filepath", 1);
}
$filename = $pathparts['filename'];
$normalized = core_component::normalize_component($filename);
if (count($normalized) == 1 || empty($normalized[1])) {
$componentname = $normalized[0];
} else {
$componentname = implode('_', $normalized);
}
$result = $DB->get_record('tool_customlang_components', ['name' => $componentname]);
if (!$result) {
$this->log[] = new logstatus('notice_missingcomponent', notification::NOTIFY_ERROR, null, $componentname);
return null;
}
return $result;
}
/**
* Import an array of strings into the customlang tables.
*
* @param langstring[] $strings the langstring to set
* @param stdClass $component the target component
*/
private function import_strings(array $strings, stdClass $component): void {
global $DB;
foreach ($strings as $newstring) {
// Check current DB entry.
$customlang = $DB->get_record('tool_customlang', [
'componentid' => $component->id,
'stringid' => $newstring->id,
'lang' => $this->lng,
]);
if (!$customlang) {
$customlang = null;
}
if ($this->can_save_string($customlang, $newstring, $component)) {
$customlang->local = $newstring->text;
$customlang->timecustomized = $newstring->timemodified;
$customlang->outdated = 0;
$customlang->modified = 1;
$DB->update_record('tool_customlang', $customlang);
}
}
}
/**
* Determine if a specific string can be saved based on the current importmode.
*
* @param stdClass $customlang customlang original record
* @param langstring $newstring the new strign to store
* @param stdClass $component the component target
* @return bool if the string can be stored
*/
private function can_save_string(?stdClass $customlang, langstring $newstring, stdClass $component): bool {
$result = false;
$message = 'notice_success';
if (empty($customlang)) {
$message = 'notice_inexitentstring';
$this->log[] = new logstatus($message, notification::NOTIFY_ERROR, null, $component->name, $newstring);
return $result;
}
switch ($this->importmode) {
case self::IMPORTNEW:
$result = empty($customlang->local);
$warningmessage = 'notice_ignoreupdate';
break;
case self::IMPORTUPDATE:
$result = !empty($customlang->local);
$warningmessage = 'notice_ignorenew';
break;
case self::IMPORTALL:
$result = true;
break;
}
if ($result) {
$errorlevel = notification::NOTIFY_SUCCESS;
} else {
$errorlevel = notification::NOTIFY_ERROR;
$message = $warningmessage;
}
$this->log[] = new logstatus($message, $errorlevel, null, $component->name, $newstring);
return $result;
}
}
@@ -1,177 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Language string based on David Mudrak langstring from local_amos.
*
* @package tool_customlang
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_customlang\local\mlang;
use moodle_exception;
use stdclass;
/**
* Class containing a lang string cleaned.
*
* @package tool_customlang
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Represents a single string
*/
class langstring {
/** @var string identifier */
public $id = null;
/** @var string */
public $text = '';
/** @var int the time stamp when this string was saved */
public $timemodified = null;
/** @var bool is deleted */
public $deleted = false;
/** @var stdclass extra information about the string */
public $extra = null;
/**
* Class constructor.
*
* @param string $id string identifier
* @param string $text string text
* @param int $timemodified
* @param int $deleted
* @param stdclass $extra
*/
public function __construct(string $id, string $text = '', int $timemodified = null,
int $deleted = 0, stdclass $extra = null) {
if (is_null($timemodified)) {
$timemodified = time();
}
$this->id = $id;
$this->text = $text;
$this->timemodified = $timemodified;
$this->deleted = $deleted;
$this->extra = $extra;
}
/**
* Given a string text, returns it being formatted properly for storing in AMOS repository.
*
* Note: This method is taken directly from local_amos as it is highly tested and robust.
* The Moodle 1.x part is keep on puspose to make it easier the copy paste from both codes.
* This could change in the future when AMOS stop suporting the 1.x langstrings.
*
* We need to know for what branch the string should be prepared due to internal changes in
* format required by get_string()
* - for get_string() in Moodle 1.6 - 1.9 use $format == 1
* - for get_string() in Moodle 2.0 and higher use $format == 2
*
* Typical usages of this methods:
* $t = langstring::fix_syntax($t); // sanity new translations of 2.x strings
* $t = langstring::fix_syntax($t, 1); // sanity legacy 1.x strings
* $t = langstring::fix_syntax($t, 2, 1); // convert format of 1.x strings into 2.x
*
* Backward converting 2.x format into 1.x is not supported
*
* @param string $text string text to be fixed
* @param int $format target get_string() format version
* @param int $from which format version does the text come from, defaults to the same as $format
* @return string
*/
public static function fix_syntax(string $text, int $format = 2, ?int $from = null): string {
if (is_null($from)) {
$from = $format;
}
// Common filter.
$clean = trim($text);
$search = [
// Remove \r if it is part of \r\n.
'/\r(?=\n)/',
// Control characters to be replaced with \n
// LINE TABULATION, FORM FEED, CARRIAGE RETURN, END OF TRANSMISSION BLOCK,
// END OF MEDIUM, SUBSTITUTE, BREAK PERMITTED HERE, NEXT LINE, START OF STRING,
// STRING TERMINATOR and Unicode character categorys Zl and Zp.
'/[\x{0B}-\r\x{17}\x{19}\x{1A}\x{82}\x{85}\x{98}\x{9C}\p{Zl}\p{Zp}]/u',
// Control characters to be removed
// NULL, ENQUIRY, ACKNOWLEDGE, BELL, SHIFT {OUT,IN}, DATA LINK ESCAPE,
// DEVICE CONTROL {ONE,TWO,THREE,FOUR}, NEGATIVE ACKNOWLEDGE, SYNCHRONOUS IDLE, ESCAPE,
// DELETE, PADDING CHARACTER, HIGH OCTET PRESET, NO BREAK HERE, INDEX,
// {START,END} OF SELECTED AREA, CHARACTER TABULATION {SET,WITH JUSTIFICATION},
// LINE TABULATION SET, PARTIAL LINE {FORWARD,BACKWARD}, REVERSE LINE FEED,
// SINGLE SHIFT {TWO,THREE}, DEVICE CONTROL STRING, PRIVATE USE {ONE,TWO},
// SET TRANSMIT STATE, MESSAGE WAITING, {START,END} OF GUARDED AREA,
// {SINGLE {GRAPHIC,} CHARACTER,CONTROL SEQUENCE} INTRODUCER, OPERATING SYSTEM COMMAND,
// PRIVACY MESSAGE, APPLICATION PROGRAM COMMAND, ZERO WIDTH {,NO-BREAK} SPACE,
// REPLACEMENT CHARACTER.
'/[\0\x{05}-\x{07}\x{0E}-\x{16}\x{1B}\x{7F}\x{80}\x{81}\x{83}\x{84}\x{86}-\x{93}\x{95}-\x{97}\x{99}-\x{9B}\x{9D}-\x{9F}\x{200B}\x{FEFF}\x{FFFD}]++/u',
// Remove trailing whitespace at the end of lines in a multiline string.
'/[ \t]+(?=\n)/',
];
$replace = [
'',
"\n",
'',
'',
];
$clean = preg_replace($search, $replace, $clean);
if (($format === 2) && ($from === 2)) {
// Sanity translations of 2.x strings.
$clean = preg_replace("/\n{3,}/", "\n\n\n", $clean); // Collapse runs of blank lines.
} else if (($format === 2) && ($from === 1)) {
// Convert 1.x string into 2.x format.
$clean = preg_replace("/\n{3,}/", "\n\n\n", $clean); // Collapse runs of blank lines.
$clean = preg_replace('/%+/', '%', $clean); // Collapse % characters.
$clean = str_replace('\$', '@@@___XXX_ESCAPED_DOLLAR__@@@', $clean); // Remember for later.
$clean = str_replace("\\", '', $clean); // Delete all slashes.
$clean = preg_replace('/(^|[^{])\$a\b(\->[a-zA-Z0-9_]+)?/', '\\1{$a\\2}', $clean); // Wrap placeholders.
$clean = str_replace('@@@___XXX_ESCAPED_DOLLAR__@@@', '$', $clean);
$clean = str_replace('&#36;', '$', $clean);
} else if (($format === 1) && ($from === 1)) {
// Sanity legacy 1.x strings.
$clean = preg_replace("/\n{3,}/", "\n\n", $clean); // Collapse runs of blank lines.
$clean = str_replace('\$', '@@@___XXX_ESCAPED_DOLLAR__@@@', $clean);
$clean = str_replace("\\", '', $clean); // Delete all slashes.
$clean = str_replace('$', '\$', $clean); // Escape all embedded variables.
// Unescape placeholders: only $a and $a->something are allowed. All other $variables are left escaped.
$clean = preg_replace('/\\\\\$a\b(\->[a-zA-Z0-9_]+)?/', '$a\\1', $clean); // Unescape placeholders.
$clean = str_replace('@@@___XXX_ESCAPED_DOLLAR__@@@', '\$', $clean);
$clean = str_replace('"', "\\\"", $clean); // Add slashes for ".
$clean = preg_replace('/%+/', '%', $clean); // Collapse % characters.
$clean = str_replace('%', '%%', $clean); // Duplicate %.
} else {
throw new moodle_exception('Unknown get_string() format version');
}
return $clean;
}
}
@@ -1,92 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Language string based on David Mudrak langstring from local_amos.
*
* @package tool_customlang
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_customlang\local\mlang;
use moodle_exception;
use stdclass;
/**
* Class containing a lang string cleaned.
*
* @package tool_customlang
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Represents a single string
*/
class logstatus {
/** @var langstring the current string */
public $langstring = null;
/** @var string the component */
public $component = null;
/** @var string the string ID */
public $stringid = null;
/** @var string the original filename */
public $filename = null;
/** @var int the error level */
public $errorlevel = null;
/** @var string the message identifier */
private $message;
/**
* Class creator.
*
* @param string $message the message identifier to display
* @param string $errorlevel the notice level
* @param string|null $filename the filename of this log
* @param string|null $component the component of this log
* @param langstring|null $langstring the langstring of this log
*/
public function __construct(string $message, string $errorlevel, ?string $filename = null,
?string $component = null, ?langstring $langstring = null) {
$this->filename = $filename;
$this->component = $component;
$this->langstring = $langstring;
$this->message = $message;
$this->errorlevel = $errorlevel;
if ($langstring) {
$this->stringid = $langstring->id;
}
}
/**
* Get the log message.
*
* @return string the log message.
*/
public function get_message(): string {
return get_string($this->message, 'tool_customlang', $this);
}
}
@@ -1,260 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Mlang PHP based on David Mudrak phpparser for local_amos.
*
* @package tool_customlang
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_customlang\local\mlang;
use coding_exception;
use moodle_exception;
/**
* Parser of Moodle strings defined as associative array.
*
* Moodle core just includes this file format directly as normal PHP code. However
* for security reasons, we must not do this for files uploaded by anonymous users.
* This parser reconstructs the associative $string array without actually including
* the file.
*/
class phpparser {
/** @var holds the singleton instance of self */
private static $instance = null;
/**
* Prevents direct creation of object
*/
private function __construct() {
}
/**
* Prevent from cloning the instance
*/
public function __clone() {
throw new coding_exception('Cloning os singleton is not allowed');
}
/**
* Get the singleton instance fo this class
*
* @return phpparser singleton instance of phpparser
*/
public static function get_instance(): phpparser {
if (is_null(self::$instance)) {
self::$instance = new phpparser();
}
return self::$instance;
}
/**
* Parses the given data in Moodle PHP string format
*
* Note: This method is adapted from local_amos as it is highly tested and robust.
* The priority is keeping it similar to the original one to make it easier to mantain.
*
* @param string $data definition of the associative array
* @param int $format the data format on the input, defaults to the one used since 2.0
* @return langstring[] array of langstrings of this file
*/
public function parse(string $data, int $format = 2): array {
$result = [];
$strings = $this->extract_strings($data);
foreach ($strings as $id => $text) {
$cleaned = clean_param($id, PARAM_STRINGID);
if ($cleaned !== $id) {
continue;
}
$text = langstring::fix_syntax($text, 2, $format);
$result[] = new langstring($id, $text);
}
return $result;
}
/**
* Low level parsing method
*
* Note: This method is adapted from local_amos as it is highly tested and robust.
* The priority is keeping it similar to the original one to make it easier to mantain.
*
* @param string $data
* @return string[] the data strings
*/
protected function extract_strings(string $data): array {
$strings = []; // To be returned.
if (empty($data)) {
return $strings;
}
// Tokenize data - we expect valid PHP code.
$tokens = token_get_all($data);
// Get rid of all non-relevant tokens.
$rubbish = [T_WHITESPACE, T_INLINE_HTML, T_COMMENT, T_DOC_COMMENT, T_OPEN_TAG, T_CLOSE_TAG];
foreach ($tokens as $i => $token) {
if (is_array($token)) {
if (in_array($token[0], $rubbish)) {
unset($tokens[$i]);
}
}
}
$id = null;
$text = null;
$line = 0;
$expect = 'STRING_VAR'; // The first expected token is '$string'.
// Iterate over tokens and look for valid $string array assignment patterns.
foreach ($tokens as $token) {
$foundtype = null;
$founddata = null;
if (is_array($token)) {
$foundtype = $token[0];
$founddata = $token[1];
if (!empty($token[2])) {
$line = $token[2];
}
} else {
$foundtype = 'char';
$founddata = $token;
}
if ($expect == 'STRING_VAR') {
if ($foundtype === T_VARIABLE and $founddata === '$string') {
$expect = 'LEFT_BRACKET';
continue;
} else {
// Allow other code at the global level.
continue;
}
}
if ($expect == 'LEFT_BRACKET') {
if ($foundtype === 'char' and $founddata === '[') {
$expect = 'STRING_ID';
continue;
} else {
throw new moodle_exception('Parsing error. Expected character [ at line '.$line);
}
}
if ($expect == 'STRING_ID') {
if ($foundtype === T_CONSTANT_ENCAPSED_STRING) {
$id = $this->decapsulate($founddata);
$expect = 'RIGHT_BRACKET';
continue;
} else {
throw new moodle_exception('Parsing error. Expected T_CONSTANT_ENCAPSED_STRING array key at line '.$line);
}
}
if ($expect == 'RIGHT_BRACKET') {
if ($foundtype === 'char' and $founddata === ']') {
$expect = 'ASSIGNMENT';
continue;
} else {
throw new moodle_exception('Parsing error. Expected character ] at line '.$line);
}
}
if ($expect == 'ASSIGNMENT') {
if ($foundtype === 'char' and $founddata === '=') {
$expect = 'STRING_TEXT';
continue;
} else {
throw new moodle_exception('Parsing error. Expected character = at line '.$line);
}
}
if ($expect == 'STRING_TEXT') {
if ($foundtype === T_CONSTANT_ENCAPSED_STRING) {
$text = $this->decapsulate($founddata);
$expect = 'SEMICOLON';
continue;
} else {
throw new moodle_exception(
'Parsing error. Expected T_CONSTANT_ENCAPSED_STRING array item value at line '.$line
);
}
}
if ($expect == 'SEMICOLON') {
if (is_null($id) or is_null($text)) {
throw new moodle_exception('Parsing error. NULL string id or value at line '.$line);
}
if ($foundtype === 'char' and $founddata === ';') {
if (!empty($id)) {
$strings[$id] = $text;
}
$id = null;
$text = null;
$expect = 'STRING_VAR';
continue;
} else {
throw new moodle_exception('Parsing error. Expected character ; at line '.$line);
}
}
}
return $strings;
}
/**
* Given one T_CONSTANT_ENCAPSED_STRING, return its value without quotes
*
* Also processes escaped quotes inside the text.
*
* Note: This method is taken directly from local_amos as it is highly tested and robust.
*
* @param string $text value obtained by token_get_all()
* @return string value without quotes
*/
protected function decapsulate(string $text): string {
if (strlen($text) < 2) {
throw new moodle_exception('Parsing error. Expected T_CONSTANT_ENCAPSED_STRING in decapsulate()');
}
if (substr($text, 0, 1) == "'" and substr($text, -1) == "'") {
// Single quoted string.
$text = trim($text, "'");
$text = str_replace("\'", "'", $text);
$text = str_replace('\\\\', '\\', $text);
return $text;
} else if (substr($text, 0, 1) == '"' and substr($text, -1) == '"') {
// Double quoted string.
$text = trim($text, '"');
$text = str_replace('\"', '"', $text);
$text = str_replace('\\\\', '\\', $text);
return $text;
} else {
throw new moodle_exception(
'Parsing error. Unexpected quotation in T_CONSTANT_ENCAPSED_STRING in decapsulate(): '.$text
);
}
}
}
@@ -57,9 +57,8 @@ class renderer extends \plugin_renderer_base {
protected function render_tool_customlang_menu(\tool_customlang_menu $menu) {
$output = '';
foreach ($menu->get_items() as $item) {
$button = $this->single_button($item->url, $item->title, $item->method);
$output .= $this->box($button, 'menu');
$output .= $this->single_button($item->url, $item->title, $item->method);
}
return $output;
return $this->box($output, 'menu');
}
}
-135
View File
@@ -1,135 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Export custom language strings to zip files.
*
* @package tool_customlang
* @subpackage customlang
* @copyright 2020 Thomas Wedekind <thomas.wedekind@univie.ac.at>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../../../config.php');
require_once("$CFG->libdir/clilib.php");
require_once("$CFG->dirroot/$CFG->admin/tool/customlang/locallib.php");
$usage = <<<EOF
"Export custom language files to a target folder.
Useful for uploading custom langstrings to AMOS or importing or syncing them to other moodle instances.
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
-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
Examples:
Export all custom language files to the default folder:
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/export.php
Export just the english files of moodle core and the activity 'quiz' in a subfolder in my home folder:
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/export.php --lang='en' --components='moodle,quiz' --target='~/customdir'
EOF;
$dafaulttarget = "$CFG->tempdir/customlang/";
// Now get cli options.
list($options, $unrecognized) = cli_get_params(
[
'lang' => '',
'components' => '',
'target' => $dafaulttarget,
'overwrite' => false,
'help' => false,
],
['h' => 'help', 'c' => 'components', 't' => 'target', 'o' => 'overwrite']
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
echo $usage;
die;
}
if (!file_exists($options['target'])) {
mkdir($options['target'], 0777, true);
}
cli_writeln(get_string('cliexportheading', 'tool_customlang'));
$langs = [];
if ($options['lang']) {
$langs = explode(',', $options['lang']);
} else {
// No language set. We export all installed languages.
$langs = array_keys(get_string_manager()->get_list_of_translations(true));
}
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));
continue;
}
cli_heading(get_string('cliexportstartexport', 'tool_customlang', $lang));
$langdir = tool_customlang_utils::get_localpack_location($lang);
if (!file_exists($langdir)) {
// No custom files set for this language set.
cli_writeln(get_string('cliexportnofilefoundforlang', 'tool_customlang', ['lang' => $lang]));
continue;
}
$zipper = get_file_packer();
$tempzip = tempnam($CFG->tempdir . '/', 'tool_customlang_export');
$filelist = [];
if ($options['components']) {
$components = explode(',', $options['components']);
foreach ($components as $component) {
$filepath = "$langdir/$component.php";
if (file_exists($filepath)) {
$filelist["$component.php"] = $filepath;
} else {
cli_problem(
get_string('cliexportfilenotfoundforcomponent', 'tool_customlang', ['lang' => $lang, 'file' => $filepath])
);
}
}
} else {
$langfiles = scandir($langdir);
foreach ($langfiles as $file) {
if (substr($file, 0, 1) != '.') {
$filelist[$file] = "$langdir/$file";
}
}
}
if (empty($filelist)) {
cli_problem(get_string('cliexportnofilefoundforlang', 'tool_customlang', ['lang' => $lang]));
continue;
}
if ($zipper->archive_to_pathname($filelist, $filename)) {
cli_writeln(get_string('cliexportzipdone', 'tool_customlang', $filename));
} else {
cli_problem(get_string('cliexportzipfail', 'tool_customlang', $filename));
}
}
-204
View File
@@ -1,204 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI customlang import tool.
*
* @package tool_customlang
* @copyright 2020 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use tool_customlang\local\importer;
use core\output\notification;
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../../../config.php');
require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
require_once("$CFG->libdir/clilib.php");
$usage =
"Import lang customization.
It can get a single file or a folder.
If no lang is provided it will try to infere from the filename
Options:
--lang The target language (will get from filename if not provided)
--source=path File or folder of the custom lang files (zip or php files)
--mode What string should be imported. Options are:
- all: all string will be imported (default)
- new: only string with no previous customisation
- update: only strings already modified
--checkin Save strings to the language pack
-h, --help Print out this help
Examples:
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/import.php --lang=en --source=customlangs.zip
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/import.php --source=/tmp/customlangs --checkin
\$ sudo -u www-data /usr/bin/php admin/tool/customlang/cli/import.php --lang=en --source=/tmp/customlangs
";
list($options, $unrecognized) = cli_get_params(
[
'help' => false,
'lang' => false,
'source' => false,
'mode' => 'all',
'checkin' => false,
],
['h' => 'help']
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
cli_write($usage);
exit(0);
}
$source = $options['source'] ?? null;
$lang = $options['lang'] ?? null;
$modeparam = $options['mode'] ?? 'all';
$checkin = $options['checkin'] ?? false;
$modes = [
'all' => importer::IMPORTALL,
'update' => importer::IMPORTUPDATE,
'new' => importer::IMPORTNEW,
];
if (!isset($modes[$modeparam])) {
cli_error(get_string('climissingmode', 'tool_customlang'));
}
$mode = $modes[$modeparam];
if (empty($source)) {
$source = $CFG->dataroot.'/temp/customlang';
}
if (!file_exists($source)) {
cli_error(get_string('climissingsource', 'tool_customlang'));
}
// Emulate normal session - we use admin account by default.
cron_setup_user();
// Get the file list.
$files = [];
$langfiles = [];
if (is_file($source)) {
$files[] = $source;
}
if (is_dir($source)) {
$filelist = glob("$source/*");
foreach ($filelist as $filename) {
$files[] = "$filename";
}
}
$countfiles = 0;
foreach ($files as $filepath) {
// Try to get the lang.
$filelang = $lang;
// Get component from filename.
$pathparts = pathinfo($filepath);
$filename = $pathparts['filename'];
$extension = $pathparts['extension'];
if ($extension == 'zip') {
if (!$filelang) {
// Try to get the lang from the filename.
if (strrpos($filename, 'customlang_') === 0) {
$parts = explode('_', $filename);
if (!empty($parts[1])) {
$filelang = $parts[1];
}
}
}
} else if ($extension != 'php') {
// Ignore any other file extension.
continue;
}
if (empty($filelang)) {
cli_error(get_string('climissinglang', 'tool_customlang'));
}
if (!isset($langfiles[$filelang])) {
$langfiles[$filelang] = [];
}
$langfiles[$filelang][] = $filepath;
$countfiles ++;
}
if (!$countfiles) {
cli_error(get_string('climissingfiles', 'tool_customlang'));
}
foreach ($langfiles as $lng => $files) {
$importer = new importer($lng, $mode);
$storedfiles = [];
$fs = get_file_storage();
cli_heading(get_string('clifiles', 'tool_customlang', $lng));
foreach ($files as $file) {
// Generate a valid stored_file from this file.
$record = (object)[
'filearea' => 'draft',
'component' => 'user',
'filepath' => '/',
'itemid' => file_get_unused_draft_itemid(),
'license' => $CFG->sitedefaultlicense,
'author' => '',
'filename' => clean_param(basename($file), PARAM_FILE),
'contextid' => \context_user::instance($USER->id)->id,
'userid' => $USER->id,
];
cli_writeln($file);
$storedfiles[] = $fs->create_file_from_pathname($record, $file);
}
cli_writeln("");
// Import files.
cli_heading(get_string('cliimporting', 'tool_customlang', $modeparam));
$importer->import($storedfiles);
// Display logs.
$log = $importer->get_log();
if (empty($log)) {
cli_problem(get_string('clinolog', 'tool_customlang', $lng));
}
foreach ($log as $message) {
if ($message->errorlevel == notification::NOTIFY_ERROR) {
cli_problem($message->get_message());
} else {
cli_writeln($message->get_message());
}
}
// Do the checkin if necessary.
if ($checkin) {
tool_customlang_utils::checkin($lng);
cli_writeln(get_string('savecheckin', 'tool_customlang'));
}
cli_writeln("");
}
exit(0);
-9
View File
@@ -46,14 +46,5 @@ $capabilities = array(
'manager' => CAP_ALLOW
),
),
/* allows the user to export the current language customization */
'tool/customlang:export' => array(
'riskbitmask' => RISK_CONFIG,
'captype' => 'read',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => array(
'manager' => CAP_ALLOW
),
),
);
-3
View File
@@ -44,8 +44,5 @@ function xmldb_tool_customlang_upgrade($oldversion) {
// Automatically generated Moodle v3.9.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v3.10.0 release upgrade line.
// Put any upgrade step following this.
return true;
}
-68
View File
@@ -1,68 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Performs the custom lang export.
*
* @package tool_customlang
* @subpackage customlang
* @copyright 2020 Thomas Wedekind <thomas.wedekind@univie.ac.at>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require(__DIR__ . '/../../../config.php');
require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
require_once($CFG->libdir.'/adminlib.php');
global $PAGE, $CFG;
require_login(SITEID, false);
require_capability('tool/customlang:export', context_system::instance());
$lng = required_param('lng', PARAM_LANG);
admin_externalpage_setup('toolcustomlang', '', null,
new moodle_url('/admin/tool/customlang/import.php', ['lng' => $lng]));
$form = new \tool_customlang\form\export(null, ['lng' => $lng]);
if ($form->is_cancelled()) {
redirect('index.php');
die();
} else if ($formdata = $form->get_data()) {
$tempzip = tempnam($CFG->tempdir . '/', 'tool_customlang_export');
$filelist = [];
foreach ($formdata->files as $file) {
$filepath = tool_customlang_utils::get_localpack_location($lng). '/' . $file;
if (file_exists($filepath)) {
$filelist[$file] = $filepath;
}
}
$zipper = new zip_packer();
if (!empty($filelist) && $zipper->archive_to_pathname($filelist, $tempzip)) {
// Filename include the lang name so the file can be imported with automatic language detection.
send_temp_file($tempzip, "customlang_$lng.zip");
die();
}
}
$output = $PAGE->get_renderer('tool_customlang');
echo $output->header();
echo $output->heading(get_string('pluginname', 'tool_customlang'));
$form->display();
echo $OUTPUT->footer();

Some files were not shown because too many files have changed in this diff Show More