Compare commits

...

49 Commits

Author SHA1 Message Date
Mihail Geshoski a0a0458154 Moodle release 4.1.19 2025-06-06 12:26:16 +08:00
Sara Arjona 58d1571e08 weekly release 4.1.18+ 2025-06-05 16:43:46 +02:00
Michael Hawkins 75283557ad MDL-83762 core_files: Bind resolve IPs and ports to cURL calls 2025-06-05 12:10:26 +07:00
Vincent Schneider 7d23d3ae3a MDL-84518 course: improved course visibility state handling 2025-06-05 11:23:19 +07:00
Mark Johnson af2c368089 MDL-85323 core: Don't cache the login page 2025-06-05 11:02:54 +07:00
meirzamoodle 3b7f2aa473 MDL-85375 libraries: Escaping a query parameter on pg_insert_id() 2025-06-02 09:55:58 +07:00
Vincent Schneider 00bef0f91d MDL-84706 bigbluebuttonbn: improved authorization and mitigate CSRF risks 2025-05-30 08:40:21 +00:00
Huong Nguyen 26e53e8cc2 MDL-79993 course: Fix PHPUnit failure 2025-05-30 08:40:21 +00:00
raortegar be0dea2892 MDL-79993 course: Improve user access to recent courses service 2025-05-30 08:40:21 +00:00
Vincent Schneider e522e7fc67 MDL-84497 badges: fix missing action sesskey checks. 2025-05-30 08:40:21 +00:00
Michael Hawkins 7e19a2a640 weekly release 4.1.18+ 2025-05-30 16:29:50 +08:00
Michael Hawkins 724275abbc Merge branch 'install_401_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_401_STABLE 2025-05-30 16:29:43 +08:00
Huong Nguyen ea79441d28 Merge branch 'MDL-85525-401' of https://github.com/andelacruz/moodle into MOODLE_401_STABLE 2025-05-29 09:52:08 +07:00
Huong Nguyen ca580b25b9 Merge branch 'MDL-85400-401' of https://github.com/lameze/moodle into MOODLE_401_STABLE 2025-05-29 09:00:17 +07:00
Huong Nguyen 2f785afb00 Merge branch 'MDL-85389-401' of https://github.com/andelacruz/moodle into MOODLE_401_STABLE 2025-05-29 08:53:08 +07:00
AMOS bot 7b6fddd811 Automatically generated installer lang files 2025-05-29 00:07:40 +00:00
andelacruz ac77c1c217 MDL-85525 mod_quiz: Behat test for quiz attempt page block display 2025-05-28 16:20:56 +08:00
andelacruz 71bbfc2495 MDL-85389 mod_lesson: Behat for filtering lesson reports/essays by group 2025-05-28 15:42:08 +08:00
sam marshall c56c08e9ce MDL-85400 PHPunit: Hard to test code that uses encryption
This change stops the encryption code setting created key files to
read-only during PHPunit runs, which means they will be safely
deleted when the system resets after a test.
2025-05-28 13:14:34 +08:00
Huong Nguyen 4c3df551a4 weekly release 4.1.18+ 2025-05-23 11:04:05 +07:00
Huong Nguyen 516b81954a Merge branch 'install_401_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_401_STABLE 2025-05-23 11:04:04 +07:00
Huong Nguyen 4caed80b37 Merge branch 'MDL-84793-m401' of https://github.com/sammarshallou/moodle into MOODLE_401_STABLE 2025-05-22 10:49:00 +07:00
Huong Nguyen 7f6e49af41 Merge branch 'MDL-84918-401' of https://github.com/HuongNV13/moodle into MOODLE_401_STABLE 2025-05-22 10:35:05 +07:00
David Woloszyn 69cca28118 MDL-84918 core: Add zend.exception_ignore_args environment check 2025-05-22 10:12:03 +07:00
Huong Nguyen 3e30033749 MDL-84918 core: Add initial environment requirements for Moodle 5.1 2025-05-22 10:12:03 +07:00
Huong Nguyen d61b9111fa Merge branch 'MDL-85374-401' of https://github.com/andrewnicols/moodle into MOODLE_401_STABLE 2025-05-21 09:56:32 +07:00
AMOS bot 07a30d6650 Automatically generated installer lang files 2025-05-21 00:07:37 +00:00
Andrew Nicols 6f25549278 MDL-85374 report_competency: Create custom step for setting autocomplete
The autocompletes used in the competency report have been bastardised to
redirect on selection. Unfortunately this also applies when when making
null-op changes like deleting the initial "Please select a value"
option.

The autocomplete code removes all current options before creating an
option, and because of this redirect the browser is redirecting before
the new value can be entered, but we retain a reference to the field as
`$this->field`, which is now stale.
2025-05-20 13:09:53 +08:00
Mihail Geshoski 5ee4098ce5 weekly release 4.1.18+ 2025-05-16 12:59:25 +08:00
Mihail Geshoski 44956b2463 Merge branch 'install_401_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_401_STABLE 2025-05-16 12:59:18 +08:00
sam marshall e65075c421 MDL-84793 Behat: Allow CLI scripts to run on Behat instance 2025-05-15 08:51:54 +01:00
Huong Nguyen 3d95f94ca6 Merge branch 'MDL-85279-401' of https://github.com/andelacruz/moodle into MOODLE_401_STABLE 2025-05-15 11:43:10 +07:00
andelacruz 1b51d716e2 MDL-85279 mod_assign: Renamed behat test to a more specific name 2025-05-14 15:17:01 +08:00
andelacruz 7602fa7ad9 MDL-85279 mod_page: Fix behat to match the expected behaviour 2025-05-14 15:13:15 +08:00
AMOS bot f2ef4c6808 Automatically generated installer lang files 2025-05-10 00:07:38 +00:00
Huong Nguyen 757f0a56c9 weekly release 4.1.18+ 2025-05-09 09:50:36 +07:00
Huong Nguyen e22f3d47c2 Merge branch 'install_401_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_401_STABLE 2025-05-09 09:50:35 +07:00
Huong Nguyen 1ef498d989 Merge branch 'MDL-84654-401' of https://github.com/andelacruz/moodle into MOODLE_401_STABLE 2025-05-08 08:44:56 +07:00
AMOS bot 747fff61c4 Automatically generated installer lang files 2025-05-07 00:07:33 +00:00
Angelia Dela Cruz 0f368a42cc MDL-84654 mod_assign: Assignment additional files can be hidden 2025-05-06 13:24:37 +08:00
Huong Nguyen 186284ec1f Merge branch 'MDL-85310-401' of https://github.com/andelacruz/moodle into MOODLE_401_STABLE 2025-05-06 10:32:40 +07:00
Huong Nguyen cdfdfc30d9 Merge branch 'MDL-85226-401' of https://github.com/mackensen/moodle into MOODLE_401_STABLE 2025-05-06 10:30:38 +07:00
AMOS bot 6c95086bc9 Automatically generated installer lang files 2025-05-01 00:07:39 +00:00
Angelia Dela Cruz 45ef55471b MDL-85310 qtype: Renamed duplicate scenario names to fix warning 2025-04-30 13:36:18 +08:00
AMOS bot ac270cb26f Automatically generated installer lang files 2025-04-23 00:07:39 +00:00
AMOS bot b2ba6624ce Automatically generated installer lang files 2025-04-20 00:08:01 +00:00
AMOS bot b57eb5dd88 Automatically generated installer lang files 2025-04-19 00:07:37 +00:00
AMOS bot 9bf42e7aad Automatically generated installer lang files 2025-04-18 00:07:40 +00:00
Charles Fulton 4318e21563 MDL-85226 gha: Pin mongodb extension version 2025-04-16 15:28:57 -04:00
44 changed files with 715 additions and 73 deletions
+1
View File
@@ -65,6 +65,7 @@ jobs:
extensions:
db: mysqli
- os: ubuntu-22.04
extensions: mongodb-1.19.4
php: 8.1
db: pgsql
+197
View File
@@ -4895,4 +4895,201 @@
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="5.1" requires="4.2.3">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.11.0" />
<VENDOR name="mysql" version="8.4" />
<VENDOR name="postgres" version="14" />
<VENDOR name="mssql" version="14.0" />
</DATABASE>
<PHP version="8.2.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="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_EXTENSION name="exif" level="optional"/>
</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_SETTING name="zend.exception_ignore_args" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingzendexceptionignoreargs" />
</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="required">
<FEEDBACK>
<ON_ERROR message="sixtyfourbitsrequired" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
<FEEDBACK>
<ON_CHECK message="iscustomadminwarnings" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_db_prefix_length" level="required">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_async_backup" level="recommended">
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+4
View File
@@ -36,6 +36,10 @@ if (function_exists('opcache_reset')) {
define('CLI_SCRIPT', true);
define('CACHE_DISABLE_ALL', true);
// It makes no sense to use BEHAT_CLI for this script (the Behat launch scripts expect to start
// from the normal environment), so in case user has set tne environment variable, disable it.
putenv('BEHAT_CLI=0');
// Basic functions.
require_once(__DIR__ . '/../../../../lib/clilib.php');
require_once(__DIR__ . '/../../../../lib/behat/lib.php');
+4
View File
@@ -31,6 +31,10 @@ define('ABORT_AFTER_CONFIG', true);
define('CACHE_DISABLE_ALL', true);
define('NO_OUTPUT_BUFFERING', true);
// It makes no sense to use BEHAT_CLI for this script (the Behat launch scripts expect to start
// from the normal environment), so in case user has set tne environment variable, disable it.
putenv('BEHAT_CLI=0');
require_once(__DIR__ .'/../../../../config.php');
require_once(__DIR__.'/../../../../lib/clilib.php');
require_once(__DIR__.'/../../../../lib/behat/lib.php');
+4
View File
@@ -39,6 +39,10 @@ define('NO_OUTPUT_BUFFERING', true);
define('IGNORE_COMPONENT_CACHE', true);
define('ABORT_AFTER_CONFIG', true);
// It makes no sense to use BEHAT_CLI for this script (the Behat launch scripts expect to start
// from the normal environment), so in case user has set tne environment variable, disable it.
putenv('BEHAT_CLI=0');
require_once(__DIR__ . '/../../../../lib/clilib.php');
// CLI options.
+4
View File
@@ -33,6 +33,10 @@ if (isset($_SERVER['REMOTE_ADDR'])) {
die(); // No access from web!.
}
// It makes no sense to use BEHAT_CLI for this script (the Behat launch scripts expect to start
// from the normal environment), so in case user has set tne environment variable, disable it.
putenv('BEHAT_CLI=0');
// Basic functions.
require_once(__DIR__ . '/../../../../lib/clilib.php');
require_once(__DIR__ . '/../../../../lib/behat/lib.php');
@@ -46,11 +46,11 @@ Feature: See the competencies for an activity on the course competencies page.
When I follow "Competencies"
Then I should see "Test-Comp1"
And I should see "Test-Comp2"
And I set the field "Filter competencies by resource or activity" to "PageName1"
And I set the competency filter "Filter competencies by resource or activity" to "PageName1"
And I press the enter key
And I should see "Test-Comp1"
And I should not see "Test-Comp2"
And I set the field "Filter competencies by resource or activity" to "PageName2"
And I set the competency filter "Filter competencies by resource or activity" to "PageName2"
And I press the enter key
And I should not see "Test-Comp1"
And I should not see "Test-Comp2"
+4
View File
@@ -34,6 +34,10 @@ if (function_exists('opcache_reset')) {
define('IGNORE_COMPONENT_CACHE', true);
// It makes no sense to use BEHAT_CLI for this script (you cannot initialise PHPunit starting from
// the Behat environment), so in case user has set tne environment variable, disable it.
putenv('BEHAT_CLI=0');
require_once(__DIR__.'/../../../../lib/clilib.php');
require_once(__DIR__.'/../../../../lib/phpunit/bootstraplib.php');
require_once(__DIR__.'/../../../../lib/testing/lib.php');
+4
View File
@@ -30,6 +30,10 @@ if (isset($_SERVER['REMOTE_ADDR'])) {
define('IGNORE_COMPONENT_CACHE', true);
// It makes no sense to use BEHAT_CLI for this script (you cannot initialise PHPunit starting from
// the Behat environment), so in case user has set tne environment variable, disable it.
putenv('BEHAT_CLI=0');
require_once(__DIR__.'/../../../../lib/clilib.php');
require_once(__DIR__.'/../../../../lib/phpunit/bootstraplib.php');
require_once(__DIR__.'/../../../../lib/testing/lib.php');
+1 -1
View File
@@ -56,7 +56,7 @@ if ($action == 'delete' && $confirm && confirm_sesskey()) {
} else {
$msg = get_string('sitebackpacknotdeleted', 'badges');
}
} else if ($action == 'moveup' || $action == 'movedown') {
} else if (($action == 'moveup' || $action == 'movedown') && confirm_sesskey()) {
// If no backpack has been selected, there isn't anything to move.
if (empty($id)) {
redirect($url);
@@ -56,13 +56,13 @@
<td> {{{backpackweburl}}} </td>
<td>
{{#canmoveup}}
<a href="{{baseurl}}?id={{id}}&action=moveup">{{#pix}}t/up, core,{{#str}}moveup{{/str}}{{/pix}}</a>
<a href="{{baseurl}}?id={{id}}&sesskey={{sesskey}}&action=moveup">{{#pix}}t/up, core,{{#str}}moveup{{/str}}{{/pix}}</a>
{{/canmoveup}}
{{^canmoveup}}
{{#pix}}spacer, moodle{{/pix}}
{{/canmoveup}}
{{#canmovedown}}
<a href="{{baseurl}}?id={{id}}&action=movedown">{{#pix}}t/down, core,{{#str}}movedown{{/str}}{{/pix}}</a>
<a href="{{baseurl}}?id={{id}}&sesskey={{sesskey}}&action=movedown">{{#pix}}t/down, core,{{#str}}movedown{{/str}}{{/pix}}</a>
{{/canmovedown}}
{{^canmovedown}}
{{#pix}}spacer, moodle{{/pix}}
+1 -1
View File
@@ -4127,7 +4127,7 @@ class core_course_external extends external_api {
self::validate_context($usercontext);
if ($userid != $USER->id and !has_capability('moodle/user:viewdetails', $usercontext)) {
if ($userid != $USER->id && !has_capability('moodle/user:viewalldetails', $usercontext)) {
return array();
}
+8 -1
View File
@@ -1757,7 +1757,14 @@ class core_course_renderer extends plugin_renderer_base {
// This is a request for the course information.
$courseid = required_param('courseid', PARAM_INT);
$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
$course = $DB->get_record('course', ['id' => $courseid], '*', IGNORE_MISSING);
if ($course === false) {
throw new \moodle_exception('invalidcourseid');
}
$coursecontext = context_course::instance($course->id, MUST_EXIST);
if ($course->visible == 0 && !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
throw new \moodle_exception('invalidcourseid');
}
$chelper = new coursecat_helper();
$chelper->set_show_courses(self::COURSECAT_SHOW_COURSES_EXPANDED);
+6
View File
@@ -3639,6 +3639,12 @@ final class externallib_test extends externallib_advanced_testcase {
$this->assignUserCapability('moodle/user:viewdetails', $usercontext, $teacherroleid);
// Sorted by course id DESC.
// User without moodle/user:viewalldetails capability will not be able to see the course details.
$result = core_course_external::get_recent_courses($student->id);
$this->assertCount(0, $result);
// User with moodle/user:viewalldetails capability will be able to see the course details.
$this->assignUserCapability('moodle/user:viewalldetails', $usercontext, $teacherroleid);
$result = core_course_external::get_recent_courses($student->id);
$this->assertCount(1, $result);
$this->assertEquals($courses[0]->id, array_shift($result)->id);
+36
View File
@@ -0,0 +1,36 @@
<?php
// This file is part of Moodle - https://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
/**
* Automatically generated strings for Moodle installer
*
* Do not edit this file manually! It contains just a subset of strings
* needed during the very first steps of installation. This file was
* generated automatically by export-installer.php (which is part of AMOS
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
* list of strings defined in /install/stringnames.txt.
*
* @package installer
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$string['language'] = 'Idioma';
$string['moodlelogo'] = 'Logo de Moodle';
$string['next'] = 'Següent';
$string['previous'] = 'Anterior';
$string['reload'] = 'Torna a carregar';
+2 -2
View File
@@ -34,8 +34,8 @@ $string['cliansweryes'] = 's';
$string['cliincorrectvalueerror'] = 'Error, valor incorrecte "{$a->value}" for "{$a->option}"';
$string['cliincorrectvalueretry'] = 'Valor incorrecte, per favor essaya novemente';
$string['clitypevalue'] = 'valor de typo';
$string['clitypevaluedefault'] = 'valor de typo,pressa Enter per usar le vaor predefinite ({$a})';
$string['cliunknowoption'] = 'Uotiones non recognoscite:
$string['clitypevaluedefault'] = 'valor de typo, pressa Enter per usar le valor predefinite ({$a})';
$string['cliunknowoption'] = 'Optiones non recognoscite:
{$a}
Per favor usa le option --help.';
$string['cliyesnoprompt'] = 'typa s (significa si) o n (significa no)';
+52
View File
@@ -0,0 +1,52 @@
<?php
// This file is part of Moodle - https://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
/**
* Automatically generated strings for Moodle installer
*
* Do not edit this file manually! It contains just a subset of strings
* needed during the very first steps of installation. This file was
* generated automatically by export-installer.php (which is part of AMOS
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
* list of strings defined in /install/stringnames.txt.
*
* @package installer
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$string['cannotcreatedboninstall'] = '<p>Non pote crear le base de datos.</p>
<p>Le base de datos specificate non existe e le date usator non ha le permission a crear le base de datos.</p>
<p>Le administrator de sito deberea verificar le configuration de base de datos.</p>';
$string['cannotcreatelangdir'] = 'Non pote crear directorio de linguage (lang)';
$string['cannotcreatetempdir'] = 'Non pote crear directorio temp';
$string['cannotdownloadcomponents'] = 'Non pote discargar componentes';
$string['cannotdownloadzipfile'] = 'Non pote discargar file ZIP';
$string['cannotfindcomponent'] = 'Non pote trovar componente';
$string['cannotsavemd5file'] = 'Non pote salveguardar file md5';
$string['cannotsavezipfile'] = 'Non pote salveguardar file ZIP';
$string['cannotunzipfile'] = 'Non pote extraher (unzip) file Zip';
$string['componentisuptodate'] = 'Componente es actualisate';
$string['dmlexceptiononinstall'] = '<p>Un error de base de datos ha occurrite [{$a->errorcode}].<br />{$a->debuginfo}</p>';
$string['downloadedfilecheckfailed'] = 'Verifica de file discargate falleva';
$string['invalidmd5'] = 'Le variabile de verifica esseva errate - essaya novemente';
$string['missingrequiredfield'] = 'Alcun campo requirite es mancante';
$string['remotedownloaderror'] = '<p>Le discargamento delcomponente sur tu servitor falleva. Per favor verifica preferentias de proxy; le extension de PHP cURL ed fortemente recommendate.</p>
<p>Tu debe discargar le file <a href="{$a->url}">{$a->url}</a> manualmente, copiar lo a "{$a->dest}" in tu servitor e extraher lo (unzip) illac.</p>';
$string['wrongdestpath'] = 'Percurso de destination errate';
$string['wrongsourcebase'] = 'Base de URL de fonte errate';
$string['wrongzipfilename'] = 'Nomine de file ZIP errate';
+33
View File
@@ -0,0 +1,33 @@
<?php
// This file is part of Moodle - https://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
/**
* Automatically generated strings for Moodle installer
*
* Do not edit this file manually! It contains just a subset of strings
* needed during the very first steps of installation. This file was
* generated automatically by export-installer.php (which is part of AMOS
* {@link http://docs.moodle.org/dev/Languages/AMOS}) using the
* list of strings defined in /install/stringnames.txt.
*
* @package installer
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$string['parentlanguage'] = 'pl';
$string['thislanguage'] = 'Polski (Workplace)';
+1
View File
@@ -1239,6 +1239,7 @@ $string['settingmaxinputvars'] = 'PHP setting max_input_vars is recommended to b
$string['settingmaxinputvarsrequired'] = 'PHP setting max_input_vars must be at least 5000.';
$string['settingmemorylimit'] = 'Insufficient memory detected, please set higher memory limit in PHP settings.';
$string['settingsafemode'] = 'Moodle is not fully compatible with safe mode, please ask server administrator to turn it off. Running Moodle under safe mode is not supported, please expect various problems if you do so.';
$string['settingzendexceptionignoreargs'] = 'It is strongly recommended that the PHP setting zend.exception_ignore_args be enabled as a security precaution.';
$string['setupsearchengine'] = 'Setup search engine';
$string['showcommentscount'] = 'Show comments count';
$string['showdetails'] = 'Show details';
+2 -1
View File
@@ -136,7 +136,8 @@ class ADODB_postgres64 extends ADOConnection{
// get the last id - never tested
function pg_insert_id($tablename,$fieldname)
{
$result=pg_query($this->_connectionID, 'SELECT last_value FROM '. $tablename .'_'. $fieldname .'_seq');
$sequence = pg_escape_identifier($this->_connectionID, $tablename .'_'. $fieldname .'_seq');
$result = pg_query($this->_connectionID, 'SELECT last_value FROM '. $sequence);
if ($result) {
$arr = @pg_fetch_row($result,0);
pg_free_result($result);
+4
View File
@@ -23,3 +23,7 @@ Removed:
Added:
* index.html - prevent directory browsing on misconfigured servers
* readme_moodle.txt - this file ;-)
Changelog:
* MDL-85375:
- Fix SQL injection in pg_insert_id() - https://github.com/ADOdb/ADOdb/commit/11107d6d6e5160b62e05dff8a3a2678cf0e3a426
-1
View File
@@ -72,7 +72,6 @@ class behat_field_manager {
* @return behat_form_field
*/
public static function get_form_field(NodeElement $fieldnode, Session $session) {
// Get the field type if is part of a moodleform.
if (self::is_moodleform_field($fieldnode)) {
$type = self::get_field_node_type($fieldnode, $session);
@@ -326,4 +326,13 @@ class behat_form_field implements behat_session_interface {
return $this->fieldlocator;
}
/**
* Returns the field node.
*
* @return NodeElement
*/
public function get_node(): NodeElement {
return $this->field;
}
}
+5
View File
@@ -341,6 +341,11 @@ function behat_is_test_site() {
if (empty($CFG->behat_wwwroot)) {
return false;
}
if (defined('CLI_SCRIPT') && CLI_SCRIPT && getenv('BEHAT_CLI')) {
// Environment variable makes CLI script run on Behat instance.
echo "BEHAT_CLI: This command line script is running on the acceptance testing site.\n\n";
return true;
}
if (isset($_SERVER['REMOTE_ADDR']) and behat_is_requested_url($CFG->behat_wwwroot)) {
// Something is accessing the web server like a real browser.
return true;
+2 -2
View File
@@ -84,8 +84,8 @@ class encryption {
throw new \moodle_exception('encryption_keyalreadyexists', 'error');
}
// Don't make it read-only in Behat or it will fail to clear for future runs.
if (defined('BEHAT_SITE_RUNNING')) {
// Don't make it read-only in tests or it will fail to clear for future runs.
if (defined('BEHAT_SITE_RUNNING') || PHPUNIT_TEST) {
$chmod = false;
}
+51 -2
View File
@@ -54,6 +54,21 @@ class curl_security_helper extends curl_security_helper_base {
'https' => 443
];
/**
* @var string the host of the URL being checked by the helper.
*/
protected $host;
/**
* @var array IP address or addresses the URL is allowed to be requested from (passed the blocked hosts check).
*/
protected $allowedips = [];
/**
* @var ?int The port the URL is allowed to be requested from (passed the allowed port check).
*/
protected $allowedport;
/**
* Checks whether the given URL is blocked by checking its address and port number against the allow/block lists.
* The behaviour of this function can be classified as strict, as it returns true for URLs which are invalid or
@@ -85,6 +100,8 @@ class curl_security_helper extends curl_security_helper_base {
return true;
}
$this->host = $parsed['host'];
// The port will be empty unless explicitly set in the $url (uncommon), so try to infer it from the supported schemes.
if (!$parsed['port'] && $parsed['scheme'] && isset($this->transportschemes[$parsed['scheme']])) {
$parsed['port'] = $this->transportschemes[$parsed['scheme']];
@@ -162,12 +179,17 @@ class curl_security_helper extends curl_security_helper_base {
return true;
}
// If any of the returned IPs are in the blocklist, block the request.
// If any of the returned IPs are in the blocklist, block the request. Otherwise, temporarily record the IPs.
$allowedips = [];
foreach ($hostips as $hostip) {
if ($this->address_explicitly_blocked($hostip)) {
return true;
}
$allowedips[] = $hostip;
}
// If none of the IPs are blocked, set them on the allow list so we can enforce them on subsequent requests.
$this->allowedips = $allowedips;
}
} else {
// Was not something we consider to be a valid IP or domain name, block it.
@@ -201,7 +223,15 @@ class curl_security_helper extends curl_security_helper_base {
return true;
}
$allowedports = $this->get_allowed_ports();
return !empty($allowedports) && !in_array($portnum, $allowedports);
$isblocked = !empty($allowedports) && !in_array($portnum, $allowedports);
// If port is allowed, add it to our allow list so we can enforce it on subsequent requests.
if (!$isblocked) {
$this->allowedport = $portnum;
}
return $isblocked;
}
/**
@@ -291,4 +321,23 @@ class curl_security_helper extends curl_security_helper_base {
return !empty($entry);
});
}
/**
* Helper that returns host, IP and port information for the URL that has passed the blocked hosts/allowed ports checks.
*
* This data is in a format compatible with CURLOPT_RESOLVE, so it can be passed directly into that option.
* Doing so will prevent cURL re-fetching the info from DNS, preventing subsequent requests to the remote host from
* modifying the IP/port to ones that haven't been validated.
*
* @return array of strings in the format hostname:port:ip_address.
* @throws \coding_exception
*/
public function get_resolve_info(): array {
if (empty($this->host || empty($this->allowedips) || empty($this->allowedport))) {
$exception = 'In the curl_security_helper class, url_is_blocked() must be called before get_resolve_info() is called.';
throw new \core\exception\coding_exception($exception);
}
return array_map(fn($ip) => "$this->host:$this->allowedport:$ip", $this->allowedips);
}
}
+13
View File
@@ -3163,6 +3163,8 @@ class curl {
private $ignoresecurity;
/** @var array $mockresponses For unit testing only - return the head of this list instead of making the next request. */
private static $mockresponses = [];
/** @var array $curlresolveinfo Resolve addresses for the URL that have passed cuRL security checks, in a CURLOPT_RESOLVE compatible format. */
private $curlresolveinfo = [];
/**
* Curl constructor.
@@ -3759,6 +3761,9 @@ class curl {
return $this->error;
}
// Set allowed resolve info if the URL is not blocked.
$this->curlresolveinfo = $this->securityhelper->get_resolve_info();
return null;
}
@@ -3794,6 +3799,10 @@ class curl {
// Set the URL as a curl option.
$this->setopt(array('CURLOPT_URL' => $url));
// Force cURL to only resolve the URL from IP/port combinations that were validated by the security helper.
// This prevents re-fetching DNS data on subsequent requests, which could return un-validated hosts/ports.
$this->setopt(['CURLOPT_RESOLVE' => $this->curlresolveinfo]);
// Create curl instance.
$curl = curl_init();
@@ -3904,6 +3913,10 @@ class curl {
curl_setopt($curl, CURLOPT_URL, $redirecturl);
// Force cURL to only resolve the URL from IP/port combinations that were validated by the security helper.
// This prevents re-fetching DNS data on subsequent requests, which could return un-validated hosts/ports.
$this->setopt(['CURLOPT_RESOLVE' => $this->curlresolveinfo]);
// If CURLOPT_UNRESTRICTED_AUTH is empty/false, don't send credentials to other hosts.
// Ref: https://curl.se/libcurl/c/CURLOPT_UNRESTRICTED_AUTH.html.
$isdifferenthost = parse_url($currenturl)['host'] !== parse_url($redirecturl)['host'];
-18
View File
@@ -32,26 +32,8 @@ namespace core;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class encryption_test extends \advanced_testcase {
/**
* Clear junk created by tests.
*/
protected function tearDown(): void {
global $CFG;
$keyfile = encryption::get_key_file(encryption::METHOD_OPENSSL);
if (file_exists($keyfile)) {
chmod($keyfile, 0700);
}
$keyfile = encryption::get_key_file(encryption::METHOD_SODIUM);
if (file_exists($keyfile)) {
chmod($keyfile, 0700);
}
remove_dir($CFG->dataroot . '/secret');
unset($CFG->nokeygeneration);
}
protected function setUp(): void {
$this->tearDown();
require_once(__DIR__ . '/fixtures/testable_encryption.php');
}
+1 -2
View File
@@ -2410,8 +2410,7 @@ function send_headers($contenttype, $cacheable = true) {
@header('Expires: ');
} else {
// Do everything we can to always prevent clients and proxies caching.
@header('Cache-Control: no-store, no-cache, must-revalidate');
@header('Cache-Control: post-check=0, pre-check=0, no-transform', false);
@header('Cache-Control: no-store, no-cache, must-revalidate, no-transform');
@header('Pragma: no-cache');
@header('Expires: Mon, 20 Aug 1969 09:23:00 GMT');
@header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
+1
View File
@@ -49,6 +49,7 @@ $context = context_system::instance();
$PAGE->set_url("$CFG->wwwroot/login/index.php");
$PAGE->set_context($context);
$PAGE->set_pagelayout('login');
$PAGE->set_cacheable(false);
/// Initialize variables
$errormsg = '';
@@ -55,7 +55,7 @@ Feature: View activity completion in the assignment activity
And the manual completion button of "Music history" is displayed as "Done"
@javascript
Scenario: The manual completion button will not be shown on the course page if the Show activity completion conditions is set to No
Scenario: Assign module manual completion button hidden if Show activity completion is set to No
Given I am on the "Course 1" course page logged in as teacher1
And I navigate to "Settings" in current page administration
And I expand all fieldsets
@@ -0,0 +1,36 @@
@mod @mod_assign
Feature: Additional files for use in assignments can be hidden
In order to display additional files only during submission
As a teacher
I need to check the 'Only show files during submission' checkbox
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | One | teacher1@example.com |
| student1 | Student | One | student1@example.com |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
@javascript @_file_upload
Scenario: Additional files are only shown during submission
Given the following "activities" exist:
| activity | course | name | submissionattachments | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled |
| assign | C1 | Assign 1 | 1 | 1 | 0 |
And I am on the "Assign 1" "assign activity editing" page logged in as teacher1
And I upload "/mod/assign/tests/fixtures/submissionsample01.txt" file to "Additional files" filemanager
And I press "Save and return to course"
When I am on the "Assign 1" "assign activity" page logged in as student1
# Confirm that Additional files are not displayed on assignment activity when student logs in.
Then "submissionsample01.txt" "link" should not exist
And I press "Add submission"
# Additional files are displayed after student presses "Add submission" button and goes to submission phase.
And "submissionsample01.txt" "link" should exist
And following "submissionsample01.txt" should download a file that:
| Has mimetype | text/plain |
| Contains text | This is just a submission testing sample. |
+11 -5
View File
@@ -68,6 +68,8 @@ $context = $instance->get_context();
require_login($course, true, $cm);
require_sesskey();
// Note : this uses the group optional_param as a value to decide which groupid.
$groupid = groups_get_activity_group($cm, true) ?: null;
if ($groupid) {
@@ -144,14 +146,18 @@ switch (strtolower($action)) {
break;
case 'play':
$recording = recording::get_record(['id' => $rid]);
if ($href = $recording->get_remote_playback_url($rtype)) {
logger::log_recording_played_event($instance, $rid);
redirect(urldecode($href));
} else {
$recordings = $instance->get_recordings();
if (!isset($recordings[$rid])) {
notification::add(get_string('recordingnotfound', 'mod_bigbluebuttonbn'), notification::ERROR);
redirect($instance->get_view_url());
}
$href = $recordings[$rid]->get_remote_playback_url($rtype);
if (!$href) {
notification::add(get_string('recordingurlnotfound', 'mod_bigbluebuttonbn'), notification::ERROR);
redirect($instance->get_view_url());
}
logger::log_recording_played_event($instance, $rid);
redirect(urldecode($href));
// We should never reach this point.
break;
}
+3 -1
View File
@@ -1034,7 +1034,8 @@ EOF;
return new moodle_url('/mod/bigbluebuttonbn/bbb_view.php', [
'action' => 'logout',
'id' => $this->cm->id,
'courseid' => $this->cm->course // Used to find the course if ever the activity is deleted
'courseid' => $this->cm->course, // Used to find the course if ever the activity is deleted
'sesskey' => sesskey(),
// while the meeting is running.
]);
}
@@ -1073,6 +1074,7 @@ EOF;
'action' => 'join',
'id' => $this->cm->id,
'bn' => $this->instancedata->id,
'sesskey' => sesskey(),
]);
}
@@ -577,6 +577,7 @@ class recording extends persistent {
'bn' => $this->raw_get('bigbluebuttonbnid'),
'rid' => $this->get('id'),
'rtype' => $clone['type'],
'sesskey' => sesskey(),
]);
return $clone;
@@ -648,4 +648,5 @@ $string['taskname:check_dismissed_recordings'] = 'Check for recordings that have
$string['userlimitreached'] = 'The number of users allowed in a session has been reached.';
$string['waitformoderator'] = 'Waiting for a moderator to join.';
$string['recordingnotfound'] = 'The recording was not found.';
$string['recordingurlnotfound'] = 'The recording URL is invalid.';
+3 -1
View File
@@ -529,7 +529,9 @@ function mod_bigbluebuttonbn_core_calendar_provide_event_action(
'action' => 'join',
'id' => $cm->id,
'bn' => $bigbluebuttonbn->id,
'timeline' => 1]
'timeline' => 1,
'sesskey' => sesskey(),
]
);
}
+99 -10
View File
@@ -6,19 +6,58 @@ Feature: In a lesson activity, teachers can review student attempts
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
# Force group mode so you don't need to set it manually on the activity.
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
| fullname | shortname | category | groupmodeforce |
| Course 1 | C1 | 0 | |
| Course 2 | C2 | | 1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| teacher1 | C2 | editingteacher |
| student1 | C2 | student |
| student2 | C2 | student |
And the following "activities" exist:
| activity | name | course | idnumber | retake |
| lesson | Test lesson name | C1 | lesson1 | 1 |
| activity | name | course | idnumber | retake |
| lesson | Test lesson name | C1 | lesson1 | 1 |
| lesson | Lesson 1 | C2 | | |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C2 | G1 |
| Group 2 | C2 | G2 |
And the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G2 |
And the following "mod_lesson > page" exist:
| lesson | qtype | title | content |
| Lesson 1 | multichoice | Multichoice question | This is a multichoice question. |
| Lesson 1 | essay | Essay question | Write an essay about anything. |
| Lesson 1 | content | Content page | First page contents. |
And the following "mod_lesson > answers" exist:
| page | answer | jumpto | score |
| Multichoice question | Correct answer | Next page | 1 |
| Multichoice question | Incorrect answer | This page | 0 |
| Essay question | | Next page | 1 |
| Content page | Previous page | Previous page | 0 |
| Content page | Next page | Next page | 0 |
And I am on the "Lesson 1" "lesson activity" page logged in as student1
And I set the following fields to these values:
| Correct answer | 1 |
And I press "Submit"
And I set the field "Your answer" to "School is awesome!"
And I press "Submit"
And I am on the "Lesson 1" "lesson activity" page logged in as student2
And I set the following fields to these values:
| Incorrect answer | 1 |
And I press "Submit"
And I set the field "Your answer" to "Once upon an essay."
And I press "Submit"
Scenario: View student attempts in a lesson containing both content and question pages
Given the following "mod_lesson > pages" exist:
@@ -96,3 +135,53 @@ Feature: In a lesson activity, teachers can review student attempts
And I should not see "High score"
And I should not see "Average score"
And I should not see "Low score"
Scenario Outline: Teacher can filter lesson essay grading by group
Given I am on the "C2" "course editing" page logged in as teacher1
And I set the field "Group mode" to "<groupmode>"
And I press "Save and display"
And I am on the "Lesson 1" "lesson activity" page
And I press "Grade essays"
When I select "Group 1" from the "<groupmode>" singleselect
Then I should see "Student 1"
And I should not see "Student 2"
And I select "Group 2" from the "<groupmode>" singleselect
And I should see "Student 2"
And I should not see "Student 1"
And I select "All participants" from the "<groupmode>" singleselect
And I should see "Student 1"
And I should see "Student 2"
Examples:
| groupmode |
| Separate groups |
| Visible groups |
Scenario Outline: Teacher can filter lesson reports by group
Given I am on the "C2" "course editing" page logged in as teacher1
And I set the field "Group mode" to "<groupmode>"
And I press "Save and display"
And I am on the "Lesson 1" "lesson activity" page
And I navigate to "Reports" in current page administration
When I select "Group 1" from the "<groupmode>" singleselect
Then I should see "Student 1"
And I should not see "Student 2"
And I select "Group 2" from the "<groupmode>" singleselect
And I should see "Student 2"
And I should not see "Student 1"
And I select "All participants" from the "<groupmode>" singleselect
And I should see "Student 1"
And I should see "Student 2"
Examples:
| groupmode |
| Separate groups |
| Visible groups |
@javascript
Scenario: Teacher can delete selected attempts
Given I am on the "Lesson 1" "lesson activity" page logged in as teacher1
And I navigate to "Reports" in current page administration
When I click on "selectall-attempts" "checkbox"
And I select "Delete selected" from the "With selected attempts..." singleselect
Then I should see "No attempts have been made on this lesson."
@@ -14,9 +14,11 @@ Feature: View activity completion information in the Page resource
| Course 1 | C1 | 0 | 1 | 1 |
| Course 2 | C2 | 0 | 1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
| teacher1 | C1 | editingteacher |
| user | course | role |
| student1 | C1 | student |
| student1 | C2 | student |
| teacher1 | C1 | editingteacher |
| teacher1 | C2 | editingteacher |
Scenario: A teacher can view a page resource automatic completion items
Given the following "activity" exists:
@@ -69,7 +71,7 @@ Feature: View activity completion information in the Page resource
And I toggle the manual completion state of "Music history"
And the manual completion button of "Music history" is displayed as "Done"
Scenario: The manual completion button will not be shown on the course page if the Show activity completion conditions is set to No as teacher
Scenario Outline: Page module manual completion button hidden if Show activity completion is set to No
Given the following "activity" exists:
| activity | page |
| course | C2 |
@@ -77,16 +79,11 @@ Feature: View activity completion information in the Page resource
| name | Music history |
| intro | A lesson learned in life |
| completion | 1 |
When I am on the "Music history" "page activity" page logged in as teacher1
When I am on the "Course 2" course page logged in as <user>
# Course 2 has 'Show activity completion conditions' set to No, so the manual completion button should not be displayed.
Then the manual completion button for "Music history" should not exist
Scenario: The manual completion button will not be shown on the course page if the Show activity completion conditions is set to No as student
Given the following "activity" exists:
| activity | page |
| course | C2 |
| idnumber | page1 |
| name | Music history |
| intro | A lesson learned in life |
| completion | 1 |
When I am on the "Music history" "page activity" page logged in as student1
Then the manual completion button for "Music history" should not exist
Examples:
| user |
| teacher1 |
| student1 |
@@ -0,0 +1,41 @@
@mod @mod_quiz
Feature: Blocks can be displayed on quiz attempt pages
In order to see blocks on quiz attempt pages
As a teacher
I need to be able to set blocks display settings for quiz
Background:
Given the following "users" exist:
| username |
| student |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "course enrolments" exist:
| user | course | role |
| student | C1 | student |
Scenario Outline: Blocks display on quiz attempt pages can be toggled
Given the following "activities" exist:
| activity | course | name | idnumber | showblocks |
| quiz | C1 | Quiz 1 | q1 | <blockdisplay> |
And the following "question categories" exist:
| contextlevel | reference | name |
| Activity module | q1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name |
| Test questions | truefalse | TF1 |
And quiz "Quiz 1" contains the following questions:
| question | page |
| TF1 | 1 |
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| comments | Activity module | q1 | mod-quiz-attempt | side-pre |
When I am on the "Quiz 1" "quiz activity" page logged in as student
And I press "Attempt quiz"
Then "Comments" "block" <blockvisibility> exist
Examples:
| blockdisplay | blockvisibility |
| 1 | should |
| 0 | should not |
@@ -37,7 +37,7 @@ Feature: Preview a Multiple choice question
And I should see "Parts, but only parts, of your response are correct."
@javascript @_switch_window
Scenario: Preview a Multiple choice question and submit a correct response.
Scenario: Preview a Multiple choice question and submit multiple correct responses.
When I am on the "Multi-choice-001" "core_question > preview" page logged in as teacher
And I expand all fieldsets
And I set the field "How questions behave" to "Immediate feedback"
@@ -53,7 +53,7 @@ Feature: Preview a Multiple choice question
And I should see "The correct answers are: One, Three"
@javascript @_switch_window
Scenario: Preview a Multiple choice question and submit a correct response.
Scenario: Preview a Multiple choice question and submit a single correct response.
When I am on the "Multi-choice-002" "core_question > preview" page logged in as teacher
And I expand all fieldsets
And I set the field "How questions behave" to "Immediate feedback"
@@ -76,4 +76,52 @@ class behat_report_competency extends behat_base {
];
}
/**
* Set the value of a competency filter.
*
* @When /^I set the competency filter "([^"]*)" to "([^"]*)"$/
* @param string $fieldlocator The field locator.
* @param string $value The value to set.
* @throws Exception
*/
public function set_competency_filter(
string $fieldlocator,
string $value
): void {
$field = behat_field_manager::get_form_field_from_label($fieldlocator, $this)->get_node();
$session = $this->getSession();
$value = trim($value);
// Click into the field.
$field->click();
// Remove any existing text.
do {
behat_base::type_keys($session, [behat_keys::BACKSPACE, behat_keys::DELETE]);
} while (strlen($field->getValue()) > 0);
$this->wait_for_pending_js();
// Type in the new value.
behat_base::type_keys($session, str_split($value));
$this->wait_for_pending_js();
// If the autocomplete found suggestions, then it will have:
// 1) marked itself as expanded; and
// 2) have an aria-selected suggestion in the list.
$expanded = $field->getAttribute('aria-expanded');
$suggestion = $field->getParent()->getParent()->find('css', '.form-autocomplete-suggestions > [aria-selected="true"]');
if ($expanded && null !== $suggestion) {
// A suggestion was found.
// Click on the first item in the list.
$suggestion->click();
} else {
throw new \InvalidArgumentException(
"Unable to find '{$value}' in the list of options."
);
}
$this->wait_for_pending_js();
}
}
@@ -50,7 +50,7 @@ Feature: See the competencies for an activity
Scenario: Go to the competency breakdown report
When I navigate to "Reports" in current page administration
And I click on "Competency breakdown" "link"
And I set the field "Filter competencies by resource or activity" to "PageName1"
And I set the competency filter "Filter competencies by resource or activity" to "PageName1"
Then I should see "Test-Comp1"
And I should not see "Test-Comp2"
And I should see "Ann, Jill, Grainne, Beauchamp"
+2 -2
View File
@@ -29,9 +29,9 @@
defined('MOODLE_INTERNAL') || die();
$version = 2022112818.00; // 20221128 = branching date YYYYMMDD - do not modify!
$version = 2022112819.00; // 20221128 = branching date YYYYMMDD - do not modify!
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '4.1.18 (Build: 20250414)'; // Human-friendly version name
$release = '4.1.19 (Build: 20250609)'; // Human-friendly version name
$branch = '401'; // This version's branch.
$maturity = MATURITY_STABLE; // This version's maturity level.