Compare commits

..

419 Commits

Author SHA1 Message Date
Huong Nguyen 02e8cebdd2 Moodle release 4.4.5 2024-12-06 13:13:12 +07:00
Huong Nguyen 024051b719 weekly release 4.4.4+ 2024-12-05 22:32:58 +07:00
Sara Arjona 6423996066 Merge branch 'MDL-75610-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-12-05 16:13:21 +01:00
Jun Pataleta 490e544204 MDL-75610 core: Revert the addition of .upgradenotes
Upgrade notes generated by the `upgradenotes` tool is only available
from Moodle 4.5. For 4.4 and below, we should still update the
appropriate upgrade.txt file.
2024-12-05 21:34:05 +08:00
Huong Nguyen 62395a5aca MDL-83921 competency: Update unit tests with latest changes 2024-12-05 18:37:08 +08:00
Huong Nguyen 41ed00e59a MDL-82379 core_user: Move email change token to user private access key 2024-12-05 13:38:21 +08:00
Huong Nguyen ba74b9be02 Merge branch 'MDL-83606-404' of https://github.com/NashTechOpenUniversity/moodle into MOODLE_404_STABLE 2024-12-05 12:10:07 +07:00
Jun Pataleta 16f8d04930 Merge branch 'MDL-83727-404' of https://github.com/NashTechOpenUniversity/moodle into MOODLE_404_STABLE 2024-12-05 12:36:00 +08:00
Huong Nguyen b389ec0b8b Merge branch 'MDL-83641-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-12-05 11:29:30 +07:00
Huong Nguyen 1c8ac6a361 MDL-83921 competency: Bump version 2024-12-05 11:21:32 +07:00
Michael Hawkins c748e7d7e9 MDL-83921 competency: Match web service capability check with page check 2024-12-05 11:21:23 +07:00
Jun Pataleta fcff77046d Merge branch 'MDL-83823-404-enfix' of https://github.com/mudrd8mz/moodle into MOODLE_404_STABLE 2024-12-05 11:48:39 +08:00
Huong Nguyen d01b671f2d Merge branch 'MDL-83584-m404' of https://github.com/sammarshallou/moodle into MOODLE_404_STABLE 2024-12-05 10:13:00 +07:00
Huong Nguyen 2d35e0a180 Merge branch 'MDL-83223-404' of https://github.com/meirzamoodle/moodle into MOODLE_404_STABLE 2024-12-05 10:08:58 +07:00
Huong Nguyen a8b11d8923 MDL-82963 Tag: Improve validation for users tagged with sepecified tag 2024-12-05 11:03:13 +08:00
Jun Pataleta 6cc0eabc7e Merge branch 'MDL-83844-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-12-05 10:35:36 +08:00
Jun Pataleta 4a1811b769 Merge branch 'MDL-83710-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-12-05 09:55:13 +08:00
Helen Foster ffabf0b4b9 MDL-83823 lang: Import fixed English strings (en_fix) 2024-12-04 20:26:09 +01:00
meirzamoodle 5e078e4a78 MDL-83223 core: Use capture with addEventListener to intercept events
The issue is that Bootstrap’s dropdown component likely stops
event propagation after the first click to manage its own
dropdown behavior. This prevents your click event handler from
running on subsequent clicks.

To fix this, we can handle the event before Bootstrap’s code stops
the propagation by using capture option with addEventListener.
2024-12-04 10:37:02 +07:00
Laurent David 77c39c40e3 MDL-82757 mod_data: Improve group access handling
* Improved handling of group access to ensure correct visibility of records.
2024-12-04 02:51:26 +00:00
Jun Pataleta 8ec9af05b5 MDL-61316 core: Fix session gc unit tests 2024-12-04 02:51:26 +00:00
meirzamoodle 0ecdb05ab9 MDL-61316 core: Removed 5x multiplier from guest session expiration 2024-12-04 02:51:26 +00:00
Mark Johnson 54bc7d8197 MDL-83357 question: Fix filter cleaning in page links 2024-12-04 02:51:26 +00:00
Mark Johnson ea3848abe8 MDL-83357 question: Additional cleaning of filter params 2024-12-04 02:51:26 +00:00
Huong Nguyen 5f0201bd79 Merge branch 'MDL-82946-404' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-12-04 09:39:43 +07:00
Angelia Dela Cruz 363941c247 MDL-82946 qbank: Behat coverage for questions bulk actions 2024-12-03 10:36:29 +08:00
Huong Nguyen 60e0905018 Merge branch 'MDL-83128-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-12-03 09:32:43 +07:00
Paul Holden 987b7ef10d MDL-83641 cohort: allow 'includes' option be specified in form element. 2024-12-02 10:58:50 +00:00
Paul Holden fdb5d897de MDL-83844 mod_scorm: avoid SQL reserved words retrieving SCO timing. 2024-12-02 10:47:47 +00:00
Jun Pataleta 02d5efc450 Merge branch 'MDL-83648_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE 2024-12-02 17:24:32 +08:00
Huong Nguyen 4b2a950d08 Merge branch 'MDL-83711-404' of https://github.com/lucaboesch/moodle into MOODLE_404_STABLE 2024-12-02 14:19:46 +07:00
Shamim Rezaie 899b4fa1f4 Merge branch 'MDL-75610_404_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_404_STABLE 2024-12-02 15:24:44 +11:00
Huong Nguyen 9ce7e40f2e Merge branch 'MDL-83778-404' of https://github.com/NashTechOpenUniversity/moodle into MOODLE_404_STABLE 2024-12-02 10:44:38 +07:00
Huong Nguyen 84459c1ebf Merge branch 'MDL-83670-m404' of https://github.com/sammarshallou/moodle into MOODLE_404_STABLE 2024-12-02 10:31:06 +07:00
Huong Nguyen 495654b92b Merge branch 'MDL-82657_404_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_404_STABLE 2024-12-02 10:17:49 +07:00
Tim Hunt 6535a96989 MDL-83648 javascript dialogues: fix responsive behaviour
visibilityChanged in the dialogue base class does important things.
Therefore if ajaxException and exception also want to do something
else in response to the visibleChange event, it should use a
different method name, rather than a name that collides with the
base class method.
2024-11-29 17:05:14 +00:00
Luca Bösch 8628fc8664 MDL-83711 quiz: Quiz navigation profile pic not linking in secure mode 2024-11-29 14:25:49 +01:00
Sara Arjona 7da8af1006 weekly release 4.4.4+ 2024-11-29 12:37:03 +01:00
Khoa Nguyen 4bce55d783 MDL-83727 question: Core question privacy provider misuses lazy-loading 2024-11-29 10:55:39 +07:00
Khoa Nguyen e9cfb0ad02 MDL-83778 quiz: prevent page caching for quiz view page 2024-11-28 16:42:46 +07:00
Jun Pataleta 73a35edc24 MDL-83470 environment: Put back Oracle support for now
Even though Oracle support is planned to be dropped for 5.0, the
actual issue that drops it (MDL-83172) has not yet landed. So, it's
better to keep this in environment.xml for now and defer its removal
from environment.xml in MDL-83172.
2024-11-28 16:05:59 +07:00
Jun Pataleta 83c6906e75 Merge branch 'MDL-82475-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-11-28 13:19:08 +08:00
Huong Nguyen 3637e3db9f Merge branch 'MDL-83776-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-11-28 12:00:31 +07:00
Jun Pataleta 30d8c900a9 Merge branch 'MDL-83759-404' of https://github.com/roland04/moodle into MOODLE_404_STABLE 2024-11-28 12:28:54 +08:00
Jun Pataleta 1d5e6e4e5d Merge branch 'MDL-83412-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-11-28 12:12:08 +08:00
Huong Nguyen 276c40500c Merge branch 'MDL-83470-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-11-28 11:03:57 +07:00
Jun Pataleta e7556aa106 MDL-83412 core: Coding style fixes 2024-11-28 11:55:26 +08:00
Andrew Nicols 68c96a97b9 MDL-83412 calendartype_gregorian: Use core_date
Update timestamp_to_date_string to use core_date.
2024-11-28 11:55:25 +08:00
Andrew Nicols 213b37077c MDL-83412 core: Use LLL/LLLL for standalone Month names
We currently use MMM and MMMM which mean 'month in year', however in
some locales this is context-specific and should only be used in
conjunction with a day, for example "10 October 2024".

LLL and LLLL are for "stand-alone on the in year" and should be used
when a month is used without a day.
2024-11-28 11:55:25 +08:00
Huong Nguyen e75b7d1e0d Merge branch 'MDL-63264-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-11-28 10:46:58 +07:00
Huong Nguyen 7a77eb18c3 Merge branch 'MDL-83653_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE 2024-11-28 10:21:43 +07:00
Huong Nguyen 5d5d2f8f49 Merge branch 'MDL-82931-MOODLE_404_STABLE' of https://github.com/PhMemmel/moodle into MOODLE_404_STABLE 2024-11-28 09:44:27 +07:00
Huong Nguyen da00d28c2c Merge branch 'MDL-83661-404' of https://github.com/ferranrecio/moodle into MOODLE_404_STABLE 2024-11-28 09:39:16 +07:00
Huong Nguyen e778888ed2 Merge branch 'MDL-82932-MOODLE_404_STABLE' of https://github.com/PhMemmel/moodle into MOODLE_404_STABLE 2024-11-28 09:28:29 +07:00
Huong Nguyen b058b6681c Merge branch 'MDL-83643-404' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-11-28 09:21:16 +07:00
Jun Pataleta e2928d531e Merge branch 'MDL-83211-m404' of https://github.com/sammarshallou/moodle into MOODLE_404_STABLE 2024-11-27 23:28:46 +08:00
Jun Pataleta c3184e070a Merge branch 'MDL-83788-404' of https://github.com/andrewnicols/moodle into MOODLE_404_STABLE 2024-11-27 16:19:30 +08:00
Huong Nguyen cd7f36d194 Merge branch 'MDL-83658-MOODLE_404_STABLE' of https://github.com/praxisdigital/moodle into MOODLE_404_STABLE 2024-11-27 09:51:28 +07:00
Andrew Nicols 6f97d3a89f MDL-83788 mod_glossary: Correct assertions for assertArrayHasKey 2024-11-27 13:26:01 +11:00
Mark Johnson 4da7e5dec3 MDL-82657 qbank_managecategories: Check "includesubcategories" on reload
The "includesubcategories" parameter is passed in the URL as lowercase,
but the Javascript was looking for "includeSubcategories" in camel case.
This meant it was always being set as false (unchecked) even when the
URL said it was true.

This fixes the casing in the Javascript, and adds a behat test to
confirm the fix.
2024-11-26 13:29:02 +00:00
Shamim Rezaie 35b9ad6bbf Merge branch 'MDL-77957-404-test2' of https://github.com/rezaies/moodle into MOODLE_404_STABLE 2024-11-26 20:59:43 +11:00
Bastian Schmidt-Kuhl af68f3ca28 MDL-77957 theme_boost: Fix drawer not closing on mobile if it has focus 2024-11-26 20:52:17 +11:00
Huong Nguyen ecf91e296e Merge branch 'mdl-82762_404_wip' of https://github.com/james-cnz/moodle into MOODLE_404_STABLE 2024-11-26 12:10:51 +07:00
Huong Nguyen ef09179d1e Merge branch 'MDL-83795-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-11-26 12:03:22 +07:00
Khoa Nguyen 1ab37f0e63 MDL-83606 Question bank: Delete questions to fit one page causes errors. 2024-11-26 11:17:49 +07:00
Mikel Martín 286c3367c2 MDL-83759 theme_boost: Fix user navigation items height 2024-11-25 12:05:32 +01:00
Huong Nguyen d514c32c71 Merge branch 'MDL-83704-404' of https://github.com/andrewnicols/moodle into MOODLE_404_STABLE 2024-11-25 10:15:52 +07:00
Paul Holden 1d192cf19d MDL-83128 blocks: consistently style/align block list icons. 2024-11-22 16:22:06 +00:00
Paul Holden d805dde928 MDL-63264 enrol: retrieve additional welcome message contact data.
The `maildisplay` field is required to determine from whom to send
the welcome message.

Co-authored-by: Zak Risha <zjrisha@gmail.com>
2024-11-22 16:17:50 +00:00
Jun Pataleta 86e2e5882e MDL-83795 courseformat: Move upgrade notes to upgrade.txt 2024-11-22 23:53:34 +08:00
Jun Pataleta 505987af6c weekly release 4.4.4+ 2024-11-22 22:26:55 +08:00
Paul Holden 558b5aa693 MDL-83776 customfield_text: correct link field URL encoding. 2024-11-21 09:53:49 +00:00
Jun Pataleta 888a4f23bb MDL-83470 core: Define environment requirements for Moodle 5.0 2024-11-21 17:35:23 +08:00
Andrew Nicols e871b6fc71 Merge branch 'MDL-83551-404' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-11-21 12:26:12 +08:00
Huong Nguyen d032d75641 Merge branch 'MDL-83747-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-11-21 11:08:56 +07:00
Huong Nguyen 43a90e8197 Merge branch 'MDL-83048_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE 2024-11-21 11:01:48 +07:00
Andrew Nicols 25657e4be2 Merge branch 'MDL-83501-url-encode-nginx-paths-MOODLE_404_STABLE' of https://github.com/rajandangi/moodle into MOODLE_404_STABLE 2024-11-21 11:48:31 +08:00
Andrew Nicols 2f27619ffe Merge branch 'MDL-83226-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-11-21 11:45:11 +08:00
Philipp Memmel 80a77e7c74 MDL-82931 mod_data: Harden parsing of content format 2024-11-20 21:23:06 +01:00
Paul Holden 761f169185 Merge branch 'MDL-83570-404-fix' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-11-20 12:25:07 +00:00
Jun Pataleta a3b50194ee MDL-83570 tiny_recordrtc: Use the correct upgrade_plugin_savepoint()
And move the release upgrade line comment before the upgrade step.
2024-11-20 18:17:17 +08:00
Huong Nguyen 752b45d421 Merge branch 'MDL-83570-404' of https://github.com/meirzamoodle/moodle into MOODLE_404_STABLE 2024-11-20 16:11:35 +07:00
Frederik Milling Pytlick 7d3a4aa37d MDL-83658 core: Fix reactive debug tool logging
Fixed issue where the reactive debug panel does not log a transaction,
if the events fired are exactly the same as the previous ones.
2024-11-20 08:16:33 +01:00
meirzamoodle 55fb142c2f MDL-83570 tiny_recordrtc: Turn the audio bitrate input to Select field
The current code may have a bug. If users set the audio bit rate to
a non-supported value, such as 1000,
Firefox will display an error in the console,
while Chrome will create the recorded audio file successfully,
but it will have no sound. I tested this on Ubuntu 24.04.

The minimum bit rate threshold varies depending on the audio format.
During my tests with Firefox version 131.0.3, which uses
the audio/Ogg format, I found that the minimum supported value
is 24000. In Chrome 129.0.6668.70, which uses the audio/MP4 format,
the minimum supported value is 2400.

Due to these differences, I decided to change the input from
a text field to a select field, offering options that support both
Ogg and MP4 audio formats.

The database conversion for the old value has been provided in
the lib/db/upgrade.php. The script will find the closest match to
the current data and update it accordingly.
2024-11-20 10:08:10 +07:00
Jun Pataleta d4a98e6cfb Merge branch 'MDL-81521-404' of https://github.com/andrewnicols/moodle into MOODLE_404_STABLE 2024-11-19 15:15:25 +08:00
Huong Nguyen 97b1dd2f2f Merge branch 'MDL-83610-404' of https://github.com/marinaglancy/moodle into MOODLE_404_STABLE 2024-11-19 09:28:58 +07:00
Jun Pataleta 626ea71299 MDL-83747 mod_data: Add accessible name for delcheck checkboxes 2024-11-18 19:39:13 +08:00
Marina Glancy 98975c118e MDL-83610 behat: allow to set date fields in groups 2024-11-18 10:37:17 +00:00
Jun Pataleta 90409e8fa0 Merge branch 'MDL-83502-404' of https://github.com/ferranrecio/moodle into MOODLE_404_STABLE 2024-11-18 14:37:06 +08:00
Andrew Nicols d7898ee7da MDL-81521 mod_quiz: Fix attempt walkthrough tests 2024-11-18 10:24:55 +08:00
Andrew Nicols c6942c9bb7 MDL-81521 core: Update all possibly data providers to be static
Note: Some data providers could not be automatically be converted to
being static. These will be handled in a separate issue.
2024-11-18 10:24:55 +08:00
sam marshall 38688c0be6 MDL-83211 core_search: Indexing can miss items due to race condition
Changes search indexing so that (except for test scripts) each indexing
run indexes only items up to 5 seconds ago, and the following indexing
will start from the same point. This ensures all items are indexed,
even if an item is written to the database one or two seconds after its
timecreated value.
2024-11-15 09:34:44 +00:00
Mark Johnson a88cbdae73 MDL-75610 theme: Allow the activity title in Boost theme's secure layout 2024-11-15 08:32:57 +00:00
Mark Johnson ec498ce036 MDL-75610 output: Fix title display logic in activity header
The display logic for including the title in the activity header was
such that the title would only display if both the theme default and the
layout option for 'notitle' were undefined or false. It was not possible
to a theme to have 'notitle' default to true, but have a layout override
that as false to display the title.

This change re-writes the is_title_allowed method to encapsulte the new
logic, first checking if the current layout has the option set and using
that, and if not falling back to the theme default if that is set. If
neither is set, the title is displayed.

This also tweaks moodle_page::magic_get_layout_options to ensure the
theme is initialised before trying to return the layout options.
2024-11-15 08:32:56 +00:00
Jun Pataleta 5f85ba1793 Merge branch 'MDL-82877-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-11-15 13:31:31 +08:00
Huong Nguyen 63205f03bb weekly release 4.4.4+ 2024-11-15 09:21:36 +07:00
Jun Pataleta b820c1c5c3 Merge branch 'MDL-80926-404' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-11-14 12:05:17 +08:00
Jun Pataleta 482d0cc1dc Merge branch 'MDL-74836_404_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_404_STABLE 2024-11-14 10:46:12 +08:00
Paul Holden 195a4ce781 MDL-83710 report_questioninstances: fix missing type query params. 2024-11-13 21:16:05 +00:00
James C 785d70c2d7 MDL-82762 course: Prevent "undefined" being added to course index 2024-11-14 10:14:17 +13:00
Wiktor Wandachowicz ab25803907 MDL-83048 mod_quiz: Fixed use of grade_out_of and plugin renderer 2024-11-13 17:14:03 +00:00
Huong Nguyen 1a88833799 Merge branch 'MDL-83185-404' of https://github.com/laurentdavid/moodle into MOODLE_404_STABLE 2024-11-13 14:27:46 +07:00
Huong Nguyen 8e6355fc8c Merge branch 'MDL-80689_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE 2024-11-13 14:01:03 +07:00
Andrew Nicols 00fc817923 MDL-83704 core: Stop loading subplugins files to uninstall
The list of subplugin types was loaded from the json/php subplugins
file, but then the actual list of subplugins was loaded from the cache
in the component, rendering any benefit of using the source json/php as
pointless.
2024-11-13 10:26:21 +08:00
Andrew Nicols c8f0796ca6 MDL-83704 core: Stop loading subplugins files to fetch caps
This information is heavily cached in the component class. This should
be used wherever possible rather than checking on disk.
2024-11-13 10:17:32 +08:00
Simey Lameze afe848bcc6 MDL-83643 behat: make manual completion scenario names unique 2024-11-13 07:18:01 +08:00
Simey Lameze 89e18f1381 MDL-83551 behat: make duplicated scenario names unique 2024-11-13 06:50:56 +08:00
Nexterday 200fb340e6 MDL-74836 theme: Display activity header on secure layouts 2024-11-11 15:15:54 +00:00
Philipp Memmel 364c27227a MDL-82932 mod_data: Fix export with userdata of deleted users 2024-11-11 12:38:54 +01:00
Tim Hunt a70bbb3628 MDL-83653 file manager: report ajax errors
This is for things like when you click on a file, and then click on
the delete button, and an error happens then. Previously that was
ignored.
2024-11-08 17:14:41 +00:00
sam marshall 5bbe044927 MDL-83670 availability_group: With hidden groups, can throw warning 2024-11-08 11:59:00 +00:00
ferran a85c93018a MDL-83661 core_courseformat: fix drop file modal
When the user drags and drops a file into a course section that can
create more than one type of activity (for example a zip file) the modal
had repeated form elements ids. Now every radio option has its own id.
2024-11-08 11:45:58 +01:00
Huong Nguyen 3f9b9363d0 weekly release 4.4.4+ 2024-11-08 13:56:42 +07:00
Huong Nguyen 805ff1806a MDL-82335 qbank_columnsortorder: Fix upgrade code coding style 2024-11-08 09:04:55 +07:00
sam marshall 6ba656e2f5 MDL-83584 report_log: Group filter can get list of all users in system 2024-11-07 09:39:46 +00:00
Huong Nguyen 91d352a085 MDL-82335 qbank_columnsortorder: Cleanup upgrade code 2024-11-07 13:40:01 +07:00
Huong Nguyen 27073a36b6 Merge branch 'MDL-83619-404' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-11-07 11:05:52 +07:00
Huong Nguyen e1b6c9be56 Merge branch 'MDL-83611-404' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-11-07 11:02:35 +07:00
Huong Nguyen fee929cdaf Merge branch 'MDL-82335_404' of https://github.com/AnupamaSarjoshi/moodle into MOODLE_404_STABLE 2024-11-07 09:31:58 +07:00
Huong Nguyen a3a1e2184d Merge branch 'MDL-83316-404' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-11-07 09:27:04 +07:00
Simey Lameze 2245a4c0bc MDL-83316 behat: remove duplicated Then from new test 2024-11-07 07:49:12 +08:00
sam marshall 803f72ef0f MDL-83316 Behat: New step allows system clock change 2024-11-07 07:48:02 +08:00
Jun Pataleta 5ad4c9cf3b Merge branch 'mdl-83497_404' of https://github.com/james-cnz/moodle into MOODLE_404_STABLE 2024-11-06 22:38:45 +08:00
Anupama Sarjoshi 21fc25e46c MDL-82335 qbank_columnsortorder: Fix upgrading issue
When upgraded to Moodle 4.4 or higher, for qbank_columnsortorder
the colsize values in the config_plugins were getting incorrectly set,
resulting in errors accessing the question bank. Changes done to fix
this code and to remove the corrupted colsize value from
config_plugins table.
2024-11-06 13:31:02 +00:00
Jun Pataleta 962d7cfa55 Merge branch 'MDL-76563-404' of https://github.com/roland04/moodle into MOODLE_404_STABLE 2024-11-06 17:29:34 +08:00
Simey Lameze 37319d2c88 MDL-80926 behat: fix random and improve h5p completion test 2024-11-06 13:37:05 +08:00
Simey Lameze be5b800a80 MDL-83611 behat: increase window size to avoid randoms 2024-11-05 13:21:33 +08:00
Simey Lameze c3bc783ff4 MDL-83619 behat: enable bbb module early in the test 2024-11-05 10:23:34 +08:00
Paul Holden 58c98e14d9 MDL-82877 customfield: pass correct instanceid for restore structure. 2024-11-04 15:32:14 +00:00
Paul Holden ad201ba85a MDL-83226 customfield: set backup/restore configuration defaults. 2024-11-04 15:29:17 +00:00
Laurent David 3203fb9ae7 MDL-83185 core_courseformat: Refresh cache on group change
* When we add users to a group (or remove them), we should refresh
the course index cache so it stays in sync with what the user
can actually see.
2024-11-04 06:15:25 +01:00
ferran 84c2589c42 MDL-83185 core_courseformat: Allow global state cache invalidation 2024-11-04 06:15:25 +01:00
Huong Nguyen 99b5729824 weekly release 4.4.4+ 2024-11-01 14:29:24 +07:00
Huong Nguyen 3134bf772a Merge branch 'install_404_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_404_STABLE 2024-11-01 14:29:22 +07:00
Tim Hunt db03f2a58e MDL-80689 filepicker: better reporting of incorrect file type
Before this change, file type errors were reported like system errors. Now,
they are reported in a plain dialoue, which is more like how it works for
drag-drop upload.

Also, before this, after an upload errors, you were left with a blank
filepicker dialogue. Now, the upload form is redisplayed.
2024-10-31 11:39:16 +00:00
Tim Hunt 78cbc7cb16 MDL-80689 behat: add a transformation to get dirroot 2024-10-31 11:39:15 +00:00
Tim Hunt b784c144f8 MDL-80689 form behat: move fixture file to the expected place 2024-10-31 11:39:15 +00:00
Huong Nguyen 94ab19f544 Merge branch 'MDL-82911-404-fix' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-10-31 14:14:46 +07:00
Simey Lameze 438ef558cf MDL-82911 behat: change future times example to minutes 2024-10-31 14:15:48 +08:00
Huong Nguyen 16c1a0494c Merge branch 'MDL-82911-404' of https://github.com/andelacruz/moodle into MOODLE_404_STABLE 2024-10-31 11:23:00 +07:00
Huong Nguyen 9b0b39065c Merge branch 'MDL-83414-404' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-10-31 11:23:00 +07:00
Huong Nguyen 8b0afe2984 Merge branch 'MDL-82989-404' of https://github.com/meirzamoodle/moodle into MOODLE_404_STABLE 2024-10-31 11:22:59 +07:00
Jun Pataleta 6fa7222f0f Merge branch 'MDL-82809-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-10-31 11:22:59 +07:00
Huong Nguyen f616472d63 Merge branch 'MDL-82988-404' of https://github.com/meirzamoodle/moodle into MOODLE_404_STABLE 2024-10-31 11:22:59 +07:00
Angelia Dela Cruz cc33999469 MDL-83414 core_grades: Behat to test custom scale display 2024-10-31 09:46:39 +08:00
Angelia Dela Cruz 4736294b35 MDL-82911 mod_bigbluebuttonbn: Behat for BBB open and close date time 2024-10-29 12:09:41 +08:00
AMOS bot cc86aa7f8d Automatically generated installer lang files 2024-10-29 00:07:50 +00:00
meirzamoodle 2f5145d704 MDL-82989 communication_matrix: Apply helper to mock http_client 2024-10-27 15:55:05 +07:00
Andrew Nicols e62acd23e0 MDL-82989 PHPUnit: Add helper to mock http_client 2024-10-27 15:55:05 +07:00
meirzamoodle 5bd5d08f7e MDL-82988 general: Apply helper to get path to fixture 2024-10-27 15:45:19 +07:00
Andrew Nicols 7bec161984 MDL-82988 PHPUnit: Add helper to get path to fixture 2024-10-27 15:45:19 +07:00
Huong Nguyen f960ce6d5b weekly release 4.4.4+ 2024-10-25 08:36:04 +07:00
Huong Nguyen 9ade28a977 Merge branch 'install_404_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_404_STABLE 2024-10-25 08:36:01 +07:00
Mikel Martín 93821b6024 MDL-76563 theme: Change SCSS variable value
Change the value of the $pink SCSS colour variable so it is
colour contrast accessible on white backgrounds.
2024-10-24 13:27:57 +02:00
Jun Pataleta 731d5cc8b3 Merge branch 'MDL-82548-404' of https://github.com/roland04/moodle into MOODLE_404_STABLE 2024-10-24 12:18:11 +08:00
Jun Pataleta 2bb85117e3 Merge branch 'MDL-83423-404' of https://github.com/snake/moodle into MOODLE_404_STABLE 2024-10-24 12:13:28 +08:00
Huong Nguyen dced24e7c3 Merge branch 'MDL-83432-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-10-24 10:13:29 +07:00
Huong Nguyen 62d0705cc1 Merge branch 'MDL-83504-404' of https://github.com/marinaglancy/moodle into MOODLE_404_STABLE 2024-10-24 09:45:06 +07:00
AMOS bot 62778bb1aa Automatically generated installer lang files 2024-10-24 00:08:14 +00:00
Jun Pataleta 3d05070094 Merge branch 'MDL-81308-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-10-23 18:15:28 +08:00
Jun Pataleta 7b007b32af Merge branch 'MDL-83463-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-10-23 14:35:39 +08:00
Andrew Nicols 564de9d4a7 MDL-81308 core: Use a helper for consecutive invocation counts 2024-10-23 14:17:37 +08:00
Andrew Nicols da7c5d98ec MDL-81308 core: Update tests to not use withConsecutive 2024-10-23 14:17:36 +08:00
Jun Pataleta ff51c0bbf6 Merge branch 'MDL-83472-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-10-22 15:55:59 +08:00
Marina Glancy 33bc3cd98c MDL-83504 user: reset preference cache in unittests 2024-10-21 16:04:43 +01:00
ferran dd2c9b56bf MDL-83502 course: fix chrome file dropping in course page 2024-10-21 11:40:42 +02:00
rajandangi a3bcf54428 MDL-83501 core: URL encode paths for Nginx X-Accel-Redirect 2024-10-21 19:49:27 +10:30
James C fb6ea9b0d6 MDL-83497 course: Preserve move section dialogue info HTML 2024-10-19 16:19:37 +13:00
Paul Holden 599a3be74f MDL-83432 enrol: fix arguments to enrolment test generator. 2024-10-18 15:12:52 +01:00
Paul Holden 23a60a1220 MDL-83432 enrol_manual: reference correct role in welcome message. 2024-10-18 15:12:52 +01:00
Shamim Rezaie b097840e33 weekly release 4.4.4+ 2024-10-18 23:28:57 +11:00
Shamim Rezaie 04e7c65f0c Merge branch 'install_404_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_404_STABLE 2024-10-18 23:28:55 +11:00
Jun Pataleta 7e3638ff2e Merge branch 'MDL-83457-404' of https://github.com/roland04/moodle into MOODLE_404_STABLE 2024-10-17 12:23:24 +08:00
Jun Pataleta 540fda4055 Merge branch 'MDL-83443-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-10-17 12:17:38 +08:00
Jun Pataleta f44da13380 Merge branch 'MDL-83367-404' of https://github.com/dravek/moodle into MOODLE_404_STABLE 2024-10-17 12:08:52 +08:00
Jun Pataleta c8d55cdc52 Merge branch 'MDL-81450-MOODLE_404_STABLE' of https://github.com/PhMemmel/moodle into MOODLE_404_STABLE 2024-10-17 12:05:10 +08:00
Huong Nguyen d87999b89a Merge branch 'MDL-82580-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-10-17 10:49:26 +07:00
Jun Pataleta 6e617b9e46 Merge branch 'MDL-83143-404' of https://github.com/safatshahin/moodle into MOODLE_404_STABLE 2024-10-17 11:47:16 +08:00
Jun Pataleta 5a237cfef2 Merge branch 'MDL-82838-404' of https://github.com/justusdieckmann/moodle into MOODLE_404_STABLE 2024-10-17 10:54:39 +08:00
Huong Nguyen e05af64ecf Merge branch 'MDL-75724-404_toolbrickfield_tableheadercheck' of https://github.com/brickfield/moodle into MOODLE_404_STABLE 2024-10-17 09:44:43 +07:00
Jun Pataleta 1427cd178c Merge branch 'MDL-83002-404' of https://github.com/marinaglancy/moodle into MOODLE_404_STABLE 2024-10-16 20:32:28 +08:00
Paul Holden 6f6eae5d67 MDL-83472 phpunit: add void return type to test methods.
See also 01148a0816 from MDL-81522.
2024-10-16 13:04:13 +01:00
Paul Holden f442e8d5ad MDL-82809 reportbuilder: always apply conditions to custom report.
Including those that are otherwise unavailable to the current user,
ensuring that they are always applied when viewing report output.
2024-10-16 10:51:52 +01:00
Philipp Memmel 0ccc87c617 MDL-81450 mod_forum: Reduce size of file icon in HTML mails
@Co-authored-by: Mateusz Walczak
2024-10-16 11:32:48 +02:00
Paul Holden 92b27a6f07 MDL-82475 reportbuilder: account for duplicate profile field names.
Long-term, it would be better to not allow this scenario to happen
at all but until then we'll have to work around it (see MDL-73461).
2024-10-16 09:33:22 +01:00
Paul Holden 07bc841860 MDL-82809 reportbuilder: load custom/profile fields consistently.
Ensure that provided columns and filters for each use appropriate
checks to determine their availability (based on user permissions,
etc), rather than conditionally adding them to the entity.
2024-10-16 09:11:20 +01:00
Huong Nguyen 0282a557d0 Merge branch 'MDL-82793-MOODLE_404_STABLE' of https://github.com/phmemmel/moodle into MOODLE_404_STABLE 2024-10-16 09:26:49 +07:00
Philipp Memmel d506b8f6e2 MDL-82793 core: Make modal execute JS from template
Co-authored-by: Huong Nguyen <huongnv13@gmail.com>
2024-10-15 20:52:27 +02:00
Paul Holden 34495e01fc MDL-83463 backup: ensure defaults for course file inclusion are read. 2024-10-15 12:27:17 +01:00
Jun Pataleta cd06961249 Merge branch 'MDL-83070_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE 2024-10-15 19:09:14 +08:00
Huong Nguyen 7cdc137d8a Merge branch 'MDL-82429-404' of https://github.com/x-iy/moodle into MOODLE_404_STABLE 2024-10-15 16:25:11 +07:00
Mikel Martín 8a6d6ef675 MDL-83457 mod_feedback: Fix get_incomplete_users early return type
Fix 'feedback_get_incomplete_users' early return when there are no users with
the 'mod/feedback:complete' capability from 'false' to an empty array. That
will follow the function signature.
2024-10-15 09:57:06 +02:00
Jun Pataleta b2cf67e4f5 Merge branch 'MDL-83253-404' of https://github.com/andrewnicols/moodle into MOODLE_404_STABLE 2024-10-15 11:44:36 +08:00
Jake Dallimore 62a0b21d27 MDL-83423 mod_lti: fix JWK decoding when multiple keys missing alg
Related to MDL-77077, but was a case missed there. Now, any unusable
keys (i.e. can't be used during the JWT decode), are dropped from the
keyset if they don't have the 'alg' prop, preventing a 'missing alg'
exception during keyset parsing. Since these cannot be used during
decode, these aren't needed anyway.
2024-10-15 09:12:21 +08:00
AMOS bot cee330362c Automatically generated installer lang files 2024-10-15 00:09:32 +00:00
Michael Pound 9e7d54ebe6 MDL-75724 tool_brickfield: Ensuring correct table headers pass checks. 2024-10-14 16:56:52 +00:00
AMOS bot b51456d83a Automatically generated installer lang files 2024-10-13 00:07:52 +00:00
Paul Holden 847ab7d072 MDL-83443 enrol: use defined role name in welcome message. 2024-10-11 14:35:28 +01:00
Jake Dallimore b48e64e2a1 weekly release 4.4.4+ 2024-10-11 10:55:06 +08:00
Jake Dallimore 71e219b7db Merge branch 'install_404_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_404_STABLE 2024-10-11 10:55:05 +08:00
Safat aa0fbc3f08 MDL-83143 core_communication: Behat coverage for default to course name 2024-10-11 11:02:08 +11:00
Safat 9ef5476361 MDL-83143 core_course: Add course name as default for empty room name 2024-10-11 11:02:08 +11:00
Safat 2c363085af MDL-83143: core_communication: Fix variable name typos 2024-10-11 11:02:07 +11:00
Jun Pataleta 75573d11e9 Merge branch 'MDL-82813-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-10-10 12:04:15 +08:00
Huong Nguyen 35ca0b0616 Merge branch 'MDL-82570-404' of https://github.com/vietlx426/moodle-1 into MOODLE_404_STABLE 2024-10-10 10:52:51 +07:00
Huong Nguyen 1ff3797d8d Merge branch 'MDL-83255-MOODLE_404_STABLE' of https://github.com/TobiGa/moodle into MOODLE_404_STABLE 2024-10-10 10:11:40 +07:00
Jun Pataleta 666fffc680 Merge branch 'MDL-82912-404' of https://github.com/andelacruz/moodle into MOODLE_404_STABLE 2024-10-10 10:35:07 +08:00
Jun Pataleta 6bbb0de4eb Merge branch 'MDL-82812_404_toolbrickfieldfaicons' of https://github.com/brickfield/moodle into MOODLE_404_STABLE 2024-10-10 10:13:44 +08:00
Angelia Dela Cruz 79dcd64b34 MDL-82912 mod_workshop: Behat to view assessment after workshop close 2024-10-09 16:42:30 +08:00
Huong Nguyen 13e5a55ae9 Merge branch 'MDL-83331_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE 2024-10-09 14:47:14 +07:00
AMOS bot e5b03f9fb9 Automatically generated installer lang files 2024-10-09 00:09:23 +00:00
Max Larkin 9a72cc8837 MDL-82812 tool_brickfield: Ignore fa icons 2024-10-08 13:02:23 +01:00
Huong Nguyen 756a559024 Merge branch 'MDL-70180-404' of https://github.com/roland04/moodle into MOODLE_404_STABLE 2024-10-08 09:36:38 +07:00
AMOS bot 0685bfdb24 Automatically generated installer lang files 2024-10-08 00:07:46 +00:00
david adamson 6f73e436fb MDL-82429 tool_brickfield: Process calculated fontsizes 2024-10-08 09:32:57 +11:00
Tim Hunt b72b37c974 MDL-83331 behat: enable navigation direct to mod/.../index.php 2024-10-07 12:05:19 +01:00
Tobias Garske dc2b113bca MDL-83255 core_course: Fix activitychooser recommended tab navigation 2024-10-07 08:24:31 +00:00
Tim Hunt a9d4d93b74 MDL-83070 question restore: recode links in hints 2024-10-07 08:53:58 +01:00
Jun Pataleta d7e3bea9fa Moodle release 4.4.4 2024-10-05 14:46:37 +08:00
AMOS bot f67240b70b Automatically generated installer lang files 2024-10-05 00:07:47 +00:00
Huong Nguyen 5ce118a9c5 weekly release 4.4.3+ 2024-10-04 20:48:10 +07:00
Huong Nguyen cc27af1b7f Merge branch 'install_404_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_404_STABLE 2024-10-04 20:48:08 +07:00
David Carrillo 2128d39ed7 MDL-83367 tasks: Apply trim() to pathtophp setting
- It fixes the problem that when "pathtophp" setting is stored with
whitespaces, the "Run now" button will still show up in the tasks list,
but the task will never run
2024-10-04 15:36:31 +02:00
AMOS bot 3b8f6dee80 Automatically generated installer lang files 2024-10-04 00:07:45 +00:00
Marina Glancy 6c113ddc35 MDL-83002 theme_boost: tell behat to wait when initialising drawers 2024-10-03 15:52:13 +01:00
Michael Hawkins b08fbf57fd MDL-83352 message: Update usercantbemessaged string 2024-10-03 17:46:34 +07:00
vietlx426 fce950a59a MDL-82570 themes: Help boxes not accessible if selected consecutively 2024-10-03 16:27:29 +07:00
Jun Pataleta 54e9ee4a9e Merge branch 'MDL-83238-404-enfix' of https://github.com/mudrd8mz/moodle into MOODLE_404_STABLE 2024-10-03 16:02:02 +08:00
David Carrillo ba131ff29d MDL-83179 badges: Get type and courseid from context instead of params 2024-10-03 08:12:10 +08:00
David Mudrák 6e61b34ac2 MDL-83238 lang: Fix the changed strings in the tests, too 2024-10-02 22:04:50 +02:00
Helen Foster 06666c60f5 MDL-83238 lang: Import fixed English strings (en_fix) 2024-10-02 22:04:50 +02:00
Shamim Rezaie a0c341d039 Merge branch 'MDL-83332-404' of https://github.com/meirzamoodle/moodle into MOODLE_404_STABLE 2024-10-03 02:24:09 +10:00
Paul Holden 6e77a2070d MDL-83180 reportbuilder: correct access check for viewing schedules. 2024-10-02 16:49:26 +08:00
meirzamoodle 366d82ccd7 MDL-83332 environment: Reverts the slashargument removal on MDL-62640
We are encountering Behat failures on MacOS and possibly Windows.

This reverts commit 3202109780.
2024-10-02 13:29:14 +07:00
David Carrillo c75ec7503c MDL-83178 reportbuilder: correct access check to view badge recipients 2024-10-02 13:58:07 +08:00
Jun Pataleta 0f62b3d370 Merge branch 'm44-md83163' of https://github.com/danmarsden/moodle into MOODLE_404_STABLE 2024-10-02 12:31:22 +08:00
Dan Marsden 3100b07fb6 MDL-83310 course: remove hard-coded list of course formats from test. 2024-10-02 08:50:06 +13:00
Paul Holden 4a68972a4a MDL-83181 reportbuilder: ensure audience correctness before delete. 2024-10-01 12:41:17 +00:00
Paul Holden 1a219492f7 MDL-82386 block_rss_client: user access checks for feed edit/delete. 2024-10-01 12:41:17 +00:00
Huong Nguyen d8de6025b2 weekly release 4.4.3+ 2024-10-01 19:33:00 +07:00
Mikel Martín bdd79633d3 MDL-82548 courseformat: Fix courseindex cm anchors
In the course index the course modules links had incorrenct "href" (only the anchor) when
being displayed in a page different than course page. This patch regenerates the href for
cms in the course index when needed.
2024-10-01 11:01:48 +02:00
Jun Pataleta 823e8d94de Merge branch 'MDL-83264-404-1' of https://github.com/mihailges/moodle into MOODLE_404_STABLE 2024-10-01 12:47:13 +08:00
Mihail Geshoski 54da83f40a MDL-83264 mod_quiz: Return the correct name for top categories 2024-10-01 09:43:13 +08:00
Shamim Rezaie 759bf6e3b6 Merge branch 'MDL-81590-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-09-30 23:01:29 +10:00
Huong Nguyen e3460d67f3 weekly release 4.4.3+ 2024-09-27 18:44:03 +07:00
Huong Nguyen a99970eeb5 NOBUG: Fixed SVG browser compatibility 2024-09-27 18:44:01 +07:00
Huong Nguyen 96321d7b45 Merge branch 'install_404_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_404_STABLE 2024-09-27 18:44:00 +07:00
Jun Pataleta 971fd1cf26 MDL-81590 core: Build the context path without using DIRECTORY_SEPARATOR 2024-09-27 15:44:37 +08:00
Jun Pataleta c187fde227 Merge branch 'MDL-80929-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-27 12:40:18 +08:00
Huong Nguyen 7df5aeed41 Merge branch 'MDL-83205-404' of https://github.com/andrewnicols/moodle into MOODLE_404_STABLE 2024-09-27 11:27:05 +07:00
Huong Nguyen 21e23bef57 Merge branch 'MDL-82483-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-27 11:15:54 +07:00
Jun Pataleta 04d887ec89 Merge branch 'MDL-82602-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-27 12:10:46 +08:00
Huong Nguyen 12c97671bc Merge branch 'MDL-80974-MOODLE_404_STABLE' of https://github.com/sh-csg/moodle into MOODLE_404_STABLE 2024-09-27 11:08:52 +07:00
Jun Pataleta 3a1d250c27 Merge branch 'MDL-82973-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-27 12:06:01 +08:00
Jun Pataleta 3dadbe85af Merge branch 'MDL-83163-m404' of https://github.com/sammarshallou/moodle into MOODLE_404_STABLE 2024-09-27 11:59:25 +08:00
Andrew Nicols 9f3174a32d Merge branch 'MDL-83094-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-27 11:05:55 +08:00
Jun Pataleta bba5ec68ec Merge branch 'MDL-81157-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-27 10:28:24 +08:00
Jun Pataleta 7b354279c7 Merge branch 'MDL-82581-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-27 10:10:45 +08:00
AMOS bot 78380cc2a3 Automatically generated installer lang files 2024-09-27 00:07:45 +00:00
Andrew Nicols 0feec6d5f0 Merge branch 'MDL-83268-404' of https://github.com/sarjona/moodle into MOODLE_404_STABLE 2024-09-26 22:07:53 +08:00
Sara Arjona 03edcc984e MDL-83268 core_h5p: Fix version number 2024-09-26 16:02:17 +02:00
Andrew Nicols 264e5dcb44 Merge branch 'MDL-83268-404' of https://github.com/sarjona/moodle into MOODLE_404_STABLE 2024-09-26 21:32:37 +08:00
Sara Arjona 2f5e3d13b2 MDL-83268 core_h5p: Fix required Moodle version 2024-09-26 15:25:42 +02:00
Andrew Nicols 26d77f3735 Merge branch 'MDL-83268-404' of https://github.com/sarjona/moodle into MOODLE_404_STABLE 2024-09-26 21:06:53 +08:00
Jun Pataleta 4d1919014f Merge branch 'MDL-79288-404_blockaccessreview_colourcontrastcheck' of https://github.com/brickfield/moodle into MOODLE_404_STABLE 2024-09-26 19:45:02 +08:00
Sara Arjona 2fad1f88f1 MDL-83268 core_h5p: Remove unused font files
In https://h5ptechnology.atlassian.net/browse/HFP-4105, the
fonts/h5p-core-29.svg was merged with some conflicts.
Looking at the patch there, it seems all the h5p-core-29* fonts
can be removed because the ones used by the library are the
h5p-core-30-*.

I haven't added a note in the upgrade because it seems an error
on their release process (so I don't think it's worth adding
a note because it should be fixed in future releases).
2024-09-26 10:35:26 +02:00
Sara Arjona 0bcf1e2dcc MDL-83268 core_h5p: Remove the h5plib_v126 plugin
The h5plib_v126 plugin can be removed because it has been replaced
with h5plib_v127, which is using the latest versions of the
libraries.
2024-09-26 10:35:26 +02:00
Sara Arjona 76ed1fd12a MDL-83268 core_h5p: Add editor lib changes after upgrading it 2024-09-26 10:35:26 +02:00
Sara Arjona d205a07d40 MDL-83268 core_h5p: Upgrade editor lib to 1.27
This commit is upgrading the joubel/editor library to the one
tagged as moodle-1.27.0 (which also increases the coreApi minorVersion).
2024-09-26 10:35:25 +02:00
Sara Arjona 5670b0932c MDL-83268 core_h5p: Add core lib changes after upgrading it 2024-09-26 10:35:25 +02:00
Sara Arjona 67cec533ea MDL-83268 core_h5p: Upgrade core lib to 1.27
This commit is upgrading the joubel/core library to the one
tagged as moodle-1.27.0 (which also increases the coreApi minorVersion).
That's why the previous commit was duplicating the existing
h5plib_v126.
2024-09-26 10:35:25 +02:00
Sara Arjona 1550715d9b MDL-83268 h5plib: Create first version of h5plib_v127
AMOS BEGIN
  CPY [editor:a11ytitleshowlabel,h5plib_v126],[editor:a11ytitleshowlabel,h5plib_v127]
  CPY [editor:a11ytitlehidelabel,h5plib_v126],[editor:a11ytitlehidelabel,h5plib_v127]
  CPY [editor:atoz,h5plib_v126],[editor:atoz,h5plib_v127]
  CPY [editor:add,h5plib_v126],[editor:add,h5plib_v127]
  CPY [editor:addauthor,h5plib_v126],[editor:addauthor,h5plib_v127]
  CPY [editor:addentity,h5plib_v126],[editor:addentity,h5plib_v127]
  CPY [editor:addfile,h5plib_v126],[editor:addfile,h5plib_v127]
  CPY [editor:addnewchange,h5plib_v126],[editor:addnewchange,h5plib_v127]
  CPY [editor:addtitle,h5plib_v126],[editor:addtitle,h5plib_v127]
  CPY [editor:addvideodescription,h5plib_v126],[editor:addvideodescription,h5plib_v127]
  CPY [editor:avtablistlabel,h5plib_v126],[editor:avtablistlabel,h5plib_v127]
  CPY [editor:belowmin,h5plib_v126],[editor:belowmin,h5plib_v127]
  CPY [editor:cancel,h5plib_v126],[editor:cancel,h5plib_v127]
  CPY [editor:cancellabel,h5plib_v126],[editor:cancellabel,h5plib_v127]
  CPY [editor:changefile,h5plib_v126],[editor:changefile,h5plib_v127]
  CPY [editor:changelanguage,h5plib_v126],[editor:changelanguage,h5plib_v127]
  CPY [editor:changelibrary,h5plib_v126],[editor:changelibrary,h5plib_v127]
  CPY [editor:changelogdescription,h5plib_v126],[editor:changelogdescription,h5plib_v127]
  CPY [editor:close,h5plib_v126],[editor:close,h5plib_v127]
  CPY [editor:commonfields,h5plib_v126],[editor:commonfields,h5plib_v127]
  CPY [editor:commonfieldsdescription,h5plib_v126],[editor:commonfieldsdescription,h5plib_v127]
  CPY [editor:confirmchangelibrary,h5plib_v126],[editor:confirmchangelibrary,h5plib_v127]
  CPY [editor:confirmdeletechangelog,h5plib_v126],[editor:confirmdeletechangelog,h5plib_v127]
  CPY [editor:confirmimageremoval,h5plib_v126],[editor:confirmimageremoval,h5plib_v127]
  CPY [editor:confirmpastebuttontext,h5plib_v126],[editor:confirmpastebuttontext,h5plib_v127]
  CPY [editor:confirmpastecontent,h5plib_v126],[editor:confirmpastecontent,h5plib_v127]
  CPY [editor:confirmremoval,h5plib_v126],[editor:confirmremoval,h5plib_v127]
  CPY [editor:confirmremoveauthor,h5plib_v126],[editor:confirmremoveauthor,h5plib_v127]
  CPY [editor:contenttypebackbuttonlabel,h5plib_v126],[editor:contenttypebackbuttonlabel,h5plib_v127]
  CPY [editor:contenttypecacheoutdated,h5plib_v126],[editor:contenttypecacheoutdated,h5plib_v127]
  CPY [editor:contenttypecacheoutdateddesc,h5plib_v126],[editor:contenttypecacheoutdateddesc,h5plib_v127]
  CPY [editor:contenttypedemobuttonlabel,h5plib_v126],[editor:contenttypedemobuttonlabel,h5plib_v127]
  CPY [editor:contenttypedetailbuttonlabel,h5plib_v126],[editor:contenttypedetailbuttonlabel,h5plib_v127]
  CPY [editor:contenttypegetbuttonlabel,h5plib_v126],[editor:contenttypegetbuttonlabel,h5plib_v127]
  CPY [editor:contenttypeiconalttext,h5plib_v126],[editor:contenttypeiconalttext,h5plib_v127]
  CPY [editor:contenttypeinstallbuttonlabel,h5plib_v126],[editor:contenttypeinstallbuttonlabel,h5plib_v127]
  CPY [editor:contenttypeinstallerror,h5plib_v126],[editor:contenttypeinstallerror,h5plib_v127]
  CPY [editor:contenttypeinstallsuccess,h5plib_v126],[editor:contenttypeinstallsuccess,h5plib_v127]
  CPY [editor:contenttypeinstallingbuttonlabel,h5plib_v126],[editor:contenttypeinstallingbuttonlabel,h5plib_v127]
  CPY [editor:contenttypelicensepaneltitle,h5plib_v126],[editor:contenttypelicensepaneltitle,h5plib_v127]
  CPY [editor:contenttypenotinstalled,h5plib_v126],[editor:contenttypenotinstalled,h5plib_v127]
  CPY [editor:contenttypenotinstalleddesc,h5plib_v126],[editor:contenttypenotinstalleddesc,h5plib_v127]
  CPY [editor:contenttypeowner,h5plib_v126],[editor:contenttypeowner,h5plib_v127]
  CPY [editor:contenttyperestricted,h5plib_v126],[editor:contenttyperestricted,h5plib_v127]
  CPY [editor:contenttyperestricteddesc,h5plib_v126],[editor:contenttyperestricteddesc,h5plib_v127]
  CPY [editor:contenttypesearchfieldplaceholder,h5plib_v126],[editor:contenttypesearchfieldplaceholder,h5plib_v127]
  CPY [editor:contenttypesectionall,h5plib_v126],[editor:contenttypesectionall,h5plib_v127]
  CPY [editor:contenttypeunsupportedapiversioncontent,h5plib_v126],[editor:contenttypeunsupportedapiversioncontent,h5plib_v127]
  CPY [editor:contenttypeunsupportedapiversiontitle,h5plib_v126],[editor:contenttypeunsupportedapiversiontitle,h5plib_v127]
  CPY [editor:contenttypeupdateavailable,h5plib_v126],[editor:contenttypeupdateavailable,h5plib_v127]
  CPY [editor:contenttypeupdatebuttonlabel,h5plib_v126],[editor:contenttypeupdatebuttonlabel,h5plib_v127]
  CPY [editor:contenttypeupdatesuccess,h5plib_v126],[editor:contenttypeupdatesuccess,h5plib_v127]
  CPY [editor:contenttypeupdatingbuttonlabel,h5plib_v126],[editor:contenttypeupdatingbuttonlabel,h5plib_v127]
  CPY [editor:contenttypeusebuttonlabel,h5plib_v126],[editor:contenttypeusebuttonlabel,h5plib_v127]
  CPY [editor:contributetranslations,h5plib_v126],[editor:contributetranslations,h5plib_v127]
  CPY [editor:copiedbutton,h5plib_v126],[editor:copiedbutton,h5plib_v127]
  CPY [editor:copiedtoclipboard,h5plib_v126],[editor:copiedtoclipboard,h5plib_v127]
  CPY [editor:copybutton,h5plib_v126],[editor:copybutton,h5plib_v127]
  CPY [editor:copytoclipboard,h5plib_v126],[editor:copytoclipboard,h5plib_v127]
  CPY [editor:createcontenttablabel,h5plib_v126],[editor:createcontenttablabel,h5plib_v127]
  CPY [editor:currentmenuselected,h5plib_v126],[editor:currentmenuselected,h5plib_v127]
  CPY [editor:editcopyright,h5plib_v126],[editor:editcopyright,h5plib_v127]
  CPY [editor:editimage,h5plib_v126],[editor:editimage,h5plib_v127]
  CPY [editor:editmode,h5plib_v126],[editor:editmode,h5plib_v127]
  CPY [editor:enteraudiotitle,h5plib_v126],[editor:enteraudiotitle,h5plib_v127]
  CPY [editor:enteraudiourl,h5plib_v126],[editor:enteraudiourl,h5plib_v127]
  CPY [editor:enterfullscreenbuttonlabel,h5plib_v126],[editor:enterfullscreenbuttonlabel,h5plib_v127]
  CPY [editor:entervideotitle,h5plib_v126],[editor:entervideotitle,h5plib_v127]
  CPY [editor:entervideourl,h5plib_v126],[editor:entervideourl,h5plib_v127]
  CPY [editor:errorcalculatingmaxscore,h5plib_v126],[editor:errorcalculatingmaxscore,h5plib_v127]
  CPY [editor:errorcommunicatinghubcontent,h5plib_v126],[editor:errorcommunicatinghubcontent,h5plib_v127]
  CPY [editor:errorcommunicatinghubtitle,h5plib_v126],[editor:errorcommunicatinghubtitle,h5plib_v127]
  CPY [editor:errorheader,h5plib_v126],[editor:errorheader,h5plib_v127]
  CPY [editor:errornotsupported,h5plib_v126],[editor:errornotsupported,h5plib_v127]
  CPY [editor:errorparamsbroken,h5plib_v126],[editor:errorparamsbroken,h5plib_v127]
  CPY [editor:errortoohighversion,h5plib_v126],[editor:errortoohighversion,h5plib_v127]
  CPY [editor:example,h5plib_v126],[editor:example,h5plib_v127]
  CPY [editor:exceedsmax,h5plib_v126],[editor:exceedsmax,h5plib_v127]
  CPY [editor:exitfullscreenbuttonlabel,h5plib_v126],[editor:exitfullscreenbuttonlabel,h5plib_v127]
  CPY [editor:expandcollapse,h5plib_v126],[editor:expandcollapse,h5plib_v127]
  CPY [editor:filetolarge,h5plib_v126],[editor:filetolarge,h5plib_v127]
  CPY [editor:fillinthefieldsbelow,h5plib_v126],[editor:fillinthefieldsbelow,h5plib_v127]
  CPY [editor:gethelp,h5plib_v126],[editor:gethelp,h5plib_v127]
  CPY [editor:h5pfileuploadservererrorcontent,h5plib_v126],[editor:h5pfileuploadservererrorcontent,h5plib_v127]
  CPY [editor:h5pfileuploadservererrortitle,h5plib_v126],[editor:h5pfileuploadservererrortitle,h5plib_v127]
  CPY [editor:h5pfilevalidationfailedcontent,h5plib_v126],[editor:h5pfilevalidationfailedcontent,h5plib_v127]
  CPY [editor:h5pfilevalidationfailedtitle,h5plib_v126],[editor:h5pfilevalidationfailedtitle,h5plib_v127]
  CPY [editor:h5pfilewrongextensioncontent,h5plib_v126],[editor:h5pfilewrongextensioncontent,h5plib_v127]
  CPY [editor:h5pfilewrongextensiontitle,h5plib_v126],[editor:h5pfilewrongextensiontitle,h5plib_v127]
  CPY [editor:height,h5plib_v126],[editor:height,h5plib_v127]
  CPY [editor:hide,h5plib_v126],[editor:hide,h5plib_v127]
  CPY [editor:hideimportantinstructions,h5plib_v126],[editor:hideimportantinstructions,h5plib_v127]
  CPY [editor:hubpanellabel,h5plib_v126],[editor:hubpanellabel,h5plib_v127]
  CPY [editor:illegaldecimalnumber,h5plib_v126],[editor:illegaldecimalnumber,h5plib_v127]
  CPY [editor:imagelightboxprogress,h5plib_v126],[editor:imagelightboxprogress,h5plib_v127]
  CPY [editor:imagelightboxtitle,h5plib_v126],[editor:imagelightboxtitle,h5plib_v127]
  CPY [editor:importantinstructions,h5plib_v126],[editor:importantinstructions,h5plib_v127]
  CPY [editor:insert,h5plib_v126],[editor:insert,h5plib_v127]
  CPY [editor:invalidformat,h5plib_v126],[editor:invalidformat,h5plib_v127]
  CPY [editor:language,h5plib_v126],[editor:language,h5plib_v127]
  CPY [editor:librarymissing,h5plib_v126],[editor:librarymissing,h5plib_v127]
  CPY [editor:licensecandistribute,h5plib_v126],[editor:licensecandistribute,h5plib_v127]
  CPY [editor:licensecanholdliable,h5plib_v126],[editor:licensecanholdliable,h5plib_v127]
  CPY [editor:licensecanmodify,h5plib_v126],[editor:licensecanmodify,h5plib_v127]
  CPY [editor:licensecansublicense,h5plib_v126],[editor:licensecansublicense,h5plib_v127]
  CPY [editor:licensecanusecommercially,h5plib_v126],[editor:licensecanusecommercially,h5plib_v127]
  CPY [editor:licensecannotholdliable,h5plib_v126],[editor:licensecannotholdliable,h5plib_v127]
  CPY [editor:licensedescription,h5plib_v126],[editor:licensedescription,h5plib_v127]
  CPY [editor:licensefetchdetailsfailed,h5plib_v126],[editor:licensefetchdetailsfailed,h5plib_v127]
  CPY [editor:licensemodalsubtitle,h5plib_v126],[editor:licensemodalsubtitle,h5plib_v127]
  CPY [editor:licensemodaltitle,h5plib_v126],[editor:licensemodaltitle,h5plib_v127]
  CPY [editor:licensemustincludecopyright,h5plib_v126],[editor:licensemustincludecopyright,h5plib_v127]
  CPY [editor:licensemustincludelicense,h5plib_v126],[editor:licensemustincludelicense,h5plib_v127]
  CPY [editor:licenseunspecified,h5plib_v126],[editor:licenseunspecified,h5plib_v127]
  CPY [editor:listbelowmin,h5plib_v126],[editor:listbelowmin,h5plib_v127]
  CPY [editor:listexceedsmax,h5plib_v126],[editor:listexceedsmax,h5plib_v127]
  CPY [editor:listlabel,h5plib_v126],[editor:listlabel,h5plib_v127]
  CPY [editor:loading,h5plib_v126],[editor:loading,h5plib_v127]
  CPY [editor:loadingimageeditor,h5plib_v126],[editor:loadingimageeditor,h5plib_v127]
  CPY [editor:logthischange,h5plib_v126],[editor:logthischange,h5plib_v127]
  CPY [editor:loggedchanges,h5plib_v126],[editor:loggedchanges,h5plib_v127]
  CPY [editor:maxscoresemanticsmissing,h5plib_v126],[editor:maxscoresemanticsmissing,h5plib_v127]
  CPY [editor:metadata,h5plib_v126],[editor:metadata,h5plib_v127]
  CPY [editor:metadatasharingandlicensinginfo,h5plib_v126],[editor:metadatasharingandlicensinginfo,h5plib_v127]
  CPY [editor:missingproperty,h5plib_v126],[editor:missingproperty,h5plib_v127]
  CPY [editor:missingtranslation,h5plib_v126],[editor:missingtranslation,h5plib_v127]
  CPY [editor:newchangehasbeenlogged,h5plib_v126],[editor:newchangehasbeenlogged,h5plib_v127]
  CPY [editor:newestfirst,h5plib_v126],[editor:newestfirst,h5plib_v127]
  CPY [editor:nextimage,h5plib_v126],[editor:nextimage,h5plib_v127]
  CPY [editor:nochangeshavebeenlogged,h5plib_v126],[editor:nochangeshavebeenlogged,h5plib_v127]
  CPY [editor:nocontenttypesavailable,h5plib_v126],[editor:nocontenttypesavailable,h5plib_v127]
  CPY [editor:nocontenttypesavailabledesc,h5plib_v126],[editor:nocontenttypesavailabledesc,h5plib_v127]
  CPY [editor:nofollow,h5plib_v126],[editor:nofollow,h5plib_v127]
  CPY [editor:notimageordimensionsfield,h5plib_v126],[editor:notimageordimensionsfield,h5plib_v127]
  CPY [editor:numresults,h5plib_v126],[editor:numresults,h5plib_v127]
  CPY [editor:numberfield,h5plib_v126],[editor:numberfield,h5plib_v127]
  CPY [editor:ok,h5plib_v126],[editor:ok,h5plib_v127]
  CPY [editor:onlynumbers,h5plib_v126],[editor:onlynumbers,h5plib_v127]
  CPY [editor:or,h5plib_v126],[editor:or,h5plib_v127]
  CPY [editor:orderitemdown,h5plib_v126],[editor:orderitemdown,h5plib_v127]
  CPY [editor:orderitemup,h5plib_v126],[editor:orderitemup,h5plib_v127]
  CPY [editor:outofstep,h5plib_v126],[editor:outofstep,h5plib_v127]
  CPY [editor:pasteandreplacebutton,h5plib_v126],[editor:pasteandreplacebutton,h5plib_v127]
  CPY [editor:pasteandreplacefromclipboard,h5plib_v126],[editor:pasteandreplacefromclipboard,h5plib_v127]
  CPY [editor:pastebutton,h5plib_v126],[editor:pastebutton,h5plib_v127]
  CPY [editor:pastecontent,h5plib_v126],[editor:pastecontent,h5plib_v127]
  CPY [editor:pastecontentnotsupported,h5plib_v126],[editor:pastecontentnotsupported,h5plib_v127]
  CPY [editor:pastecontentrestricted,h5plib_v126],[editor:pastecontentrestricted,h5plib_v127]
  CPY [editor:pasteerror,h5plib_v126],[editor:pasteerror,h5plib_v127]
  CPY [editor:pastefromclipboard,h5plib_v126],[editor:pastefromclipboard,h5plib_v127]
  CPY [editor:pastenocontent,h5plib_v126],[editor:pastenocontent,h5plib_v127]
  CPY [editor:pastetoonew,h5plib_v126],[editor:pastetoonew,h5plib_v127]
  CPY [editor:pastetooold,h5plib_v126],[editor:pastetooold,h5plib_v127]
  CPY [editor:popularfirst,h5plib_v126],[editor:popularfirst,h5plib_v127]
  CPY [editor:previousimage,h5plib_v126],[editor:previousimage,h5plib_v127]
  CPY [editor:proceedbuttonlabel,h5plib_v126],[editor:proceedbuttonlabel,h5plib_v127]
  CPY [editor:readless,h5plib_v126],[editor:readless,h5plib_v127]
  CPY [editor:readmore,h5plib_v126],[editor:readmore,h5plib_v127]
  CPY [editor:recentlyusedfirst,h5plib_v126],[editor:recentlyusedfirst,h5plib_v127]
  CPY [editor:reloadbuttonlabel,h5plib_v126],[editor:reloadbuttonlabel,h5plib_v127]
  CPY [editor:removefile,h5plib_v126],[editor:removefile,h5plib_v127]
  CPY [editor:removeimage,h5plib_v126],[editor:removeimage,h5plib_v127]
  CPY [editor:removeitem,h5plib_v126],[editor:removeitem,h5plib_v127]
  CPY [editor:requiredproperty,h5plib_v126],[editor:requiredproperty,h5plib_v127]
  CPY [editor:resettooriginallabel,h5plib_v126],[editor:resettooriginallabel,h5plib_v127]
  CPY [editor:savelabel,h5plib_v126],[editor:savelabel,h5plib_v127]
  CPY [editor:savemetadata,h5plib_v126],[editor:savemetadata,h5plib_v127]
  CPY [editor:screenshots,h5plib_v126],[editor:screenshots,h5plib_v127]
  CPY [editor:scriptmissing,h5plib_v126],[editor:scriptmissing,h5plib_v127]
  CPY [editor:searchresults,h5plib_v126],[editor:searchresults,h5plib_v127]
  CPY [editor:selectfiletoupload,h5plib_v126],[editor:selectfiletoupload,h5plib_v127]
  CPY [editor:selectlibrary,h5plib_v126],[editor:selectlibrary,h5plib_v127]
  CPY [editor:semanticserror,h5plib_v126],[editor:semanticserror,h5plib_v127]
  CPY [editor:show,h5plib_v126],[editor:show,h5plib_v127]
  CPY [editor:showimportantinstructions,h5plib_v126],[editor:showimportantinstructions,h5plib_v127]
  CPY [editor:tabtitlebasicfileupload,h5plib_v126],[editor:tabtitlebasicfileupload,h5plib_v127]
  CPY [editor:tabtitleinputlinkurl,h5plib_v126],[editor:tabtitleinputlinkurl,h5plib_v127]
  CPY [editor:textfield,h5plib_v126],[editor:textfield,h5plib_v127]
  CPY [editor:thecontenttype,h5plib_v126],[editor:thecontenttype,h5plib_v127]
  CPY [editor:thiswillpotentially,h5plib_v126],[editor:thiswillpotentially,h5plib_v127]
  CPY [editor:title,h5plib_v126],[editAMOS END
  or:title,h5plib_v127]
  CPY [editor:toolong,h5plib_v126],[editor:toolong,h5plib_v127]
  CPY [editor:tryagain,h5plib_v126],[editor:tryagain,h5plib_v127]
  CPY [editor:tutorial,h5plib_v126],[editor:tutorial,h5plib_v127]
  CPY [editor:unabletointerpreterror,h5plib_v126],[editor:unabletointerpreterror,h5plib_v127]
  CPY [editor:unabletointerpretsolution,h5plib_v126],[editor:unabletointerpretsolution,h5plib_v127]
  CPY [editor:unknownfieldpath,h5plib_v126],[editor:unknownfieldpath,h5plib_v127]
  CPY [editor:uploadinstructionstitle,h5plib_v126],[editor:uploadinstructionstitle,h5plib_v127]
  CPY [editor:uploadplaceholder,h5plib_v126],[editor:uploadplaceholder,h5plib_v127]
  CPY [editor:uploadsuccess,h5plib_v126],[editor:uploadsuccess,h5plib_v127]
  CPY [editor:uploadtablabel,h5plib_v126],[editor:uploadtablabel,h5plib_v127]
  CPY [editor:uploadvideotitle,h5plib_v126],[editor:uploadvideotitle,h5plib_v127]
  CPY [editor:uploading,h5plib_v126],[editor:uploading,h5plib_v127]
  CPY [editor:uploadingthrobber,h5plib_v126],[editor:uploadingthrobber,h5plib_v127]
  CPY [editor:usedforsearchingreportsandcopyrightinformation,h5plib_v126],[editor:usedforsearchingreportsandcopyrightinformation,h5plib_v127]
  CPY [editor:videoquality,h5plib_v126],[editor:videoquality,h5plib_v127]
  CPY [editor:videoqualitydefaultlabel,h5plib_v126],[editor:videoqualitydefaultlabel,h5plib_v127]
  CPY [editor:videoqualitydescription,h5plib_v126],[editor:videoqualitydescription,h5plib_v127]
  CPY [editor:warningchangebrowsingtoseeresults,h5plib_v126],[editor:warningchangebrowsingtoseeresults,h5plib_v127]
  CPY [editor:warningnocontenttypesinstalled,h5plib_v126],[editor:warningnocontenttypesinstalled,h5plib_v127]
  CPY [editor:warningupdateavailablebody,h5plib_v126],[editor:warningupdateavailablebody,h5plib_v127]
  CPY [editor:warningupdateavailabletitle,h5plib_v126],[editor:warningupdateavailabletitle,h5plib_v127]
  CPY [editor:width,h5plib_v126],[editor:width,h5plib_v127]
AMOS END
2024-09-26 10:35:25 +02:00
Jun Pataleta 81e23f4c02 Merge branch 'MDL-83263-404' of https://github.com/mihailges/moodle into MOODLE_404_STABLE 2024-09-26 16:28:47 +08:00
Michael Pound d8a9c0b987 MDL-79288 block_accessreview: Improve heatmap colour contrast. 2024-09-26 08:10:53 +00:00
Andrew Nicols a89faaf6e5 MDL-83253 core: Ignore invalid components for deprecated cap info
When checking for deprecated capabilty info, if a component is invalid,
skip loading of that component.
2024-09-26 15:17:40 +08:00
Huong Nguyen 881d5fb544 Merge branch 'MDL-62640-404' of https://github.com/meirzamoodle/moodle into MOODLE_404_STABLE 2024-09-26 11:07:20 +07:00
Cameron Ball 3f8ed2a39c MDL-82298 navigation: Update behat tests for theme_classic 2024-09-26 11:14:53 +08:00
Jun Pataleta e1f3a16764 Merge branch 'MDL-83235-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-26 09:25:41 +08:00
Sara Arjona 8cb9876cf8 Merge branch 'MDL-83173-404' of https://github.com/stevandoMoodle/moodle into MOODLE_404_STABLE 2024-09-25 17:11:36 +02:00
Andrew Nicols 24dadc7a7f Merge branch 'MDL-82298-404' of https://github.com/andrewnicols/moodle into MOODLE_404_STABLE 2024-09-25 22:55:25 +08:00
Andrew Nicols 1cc03ca6b9 MDL-82298 navigation: Update behat tests 2024-09-25 22:38:20 +08:00
Karjun Loong 35fd32ffb4 MDL-82298 navigation: Add behat tests for secondary menu navigation 2024-09-25 22:38:20 +08:00
Jose 5a010c604d MDL-82298 navigation: Add setting data-disableactive on moremenu items
This setting will avoid conflicts between checkmark and
bfcache. The removed function added as part of the MDL-77732
is no longer required as the behaviour on the menu items (including the
secondary navigation) is not altered anymore by the menuItemHelper function
(menu_navigation file).
2024-09-25 22:38:19 +08:00
Mihail Geshoski a646166319 MDL-83263 grade: Handle undefined array key on grade override revert 2024-09-25 17:27:13 +08:00
Huong Nguyen 6d65eb3a1f Merge branch 'MDL-72856-M404' of https://github.com/michael-milette/moodle into MOODLE_404_STABLE 2024-09-25 08:58:20 +07:00
Sara Arjona 9a19ddfef4 weekly release 4.4.3+ 2024-09-24 16:51:58 +02:00
Stevani Andolo ffaed1fc50 MDL-83173 course: Fixed overlaps courses cards three dots 2024-09-24 09:51:59 +08:00
Shamim Rezaie 2c111a05ea Merge branch 'MDL-77625_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE 2024-09-24 02:53:19 +10:00
Bas Brands e2712c4065 MDL-70180 theme_boost: Allow form autoselect modal overflow
Co-authored-by: Mikel Martín <mikel@moodle.com>
2024-09-23 15:07:34 +02:00
Paul Holden 6865cf828b MDL-83235 qbank_columnsortorder: correct config retrieval ordering.
There is a unique index on plugin/name, so having a trailing order
clause on value would produce no effect. We also cannot order by
CLOB fields on Oracle, lest it complain loudly.
2024-09-23 08:56:38 +01:00
meirzamoodle 3202109780 MDL-62640 environment: Remove the deprecated slash argument check 2024-09-23 13:04:30 +07:00
Sara Arjona 0cd33e81ce Merge branch 'MDL-81612_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE 2024-09-23 07:36:18 +02:00
Huong Nguyen f5f2e79a72 Merge branch 'MDL-83204-404' of https://github.com/roland04/moodle into MOODLE_404_STABLE 2024-09-23 11:12:45 +07:00
Paul Holden 4a4a42cdce MDL-82580 report_log: preserve filter by individual user. 2024-09-20 20:54:15 +01:00
Paul Holden c36fe51c48 MDL-82581 mod_label: avoid overflowing length of label name. 2024-09-20 19:26:56 +01:00
Sara Arjona 11fc78ed62 weekly release 4.4.3+ 2024-09-20 16:36:04 +02:00
Sara Arjona a635c64779 Merge branch 'install_404_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_404_STABLE 2024-09-20 16:35:58 +02:00
Ilya Tregubov ff4f52ddcf Merge branch 'MDL-82663-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-20 10:17:24 +08:00
Huong Nguyen 3342532dfa Merge branch 'MDL-82740-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-09-20 08:44:20 +07:00
Ilya Tregubov 931ac8545a Merge branch 'MDL-74188-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-20 09:39:37 +08:00
Ilya Tregubov 4eed515242 Merge branch 'MDL-82488-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-20 09:25:13 +08:00
Sara Arjona 32162a7fe4 Merge branch 'MDL-83050-404' of https://github.com/laurentdavid/moodle into MOODLE_404_STABLE 2024-09-19 17:06:05 +02:00
Tim Hunt bc8b2d8b63 MDL-81612 assign: show current value when editing a student's extension
Also, if there is not currently an extension set, the set extension form
will default to whatever is the latest out of the due date, the cut-off date
and midnight tonight (in the server time-zone).
2024-09-19 16:02:12 +01:00
Tim Hunt ba94804e81 MDL-81612 assign: test generation of extensions
Also, some other improvements.

* In Behat you can now use either idnumber of name to identify an
  assignment you are generating things for.
* create_submission generator methods now wants the cmid in $data['cmid']
  not the confusingly named 'assignid'. The old name is accepted, but
  generates a debugging warning. (That will fail the test, but in a way
  that explains how to fix it.)
2024-09-19 16:02:12 +01:00
Jun Pataleta ad913b65ee MDL-82740 core: Check for monologo icons in theme overrides 2024-09-19 20:48:48 +08:00
Paul Holden 90fd319190 MDL-82813 group: correctly format group description property. 2024-09-19 13:44:58 +01:00
Laurent David 289f2b427a MDL-83050 core_courseformat: Fix index highlight for collapsed section
* Collapsed sections on course index is not highlighting the correct
element when scrolling over subelements.
2024-09-19 12:01:02 +02:00
Mikel Martín ae73896f2b MDL-83204 tool_policy: Fix footer link spacing 2024-09-19 11:28:37 +02:00
Mikel Martín 42be864b55 MDL-83204 tool_mobile: Fix footer link spacing 2024-09-19 11:28:36 +02:00
Huong Nguyen 7fbbd368f6 Merge branch 'MDL-83199-404' of https://github.com/mihailges/moodle into MOODLE_404_STABLE 2024-09-19 15:40:30 +07:00
Ilya Tregubov 003d6ee817 Merge branch 'MDL-82909-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-19 15:08:32 +08:00
Ilya Tregubov 084dbef995 Merge branch 'MDL-82494-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-19 14:05:19 +08:00
Andrew Nicols ecceaffca1 MDL-83205 core: Ensure that redis lock expiry is valid
PHP allows the specification of invalid values for `max_execution_time`,
including negative values. These should be normalised the same way that
an empty (unlimited) value is.
2024-09-19 13:36:52 +08:00
Ilya Tregubov b0600e2954 Merge branch 'MDL-81987_404_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_404_STABLE 2024-09-19 12:50:33 +08:00
Huong Nguyen 0df6fd6b43 Merge branch 'MDL-83122-404' of https://github.com/safatshahin/moodle into MOODLE_404_STABLE 2024-09-19 10:39:35 +07:00
Jun Pataleta e66e5955e7 MDL-79628 core: Add upgrade notes for the navigation_cache changes 2024-09-19 11:11:31 +08:00
Jun Pataleta d73ad2127e Merge branch 'MDL-79628-move-navcache-to-muc-feature-MOODLE_404_STABLE' of https://github.com/rajandangi/moodle into MOODLE_404_STABLE 2024-09-19 11:10:06 +08:00
Jun Pataleta fdb513461b Merge branch 'MDL-80965-404-behat-fix' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-09-19 08:41:05 +08:00
AMOS bot 0e69b95fbb Automatically generated installer lang files 2024-09-19 00:09:33 +00:00
Simey Lameze 3792869ef7 MDL-80965 behat: remove wrong tag from step 2024-09-19 07:49:22 +08:00
Sara Arjona a290cc77a3 Merge branch 'MDL-74917-404-wrong-post-actions-list-in-statslib' of https://github.com/melanietreitinger/moodle into MOODLE_404_STABLE 2024-09-18 17:19:14 +02:00
Mihail Geshoski 5ec04e7808 MDL-83199 core: Adjust the padding for the bulk actions content area 2024-09-18 17:30:22 +08:00
Huong Nguyen f129cbbe62 Merge branch 'MDL-81278-404' of https://github.com/mickhawkins/moodle into MOODLE_404_STABLE 2024-09-18 16:08:46 +07:00
Ilya Tregubov 9317b4d86e Merge branch 'MDL-80965-404' of https://github.com/ilyatregubov/moodle into MOODLE_404_STABLE 2024-09-18 15:33:21 +08:00
Ilya Tregubov 86a71669ee MDL-80965 mod_quiz: Code style fixes. 2024-09-18 15:29:49 +08:00
Luca Bösch 76d79b57c4 MDL-80965 mod_quiz: Put back random q category on the question page. 2024-09-18 15:29:49 +08:00
AMOS bot 6aa7832084 Automatically generated installer lang files 2024-09-18 00:07:44 +00:00
Paul Holden fbc8123eb4 MDL-82973 tool_usertours: add missing filelib library require. 2024-09-17 16:49:14 +01:00
Sara Arjona a4dd8fedf0 Merge branch 'MDL-82389-404' of https://github.com/ssj365/moodle into MOODLE_404_STABLE 2024-09-17 17:31:47 +02:00
Julien fc1e46db15 MDL-77625 question restore: test restoring a quiz into a course twice
The verifies that the previous two commits are doing the right thing.
2024-09-17 16:17:36 +01:00
Tim Hunt 26af25312c MDL-77625 question restore: fix restore of existing questions
Continuing from the last commit, the code to restore question
bank entries, versions and questions, was not taking note of
whether the first stage had indentified questions that did not
need to be restored. This is tricky, but the mapping can only be
worked out for questions, but in the backup file, the questions are
inside the question_bank_entries, and versions, so we encounter
those first.

Now, the code just saves the QBE and QV when it encounters them,
and then does all the processing when it gets to the question,
correctly taking note of whether each question should be restored or not.
In cases where a particular question does not need to be restored,
we still set up the corresponding mappings.
2024-09-17 16:17:35 +01:00
Tim Hunt 64c54d9510 MDL-77625 question restore: fix pre-parsing of questions
Restore of categories and questions happens in several phases.
First, the file is scanned for which questions and categories
it contains, to work out if these are new questions which need
to be restored, or if they already exist in the database in a
place that can be used.

That code had not been updated to cope with the Moodle 4.0
versioning changes, so it is updated here (while still keeping
the code to cope with the old backup format.)
2024-09-17 16:17:34 +01:00
Sara Arjona 62c4f8a76c weekly release 4.4.3+ 2024-09-17 15:09:23 +02:00
Safat 237a803050 MDL-83122 core_communication: Fix exception for delete user hook 2024-09-17 16:08:06 +10:00
sam marshall 32ac490e77 MDL-83163 core_course: Fresh install fails if dependency on format
If any plugin had dependency on a course format, Moodle fresh install
showed dependency errors (even though course format exists).
2024-09-16 15:44:25 +01:00
Jun Pataleta 54b01d1943 Merge branch 'MDL-83127-404' of https://github.com/lucaboesch/moodle into MOODLE_404_STABLE 2024-09-16 15:59:01 +08:00
Sara Arjona 8069aeec1e Merge branch 'MDL-82875_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE 2024-09-16 09:44:07 +02:00
Michael Hawkins e715380d4b MDL-81278 core: Update security.txt expiry 2024-09-16 14:50:32 +08:00
Paul Holden 20c681e5f8 MDL-81157 files: consistent repository button styling on small screen. 2024-09-15 11:13:03 +01:00
Paul Holden cfcaf488be MDL-82909 theme_boost: ensure we target immediate loading icon only.
Ignoring those used within inplace editable components in the table.
2024-09-15 11:11:44 +01:00
Paul Holden 2a65efd9a3 MDL-82909 javascript: replace custom loading icon with existing module. 2024-09-15 11:11:44 +01:00
Tim Hunt 46748714da MDL-82875 question export: test for not exporting hidden questions 2024-09-13 16:04:16 +01:00
Vithusha Kethiri 846e242aec MDL-82875 qbank_export: Fix removing hidden questions from the export 2024-09-13 16:04:16 +01:00
Sara Arjona 49d8babe8b weekly release 4.4.3+ 2024-09-13 13:20:49 +02:00
Sara Arjona 5102249c52 Merge branch 'install_404_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_404_STABLE 2024-09-13 13:20:45 +02:00
Luca Bösch 37f5141f60 MDL-83127 qtype_ordering: handle NULL in question_hints table entries. 2024-09-13 12:07:57 +02:00
Paul Holden b9e73bd65e MDL-83094 customfield: align persistent definitions with DB schema.
Where the field/category tables allow nulls, the definition within
each corresponding persistent should match.
2024-09-12 17:36:59 +01:00
Melanie Treitinger 4a0cb6e1b5 MDL-74917 core: fix typo in function stats_get_post_actions
Fix phpunit test and apply coding guidelines.
2024-09-12 10:53:16 +02:00
Paul Holden bfe4d189cb MDL-82602 webservice: correct config link to enable for mobile. 2024-09-12 08:05:06 +01:00
Jun Pataleta 4058934644 Merge branch 'mdl-83046_404' of https://github.com/james-cnz/moodle into MOODLE_404_STABLE 2024-09-12 13:40:33 +08:00
Huong Nguyen ca8e5915e6 Merge branch 'MDL-82545_404_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_404_STABLE 2024-09-12 10:46:52 +07:00
Huong Nguyen 2247cd68a4 Merge branch 'MDL-82959-MOODLE_404_STABLE' of https://github.com/sh-csg/moodle into MOODLE_404_STABLE 2024-09-12 10:35:11 +07:00
james-cnz 36c8faede8 MDL-83046 course: Add non-delegated sections before delegated ones 2024-09-12 12:11:31 +12:00
AMOS bot 31e1e17590 Automatically generated installer lang files 2024-09-12 00:07:43 +00:00
Shamiso.Jaravaza d79acfdd59 MDL-82389 mod_bigbluebuttonbn: Fix disablenotes 2024-09-11 09:34:34 -06:00
Huong Nguyen bc1324af4d Merge branch 'MDL-68676-404' of https://github.com/rhell4/moodle into MOODLE_404_STABLE 2024-09-11 15:50:10 +07:00
Huong Nguyen 367d1c7cb7 Merge branch 'MDL-75692-404' of https://github.com/laurentdavid/moodle into MOODLE_404_STABLE 2024-09-11 15:45:21 +07:00
Jun Pataleta 8346e2b912 Merge branch 'MDL-82270-extra_backslash-404' of https://github.com/mathbruyen/moodle into MOODLE_404_STABLE 2024-09-11 15:53:46 +08:00
Jun Pataleta 09274be2e0 Merge branch 'MDL-82492-404' of https://github.com/vladaskidanovas/moodle into MOODLE_404_STABLE 2024-09-11 15:36:45 +08:00
Huong Nguyen d8f262e0b5 Merge branch 'MDL-79020-404' of https://github.com/ferranrecio/moodle into MOODLE_404_STABLE 2024-09-11 09:19:22 +07:00
AMOS bot 692f8031bf Automatically generated installer lang files 2024-09-11 00:07:49 +00:00
Huong Nguyen f86b97fdd6 weekly release 4.4.3+ 2024-09-10 20:03:01 +07:00
Laurent David faf0e0654d MDL-75692 core_h5p: Debounce resize events
* Make sure that we don't call the resize event too often to
avoid infinite loop when content is auto resizing (fonts for example)
2024-09-10 11:32:00 +02:00
Huong Nguyen bc3050ad0c Merge branch 'MDL-83047-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-09-10 10:47:24 +07:00
Huong Nguyen 2412b1278b Merge branch 'MDL-83038-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-10 09:34:28 +07:00
Jun Pataleta cb6904b002 MDL-83047 theme_boost: Add upgrade note for theme plugins 2024-09-10 10:33:30 +08:00
Sara Arjona 2cf32c40e9 Merge branch 'MDL-83037-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-09 17:21:59 +02:00
Jun Pataleta a4ee77a654 MDL-83047 theme_boost: Apply background colour only on select layouts
* Apply the styling of `background-color` for `.page-header-headings`
only in the maintenance and secure layouts.
2024-09-09 17:01:11 +08:00
Huong Nguyen 15e04d6651 Merge branch 'MDL-82860-404' of https://github.com/meirzamoodle/moodle into MOODLE_404_STABLE 2024-09-09 14:32:20 +07:00
meirzamoodle 8ccba0808b MDL-82860 atto_link: Set value as default to avoid unexpected behaviour 2024-09-09 08:11:56 +07:00
Jun Pataleta 9ecb8de2bb weekly release 4.4.3+ 2024-09-07 06:45:35 +08:00
Stefan Hanauska 851c6d00b6 MDL-82959 tool_recyclebin: Avoid null value for forcedsettings 2024-09-06 19:47:31 +02:00
Paul Holden 864bbf86db MDL-83038 mod_quiz: use dummy URL in quiz grading page external call. 2024-09-06 12:26:11 +01:00
Paul Holden 08127c83a7 MDL-83037 badges: ensure image is specified in Behat test generator. 2024-09-06 11:25:35 +01:00
ferranrecio c4f9163dc0 MDL-79020 core_courseformat: hide completion edit link in bulk edit 2024-09-06 11:11:16 +02:00
Jun Pataleta dfaa31d4f0 Merge branch 'MDL-63399-404' of https://github.com/lameze/moodle into MOODLE_404_STABLE 2024-09-06 12:29:21 +08:00
Simey Lameze f62ef26f37 MDL-63399 behat: update existing tests to use the better download steps
Co-authored-by: Tim Hunt <T.J.Hunt@open.ac.uk>
2024-09-06 12:14:33 +08:00
Simey Lameze 3dc10958bc MDL-63399 behat: new steps to verify downloads
Co-authored-by: Tim Hunt <T.J.Hunt@open.ac.uk>
2024-09-06 12:06:44 +08:00
Huong Nguyen 7901350509 Merge branch 'MDL-82948-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-09-06 11:01:14 +07:00
Huong Nguyen 298810e993 Merge branch 'MDL-82677-404' of https://github.com/junpataleta/moodle into MOODLE_404_STABLE 2024-09-06 10:50:55 +07:00
rajandangi 3c04cc40d0 MDL-79628 navigation: Refactor navigation_cache to use MUC 2024-09-06 09:44:47 +09:30
Huong Nguyen 125db05313 Merge branch 'MDL-80946_MOODLE_404_STABLE' of https://github.com/michaelkotlyar/moodle into MOODLE_404_STABLE 2024-09-05 15:53:59 +07:00
Michael Kotlyar c34b5f79cd MDL-80946 quizaccess_seb: Remove invalidkeys text if not using SEB. 2024-09-05 09:07:38 +01:00
Huong Nguyen e4b96893b8 Merge branch 'MDL-81909-404' of https://github.com/rezaies/moodle into MOODLE_404_STABLE 2024-09-05 14:49:53 +07:00
Shamim Rezaie 452d92d9bb MDL-81909 mod_assign: fix test_attempt_reopen_method_untilpass 2024-09-05 03:27:03 +10:00
Michael Milette e55e9974b8 MDL-72856 lib: Only inject one robots/noindex in head of Additional HTML 2024-09-04 12:32:01 -04:00
Sara Arjona fd5c2b3aa4 Merge branch 'MDL-82995_MOODLE_404_STABLE_feedback_broken_audio_video' of https://github.com/JordanKrauseDE/moodle into MOODLE_404_STABLE 2024-09-04 12:59:10 +02:00
JordanKrauseDE 1fd5899e70 MDL-82995 feedback: fixed audio and video width 2024-09-04 09:27:40 +02:00
Huong Nguyen b9a191dda8 Merge branch 'MDL-80225-404' of https://github.com/ssj365/moodle into MOODLE_404_STABLE 2024-09-04 09:30:04 +07:00
Paul Holden 89506cd08d MDL-80929 customfield: observe backup/restore settings to include. 2024-09-03 13:56:27 +01:00
Paul Holden e8c5f37306 MDL-80929 restore: consistent settings definition for custom fields. 2024-09-03 13:49:56 +01:00
Jun Pataleta 6a7b69a30a weekly release 4.4.3+ 2024-09-03 20:05:13 +08:00
Mathieu Bruyen ddbc161632 MDL-82270 tool_policy: fix guest policy template markup.
Remove extra backslash producing invalid markup in consent banner.
2024-09-03 09:47:28 +02:00
Jun Pataleta 4b6b859ca0 Merge branch 'MDL-82957-404' of https://github.com/roland04/moodle into MOODLE_404_STABLE 2024-09-03 11:42:24 +08:00
Jun Pataleta 66896b275a Merge branch 'MDL-82804-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-03 10:32:18 +08:00
Jun Pataleta 2558c6a9b9 Merge branch 'MDL-82717-404' of https://github.com/liamgm/moodle into MOODLE_404_STABLE 2024-09-03 10:29:25 +08:00
Jun Pataleta 890f2e7c57 MDL-82255 editor_tiny: No need for extra styles for RTL 2024-09-02 16:55:53 +08:00
Jun Pataleta eb05d37e5b Merge branch 'MDL-82255-404' of https://github.com/raortegar/moodle into MOODLE_404_STABLE 2024-09-02 16:01:50 +08:00
Ilya Tregubov b85b5dd74e Merge branch 'MDL-82220-404' of https://github.com/paulholden/moodle into MOODLE_404_STABLE 2024-09-02 10:10:03 +08:00
Paul Holden 230831bc70 MDL-82494 user: correct profile field name formatting method.
Add optional `$escape` parameter to allow for unescaped return.
2024-08-30 09:48:08 +01:00
Paul Holden 60e11dc998 MDL-82488 customfield: allow for unescaped field formatted names.
Resolves double encoding of the same in Report builder editor.
2024-08-30 09:44:41 +01:00
Mikel Martín 88730f6a8d MDL-82957 course: Fix section bulk actions alignment 2024-08-30 09:14:19 +02:00
Paul Holden cd69894e95 MDL-82804 badges: define no results notice inside report instances.
When doing so from calling code, the property is not persisted when
filtering/paging (or any AJAX interaction); instead, it should be
set from within the report instance itself.
2024-08-29 16:37:58 +01:00
Paul Holden c83eaf4066 MDL-82483 tag: update the max length constant to match schema. 2024-08-29 10:38:00 +01:00
Liam Moran e78fe25155 MDL-82717 enrol_lti: Make contextmembershipsurl property immutable
The contextmembershipsurl property on the nrsp_info object is itself
an object of type moodle_url so its getter should return a copy
of the moodle_url object instead of a reference to the class-internal
object. This commit adds a test for get_context_memberships_url and
updates the getter so the property is immutable.
2024-08-29 03:44:54 -05:00
Jun Pataleta 5f1db200b1 MDL-82948 theme_boost: Make <blockquote>'s border a bit darker 2024-08-29 16:04:31 +08:00
raortegar c5ef86c3bf MDL-82255 editor_tiny: Style blockquote in editor 2024-08-29 09:20:46 +02:00
Stefan Hanauska faac67e2ea MDL-80974 enrol: Set category context for enrol form 2024-08-28 12:33:40 +02:00
Paul Holden 8caac3da44 MDL-82663 user: fix check for current user removing own enrolment.
We only need to remove the current user from selection if they were
ever part of the selection originally.
2024-08-27 16:55:20 +01:00
Mark Johnson 67674462dd MDL-82545 gradereport_grader: Limit grades per page
This replaces the limit on the number of students per page with a number
of grades per page, to take into account the number of grade items on a
course.
2024-08-22 11:04:20 +01:00
Shamiso.Jaravaza f354ba61e6 MDL-80225 mod_bigbluebuttonbn: Fix missing recordings 2024-08-21 21:02:54 -06:00
Justus Dieckmann a7f5c1eb05 MDL-82838 tool_mfa: Prevent accidental resubmission of token 2024-08-20 16:44:24 +02:00
vlad.kidanov 1ba60572b3 MDL-82492 gradereport_grader: Grader report HTML output optimization 2024-08-20 10:34:29 +01:00
Paul Holden c804789bbb MDL-74188 notes: consistent formatting of text content.
Each method of adding notes, either via UI or external service (via
course participant actions), defined the format of the content
different from one another. Neither of those formats were correct.
2024-08-16 10:20:01 +01:00
Paul Holden ddd99c03d2 MDL-82220 group: check valid mapping when restoring custom fields. 2024-08-16 10:09:04 +01:00
Paul Holden 8aa860d7b7 MDL-82220 backup: ensure correct group/ing custom fields are included.
We should include only the custom field values that belong to those
groups and/or groupings that are being backed up.
2024-08-16 10:09:04 +01:00
Mark Johnson b5519852fc MDL-81987 redis: Set connection and read timeouts to 10 seconds
This allows the site to continue operating in case of degraded
performance, rather than throwing exceptions.
2024-08-08 13:17:03 +01:00
Jun Pataleta 731e8a1e01 MDL-82677 theme: Set a background colour for page heading
* Set a background colour for the .page-header-headings class.
* Assign the .page-header-headings class to the maintenance mode
template's page header div.
2024-08-02 17:25:21 +08:00
Rossco Hellmans 375c921a69 MDL-68676 mod_assign: check accessallgroups in can_edit_submission()
In can_edit_submission() when the assign group mode is SEPARATEGROUPS
check if the user has the moodle/site:accessallgroups capability before
checking if they are a shared groupmember. Due to the teamsubmission
setting students might not be in a group but can still submit, which
means they are not returned in get_shared_group_members().
2024-06-22 13:44:59 +10:00
1512 changed files with 20780 additions and 22268 deletions
+195
View File
@@ -4703,4 +4703,199 @@
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="5.0" 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" />
<VENDOR name="oracle" version="19" />
</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_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_oracle_usage" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_async_backup" level="recommended">
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+1 -1
View File
@@ -180,7 +180,7 @@ class generator_test extends \advanced_testcase {
*
* @return array
*/
public function create_preset_provider(): array {
public static function create_preset_provider(): array {
return [
'Default values' => [
],
+6 -6
View File
@@ -84,7 +84,7 @@ class helper_test extends \advanced_testcase {
*
* @return array
*/
public function create_preset_provider(): array {
public static function create_preset_provider(): array {
return [
'Default values' => [
],
@@ -177,7 +177,7 @@ class helper_test extends \advanced_testcase {
*
* @return array
*/
public function add_item_provider(): array {
public static function add_item_provider(): array {
return [
'Setting without plugin' => [
'name' => 'settingname',
@@ -239,7 +239,7 @@ class helper_test extends \advanced_testcase {
*
* @return array
*/
public function add_plugin_provider(): array {
public static function add_plugin_provider(): array {
return [
'Plugin: enabled (using int)' => [
'type' => 'plugintype',
@@ -321,7 +321,7 @@ class helper_test extends \advanced_testcase {
*
* @return array
*/
public function change_default_preset_provider(): array {
public static function change_default_preset_provider(): array {
return [
'Starter preset' => [
'preset' => 'starter',
@@ -364,7 +364,7 @@ class helper_test extends \advanced_testcase {
'preset' => 'unexisting',
],
'Valid XML file' => [
'preset' => __DIR__ . '/fixtures/import_settings_plugins.xml',
'preset' => self::get_fixture_path(__NAMESPACE__, 'import_settings_plugins.xml'),
'settings' => [
'allowemojipicker' => 1,
'enableportfolios' => 1,
@@ -377,7 +377,7 @@ class helper_test extends \advanced_testcase {
],
],
'Invalid XML file' => [
'preset' => __DIR__ . '/fixtures/invalid_xml_file.xml',
'preset' => self::get_fixture_path(__NAMESPACE__, 'invalid_xml_file.xml'),
],
'Unexisting XML file' => [
'preset' => __DIR__ . '/fixtures/unexisting.xml',
@@ -72,7 +72,7 @@ class adminpresets_admin_setting_bloglevel_test extends \advanced_testcase {
*
* @return array
*/
public function save_value_provider(): array {
public static function save_value_provider(): array {
return [
'Save the bloglevel and set blog_menu block visibility to true' => [
'setttingvalue' => BLOG_USER_LEVEL,
@@ -66,7 +66,7 @@ class adminpresets_admin_setting_sitesettext_test extends \advanced_testcase {
*
* @return array
*/
public function save_value_provider(): array {
public static function save_value_provider(): array {
return [
'Fullname: different value' => [
'settingname' => 'fullname',
@@ -77,7 +77,7 @@ class adminpresets_setting_test extends \advanced_testcase {
*
* @return array
*/
public function save_value_provider(): array {
public static function save_value_provider(): array {
return [
'Core setting with the same value is not saved' => [
'category' => 'optionalsubsystems',
@@ -167,7 +167,7 @@ class adminpresets_setting_test extends \advanced_testcase {
*
* @return array
*/
public function save_attributes_values_provider(): array {
public static function save_attributes_values_provider(): array {
return [
'Plugin setting with the same value is not saved' => [
'category' => 'modsettinglesson',
+23 -9
View File
@@ -367,7 +367,7 @@ class manager_test extends \advanced_testcase {
*
* @return array
*/
public function export_preset_provider(): array {
public static function export_preset_provider(): array {
return [
'Export settings and plugins, excluding sensible' => [
'includesensible' => false,
@@ -530,26 +530,32 @@ class manager_test extends \advanced_testcase {
*
* @return array
*/
public function import_preset_provider(): array {
public static function import_preset_provider(): array {
return [
'Import settings from an empty file' => [
'filecontents' => '',
'expectedpreset' => false,
],
'Import settings and plugins from a valid XML file' => [
'filecontents' => file_get_contents(__DIR__ . '/fixtures/import_settings_plugins.xml'),
'filecontents' => file_get_contents(
filename: self::get_fixture_path(__NAMESPACE__, 'import_settings_plugins.xml')
),
'expectedpreset' => true,
'expectedsettings' => true,
'expectedplugins' => true,
],
'Import only settings from a valid XML file' => [
'filecontents' => file_get_contents(__DIR__ . '/fixtures/import_settings.xml'),
'filecontents' => file_get_contents(
filename: self::get_fixture_path(__NAMESPACE__, 'import_settings.xml')
),
'expectedpreset' => true,
'expectedsettings' => true,
'expectedplugins' => false,
],
'Import settings and plugins from a valid XML file with Starter name, which will be marked as non-core' => [
'filecontents' => file_get_contents(__DIR__ . '/fixtures/import_starter_name.xml'),
'filecontents' => file_get_contents(
filename: self::get_fixture_path(__NAMESPACE__, 'import_starter_name.xml')
),
'expectedpreset' => true,
'expectedsettings' => true,
'expectedplugins' => true,
@@ -558,7 +564,9 @@ class manager_test extends \advanced_testcase {
'expectedpresetname' => 'Starter',
],
'Import settings from an invalid XML file' => [
'filecontents' => file_get_contents(__DIR__ . '/fixtures/invalid_xml_file.xml'),
'filecontents' => file_get_contents(
filename: self::get_fixture_path(__NAMESPACE__, 'invalid_xml_file.xml')
),
'expectedpreset' => false,
'expectedsettings' => false,
'expectedplugins' => false,
@@ -566,20 +574,26 @@ class manager_test extends \advanced_testcase {
'expectedexception' => \Exception::class,
],
'Import unexisting settings category' => [
'filecontents' => file_get_contents(__DIR__ . '/fixtures/unexisting_category.xml'),
'filecontents' => file_get_contents(
filename: self::get_fixture_path(__NAMESPACE__, 'unexisting_category.xml')
),
'expectedpreset' => false,
'expectedsettings' => false,
'expectedplugins' => false,
],
'Import unexisting setting' => [
'filecontents' => file_get_contents(__DIR__ . '/fixtures/unexisting_setting.xml'),
'filecontents' => file_get_contents(
filename: self::get_fixture_path(__NAMESPACE__, 'unexisting_setting.xml')
),
'expectedpreset' => false,
'expectedsettings' => false,
'expectedplugins' => false,
'expecteddebugging' => true,
],
'Import valid settings with one unexisting setting too' => [
'filecontents' => file_get_contents(__DIR__ . '/fixtures/import_settings_with_unexisting_setting.xml'),
'filecontents' => file_get_contents(
filename: self::get_fixture_path(__NAMESPACE__, 'import_settings_with_unexisting_setting.xml'),
),
'expectedpreset' => true,
'expectedsettings' => false,
'expectedplugins' => false,
+2 -2
View File
@@ -874,8 +874,8 @@ class core_admin_renderer extends plugin_renderer_base {
protected function mobile_configuration_warning($mobileconfigured) {
$output = '';
if (!$mobileconfigured) {
$settingslink = new moodle_url('/admin/settings.php', ['section' => 'mobilesettings']);
$configurebutton = $this->single_button($settingslink, get_string('enablemobilewebservice', 'admin'));
$settingslink = new moodle_url('/admin/search.php', ['query' => 'enablemobilewebservice']);
$configurebutton = $this->single_button($settingslink, get_string('enablemobilewebservice', 'admin'), 'get');
$output .= $this->warning(get_string('mobilenotconfiguredwarning', 'admin') . '&nbsp;' . $configurebutton);
}
+1 -1
View File
@@ -84,7 +84,7 @@ class preset_test extends \advanced_testcase {
public function test_mixed_levels(): void {
// The problem here is that we cannot guarantee plugin contexts
// have unique short names, so we have to also support level numbers.
$xml = file_get_contents(__DIR__ . '/fixtures/mixed_levels.xml');
$xml = file_get_contents(self::get_fixture_path(__NAMESPACE__, 'mixed_levels.xml'));
$this->assertTrue(\core_role_preset::is_valid_preset($xml));
$preset = \core_role_preset::parse_preset($xml);
+24 -1
View File
@@ -420,6 +420,12 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
new lang_string('generalgroups', 'backup'), new lang_string('configgeneralgroups', 'backup'),
array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_competencies', new lang_string('generalcompetencies','backup'), new lang_string('configgeneralcompetencies','backup'), array('value'=>1, 'locked'=>0)));
$temp->add(new admin_setting_configcheckbox_with_lock(
'backup/backup_general_customfield',
new lang_string('generalcustomfield', 'backup'),
new lang_string('configgeneralcustomfield', 'backup'),
['value' => 1, 'locked' => 0],
));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_contentbankcontent',
new lang_string('generalcontentbankcontent', 'backup'),
new lang_string('configgeneralcontentbankcontent', 'backup'),
@@ -431,7 +437,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)));
@@ -460,6 +465,12 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
new lang_string('generalgroups', 'backup'), new lang_string('configgeneralgroups', 'backup'),
array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_competencies', new lang_string('generalcompetencies','backup'), new lang_string('configgeneralcompetencies','backup'), array('value'=>1, 'locked'=>0)));
$temp->add(new admin_setting_configcheckbox_with_lock(
'backup/backup_import_customfield',
new lang_string('generalcustomfield', 'backup'),
new lang_string('configgeneralcustomfield', 'backup'),
['value' => 1, 'locked' => 0],
));
$temp->add(new admin_setting_configcheckbox_with_lock(
'backup/backup_import_contentbankcontent',
new lang_string('generalcontentbankcontent', 'backup'),
@@ -589,6 +600,12 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_groups', new lang_string('generalgroups', 'backup'),
new lang_string('configgeneralgroups', 'backup'), 1));
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_competencies', new lang_string('generalcompetencies','backup'), new lang_string('configgeneralcompetencies','backup'), 1));
$temp->add(new admin_setting_configcheckbox(
'backup/backup_auto_customfield',
new lang_string('generalcustomfield', 'backup'),
new lang_string('configgeneralcustomfield', 'backup'),
1,
));
$temp->add(new admin_setting_configcheckbox(
'backup/backup_auto_contentbankcontent',
new lang_string('generalcontentbankcontent', 'backup'),
@@ -668,6 +685,12 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_competencies',
new lang_string('generalcompetencies', 'backup'),
new lang_string('configrestorecompetencies', 'backup'), array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock(
'restore/restore_general_customfield',
new lang_string('generalcustomfield', 'backup'),
new lang_string('configrestorecustomfield', 'backup'),
['value' => 1, 'locked' => 0],
));
$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)));
+1 -1
View File
@@ -85,7 +85,7 @@ class set_block_protection_test extends \externallib_advanced_testcase {
*
* @return array
*/
public function execute_provider(): array {
public static function execute_provider(): array {
return [
[
'block_login',
+2 -2
View File
@@ -72,7 +72,7 @@ class set_plugin_order_test extends \externallib_advanced_testcase {
*
* @return array
*/
public function execute_editor_provider(): array {
public static function execute_editor_provider(): array {
$pluginmanager = \core_plugin_manager::instance();
$allplugins = array_keys($pluginmanager->get_plugins_of_type('editor'));
@@ -142,7 +142,7 @@ class set_plugin_order_test extends \externallib_advanced_testcase {
$this->assertIsArray(set_plugin_order::execute($plugin, 1));
}
public function execute_non_orderable_provider(): array {
public static function execute_non_orderable_provider(): array {
return [
// Activities do not support ordering.
['mod_assign'],
+1 -1
View File
@@ -66,7 +66,7 @@ class set_plugin_state_test extends \externallib_advanced_testcase {
*
* @return array
*/
public function execute_standard_provider(): array {
public static function execute_standard_provider(): array {
$generatetestsfor = function (string $plugin): array {
return [
[
@@ -110,7 +110,7 @@ class task_logs_test extends core_reportbuilder_testcase {
*
* @return array[]
*/
public function datasource_filters_provider(): array {
public static function datasource_filters_provider(): array {
return [
'Filter name' => ['task_log:name', [
'task_log:name_values' => [send_schedules::class],
@@ -5,16 +5,18 @@ Feature: I can download a preset
| name |
| Custom preset |
@javascript
Scenario: Custom preset settings can be downloaded
Given I log in as "admin"
And I navigate to "Site admin presets" in site administration
When I open the action menu in "Custom preset" "table_row"
Then following "Download" "link" in the "Custom preset" "table_row" should download between "0" and "5000" bytes
Then following "Download" in the "Custom preset" "table_row" should download a file that:
| Has mimetype | text/xml |
| Contains text in xml element | Custom preset |
@javascript
Scenario: Core preset settings can be downloaded
Given I log in as "admin"
And I navigate to "Site admin presets" in site administration
When I open the action menu in "Starter" "table_row"
Then following "Download" "link" in the "Starter" "table_row" should download between "0" and "5000" bytes
Then following "Download" in the "Starter" "table_row" should download a file that:
| Has mimetype | text/xml |
| Contains text in xml element | Starter |
@@ -70,7 +70,7 @@ class base_test extends \advanced_testcase {
*
* @return array
*/
public function log_provider(): array {
public static function log_provider(): array {
return [
// Action = base.
'action=base and mode = show' => [
@@ -156,7 +156,7 @@ class export_test extends \advanced_testcase {
*
* @return array
*/
public function export_execute_provider(): array {
public static function export_execute_provider(): array {
return [
'Export settings and plugins, excluding sensible' => [
'includesensible' => false,
@@ -190,7 +190,7 @@ class import_test extends \advanced_testcase {
*
* @return array
*/
public function import_execute_provider(): array {
public static function import_execute_provider(): array {
$fixturesfolder = __DIR__ . '/../../../../../presets/tests/fixtures/';
return [
@@ -0,0 +1,61 @@
@tool @tool_behat
Feature: Frozen clock in Behat
In order to write tests that depend on the current system time
As a test writer
I need to set the time using a Behat step
Background:
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "activities" exist:
| activity | course | name | idnumber | externalurl |
| url | C1 | Fixture | url1 | #wwwroot#/admin/tool/behat/tests/fixtures/core/showtime.php |
| forum | C1 | TestForum | forum1 | |
Scenario: Time has been frozen
# Set up 2 forum discussions at different times. This tests the clock in the Behat CLI process.
Given the time is frozen at "2024-03-01 12:34:56"
And the following "mod_forum > discussions" exist:
| user | forum | name | message |
| admin | forum1 | Subject1 | Message1 |
And the time is frozen at "2024-08-01 12:34:56"
And the following "mod_forum > discussions" exist:
| user | forum | name | message |
| admin | forum1 | Subject2 | Message2 |
When I am on the "TestForum" "forum activity" page logged in as admin
Then I should see "1 Mar 2024" in the "Subject1" "table_row"
And I should see "1 Aug 2024" in the "Subject2" "table_row"
# Also view time on the fixture page. This tests the clock for Behat web server requests.
And I am on the "Fixture" "url activity" page
And I should see "Behat time is not the same as real time"
# This Unix time corresponds to 12:34:56 in Perth time zone.
And I should see "Unix time 1722486896"
And I should see "Date-time 2024-08-01 12:34:56"
# This scenario is second, to verify that the clock automatically goes back to normal after test.
Scenario: Time is normal
Given the following "mod_forum > discussions" exist:
| user | forum | name | message |
| admin | forum1 | Subject1 | Message1 |
When I am on the "TestForum" "forum activity" page logged in as admin
# The time should be the real current time, not the frozen time.
Then I should see "## today ##%d %b %Y##" in the "Subject1" "table_row"
And I am on the "Fixture" "url activity" page
And I should see "Behat time is the same as real time"
Scenario: Time is frozen and then unfrozen
Given the time is frozen at "2024-03-01 12:34:56"
And the following "mod_forum > discussions" exist:
| user | forum | name | message |
| admin | forum1 | Subject1 | Message1 |
And the time is no longer frozen
And the following "mod_forum > discussions" exist:
| user | forum | name | message |
| admin | forum1 | Subject2 | Message2 |
When I am on the "TestForum" "forum activity" page logged in as admin
Then I should see "1 Mar 2024" in the "Subject1" "table_row"
# The time should be the real current time, not the frozen time for this entry.
And I should see "## today ##%d %b %Y##" in the "Subject2" "table_row"
And I am on the "Fixture" "url activity" page
And I should see "Behat time is the same as real time"
+1 -1
View File
@@ -25,7 +25,7 @@ Feature: Confirm that we can open multiple browser tabs
And I open a tab named "CourseViewer4" on the "My courses" page
# Switch between all the tabs and confirm their different contents.
Then I should see "You're not enrolled in any course"
Then I should see "You're not enrolled in any courses."
And I switch to "CourseViewer2" tab
And "Course 3" "heading" should exist
And I switch to "CourseViewer1" tab
@@ -53,7 +53,7 @@ class behat_form_text_test extends \basic_testcase {
*
* @return array of value and expectation pairs to be tested.
*/
public function provider_test_set_get_value() {
public static function provider_test_set_get_value(): array {
return [
'null' => [null, null],
'int' => [3, 3],
@@ -68,7 +68,7 @@ class behat_form_text_test extends \basic_testcase {
*
* @param mixed $value value to be set.
* @param mixed $expectation value to be checked.
* @dataProvider provider_test_set_get_value()
* @dataProvider provider_test_set_get_value
*/
public function test_set_get_value($value, $expectation): void {
$session = $this->createMock(Session::class);
@@ -85,7 +85,7 @@ class behat_form_text_test extends \basic_testcase {
*
* @return array of decsep, value, match and result pairs to be tested.
*/
public function provider_test_matches() {
public static function provider_test_matches(): array {
return [
'lazy true' => ['.', 'hello', 'hello', true],
'lazy false' => ['.', 'hello', 'bye', false],
@@ -113,7 +113,7 @@ class behat_form_text_test extends \basic_testcase {
* @param mixed $value value to be set.
* @param mixed $match value to be matched.
* @param bool $result expected return status of the function.
* @dataProvider provider_test_matches()
* @dataProvider provider_test_matches
*/
public function test_matches($decsep, $value, $match, $result): void {
global $CFG;
+52
View File
@@ -0,0 +1,52 @@
<?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/>.
/**
* Fixture to show the current server time using \core\clock.
*
* @package tool_behat
* @copyright 2024 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// phpcs:disable moodle.Files.RequireLogin.Missing
require(__DIR__ . '/../../../../../../config.php');
defined('BEHAT_SITE_RUNNING') || die('Behat fixture');
$PAGE->set_context(\context_system::instance());
$PAGE->set_url(new \moodle_url('/admin/tool/behat/tests/fixtures/core/showtime.php'));
echo $OUTPUT->header();
$clock = \core\di::get(\core\clock::class);
$dt = $clock->now();
$realbefore = time();
$time = $clock->time();
$realafter = time();
echo html_writer::div('Unix time ' . $time);
echo html_writer::div('Date-time ' . $dt->format('Y-m-d H:i:s'));
echo html_writer::div('TZ ' . $dt->getTimezone()->getName());
if ($time >= $realbefore && $time <= $realafter) {
echo html_writer::div('Behat time is the same as real time');
} else {
echo html_writer::div('Behat time is not the same as real time');
}
echo $OUTPUT->footer();
+5 -5
View File
@@ -107,11 +107,11 @@ class manager_util_test extends \advanced_testcase {
*/
private function get_behat_config_util($behatconfigutil, $notheme = false) {
// Create a map of arguments to return values.
$map = array(
array('withfeatures', __DIR__.'/fixtures/theme/withfeatures'),
array('nofeatures', __DIR__.'/fixtures/theme/nofeatures'),
array('defaulttheme', __DIR__.'/fixtures/theme/defaulttheme'),
);
$map = [
['withfeatures', self::get_fixture_path(__NAMESPACE__, 'theme/withfeatures')],
['nofeatures', self::get_fixture_path(__NAMESPACE__, 'theme/nofeatures')],
['defaulttheme', self::get_fixture_path(__NAMESPACE__, 'theme/defaulttheme')],
];
// List of themes is const for test.
if ($notheme) {
$themelist = array('defaulttheme');
@@ -410,13 +410,13 @@ class brickfield_accessibility_color_test extends brickfield_accessibility_test
$pos3 = stripos($fontsize, 'px');
if ($pos1 !== false) {
$rem = substr($fontsize, 0, -3);
$newfontsize = $newfontsize * $rem;
$newfontsize = is_numeric($rem) ? $newfontsize * $rem : $newfontsize;
} else if ($pos2 !== false) {
$em = substr($fontsize, 0, -2);
$newfontsize = $newfontsize * $em;
$newfontsize = is_numeric($em) ? $newfontsize * $em : $newfontsize;
} else if ($pos3 !== false) {
$px = substr($fontsize, 0, -2);
$newfontsize = 0.75 * $px;
$newfontsize = is_numeric($px) ? 0.75 * $px : $newfontsize;
} else if (in_array($fontsize, array_keys($this->fontsizenames))) {
$newfontsize = $this->fontsizenames[$fontsize];
} else {
@@ -16,7 +16,7 @@
namespace tool_brickfield\local\htmlchecker\common\checks;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_tag_test;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_test;
/**
* Brickfield accessibility HTML checker library.
@@ -28,11 +28,25 @@ use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_tag_test;
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class i_is_not_used extends brickfield_accessibility_tag_test {
class i_is_not_used extends brickfield_accessibility_test {
/** @var int The default severity code for this test. */
public $defaultseverity = \tool_brickfield\local\htmlchecker\brickfield_accessibility::BA_TEST_SEVERE;
/** @var string The tag this test will fire on. */
public $tag = 'i';
/**
* Check for any i elements and flag them as errors
* while allowing font awesome icons to be used.
*/
public function check(): void {
foreach ($this->get_all_elements('i') as $element) {
// Ensure this is not a font awesome icon with aria-hidden.
if (str_contains($element->getAttribute('class'), 'fa-') && $element->getAttribute('aria-hidden') === 'true') {
continue;
}
$this->add_report($element);
}
}
}
@@ -46,7 +46,7 @@ class table_data_should_have_th extends brickfield_accessibility_table_test {
foreach ($tr->childNodes as $th) {
if ($this->property_is_equal($th, 'tagName', 'th')) {
break 3;
} else {
} else if ($th->nodeName != '#text') {
$this->add_report($table);
break 3;
}
@@ -57,7 +57,7 @@ class table_data_should_have_th extends brickfield_accessibility_table_test {
foreach ($child->childNodes as $th) {
if ($this->property_is_equal($th, 'tagName', 'th')) {
break 2;
} else {
} else if ($th->nodeName != '#text') {
$this->add_report($table);
break 2;
}
@@ -32,7 +32,7 @@ require_once('all_checks.php');
* Class test_css_text_has_contrast_test
* @covers \tool_brickfield\local\htmlchecker\brickfield_accessibility
*/
class css_text_has_contrast_test extends all_checks {
final class css_text_has_contrast_test extends all_checks {
/** @var string The check type. */
protected $checktype = 'css_text_has_contrast';
@@ -227,6 +227,18 @@ EOD;
This is contrasty enough.</p></body>
EOD;
/** @var string HTML with calculated size colour values. */
private $calculatedfail = <<<EOD
<body><p style="color:#EF0000; background-color:white; font-size: calc(0.90375rem + 0.045vw)">
This is not contrasty enough.</p></body>
EOD;
/** @var string HTML with calculated size colour values. */
private $calculatedpass = <<<EOD
<body><p style="color:#E60000; background-color:white; font-size: calc(0.90375rem + 0.045vw);">
This is contrasty enough.</p></body>
EOD;
/**
* Test for the area assign intro
*/
@@ -458,4 +470,20 @@ EOD;
$results = $this->get_checker_results($html);
$this->assertEmpty($results);
}
/**
* Test for calculated (12pt) text with insufficient contrast of 4.49.
*/
public function test_check_for_calculated_fail(): void {
$results = $this->get_checker_results($this->calculatedfail);
$this->assertTrue($results[0]->element->tagName == 'p');
}
/**
* Test for calculated (12pt) text with sufficient contrast of 4.81.
*/
public function test_check_for_calculated_pass(): void {
$results = $this->get_checker_results($this->calculatedpass);
$this->assertEmpty($results);
}
}
@@ -30,6 +30,8 @@ require_once('all_checks.php');
/**
* Class i_is_not_used_testcase
*
* @covers \tool_brickfield\local\htmlchecker\common\checks\i_is_not_used
*/
class i_is_not_used_test extends all_checks {
/** @var string Check type */
@@ -71,4 +73,13 @@ EOD;
$results = $this->get_checker_results($this->htmlpass);
$this->assertEmpty($results);
}
/**
* Test for font awesome icon.
*/
public function test_fa_icon(): void {
$html = '<div><i class="fa fa-user"></i><i>Hello there</i><i class="fa fa-address-book" aria-hidden="true"></i></div>';
$results = $this->get_checker_results($html);
$this->assertCount(2, $results);
}
}
@@ -30,6 +30,8 @@ require_once('all_checks.php');
/**
* Class table_data_should_have_th_test
*
* @covers \tool_brickfield\local\htmlchecker\common\checks\table_data_should_have_th
*/
class table_data_should_have_th_test extends all_checks {
/** @var string Check type */
@@ -113,6 +115,117 @@ EOD;
</table>
</body>
</html>
EOD;
/** @var string HTML that should not get flagged. */
private $htmlpass3 = <<<EOD
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Table should have at least one th - pass</title>
</head>
<body>
<table>
<thead>
<tr>
<th>
This is table heading
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
This is a tables data
</td>
</tr>
</tbody>
</table>
</body>
</html>
EOD;
/** @var string HTML that should not get flagged. */
private $htmlpass4 = <<<EOD
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Table should have at least one th - pass</title>
</head>
<body>
<table>
<tr>
<th>
This is table heading
</th>
</tr>
<tr>
<td>
This is a tables data
</td>
</tr>
</table>
</body>
</html>
EOD;
/** @var string HTML that should not get flagged. */
private $htmlpass5 = <<<EOD
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Table should have at least one th - pass</title>
</head>
<body>
<table>
<thead>
<tr>
<th>
This is table heading
</th>
</tr>
</thead>
<tbody>
<tr>
<th>
This is a table heading in table data
</th>
</tr>
<tr>
<td>
This is a tables data
</td>
</tr>
</tbody>
</table>
</body>
</html>
EOD;
/** @var string HTML that should not get flagged. */
private $htmlpass6 = <<<EOD
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Table should have at least one th - pass</title>
</head>
<body>
<table>
<tbody>
<tr>
<th>
This is a table heading in table data
</th>
</tr>
<tr>
<td>
This is a tables data
</td>
</tr>
</tbody>
</table>
</body>
</html>
EOD;
/**
* Test that th does not exist
@@ -134,5 +247,17 @@ EOD;
$results = $this->get_checker_results($this->htmlpass2);
$this->assertEmpty($results);
$results = $this->get_checker_results($this->htmlpass3);
$this->assertEmpty($results);
$results = $this->get_checker_results($this->htmlpass4);
$this->assertEmpty($results);
$results = $this->get_checker_results($this->htmlpass5);
$this->assertEmpty($results);
$results = $this->get_checker_results($this->htmlpass6);
$this->assertEmpty($results);
}
}
+5 -5
View File
@@ -30,7 +30,7 @@ use tool_brickfield\local\tool\tool;
class tool_test extends \advanced_testcase {
/** @var string base 64 image */
protected $base64img = <<<EOF
protected static string $base64img = <<<EOF
<img src="data:image/gif;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/
8mJl+fn/9ZWb8/PzWlwv///6wWGbImAPgTEMImIN9gUFCEm/gDALULDN8PAD6atYdCTX9gUNKlj8wZAKUsAOzZz+UMAOsJAP/Z2ccMDA8PD/95eX5N
WvsJCOVNQPtfX/8zM8+QePLl38MGBr8JCP+zs9myn/8GBqwpAP/GxgwJCPny78lzYLgjAJ8vAP9fX/+MjMUcAN8zM/9wcM8ZGcATEL+QePdZWf/29u
@@ -118,11 +118,11 @@ EOF;
* Base64 image provider.
* @return array
*/
public function base64_img_provider(): array {
public static function base64_img_provider(): array {
$img = '<img src="myimage.jpg" />';
return [
'Image tag alone (base64)' => [
$this->base64img,
self::$base64img,
true,
],
'Image tag alone (link)' => [
@@ -130,7 +130,7 @@ EOF;
false,
],
'Image tag in string (base64)' => [
"This is my image {$this->base64img}.",
"This is my image " . self::$base64img,
true,
],
'Image tag in string (link)' => [
@@ -162,7 +162,7 @@ EOF;
}
public function test_truncate_base64(): void {
$truncated = tool::truncate_base64($this->base64img);
$truncated = tool::truncate_base64(self::$base64img);
$this->assertStringContainsString('<img src="data:image/gif;base64..."', $truncated);
}
}
@@ -63,11 +63,9 @@ class assign_role_cohort extends moodleform {
$mform->addElement('select', 'roleid', get_string('selectrole', 'tool_cohortroles'), $options);
$mform->addRule('roleid', null, 'required');
$context = context_system::instance();
$options = array(
'multiple' => true,
'data-contextid' => $context->id,
'data-includes' => 'all'
'includes' => 'all',
);
$mform->addElement('cohort', 'cohortids', get_string('selectcohorts', 'tool_cohortroles'), $options);
$mform->addRule('cohortids', null, 'required');
@@ -60,7 +60,7 @@ class langstring_test extends advanced_testcase {
*
* @return array
*/
public function fix_syntax_data(): array {
public static function fix_syntax_data(): array {
return [
// Syntax sanity v1 strings.
[
@@ -79,7 +79,7 @@ class phpparser_test extends advanced_testcase {
*
* @return array
*/
public function parse_provider(): array {
public static function parse_provider(): array {
return [
'Invalid PHP code' => [
'No PHP code', [], false
+8 -8
View File
@@ -633,7 +633,7 @@ class api_test extends \advanced_testcase {
*
* @return array
*/
public function data_request_creation_provider() {
public static function data_request_creation_provider(): array {
return [
'Export request by user, automatic approval off' => [
false, api::DATAREQUEST_TYPE_EXPORT, 'automaticdataexportapproval', false, 0,
@@ -815,7 +815,7 @@ class api_test extends \advanced_testcase {
*
* @return array
*/
public function get_data_requests_provider() {
public static function get_data_requests_provider(): array {
$completeonly = [api::DATAREQUEST_STATUS_COMPLETE, api::DATAREQUEST_STATUS_DOWNLOAD_READY, api::DATAREQUEST_STATUS_DELETED];
$completeandcancelled = array_merge($completeonly, [api::DATAREQUEST_STATUS_CANCELLED]);
@@ -1000,7 +1000,7 @@ class api_test extends \advanced_testcase {
/**
* Data provider for test_has_ongoing_request.
*/
public function status_provider() {
public static function status_provider(): array {
return [
[api::DATAREQUEST_STATUS_AWAITING_APPROVAL, true],
[api::DATAREQUEST_STATUS_APPROVED, true],
@@ -1090,7 +1090,7 @@ class api_test extends \advanced_testcase {
*
* @return array
*/
public function notify_dpo_provider() {
public static function notify_dpo_provider(): array {
return [
[false, api::DATAREQUEST_TYPE_EXPORT, 'requesttypeexport', 'Export my user data'],
[false, api::DATAREQUEST_TYPE_DELETE, 'requesttypedelete', 'Delete my user data'],
@@ -1442,7 +1442,7 @@ class api_test extends \advanced_testcase {
/**
* Data provider for invalid contextlevel fetchers.
*/
public function invalid_effective_contextlevel_provider() {
public static function invalid_effective_contextlevel_provider(): array {
return [
[CONTEXT_COURSECAT],
[CONTEXT_COURSE],
@@ -2002,7 +2002,7 @@ class api_test extends \advanced_testcase {
/**
* Data provider for \tool_dataprivacy_api_testcase::test_set_context_defaults
*/
public function set_context_defaults_provider() {
public static function set_context_defaults_provider(): array {
$contextlevels = [
[CONTEXT_COURSECAT],
[CONTEXT_COURSE],
@@ -2477,7 +2477,7 @@ class api_test extends \advanced_testcase {
*
* @return array
*/
public function queue_data_request_task_provider() {
public static function queue_data_request_task_provider(): array {
return [
'With user ID provided' => [true],
'Without user ID provided' => [false],
@@ -2514,7 +2514,7 @@ class api_test extends \advanced_testcase {
/**
* Data provider for test_is_automatic_request_approval_on().
*/
public function automatic_request_approval_setting_provider() {
public static function automatic_request_approval_setting_provider(): array {
return [
'Data export, not set' => [
'automaticdataexportapproval', api::DATAREQUEST_TYPE_EXPORT, null, false
@@ -55,7 +55,8 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "200000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
And I wait "1" seconds
@@ -90,7 +91,8 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Export all of my personal data" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "200000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
@@ -128,7 +130,8 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "200000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
@@ -187,7 +190,8 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "172000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
And the following config values are set as admin:
| privacyrequestexpiry | 1 | tool_dataprivacy |
And I wait "1" seconds
@@ -231,7 +235,8 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "180000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
@javascript
Scenario: Filter before export data for a user and download it in the view request action
@@ -264,4 +269,5 @@ Feature: Data export from the privacy API
And I reload the page
And I should see "Download ready" in the "Victim User 1" "table_row"
And I open the action menu in "Victim User 1" "table_row"
And following "Download" should download between "1" and "180000" bytes
And following "Download" should download a file that:
| Contains file in zip | index.html |
@@ -35,7 +35,7 @@ class data_request_test extends data_privacy_testcase {
*
* @return array
*/
public function status_state_provider(): array {
public static function status_state_provider(): array {
return [
[
'state' => api::DATAREQUEST_STATUS_PENDING,
@@ -138,9 +138,9 @@ class data_request_test extends data_privacy_testcase {
*
* @return array
*/
public function non_resettable_provider(): array {
public static function non_resettable_provider(): array {
$states = [];
foreach ($this->status_state_provider() as $thisstatus) {
foreach (self::status_state_provider() as $thisstatus) {
if (!$thisstatus['resettable']) {
$states[] = $thisstatus;
}
@@ -1370,12 +1370,20 @@ class expired_contexts_test extends \advanced_testcase {
])
->getMock();
$mockprivacymanager->expects($this->atLeastOnce())->method('delete_data_for_user');
$mockprivacymanager->expects($this->exactly(2))
$deleteinvocations = $this->exactly(2);
$mockprivacymanager->expects($deleteinvocations)
->method('delete_data_for_all_users_in_context')
->withConsecutive(
[$blockcontext],
[$usercontext]
);
->willReturnCallback(function ($context) use (
$deleteinvocations,
$blockcontext,
$usercontext,
): void {
match (self::getInvocationCount($deleteinvocations)) {
1 => $this->assertEquals($blockcontext, $context),
2 => $this->assertEquals($usercontext, $context),
default => $this->fail('Unexpected invocation count'),
};
});
$manager = $this->getMockBuilder(\tool_dataprivacy\expired_contexts_manager::class)
->onlyMethods(['get_privacy_manager'])
@@ -1588,12 +1596,20 @@ class expired_contexts_test extends \advanced_testcase {
])
->getMock();
$mockprivacymanager->expects($this->atLeastOnce())->method('delete_data_for_user');
$mockprivacymanager->expects($this->exactly(2))
$deleteinvocations = $this->exactly(2);
$mockprivacymanager->expects($deleteinvocations)
->method('delete_data_for_all_users_in_context')
->withConsecutive(
[$blockcontext],
[$usercontext]
);
->willReturnCallback(function ($context) use (
$deleteinvocations,
$blockcontext,
$usercontext,
): void {
match (self::getInvocationCount($deleteinvocations)) {
1 => $this->assertEquals($blockcontext, $context),
2 => $this->assertEquals($usercontext, $context),
default => $this->fail('Unexpected invocation count'),
};
});
$manager = $this->getMockBuilder(\tool_dataprivacy\expired_contexts_manager::class)
->onlyMethods(['get_privacy_manager'])
@@ -1641,12 +1657,20 @@ class expired_contexts_test extends \advanced_testcase {
])
->getMock();
$mockprivacymanager->expects($this->atLeastOnce())->method('delete_data_for_user');
$mockprivacymanager->expects($this->exactly(2))
$deleteinvocations = $this->exactly(2);
$mockprivacymanager->expects($deleteinvocations)
->method('delete_data_for_all_users_in_context')
->withConsecutive(
[$blockcontext],
[$usercontext]
);
->willReturnCallback(function ($context) use (
$deleteinvocations,
$blockcontext,
$usercontext,
): void {
match (self::getInvocationCount($deleteinvocations)) {
1 => $this->assertEquals($blockcontext, $context),
2 => $this->assertEquals($usercontext, $context),
default => $this->fail('Unexpected invocation count'),
};
});
$manager = $this->getMockBuilder(\tool_dataprivacy\expired_contexts_manager::class)
->onlyMethods(['get_privacy_manager'])
@@ -1860,12 +1884,20 @@ class expired_contexts_test extends \advanced_testcase {
])
->getMock();
$mockprivacymanager->expects($this->never())->method('delete_data_for_user');
$mockprivacymanager->expects($this->exactly(2))
$deleteinvocations = $this->exactly(2);
$mockprivacymanager->expects($deleteinvocations)
->method('delete_data_for_all_users_in_context')
->withConsecutive(
[$forumcontext],
[$coursecontext]
);
->willReturnCallback(function ($context) use (
$deleteinvocations,
$forumcontext,
$coursecontext,
): void {
match (self::getInvocationCount($deleteinvocations)) {
1 => $this->assertEquals($forumcontext, $context),
2 => $this->assertEquals($coursecontext, $context),
default => $this->fail('Unexpected invocation count'),
};
});
$manager = $this->getMockBuilder(\tool_dataprivacy\expired_contexts_manager::class)
->onlyMethods(['get_privacy_manager'])
@@ -1918,7 +1950,7 @@ class expired_contexts_test extends \advanced_testcase {
*
* @return array
*/
public function can_process_deletion_provider(): array {
public static function can_process_deletion_provider(): array {
return [
'Pending' => [
expired_context::STATUS_EXPIRED,
@@ -1956,7 +1988,7 @@ class expired_contexts_test extends \advanced_testcase {
*
* @return array
*/
public function is_complete_provider(): array {
public static function is_complete_provider(): array {
return [
'Pending' => [
expired_context::STATUS_EXPIRED,
@@ -1991,7 +2023,7 @@ class expired_contexts_test extends \advanced_testcase {
*
* @return array
*/
public function is_fully_expired_provider(): array {
public static function is_fully_expired_provider(): array {
return [
'Fully expired' => [
[
+2 -2
View File
@@ -580,7 +580,7 @@ class external_test extends externallib_advanced_testcase {
/**
* Data provider for \tool_dataprivacy_external_testcase::test_XX_options().
*/
public function get_options_provider() {
public static function get_options_provider(): array {
return [
[false, false],
[false, true],
@@ -705,7 +705,7 @@ class external_test extends externallib_advanced_testcase {
/**
* Data provider for \tool_dataprivacy_external_testcase::get_activity_options().
*/
public function get_activity_options_provider() {
public static function get_activity_options_provider(): array {
return [
[false, false, true],
[false, true, true],
@@ -57,7 +57,7 @@ class filtered_userlist_test extends \advanced_testcase {
*
* @return array
*/
public function apply_expired_contexts_filters_provider(): array {
public static function apply_expired_contexts_filters_provider(): array {
return [
// Entire list should be preserved.
'No overrides' => [
@@ -38,20 +38,20 @@ class httpsreplace_test extends \advanced_testcase {
/**
* Data provider for test_upgrade_http_links
*/
public function upgrade_http_links_provider() {
public static function upgrade_http_links_provider(): array {
global $CFG;
// Get the http url, since the default test wwwroot is https.
$wwwroothttp = preg_replace('/^https:/', 'http:', $CFG->wwwroot);
return [
"Test image from another site should be replaced" => [
"content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">',
"content" => '<img src="' . self::getExternalTestFileUrl('/test.jpg', false) . '">',
"outputregex" => '/UPDATE/',
"expectedcontent" => '<img src="' . $this->get_converted_http_link('/test.jpg') . '">',
"expectedcontent" => '<img src="' . self::get_converted_http_link('/test.jpg') . '">',
],
"Test object from another site should be replaced" => [
"content" => '<object data="' . $this->getExternalTestFileUrl('/test.swf', false) . '">',
"content" => '<object data="' . self::getExternalTestFileUrl('/test.swf', false) . '">',
"outputregex" => '/UPDATE/',
"expectedcontent" => '<object data="' . $this->get_converted_http_link('/test.swf') . '">',
"expectedcontent" => '<object data="' . self::get_converted_http_link('/test.swf') . '">',
],
"Test image from a site with international name should be replaced" => [
"content" => '<img src="http://中国互联网络信息中心.中国/logosy/201706/W01.png">',
@@ -79,9 +79,9 @@ class httpsreplace_test extends \advanced_testcase {
"expectedcontent" => '<img src="https://anothersite.com?param=http://asdf.com">',
],
"Search for params should be case insensitive" => [
"content" => '<object DATA="' . $this->getExternalTestFileUrl('/test.swf', false) . '">',
"content" => '<object DATA="' . self::getExternalTestFileUrl('/test.swf', false) . '">',
"outputregex" => '/UPDATE/',
"expectedcontent" => '<object DATA="' . $this->get_converted_http_link('/test.swf') . '">',
"expectedcontent" => '<object DATA="' . self::get_converted_http_link('/test.swf') . '">',
],
"URL should be case insensitive" => [
"content" => '<object data="HTTP://some.site/path?query">',
@@ -89,30 +89,30 @@ class httpsreplace_test extends \advanced_testcase {
"expectedcontent" => '<object data="https://some.site/path?query">',
],
"More params should not interfere" => [
"content" => '<img alt="A picture" src="' . $this->getExternalTestFileUrl('/test.png', false) .
"content" => '<img alt="A picture" src="' . self::getExternalTestFileUrl('/test.png', false) .
'" width="1”><p style="font-size: \'20px\'"></p>',
"outputregex" => '/UPDATE/',
"expectedcontent" => '<img alt="A picture" src="' . $this->get_converted_http_link('/test.png') .
"expectedcontent" => '<img alt="A picture" src="' . self::get_converted_http_link('/test.png') .
'" width="1”><p style="font-size: \'20px\'"></p>',
],
"Broken URL should not be changed" => [
"content" => '<img src="broken.' . $this->getExternalTestFileUrl('/test.png', false) . '">',
"content" => '<img src="broken.' . self::getExternalTestFileUrl('/test.png', false) . '">',
"outputregex" => '/^$/',
"expectedcontent" => '<img src="broken.' . $this->getExternalTestFileUrl('/test.png', false) . '">',
"expectedcontent" => '<img src="broken.' . self::getExternalTestFileUrl('/test.png', false) . '">',
],
"Link URL should not be changed" => [
"content" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '">' .
$this->getExternalTestFileUrl('/test.png', false) . '</a>',
"content" => '<a href="' . self::getExternalTestFileUrl('/test.png', false) . '">' .
self::getExternalTestFileUrl('/test.png', false) . '</a>',
"outputregex" => '/^$/',
"expectedcontent" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '">' .
$this->getExternalTestFileUrl('/test.png', false) . '</a>',
"expectedcontent" => '<a href="' . self::getExternalTestFileUrl('/test.png', false) . '">' .
self::getExternalTestFileUrl('/test.png', false) . '</a>',
],
"Test image from another site should be replaced but link should not" => [
"content" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '"><img src="' .
$this->getExternalTestFileUrl('/test.jpg', false) . '"></a>',
"content" => '<a href="' . self::getExternalTestFileUrl('/test.png', false) . '"><img src="' .
self::getExternalTestFileUrl('/test.jpg', false) . '"></a>',
"outputregex" => '/UPDATE/',
"expectedcontent" => '<a href="' . $this->getExternalTestFileUrl('/test.png', false) . '"><img src="' .
$this->get_converted_http_link('/test.jpg') . '"></a>',
"expectedcontent" => '<a href="' . self::getExternalTestFileUrl('/test.png', false) . '"><img src="' .
self::get_converted_http_link('/test.jpg') . '"></a>',
],
];
}
@@ -127,8 +127,8 @@ class httpsreplace_test extends \advanced_testcase {
* @param string $path Path to be rewritten
* @return string
*/
protected function get_converted_http_link($path) {
return preg_replace('/^http:/', 'https:', $this->getExternalTestFileUrl($path, false));
protected static function get_converted_http_link($path) {
return preg_replace('/^http:/', 'https:', self::getExternalTestFileUrl($path, false));
}
/**
@@ -160,15 +160,15 @@ class httpsreplace_test extends \advanced_testcase {
/**
* Data provider for test_http_link_stats
*/
public function http_link_stats_provider() {
public static function http_link_stats_provider(): array {
global $CFG;
// Get the http url, since the default test wwwroot is https.
$wwwrootdomain = 'www.example.com';
$wwwroothttp = preg_replace('/^https:/', 'http:', $CFG->wwwroot);
$testdomain = $this->get_converted_http_link('');
$testdomain = self::get_converted_http_link('');
return [
"Test image from an available site so shouldn't be reported" => [
"content" => '<img src="' . $this->getExternalTestFileUrl('/test.jpg', false) . '">',
"content" => '<img src="' . self::getExternalTestFileUrl('/test.jpg', false) . '">',
"domain" => $testdomain,
"expectedcount" => 0,
],
@@ -48,7 +48,7 @@ class controller_test extends \advanced_testcase {
*
* @return array
*/
public function uninstall_lang_invalid_provider(): array {
public static function uninstall_lang_invalid_provider(): array {
return [
'Empty string' => [''],
'Meaningless empty string' => [' '],
+16 -4
View File
@@ -55,8 +55,14 @@ final class locale_test extends \advanced_testcase {
'set_locale',
])
->getMock();
$mock->method('get_locale')->will($this->onConsecutiveCalls('en'));
$mock->method('set_locale')->will($this->onConsecutiveCalls('es', 'en'));
$mock->method('get_locale')->will($this->returnValue('en'));
$setinvocations = $this->exactly(2);
$mock
->expects($setinvocations)
->method('set_locale')->willReturnCallback(fn () => match (self::getInvocationCount($setinvocations)) {
1 => 'es',
2 => 'en',
});
// Test what happen when locale is available on system.
$result = $mock->check_locale_availability('en');
@@ -72,8 +78,14 @@ final class locale_test extends \advanced_testcase {
'set_locale',
])
->getMock();
$mock->method('get_locale')->will($this->onConsecutiveCalls('en'));
$mock->method('set_locale')->will($this->onConsecutiveCalls(false, 'en'));
$mock->expects($this->exactly(1))->method('get_locale')->will($this->returnValue('en'));
$setinvocations = $this->exactly(2);
$mock
->expects($setinvocations)
->method('set_locale')->willReturnCallback(fn () => match (self::getInvocationCount($setinvocations)) {
1 => false,
2 => 'en',
});
// Test what happen when locale is not available on system.
$result = $mock->check_locale_availability('en');
@@ -389,7 +389,7 @@ class store_test extends \advanced_testcase {
*
* @return array Array of parameters
*/
public function decode_other_provider(): array {
public static function decode_other_provider(): array {
return [
[['info' => 'd2819896', 'logurl' => 'discuss.php?d=2819896']],
[null],
+2
View File
@@ -864,6 +864,8 @@ class external extends external_api {
$context = context_system::instance();
self::validate_context($context);
require_capability('moodle/competency:templatemanage', $context);
$output = $PAGE->get_renderer('tool_lp');
list($filtercapsql, $filtercapparams) = api::filter_users_with_capability_on_user_context_sql($cap,
+1 -1
View File
@@ -128,7 +128,7 @@ $functions = array(
'classpath' => '',
'description' => 'Search for users.',
'type' => 'read',
'capabilities' => '',
'capabilities' => 'moodle/competency:templatemanage',
'ajax' => true,
),
// This function was originally in this plugin but has been moved to core.
+10 -7
View File
@@ -141,17 +141,14 @@ class externallib_test extends externallib_advanced_testcase {
'email' => 'bobbyyy@dyyylan.com', 'phone1' => '123456', 'phone2' => '78910', 'department' => 'Marketing',
'institution' => 'HQ'));
// First we search with no capability assigned.
// Assign capability required to perform the search.
$this->setUser($ux);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
$result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(0, $result['users']);
$this->assertEquals(0, $result['count']);
$systemcontext = \context_system::instance();
$customrole = $this->assignUserCapability('moodle/competency:templatemanage', $systemcontext->id);
// Now we assign a different capability.
$usercontext = \context_user::instance($u1->id);
$systemcontext = \context_system::instance();
$customrole = $this->assignUserCapability('moodle/competency:planview', $usercontext->id);
$this->assignUserCapability('moodle/competency:templatemanage', $usercontext->id, $customrole);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
$result = external_api::clean_returnvalue(external::search_users_returns(), $result);
@@ -187,6 +184,8 @@ class externallib_test extends externallib_advanced_testcase {
$ux3 = $dg->create_user();
role_assign($this->creatorrole, $ux3->id, $usercontext->id);
$this->setUser($ux3);
$systemcontext = \context_system::instance();
$customrole = $this->assignUserCapability('moodle/competency:templatemanage', $systemcontext->id, $customrole);
$result = external::search_users('yyylan', 'moodle/competency:planmanage');
$result = external_api::clean_returnvalue(external::search_users_returns(), $result);
$this->assertCount(1, $result['users']);
@@ -262,6 +261,7 @@ class externallib_test extends externallib_advanced_testcase {
// Now do the test.
$this->setUser($master);
$dummyrole = $this->assignUserCapability('moodle/competency:templatemanage', $syscontext->id);
$result = external::search_users('MOODLER', 'moodle/site:config');
$this->assertCount(2, $result['users']);
$this->assertEquals(2, $result['count']);
@@ -269,6 +269,7 @@ class externallib_test extends externallib_advanced_testcase {
$this->assertArrayHasKey($slave3->id, $result['users']);
$this->setUser($manager);
$this->assignUserCapability('moodle/competency:templatemanage', $syscontext->id, $dummyrole);
$result = external::search_users('MOODLER', 'moodle/site:config');
$this->assertCount(1, $result['users']);
$this->assertEquals(1, $result['count']);
@@ -377,6 +378,8 @@ class externallib_test extends externallib_advanced_testcase {
// Switch to a user that cannot view identity fields.
$this->setUser($ux);
$systemcontext = \context_system::instance();
$this->assignUserCapability('moodle/competency:templatemanage', $systemcontext->id, $dummyrole);
$CFG->showuseridentity = 'idnumber,email,phone1,phone2,department,institution';
// Only names are included.
+1 -1
View File
@@ -25,6 +25,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2024042200; // The current plugin version (Date: YYYYMMDDXX).
$plugin->version = 2024042201; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics).
+3 -1
View File
@@ -31,7 +31,9 @@ class import_test extends \advanced_testcase {
$this->resetAfterTest(true);
$this->setAdminUser();
$importer = new framework_importer(file_get_contents(__DIR__ . '/fixtures/example.csv'));
$importer = new framework_importer(
file_get_contents(self::get_fixture_path(__NAMESPACE__, 'example.csv')),
);
$this->assertEquals('', $importer->get_error());
@@ -1,3 +1,3 @@
define("tool_mfa/autosubmit_verification_code",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0;_exports.init=()=>{const codeInput=document.querySelector("#id_verificationcode"),codeForm=codeInput.closest("form"),submitButton=codeForm.querySelector("#id_submitbutton");codeInput.addEventListener("keyup",(function(){this.value.length>=6&&codeForm.submit()})),codeInput.disabled&&(submitButton.disabled=!0)}}));
define("tool_mfa/autosubmit_verification_code",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0;_exports.init=()=>{const codeInput=document.querySelector("#id_verificationcode"),codeForm=codeInput.closest("form"),submitButton=codeForm.querySelector("#id_submitbutton");codeInput.addEventListener("input",(function(){this.value.length>=6&&(codeForm.submit(),codeInput.readOnly=!0,submitButton.disabled=!0)})),codeInput.disabled&&(submitButton.disabled=!0)}}));
//# sourceMappingURL=autosubmit_verification_code.min.js.map
@@ -1 +1 @@
{"version":3,"file":"autosubmit_verification_code.min.js","sources":["../src/autosubmit_verification_code.js"],"sourcesContent":["\n// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to autosubmit the verification code element when it reaches 6 characters.\n *\n * @module tool_mfa/autosubmit_verification_code\n * @copyright 2020 Peter Burnett <peterburnett@catalyst-au.net>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport const init = () => {\n const codeInput = document.querySelector(\"#id_verificationcode\");\n const codeForm = codeInput.closest(\"form\");\n const submitButton = codeForm.querySelector(\"#id_submitbutton\");\n\n // Event listener for code input field.\n codeInput.addEventListener('keyup', function() {\n if (this.value.length >= 6) {\n // Submits the closes form (parent).\n codeForm.submit();\n }\n });\n\n // Disable the submit button if the input field is disabled.\n // This occurs if there are no more attempts left for the factor.\n if (codeInput.disabled) {\n submitButton.disabled = true;\n }\n};\n"],"names":["codeInput","document","querySelector","codeForm","closest","submitButton","addEventListener","this","value","length","submit","disabled"],"mappings":"0KAwBoB,WACVA,UAAYC,SAASC,cAAc,wBACnCC,SAAWH,UAAUI,QAAQ,QAC7BC,aAAeF,SAASD,cAAc,oBAG5CF,UAAUM,iBAAiB,SAAS,WAC5BC,KAAKC,MAAMC,QAAU,GAErBN,SAASO,YAMbV,UAAUW,WACVN,aAAaM,UAAW"}
{"version":3,"file":"autosubmit_verification_code.min.js","sources":["../src/autosubmit_verification_code.js"],"sourcesContent":["\n// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to autosubmit the verification code element when it reaches 6 characters.\n *\n * @module tool_mfa/autosubmit_verification_code\n * @copyright 2020 Peter Burnett <peterburnett@catalyst-au.net>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport const init = () => {\n const codeInput = document.querySelector(\"#id_verificationcode\");\n const codeForm = codeInput.closest(\"form\");\n const submitButton = codeForm.querySelector(\"#id_submitbutton\");\n\n // Event listener for code input field.\n codeInput.addEventListener('input', function() {\n if (this.value.length >= 6) {\n // Submits the closest form (parent) and prevents accidental resubmission.\n codeForm.submit();\n codeInput.readOnly = true;\n submitButton.disabled = true;\n }\n });\n\n // Disable the submit button if the input field is disabled.\n // This occurs if there are no more attempts left for the factor.\n if (codeInput.disabled) {\n submitButton.disabled = true;\n }\n};\n"],"names":["codeInput","document","querySelector","codeForm","closest","submitButton","addEventListener","this","value","length","submit","readOnly","disabled"],"mappings":"0KAwBoB,WACVA,UAAYC,SAASC,cAAc,wBACnCC,SAAWH,UAAUI,QAAQ,QAC7BC,aAAeF,SAASD,cAAc,oBAG5CF,UAAUM,iBAAiB,SAAS,WAC5BC,KAAKC,MAAMC,QAAU,IAErBN,SAASO,SACTV,UAAUW,UAAW,EACrBN,aAAaO,UAAW,MAM5BZ,UAAUY,WACVP,aAAaO,UAAW"}
@@ -28,10 +28,12 @@ export const init = () => {
const submitButton = codeForm.querySelector("#id_submitbutton");
// Event listener for code input field.
codeInput.addEventListener('keyup', function() {
codeInput.addEventListener('input', function() {
if (this.value.length >= 6) {
// Submits the closes form (parent).
// Submits the closest form (parent) and prevents accidental resubmission.
codeForm.submit();
codeInput.readOnly = true;
submitButton.disabled = true;
}
});
@@ -32,7 +32,7 @@ class factor_test extends \advanced_testcase {
*
* @return array of different country codes and phone numbers.
*/
public function format_number_provider(): array {
public static function format_number_provider(): array {
return [
'Phone number with local format' => [
@@ -88,7 +88,7 @@ class factor_test extends \advanced_testcase {
*
* @return array with different phone numebr tests
*/
public function is_valid_phonenumber_provider(): array {
public static function is_valid_phonenumber_provider(): array {
return [
['+919367788755', true],
['8989829304', false],
@@ -275,7 +275,7 @@ class factor_test extends \advanced_testcase {
* Increments by 30 minutes to cover half hour and hour cases.
* Starting timestamp: 2022-01-15 07:30:00 Australia/Melbourne time.
*/
public function timestamp_provider() {
public static function timestamp_provider(): array {
$starttimestamp = 1642192200;
foreach (range(0, 23) as $i) {
$timestamps[] = [$starttimestamp + ($i * HOURSECS)];
@@ -51,7 +51,7 @@ class admin_setting_managemfa_test extends \advanced_testcase {
*
* @return array
*/
public function get_factor_combinations_provider() {
public static function get_factor_combinations_provider(): array {
$provider = [];
$factors = [];
+1 -1
View File
@@ -157,7 +157,7 @@ class manager_test extends \advanced_testcase {
*
* @return array
*/
public static function should_redirect_urls_provider() {
public static function should_redirect_urls_provider(): array {
$badurl1 = new \moodle_url('/');
$badparam1 = $badurl1->out();
$badurl2 = new \moodle_url('admin/tool/mfa/auth.php');
+3 -1
View File
@@ -76,7 +76,9 @@ class hook_callbacks {
return;
}
$hook->add_html(
html_writer::link($url, get_string('getmoodleonyourmobile', 'tool_mobile'), ['class' => 'mobilelink']),
html_writer::div(
html_writer::link($url, get_string('getmoodleonyourmobile', 'tool_mobile'), ['class' => 'mobilelink']),
),
);
}
+1 -1
View File
@@ -52,7 +52,7 @@ class lib_test extends \advanced_testcase {
*
* @return array
*/
public function get_endpoints_provider() {
public static function get_endpoints_provider(): array {
global $CFG;
return [
[
@@ -59,7 +59,7 @@ class import_handler_info_test extends \advanced_testcase {
*
* @return array the data for creation of the info object.
*/
public function handler_info_data_provider() {
public static function handler_info_data_provider(): array {
return [
'All data present' => ['label', 'Add a label to the course', false],
'Empty module name' => ['', 'Add a file resource to the course', true],
@@ -53,10 +53,10 @@ class remote_resource_test extends \advanced_testcase {
*
* @return array
*/
public function remote_resource_data_provider() {
public static function remote_resource_data_provider(): array {
return [
'With filename and extension' => [
$this->getExternalTestFileUrl('/test.html'),
self::getExternalTestFileUrl('/test.html'),
(object) [
'name' => 'Test html file',
'description' => 'Full description of the html file'
@@ -78,8 +78,8 @@ class remote_resource_test extends \advanced_testcase {
* Test confirming the network based operations of a remote_resource.
*/
public function test_network_features(): void {
$url = $this->getExternalTestFileUrl('/test.html');
$nonexistenturl = $this->getExternalTestFileUrl('/test.htmlzz');
$url = self::getExternalTestFileUrl('/test.html');
$nonexistenturl = self::getExternalTestFileUrl('/test.htmlzz');
$remoteres = new remote_resource(
new \curl(),
@@ -55,7 +55,7 @@ class url_test extends \advanced_testcase {
*
* @return array
*/
public function url_provider() {
public static function url_provider(): array {
return [
'No path' => [
'url' => 'https://example.moodle.net',
+4 -1
View File
@@ -79,7 +79,10 @@ class hook_callbacks {
if (!empty($policies)) {
$url = new moodle_url('/admin/tool/policy/viewall.php', ['returnurl' => $PAGE->url]);
$hook->add_html(
html_writer::link($url, get_string('userpolicysettings', 'tool_policy'), ['class' => 'policiesfooter']),
html_writer::div(
html_writer::link($url, get_string('userpolicysettings', 'tool_policy')),
'policiesfooter',
),
);
}
}
@@ -61,7 +61,7 @@
<ul>
{{#policies}}
<li>
<a href=\"{{pluginbaseurl}}/view.php?versionid={{id}}{{#returnurl}}&amp;returnurl={{.}}{{/returnurl}} {{!
<a href="{{pluginbaseurl}}/view.php?versionid={{id}}{{#returnurl}}&amp;returnurl={{.}}{{/returnurl}}" {{!
}}data-action="view-guest" data-versionid="{{id}}" data-behalfid="1">
{{{name}}}
</a>
@@ -117,7 +117,7 @@ class category_bin extends base_bin {
// This hack will be removed once recycle bin switches to use its own backup mode, with
// own preferences and 100% separate from MOODLE_AUTOMATED.
// TODO: Remove this as part of MDL-65228.
$forcedbackupsettings = $CFG->forced_plugin_settings['backup'] ?? null;
$forcedbackupsettings = $CFG->forced_plugin_settings['backup'] ?? [];
$CFG->forced_plugin_settings['backup']['backup_auto_storage'] = 0;
$CFG->forced_plugin_settings['backup']['backup_auto_files'] = 1;
@@ -253,7 +253,7 @@ class category_bin extends base_bin {
// This hack will be removed once recycle bin switches to use its own backup mode, with
// own preferences and 100% separate from MOODLE_AUTOMATED.
// TODO: Remove this as part of MDL-65228.
$forcedrestoresettings = $CFG->forced_plugin_settings['restore'] ?? null;
$forcedrestoresettings = $CFG->forced_plugin_settings['restore'] ?? [];
$CFG->forced_plugin_settings['restore']['restore_general_users'] = 1;
$CFG->forced_plugin_settings['restore']['restore_general_groups'] = 1;
+1 -1
View File
@@ -121,7 +121,7 @@ class course_bin extends base_bin {
// This hack will be removed once recycle bin switches to use its own backup mode, with
// own preferences and 100% separate from MOODLE_AUTOMATED.
// TODO: Remove this as part of MDL-65228.
$forcedbackupsettings = $CFG->forced_plugin_settings['backup'] ?? null;
$forcedbackupsettings = $CFG->forced_plugin_settings['backup'] ?? [];
$CFG->forced_plugin_settings['backup']['backup_auto_storage'] = 0;
$CFG->forced_plugin_settings['backup']['backup_auto_files'] = 1;
@@ -175,7 +175,7 @@ class category_bin_test extends \advanced_testcase {
* Used to verify that recycle bin is immune to various settings. Provides plugin, name, value for
* direct usage with set_config()
*/
public function recycle_bin_settings_provider() {
public static function recycle_bin_settings_provider(): array {
return [
'backup/backup_auto_storage moodle' => [[
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 0],
@@ -175,7 +175,7 @@ class course_bin_test extends \advanced_testcase {
* Used to verify that recycle bin is immune to various settings. Provides plugin, name, value for
* direct usage with set_config()
*/
public function recycle_bin_settings_provider() {
public static function recycle_bin_settings_provider(): array {
return [
'backup/backup_auto_storage moodle' => [[
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 0],
+25 -8
View File
@@ -967,8 +967,14 @@ class course_test extends \advanced_testcase {
// Restore from a file, checking that the file takes priority over the templatecourse.
$mode = tool_uploadcourse_processor::MODE_CREATE_NEW;
$updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
$data = array('shortname' => 'A1', 'backupfile' => __DIR__ . '/fixtures/backup.mbz',
'summary' => 'A', 'category' => 1, 'fullname' => 'A1', 'templatecourse' => $c1->shortname);
$data = [
'shortname' => 'A1',
'backupfile' => self::get_fixture_path(__NAMESPACE__, 'backup.mbz'),
'summary' => 'A',
'category' => 1,
'fullname' => 'A1',
'templatecourse' => $c1->shortname,
];
$co = new tool_uploadcourse_course($mode, $updatemode, $data);
$this->assertTrue($co->prepare());
$co->proceed();
@@ -986,8 +992,13 @@ class course_test extends \advanced_testcase {
$this->assertTrue($found);
// Restoring twice from the same file should work.
$data = array('shortname' => 'B1', 'backupfile' => __DIR__ . '/fixtures/backup.mbz',
'summary' => 'B', 'category' => 1, 'fullname' => 'B1');
$data = [
'shortname' => 'B1',
'backupfile' => self::get_fixture_path(__NAMESPACE__, 'backup.mbz'),
'summary' => 'B',
'category' => 1,
'fullname' => 'B1',
];
$co = new tool_uploadcourse_course($mode, $updatemode, $data);
$this->assertTrue($co->prepare());
$co->proceed();
@@ -1020,8 +1031,14 @@ class course_test extends \advanced_testcase {
$mode = tool_uploadcourse_processor::MODE_CREATE_NEW;
$updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
$data = array('shortname' => 'A1', 'backupfile' => __DIR__ . '/fixtures/backup.mbz',
'summary' => 'A', 'category' => 1, 'fullname' => 'A1', 'templatecourse' => $c1->shortname);
$data = [
'shortname' => 'A1',
'backupfile' => self::get_fixture_path(__NAMESPACE__, 'backup.mbz'),
'summary' => 'A',
'category' => 1,
'fullname' => 'A1',
'templatecourse' => $c1->shortname,
];
$co = new tool_uploadcourse_course($mode, $updatemode, $data);
$this->assertTrue($co->prepare());
$co->proceed();
@@ -1259,7 +1276,7 @@ class course_test extends \advanced_testcase {
*
* @return array
*/
public function enrolment_uploaddata_error_provider(): array {
public static function enrolment_uploaddata_error_provider(): array {
return [
['errorcannotcreateorupdateenrolment', [
'shortname' => 'C1',
@@ -1487,7 +1504,7 @@ class course_test extends \advanced_testcase {
// Create our custom field.
$category = $this->get_customfield_generator()->create_category();
$this->create_custom_field($category, 'date', 'mydate',
['mindate' => strtotime('2020-04-01'), 'maxdate' => '2020-04-30']);
['mindate' => strtotime('2020-04-01'), 'maxdate' => strtotime('2020-04-30')]);
$mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY;
$updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY;
@@ -110,11 +110,11 @@ class processor_test extends \advanced_testcase {
$cir->load_csv_content($content, 'utf-8', 'comma');
$cir->init();
$options = array(
$options = [
'mode' => tool_uploadcourse_processor::MODE_CREATE_NEW,
'restorefile' => __DIR__ . '/fixtures/backup.mbz',
'templatecourse' => 'DoesNotExist' // Restorefile takes priority.
);
'restorefile' => self::get_fixture_path(__NAMESPACE__, 'backup.mbz'),
'templatecourse' => 'DoesNotExist', // Restorefile takes priority.
];
$defaults = array('category' => '1');
$p = new tool_uploadcourse_processor($cir, $options, $defaults);
@@ -30,7 +30,7 @@ class field_value_validators_test extends \advanced_testcase {
/**
* Data provider for \field_value_validators_testcase::test_validate_theme().
*/
public function themes_provider() {
public static function themes_provider(): array {
return [
'User themes disabled' => [
false, 'boost', 'warning', get_string('userthemesnotallowed', 'tool_uploaduser')
+5 -1
View File
@@ -562,7 +562,8 @@ class step {
* @return $this
*/
public function persist($force = false) {
global $DB;
global $CFG, $DB;
require_once("{$CFG->libdir}/filelib.php");
if (!$this->dirty && !$force) {
return $this;
@@ -719,6 +720,9 @@ class step {
* @return object
*/
public function prepare_data_for_form() {
global $CFG;
require_once("{$CFG->libdir}/filelib.php");
$data = $this->to_record();
foreach (self::get_config_keys() as $key) {
$data->$key = $this->get_config($key, configuration::get_step_default_value($key));
+5 -5
View File
@@ -106,7 +106,7 @@ final class helper_test extends \advanced_testcase {
\core\di::set(
\core\hook\manager::class,
\core\hook\manager::phpunit_get_instance([
'test_plugin1' => __DIR__ . '/fixtures/invalid_serverside_hook_fixture.php',
'test_plugin1' => self::get_fixture_path(__NAMESPACE__, 'invalid_serverside_hook_fixture.php'),
]),
);
@@ -118,7 +118,7 @@ final class helper_test extends \advanced_testcase {
\core\di::set(
\core\hook\manager::class,
\core\hook\manager::phpunit_get_instance([
'test_plugin1' => __DIR__ . '/fixtures/clientside_filter_for_serverside_hook.php',
'test_plugin1' => self::get_fixture_path(__NAMESPACE__, 'clientside_filter_for_serverside_hook.php'),
]),
);
@@ -130,7 +130,7 @@ final class helper_test extends \advanced_testcase {
\core\di::set(
\core\hook\manager::class,
\core\hook\manager::phpunit_get_instance([
'test_plugin1' => __DIR__ . '/fixtures/serverside_filter_for_clientside_hook.php',
'test_plugin1' => self::get_fixture_path(__NAMESPACE__, 'serverside_filter_for_clientside_hook.php'),
]),
);
@@ -142,7 +142,7 @@ final class helper_test extends \advanced_testcase {
\core\di::set(
\core\hook\manager::class,
\core\hook\manager::phpunit_get_instance([
'test_plugin1' => __DIR__ . '/fixtures/hook_fixtures.php',
'test_plugin1' => self::get_fixture_path(__NAMESPACE__, 'hook_fixtures.php'),
]),
);
@@ -175,7 +175,7 @@ final class helper_test extends \advanced_testcase {
\core\di::set(
\core\hook\manager::class,
\core\hook\manager::phpunit_get_instance([
'test_plugin1' => __DIR__ . '/fixtures/invalid_clientside_hook_fixture.php',
'test_plugin1' => self::get_fixture_path(__NAMESPACE__, 'invalid_clientside_hook_fixture.php'),
]),
);
+42 -13
View File
@@ -524,14 +524,30 @@ class tour_test extends \advanced_testcase {
// Mock the database.
$DB = $this->mock_database();
$DB->expects($this->exactly(3))
$deleteinvocations = $this->exactly(3);
$DB->expects($deleteinvocations)
->method('delete_records')
->withConsecutive(
[$this->equalTo('tool_usertours_tours'), $this->equalTo(['id' => $id])],
[$this->equalTo('user_preferences'), $this->equalTo(['name' => tour::TOUR_LAST_COMPLETED_BY_USER . $id])],
[$this->equalTo('user_preferences'), $this->equalTo(['name' => tour::TOUR_REQUESTED_BY_USER . $id])]
)
->willReturn(null);
->willReturnCallback(function ($table, $conditions) use ($deleteinvocations, $id) {
switch (self::getInvocationCount($deleteinvocations)) {
case 1:
$this->assertEquals('tool_usertours_tours', $table);
$this->assertEquals(['id' => $id], $conditions);
return null;
break;
case 2:
$this->assertEquals('user_preferences', $table);
$this->assertEquals(['name' => tour::TOUR_LAST_COMPLETED_BY_USER . $id], $conditions);
return null;
break;
case 3:
$this->assertEquals('user_preferences', $table);
$this->assertEquals(['name' => tour::TOUR_REQUESTED_BY_USER . $id], $conditions);
return null;
break;
default:
$this->fail('Unexpected call to delete_records');
}
});
$DB->expects($this->once())
->method('get_records')
@@ -551,7 +567,7 @@ class tour_test extends \advanced_testcase {
for ($i = 4; $i >= 0; $i--) {
$id = rand($i * 10, ($i * 10) + 9);
$mockdata[] = (object) ['id' => $id];
$expectations[] = [$this->equalTo('tool_usertours_steps'), $this->equalTo('sortorder'), 4 - $i, ['id' => $id]];
$expectations[] = [4 - $i, ['id' => $id]];
}
// Mock the database.
@@ -560,9 +576,19 @@ class tour_test extends \advanced_testcase {
->method('get_records')
->willReturn($mockdata);
$setfield = $DB->expects($this->exactly(5))
->method('set_field');
call_user_func_array([$setfield, 'withConsecutive'], $expectations);
$setfieldinvocations = $this->exactly(5);
$DB->expects($setfieldinvocations)
->method('set_field')
->willReturnCallback(function ($table, $field, $value, $conditions) use (
$setfieldinvocations,
$expectations,
): void {
$expectation = $expectations[self::getInvocationCount($setfieldinvocations) - 1];
$this->assertEquals('tool_usertours_steps', $table);
$this->assertEquals('sortorder', $field);
$this->assertEquals($expectation[0], $value);
$this->assertEquals($expectation[1], $conditions);
});
$tour->reset_step_sortorder();
}
@@ -761,9 +787,12 @@ class tour_test extends \advanced_testcase {
->getMock();
if ($getconfig) {
$tour->expects($this->exactly(count($getconfig)))
$getinvocations = $this->exactly(count($getconfig));
$tour->expects($getinvocations)
->method('get_config')
->will(call_user_func_array([$this, 'onConsecutiveCalls'], $getconfig));
->willReturnCallback(function () use ($getinvocations, $getconfig) {
return $getconfig[self::getInvocationCount($getinvocations) - 1];
});
}
if ($setconfig) {
+1 -1
View File
@@ -30,7 +30,7 @@ class analysis_test extends \advanced_testcase {
* @return null
*/
public function test_fill_firstanalyses_cache(): void {
require_once(__DIR__ . '/fixtures/test_timesplitting_upcoming_seconds.php');
require_once(self::get_fixture_path(__NAMESPACE__, 'test_timesplitting_upcoming_seconds.php'));
$this->resetAfterTest();
$modelid = 1;
+2 -1
View File
@@ -148,7 +148,8 @@ Feature: Manage analytics models
When I open the action menu in "Students at risk of not meeting the course completion conditions" "table_row"
And I choose "Export" in the open action menu
And I click on "Actions" "link" in the "Students at risk of not meeting the course completion conditions" "table_row"
And following "Export" should download between "100" and "500" bytes
And following "Export" should download a file that:
| Contains file in zip | model-config.json |
Scenario: Check invalid site elements
When I open the action menu in "Students at risk of not meeting the course completion conditions" "table_row"
+2 -3
View File
@@ -23,8 +23,7 @@ namespace core_analytics;
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class calculation_info_test extends \advanced_testcase {
final class calculation_info_test extends \advanced_testcase {
/**
* test_calculation_info description
*
@@ -88,7 +87,7 @@ class calculation_info_test extends \advanced_testcase {
*
* @return mixed[]
*/
public function provider_test_calculation_info_add_pull() {
public static function provider_test_calculation_info_add_pull(): array {
return [
'mixed-types' => ['asd', true, [123, 123, 123], (object)['asd' => 'fgfg']],
];
@@ -50,7 +50,7 @@ final class community_of_inquiry_activities_completed_by_test extends advanced_t
* @param string $availabilitylevel
* @return void
*/
public function test_get_activities_with_availability($availabilitylevel) {
public function test_get_activities_with_availability($availabilitylevel): void {
list($course, $stu1) = $this->setup_course();
@@ -113,7 +113,7 @@ final class community_of_inquiry_activities_completed_by_test extends advanced_t
*
* @return void
*/
public function test_get_activities_with_weeks() {
public function test_get_activities_with_weeks(): void {
$startdate = gmmktime('0', '0', '0', 10, 24, 2015);
$record = array(
@@ -156,7 +156,7 @@ final class community_of_inquiry_activities_completed_by_test extends advanced_t
*
* @return void
*/
public function test_get_activities_by_section() {
public function test_get_activities_by_section(): void {
// This makes debugging easier, sorry WA's +8 :).
$this->setTimezone('UTC');
@@ -226,7 +226,7 @@ final class community_of_inquiry_activities_completed_by_test extends advanced_t
*
* @return void
*/
public function test_get_activities_with_specific_restrictions() {
public function test_get_activities_with_specific_restrictions(): void {
list($course, $stu1) = $this->setup_course();
+3 -4
View File
@@ -29,8 +29,7 @@ require_once(__DIR__ . '/fixtures/test_indicator_min.php');
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class indicator_test extends \advanced_testcase {
final class indicator_test extends \advanced_testcase {
/**
* test_validate_calculated_value
*
@@ -50,7 +49,7 @@ class indicator_test extends \advanced_testcase {
*
* @return array
*/
public function validate_calculated_value() {
public static function validate_calculated_value(): array {
return [
'max' => ['test_indicator_max', [1]],
'min' => ['test_indicator_min', [-1]],
@@ -83,7 +82,7 @@ class indicator_test extends \advanced_testcase {
*
* @return array
*/
public function validate_calculated_value_exceptions() {
public static function validate_calculated_value_exceptions(): array {
return [
'max' => ['test_indicator_max', 2],
'min' => ['test_indicator_min', -2],
+55 -46
View File
@@ -31,8 +31,7 @@ require_once(__DIR__ . '/fixtures/test_target_course_level_shortname.php');
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_analytics\manager
*/
class manager_test extends \advanced_testcase {
final class manager_test extends \advanced_testcase {
/**
* test_deleted_context
*/
@@ -44,7 +43,7 @@ class manager_test extends \advanced_testcase {
set_config('enabled_stores', 'logstore_standard', 'tool_log');
$target = \core_analytics\manager::get_target('test_target_course_level_shortname');
$indicators = array('test_indicator_max', 'test_indicator_min', 'test_indicator_fullname');
$indicators = ['test_indicator_max', 'test_indicator_min', 'test_indicator_fullname'];
foreach ($indicators as $key => $indicator) {
$indicators[$key] = \core_analytics\manager::get_indicator($indicator);
}
@@ -52,10 +51,10 @@ class manager_test extends \advanced_testcase {
$model = \core_analytics\model::create($target, $indicators);
$modelobj = $model->get_model_obj();
$coursepredict1 = $this->getDataGenerator()->create_course(array('visible' => 0));
$coursepredict2 = $this->getDataGenerator()->create_course(array('visible' => 0));
$coursetrain1 = $this->getDataGenerator()->create_course(array('visible' => 1));
$coursetrain2 = $this->getDataGenerator()->create_course(array('visible' => 1));
$coursepredict1 = $this->getDataGenerator()->create_course(['visible' => 0]);
$coursepredict2 = $this->getDataGenerator()->create_course(['visible' => 0]);
$coursetrain1 = $this->getDataGenerator()->create_course(['visible' => 1]);
$coursetrain2 = $this->getDataGenerator()->create_course(['visible' => 1]);
$model->enable('\core\analytics\time_splitting\no_splitting');
@@ -65,25 +64,33 @@ class manager_test extends \advanced_testcase {
// Generate a prediction action to confirm that it is deleted when there is an important update.
$predictions = $DB->get_records('analytics_predictions');
$prediction = reset($predictions);
$prediction = new \core_analytics\prediction($prediction, array('whatever' => 'not used'));
$prediction = new \core_analytics\prediction($prediction, ['whatever' => 'not used']);
$prediction->action_executed(\core_analytics\prediction::ACTION_USEFUL, $model->get_target());
$predictioncontextid = $prediction->get_prediction_data()->contextid;
$npredictions = $DB->count_records('analytics_predictions', array('contextid' => $predictioncontextid));
$npredictionactions = $DB->count_records('analytics_prediction_actions',
array('predictionid' => $prediction->get_prediction_data()->id));
$nindicatorcalc = $DB->count_records('analytics_indicator_calc', array('contextid' => $predictioncontextid));
$npredictions = $DB->count_records('analytics_predictions', ['contextid' => $predictioncontextid]);
$npredictionactions = $DB->count_records(
'analytics_prediction_actions',
['predictionid' => $prediction->get_prediction_data()->id]
);
$nindicatorcalc = $DB->count_records('analytics_indicator_calc', ['contextid' => $predictioncontextid]);
\core_analytics\manager::cleanup();
// Nothing is incorrectly deleted.
$this->assertEquals($npredictions, $DB->count_records('analytics_predictions',
array('contextid' => $predictioncontextid)));
$this->assertEquals($npredictionactions, $DB->count_records('analytics_prediction_actions',
array('predictionid' => $prediction->get_prediction_data()->id)));
$this->assertEquals($nindicatorcalc, $DB->count_records('analytics_indicator_calc',
array('contextid' => $predictioncontextid)));
$this->assertEquals($npredictions, $DB->count_records(
'analytics_predictions',
['contextid' => $predictioncontextid]
));
$this->assertEquals($npredictionactions, $DB->count_records(
'analytics_prediction_actions',
['predictionid' => $prediction->get_prediction_data()->id]
));
$this->assertEquals($nindicatorcalc, $DB->count_records(
'analytics_indicator_calc',
['contextid' => $predictioncontextid]
));
// Now we delete a context, the course predictions and prediction actions should be deleted.
$deletedcontext = \context::instance_by_id($predictioncontextid);
@@ -91,10 +98,12 @@ class manager_test extends \advanced_testcase {
\core_analytics\manager::cleanup();
$this->assertEmpty($DB->count_records('analytics_predictions', array('contextid' => $predictioncontextid)));
$this->assertEmpty($DB->count_records('analytics_prediction_actions',
array('predictionid' => $prediction->get_prediction_data()->id)));
$this->assertEmpty($DB->count_records('analytics_indicator_calc', array('contextid' => $predictioncontextid)));
$this->assertEmpty($DB->count_records('analytics_predictions', ['contextid' => $predictioncontextid]));
$this->assertEmpty($DB->count_records(
'analytics_prediction_actions',
['predictionid' => $prediction->get_prediction_data()->id]
));
$this->assertEmpty($DB->count_records('analytics_indicator_calc', ['contextid' => $predictioncontextid]));
set_config('enabled_stores', '', 'tool_log');
get_log_manager(true);
@@ -111,7 +120,7 @@ class manager_test extends \advanced_testcase {
set_config('enabled_stores', 'logstore_standard', 'tool_log');
$target = \core_analytics\manager::get_target('test_target_course_level_shortname');
$indicators = array('test_indicator_max', 'test_indicator_min', 'test_indicator_fullname');
$indicators = ['test_indicator_max', 'test_indicator_min', 'test_indicator_fullname'];
foreach ($indicators as $key => $indicator) {
$indicators[$key] = \core_analytics\manager::get_indicator($indicator);
}
@@ -119,10 +128,10 @@ class manager_test extends \advanced_testcase {
$model = \core_analytics\model::create($target, $indicators);
$modelobj = $model->get_model_obj();
$coursepredict1 = $this->getDataGenerator()->create_course(array('visible' => 0));
$coursepredict2 = $this->getDataGenerator()->create_course(array('visible' => 0));
$coursetrain1 = $this->getDataGenerator()->create_course(array('visible' => 1));
$coursetrain2 = $this->getDataGenerator()->create_course(array('visible' => 1));
$coursepredict1 = $this->getDataGenerator()->create_course(['visible' => 0]);
$coursepredict2 = $this->getDataGenerator()->create_course(['visible' => 0]);
$coursetrain1 = $this->getDataGenerator()->create_course(['visible' => 1]);
$coursetrain2 = $this->getDataGenerator()->create_course(['visible' => 1]);
$model->enable('\core\analytics\time_splitting\no_splitting');
@@ -139,9 +148,9 @@ class manager_test extends \advanced_testcase {
\core_analytics\manager::cleanup();
$this->assertEmpty($DB->count_records('analytics_predict_samples', array('analysableid' => $coursepredict1->id)));
$this->assertEmpty($DB->count_records('analytics_train_samples', array('analysableid' => $coursepredict1->id)));
$this->assertEmpty($DB->count_records('analytics_used_analysables', array('analysableid' => $coursepredict1->id)));
$this->assertEmpty($DB->count_records('analytics_predict_samples', ['analysableid' => $coursepredict1->id]));
$this->assertEmpty($DB->count_records('analytics_train_samples', ['analysableid' => $coursepredict1->id]));
$this->assertEmpty($DB->count_records('analytics_used_analysables', ['analysableid' => $coursepredict1->id]));
set_config('enabled_stores', '', 'tool_log');
get_log_manager(true);
@@ -190,7 +199,7 @@ class manager_test extends \advanced_testcase {
$this->resetAfterTest();
// This is expected to run without an exception.
$models = $this->load_models_from_fixture_file('no_teaching');
$models = self::load_models_from_fixture_file('no_teaching');
\core_analytics\manager::validate_models_declaration($models);
}
@@ -214,34 +223,34 @@ class manager_test extends \advanced_testcase {
*
* @return array of (string)testcase => [(array)models, (string)expected exception message]
*/
public function validate_models_declaration_exceptions_provider() {
public static function validate_models_declaration_exceptions_provider(): array {
return [
'missing_target' => [
$this->load_models_from_fixture_file('missing_target'),
self::load_models_from_fixture_file('missing_target'),
'Missing target declaration',
],
'invalid_target' => [
$this->load_models_from_fixture_file('invalid_target'),
self::load_models_from_fixture_file('invalid_target'),
'Invalid target classname',
],
'missing_indicators' => [
$this->load_models_from_fixture_file('missing_indicators'),
self::load_models_from_fixture_file('missing_indicators'),
'Missing indicators declaration',
],
'invalid_indicators' => [
$this->load_models_from_fixture_file('invalid_indicators'),
self::load_models_from_fixture_file('invalid_indicators'),
'Invalid indicator classname',
],
'invalid_time_splitting' => [
$this->load_models_from_fixture_file('invalid_time_splitting'),
self::load_models_from_fixture_file('invalid_time_splitting'),
'Invalid time splitting classname',
],
'invalid_time_splitting_fq' => [
$this->load_models_from_fixture_file('invalid_time_splitting_fq'),
self::load_models_from_fixture_file('invalid_time_splitting_fq'),
'Expecting fully qualified time splitting classname',
],
'invalid_enabled' => [
$this->load_models_from_fixture_file('invalid_enabled'),
self::load_models_from_fixture_file('invalid_enabled'),
'Cannot enable a model without time splitting method specified',
],
];
@@ -253,12 +262,12 @@ class manager_test extends \advanced_testcase {
* @param string $filename
* @return array
*/
protected function load_models_from_fixture_file(string $filename) {
protected static function load_models_from_fixture_file(string $filename) {
global $CFG;
$models = null;
require($CFG->dirroot.'/analytics/tests/fixtures/db_analytics_php/'.$filename.'.php');
require("{$CFG->dirroot}/analytics/tests/fixtures/db_analytics_php/{$filename}.php");
return $models;
}
@@ -430,9 +439,9 @@ class manager_test extends \advanced_testcase {
*/
public function test_model_declaration_identifier(): void {
$noteaching1 = $this->load_models_from_fixture_file('no_teaching');
$noteaching2 = $this->load_models_from_fixture_file('no_teaching');
$noteaching3 = $this->load_models_from_fixture_file('no_teaching');
$noteaching1 = self::load_models_from_fixture_file('no_teaching');
$noteaching2 = self::load_models_from_fixture_file('no_teaching');
$noteaching3 = self::load_models_from_fixture_file('no_teaching');
// Same model declaration should always lead to same identifier.
$this->assertEquals(
@@ -474,9 +483,9 @@ class manager_test extends \advanced_testcase {
public function test_get_declared_target_and_indicators_instances(): void {
$this->resetAfterTest();
$definition = $this->load_models_from_fixture_file('no_teaching');
$definition = self::load_models_from_fixture_file('no_teaching');
list($target, $indicators) = \core_analytics\manager::get_declared_target_and_indicators_instances($definition[0]);
[$target, $indicators] = \core_analytics\manager::get_declared_target_and_indicators_instances($definition[0]);
$this->assertTrue($target instanceof \core_analytics\local\target\base);
$this->assertNotEmpty($indicators);
+1 -1
View File
@@ -135,7 +135,7 @@ class prediction_actions_test extends \advanced_testcase {
*
* @return array
*/
public function execute_actions_provider(): array {
public static function execute_actions_provider(): array {
return [
'Empty actions with no filter' => [
[],
+11 -13
View File
@@ -341,14 +341,14 @@ class prediction_test extends \advanced_testcase {
*
* @return array
*/
public function provider_ml_training_and_prediction() {
public static function provider_ml_training_and_prediction(): array {
$cases = array(
'no_splitting' => array('\core\analytics\time_splitting\no_splitting', 0, 1),
'quarters' => array('\core\analytics\time_splitting\quarters', 3, 4)
);
// We need to test all system prediction processors.
return $this->add_prediction_processors($cases);
return static::add_prediction_processors($cases);
}
/**
@@ -417,13 +417,13 @@ class prediction_test extends \advanced_testcase {
*
* @return array
*/
public function provider_ml_processors() {
public static function provider_ml_processors(): array {
$cases = [
'case' => [],
];
// We need to test all system prediction processors.
return $this->add_prediction_processors($cases);
return static::add_prediction_processors($cases);
}
/**
* Test the system classifiers returns.
@@ -507,7 +507,7 @@ class prediction_test extends \advanced_testcase {
*
* @return array
*/
public function provider_ml_classifiers_return() {
public static function provider_ml_classifiers_return(): array {
// Using verbose options as the first argument for readability.
$cases = array(
'1-samples' => array('maybe', 1, [0]),
@@ -517,7 +517,7 @@ class prediction_test extends \advanced_testcase {
);
// We need to test all system prediction processors.
return $this->add_prediction_processors($cases);
return static::add_prediction_processors($cases);
}
/**
@@ -581,13 +581,13 @@ class prediction_test extends \advanced_testcase {
*
* @return array
*/
public function provider_test_multi_classifier() {
public static function provider_test_multi_classifier(): array {
$cases = array(
'notimesplitting' => array('\core\analytics\time_splitting\no_splitting'),
);
// Add all system prediction processors.
return $this->add_prediction_processors($cases);
return static::add_prediction_processors($cases);
}
/**
@@ -777,8 +777,7 @@ class prediction_test extends \advanced_testcase {
*
* @return array
*/
public function provider_ml_test_evaluation_configuration() {
public static function provider_ml_test_evaluation_configuration(): array {
$cases = array(
'bad' => array(
'modelquality' => 'random',
@@ -797,7 +796,7 @@ class prediction_test extends \advanced_testcase {
)
)
);
return $this->add_prediction_processors($cases);
return static::add_prediction_processors($cases);
}
/**
@@ -955,8 +954,7 @@ class prediction_test extends \advanced_testcase {
* @param array $cases
* @return array
*/
protected function add_prediction_processors($cases) {
protected static function add_prediction_processors($cases): array {
$return = array();
if (defined('TEST_MLBACKEND_PYTHON_HOST') && defined('TEST_MLBACKEND_PYTHON_PORT')
+1 -1
View File
@@ -66,7 +66,7 @@ class auth_ldap_test extends \advanced_testcase {
*
* @return array[]
*/
public function auth_ldap_provider() {
public static function auth_ldap_provider(): array {
$pagesizes = [1, 3, 5, 1000];
$subcontexts = [0, 1];
$combinations = [];
+76 -73
View File
@@ -27,7 +27,7 @@ namespace auth_lti;
class auth_test extends \advanced_testcase {
/** @var string issuer URL used for test cases. */
protected $issuer = 'https://lms.example.org';
protected static string $issuer = 'https://lms.example.org';
/** @var int const representing cases where no PII is present. */
protected const PII_NONE = 0;
@@ -70,10 +70,13 @@ class auth_test extends \advanced_testcase {
* @param bool $includepicture whether to include a profile picture or not (slows tests, so defaults to false).
* @return array the users list.
*/
protected function get_mock_users_with_ids(array $ids,
string $role = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor', bool $includenames = true,
bool $includeemail = true, bool $includepicture = false): array {
protected static function get_mock_users_with_ids(
array $ids,
string $role = 'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',
bool $includenames = true,
bool $includeemail = true,
bool $includepicture = false,
): array {
$users = [];
foreach ($ids as $id) {
$user = [
@@ -91,7 +94,7 @@ class auth_test extends \advanced_testcase {
unset($user['email']);
}
if ($includepicture) {
$user['picture'] = $this->getExternalTestFileUrl('/test.jpg');
$user['picture'] = self::getExternalTestFileUrl('/test.jpg');
}
$users[] = $user;
}
@@ -137,7 +140,7 @@ class auth_test extends \advanced_testcase {
*/
protected function get_mock_launchdata_for_user(array $mockuser, array $mockmigration = []): array {
$data = [
'iss' => $this->issuer, // Must match registration in create_test_environment.
'iss' => self::$issuer, // Must match registration in create_test_environment.
'aud' => '123', // Must match registration in create_test_environment.
'sub' => $mockuser['user_id'], // User id on the platform site.
'exp' => time() + 60,
@@ -286,12 +289,12 @@ class auth_test extends \advanced_testcase {
*
* @return array the test case data.
*/
public function launch_data_provider(): array {
public static function launch_data_provider(): array {
return [
'New (unlinked) platform learner including PII, no legacy user, no migration claim' => [
'legacy_data' => null,
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -301,7 +304,7 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform learner excluding names, no legacy user, no migration claim' => [
'legacy_data' => null,
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false
@@ -312,7 +315,7 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform learner excluding emails, no legacy user, no migration claim' => [
'legacy_data' => null,
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
true,
@@ -324,7 +327,7 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform learner excluding all PII, no legacy user, no migration claim' => [
'legacy_data' => null,
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false,
@@ -345,7 +348,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -374,7 +377,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -396,7 +399,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -425,7 +428,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -454,7 +457,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -483,7 +486,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -512,7 +515,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -540,7 +543,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -569,7 +572,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false,
@@ -591,7 +594,7 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform instructor including PII, no legacy user, no migration claim' => [
'legacy_data' => null,
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor'
)[0],
@@ -601,7 +604,7 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform instructor excluding PII, no legacy user, no migration claim' => [
'legacy_data' => null,
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',
false,
@@ -622,7 +625,7 @@ class auth_test extends \advanced_testcase {
]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor'
)[0],
@@ -643,7 +646,7 @@ class auth_test extends \advanced_testcase {
'legacy_data' => null,
'launch_data' => [
'has_authenticated_before' => true,
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -654,7 +657,7 @@ class auth_test extends \advanced_testcase {
'legacy_data' => null,
'launch_data' => [
'has_authenticated_before' => true,
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false,
@@ -667,7 +670,7 @@ class auth_test extends \advanced_testcase {
'legacy_data' => null,
'launch_data' => [
'has_authenticated_before' => true,
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor'
)[0],
@@ -678,7 +681,7 @@ class auth_test extends \advanced_testcase {
'legacy_data' => null,
'launch_data' => [
'has_authenticated_before' => true,
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',
false,
@@ -691,7 +694,7 @@ class auth_test extends \advanced_testcase {
'legacy_data' => null,
'launch_data' => [
'has_authenticated_before' => false,
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',
false,
@@ -810,17 +813,17 @@ class auth_test extends \advanced_testcase {
*
* @return array the test case data.
*/
public function membership_data_provider(): array {
public static function membership_data_provider(): array {
return [
'New (unlinked) platform learner including PII, no legacy data, no consumer key bound, no legacy id' => [
'legacy_data' => null,
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => null,
'expected' => [
'PII' => self::PII_ALL,
@@ -830,14 +833,14 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform learner excluding PII, no legacy data, no consumer key bound, no legacy id' => [
'legacy_data' => null,
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false,
false
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => null,
'expected' => [
'PII' => self::PII_NONE,
@@ -847,13 +850,13 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform learner excluding names, no legacy data, no consumer key bound, no legacy id' => [
'legacy_data' => null,
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false,
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => null,
'expected' => [
'PII' => self::PII_EMAILS_ONLY,
@@ -863,14 +866,14 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform learner excluding email, no legacy data, no consumer key bound, no legacy id' => [
'legacy_data' => null,
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
true,
false
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => null,
'expected' => [
'PII' => self::PII_NAMES_ONLY,
@@ -885,13 +888,13 @@ class auth_test extends \advanced_testcase {
'consumer_key' => 'CONSUMER_1',
],
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
'legacy_user_id' => '123-abc'
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => 'CONSUMER_1',
'expected' => [
'PII' => self::PII_ALL,
@@ -906,12 +909,12 @@ class auth_test extends \advanced_testcase {
'consumer_key' => 'CONSUMER_1',
],
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => 'CONSUMER_1',
'expected' => [
'PII' => self::PII_ALL,
@@ -926,12 +929,12 @@ class auth_test extends \advanced_testcase {
'consumer_key' => 'CONSUMER_1',
],
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['123-abc'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => 'CONSUMER_1',
'expected' => [
'PII' => self::PII_ALL,
@@ -946,12 +949,12 @@ class auth_test extends \advanced_testcase {
'consumer_key' => 'CONSUMER_1',
],
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['123-abc'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => 'CONSUMER_ABCDEF',
'expected' => [
'PII' => self::PII_ALL,
@@ -966,13 +969,13 @@ class auth_test extends \advanced_testcase {
'consumer_key' => 'CONSUMER_1',
],
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
'legacy_user_id' => '123-abc'
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => null,
'expected' => [
'PII' => self::PII_ALL,
@@ -982,13 +985,13 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform learner including PII, no legacy data, consumer key bound, legacy user id sent' => [
'legacy_data' => null,
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
'legacy_user_id' => '123-abc'
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => 'CONSUMER_1',
'expected' => [
'PII' => self::PII_ALL,
@@ -998,12 +1001,12 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform instructor including PII, no legacy data, no consumer key bound, no legacy id' => [
'legacy_data' => null,
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor'
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => null,
'expected' => [
'PII' => self::PII_ALL,
@@ -1013,14 +1016,14 @@ class auth_test extends \advanced_testcase {
'New (unlinked) platform instructor excluding PII, no legacy data, no consumer key bound, no legacy id' => [
'legacy_data' => null,
'membership_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Instructor',
false,
false
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => null,
'expected' => [
'PII' => self::PII_NONE,
@@ -1031,12 +1034,12 @@ class auth_test extends \advanced_testcase {
'legacy_data' => null,
'launch_data' => [
'has_authenticated_before' => true,
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
],
'iss' => $this->issuer,
'iss' => self::$issuer,
'legacy_consumer_key' => null,
'expected' => [
'PII' => self::PII_ALL,
@@ -1056,7 +1059,7 @@ class auth_test extends \advanced_testcase {
global $DB;
$auth = get_auth_plugin('lti');
$user = $this->getDataGenerator()->create_user();
$mockiss = $this->issuer;
$mockiss = self::$issuer;
$mocksub = '1';
// Create a binding and verify it exists.
@@ -1068,7 +1071,7 @@ class auth_test extends \advanced_testcase {
$numusersbefore = $DB->count_records('user');
$matcheduser = $auth->find_or_create_user_from_launch(
$this->get_mock_launchdata_for_user(
$this->get_mock_users_with_ids([$mocksub])[0]
self::get_mock_users_with_ids([$mocksub])[0]
)
);
$numusersafter = $DB->count_records('user');
@@ -1148,17 +1151,17 @@ class auth_test extends \advanced_testcase {
*
* @return array the test case data.
*/
public function update_user_account_provider(): array {
public static function update_user_account_provider(): array {
return [
'Full PII included in both auths, no picture in either' => [
'first_launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -1171,7 +1174,7 @@ class auth_test extends \advanced_testcase {
],
'No PII included in both auths, no picture in either' => [
'first_launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false,
@@ -1179,7 +1182,7 @@ class auth_test extends \advanced_testcase {
)[0]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false,
@@ -1194,7 +1197,7 @@ class auth_test extends \advanced_testcase {
],
'First auth no PII, second auth including PII, no picture in either' => [
'first_launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false,
@@ -1202,7 +1205,7 @@ class auth_test extends \advanced_testcase {
)[0]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0],
@@ -1215,13 +1218,13 @@ class auth_test extends \advanced_testcase {
],
'First auth full PII, second auth no PII, no picture in either' => [
'first_launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
)[0]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false,
@@ -1236,13 +1239,13 @@ class auth_test extends \advanced_testcase {
],
'First auth full PII, second auth emails only, no picture in either' => [
'first_launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
)[0]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
false
@@ -1256,13 +1259,13 @@ class auth_test extends \advanced_testcase {
],
'First auth full PII, second auth names only, no picture in either' => [
'first_launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
)[0]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
true,
@@ -1277,13 +1280,13 @@ class auth_test extends \advanced_testcase {
],
'Full PII included in both auths, picture included in the second auth' => [
'first_launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner'
)[0]
],
'launch_data' => [
'user' => $this->get_mock_users_with_ids(
'user' => self::get_mock_users_with_ids(
['1'],
'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner',
true,
@@ -469,7 +469,7 @@ class condition_test extends \advanced_testcase {
$this->assertMatchesRegularExpression($description, $information);
}
public function previous_activity_data(): array {
public static function previous_activity_data(): array {
// Assign grade, condition, activity to complete, activity to test, result, resultnot, description.
return [
'Missing previous activity complete' => [
@@ -634,7 +634,7 @@ class condition_test extends \advanced_testcase {
}
public function section_previous_activity_data(): array {
public static function section_previous_activity_data(): array {
return [
// Condition, Activity completion, section to test, result, resultnot, description.
'Completion complete Section with no previous activity' => [
@@ -72,7 +72,7 @@ class frontend extends \core_availability\frontend {
require_once($CFG->libdir . '/grouplib.php');
if ($courseid != $this->allgroupscourseid) {
$this->allgroups = groups_get_all_groups($courseid, 0, 0, 'g.id, g.name');
$this->allgroups = groups_get_all_groups($courseid, 0, 0, 'g.id, g.name, g.visibility');
$this->allgroupscourseid = $courseid;
}
return $this->allgroups;
+38 -15
View File
@@ -557,10 +557,13 @@ class backup_course_structure_step extends backup_structure_step {
FROM {course_format_options}
WHERE courseid = ? AND sectionid = 0', [ backup::VAR_PARENTID ]);
$handler = core_course\customfield\course_handler::create();
$fieldsforbackup = $handler->get_instance_data_for_backup($this->task->get_courseid());
$handler->backup_define_structure($this->task->get_courseid(), $customfield);
$customfield->set_source_array($fieldsforbackup);
// Custom fields.
if ($this->get_setting_value('customfield')) {
$handler = core_course\customfield\course_handler::create();
$fieldsforbackup = $handler->get_instance_data_for_backup($this->task->get_courseid());
$handler->backup_define_structure($this->task->get_courseid(), $customfield);
$customfield->set_source_array($fieldsforbackup);
}
// Some annotations
@@ -1409,14 +1412,19 @@ class backup_groups_structure_step extends backup_structure_step {
FROM {groups} g
JOIN {backup_ids_temp} bi ON g.id = bi.itemid
WHERE bi.backupid = ?
AND bi.itemname = 'groupfinal'", array(backup::VAR_BACKUPID));
AND bi.itemname = 'groupfinal'",
[backup_helper::is_sqlparam($this->get_backupid())]
);
$grouping->set_source_sql("
SELECT g.*
FROM {groupings} g
JOIN {backup_ids_temp} bi ON g.id = bi.itemid
WHERE bi.backupid = ?
AND bi.itemname = 'groupingfinal'", array(backup::VAR_BACKUPID));
AND bi.itemname = 'groupingfinal'",
[backup_helper::is_sqlparam($this->get_backupid())]
);
$groupinggroup->set_source_table('groupings_groups', array('groupingid' => backup::VAR_PARENTID));
// This only happens if we are including users.
@@ -1424,9 +1432,20 @@ class backup_groups_structure_step extends backup_structure_step {
$member->set_source_table('groups_members', array('groupid' => backup::VAR_PARENTID));
}
$courseid = $this->task->get_courseid();
$groupcustomfield->set_source_array($this->get_group_custom_fields_for_backup($courseid));
$groupingcustomfield->set_source_array($this->get_grouping_custom_fields_for_backup($courseid));
// Custom fields.
if ($this->get_setting_value('customfield')) {
$groupcustomfieldarray = $this->get_group_custom_fields_for_backup(
$group->get_source_sql(),
[$this->get_backupid()]
);
$groupcustomfield->set_source_array($groupcustomfieldarray);
$groupingcustomfieldarray = $this->get_grouping_custom_fields_for_backup(
$grouping->get_source_sql(),
[$this->get_backupid()]
);
$groupingcustomfield->set_source_array($groupingcustomfieldarray);
}
}
// Define id annotations (as final)
@@ -1445,14 +1464,16 @@ class backup_groups_structure_step extends backup_structure_step {
/**
* Get custom fields array for group
* @param int $courseid
*
* @param string $groupsourcesql
* @param array $groupsourceparams
* @return array
*/
protected function get_group_custom_fields_for_backup(int $courseid): array {
protected function get_group_custom_fields_for_backup(string $groupsourcesql, array $groupsourceparams): array {
global $DB;
$handler = \core_group\customfield\group_handler::create();
$fieldsforbackup = [];
if ($groups = $DB->get_records('groups', ['courseid' => $courseid], '', 'id')) {
if ($groups = $DB->get_records_sql($groupsourcesql, $groupsourceparams)) {
foreach ($groups as $group) {
$fieldsforbackup = array_merge($fieldsforbackup, $handler->get_instance_data_for_backup($group->id));
}
@@ -1462,14 +1483,16 @@ class backup_groups_structure_step extends backup_structure_step {
/**
* Get custom fields array for grouping
* @param int $courseid
*
* @param string $groupingsourcesql
* @param array $groupingsourceparams
* @return array
*/
protected function get_grouping_custom_fields_for_backup(int $courseid): array {
protected function get_grouping_custom_fields_for_backup(string $groupingsourcesql, array $groupingsourceparams): array {
global $DB;
$handler = \core_group\customfield\grouping_handler::create();
$fieldsforbackup = [];
if ($groupings = $DB->get_records('groupings', ['courseid' => $courseid], '', 'id')) {
if ($groupings = $DB->get_records_sql($groupingsourcesql, $groupingsourceparams)) {
foreach ($groupings as $grouping) {
$fieldsforbackup = array_merge($fieldsforbackup, $handler->get_instance_data_for_backup($grouping->id));
}
@@ -380,7 +380,8 @@ abstract class restore_qtype_plugin extends restore_plugin {
*
* Only common stuff to all plugins, in this case:
* - question: text and feedback
* - question_answers: text and feedbak
* - question_answers: text and feedback
* - question_hints: hint
*
* Note each qtype will have, if needed, its own define_decode_contents method
*/
@@ -388,8 +389,9 @@ abstract class restore_qtype_plugin extends restore_plugin {
$contents = array();
$contents[] = new restore_decode_content('question', array('questiontext', 'generalfeedback'), 'question_created');
$contents[] = new restore_decode_content('question_answers', array('answer', 'feedback'), 'question_answer');
$contents[] = new restore_decode_content('question', ['questiontext', 'generalfeedback'], 'question_created');
$contents[] = new restore_decode_content('question_answers', ['answer', 'feedback'], 'question_answer');
$contents[] = new restore_decode_content('question_hints', ['hint'], 'question_hint');
return $contents;
}
+9 -1
View File
@@ -300,8 +300,16 @@ class restore_root_task extends restore_task {
$competencies->set_ui(new backup_setting_ui_checkbox($competencies, get_string('rootsettingcompetencies', 'backup')));
$this->add_setting($competencies);
$customfields = new restore_customfield_setting('customfields', base_setting::IS_BOOLEAN, $defaultvalue);
// Custom fields.
$defaultvalue = false;
$changeable = false;
if (isset($rootsettings['customfield']) && $rootsettings['customfield']) { // Only enabled when available.
$defaultvalue = true;
$changeable = true;
}
$customfields = new restore_customfield_setting('customfield', base_setting::IS_BOOLEAN, $defaultvalue);
$customfields->set_ui(new backup_setting_ui_checkbox($customfields, get_string('rootsettingcustomfield', 'backup')));
$customfields->get_ui()->set_changeable($changeable);
$this->add_setting($customfields);
// Define Content bank content.
+121 -115
View File
@@ -1159,11 +1159,15 @@ class restore_groups_structure_step extends restore_structure_step {
$groupinfo = $this->get_setting_value('groups');
if ($groupinfo) {
$paths[] = new restore_path_element('group', '/groups/group');
$paths[] = new restore_path_element('groupcustomfield', '/groups/groupcustomfields/groupcustomfield');
$paths[] = new restore_path_element('grouping', '/groups/groupings/grouping');
$paths[] = new restore_path_element('groupingcustomfield',
'/groups/groupings/groupingcustomfields/groupingcustomfield');
$paths[] = new restore_path_element('grouping_group', '/groups/groupings/grouping/grouping_groups/grouping_group');
// Custom fields.
if ($this->get_setting_value('customfield')) {
$paths[] = new restore_path_element('groupcustomfield', '/groups/groupcustomfields/groupcustomfield');
$paths[] = new restore_path_element('groupingcustomfield',
'/groups/groupings/groupingcustomfields/groupingcustomfield');
}
}
return $paths;
}
@@ -1235,9 +1239,11 @@ class restore_groups_structure_step extends restore_structure_step {
*/
public function process_groupcustomfield($data) {
$newgroup = $this->get_mapping('group', $data['groupid']);
$data['groupid'] = $newgroup->newitemid ?? $data['groupid'];
$handler = \core_group\customfield\group_handler::create();
$handler->restore_instance_data_from_backup($this->task, $data);
if ($newgroup && $newgroup->newitemid) {
$data['groupid'] = $newgroup->newitemid;
$handler = \core_group\customfield\group_handler::create();
$handler->restore_instance_data_from_backup($this->task, $data);
}
}
public function process_grouping($data) {
@@ -1291,10 +1297,12 @@ class restore_groups_structure_step extends restore_structure_step {
* @return void
*/
public function process_groupingcustomfield($data) {
$newgroup = $this->get_mapping('grouping', $data['groupingid']);
$data['groupingid'] = $newgroup->newitemid ?? $data['groupingid'];
$handler = \core_group\customfield\grouping_handler::create();
$handler->restore_instance_data_from_backup($this->task, $data);
$newgrouping = $this->get_mapping('grouping', $data['groupingid']);
if ($newgrouping && $newgrouping->newitemid) {
$data['groupingid'] = $newgrouping->newitemid;
$handler = \core_group\customfield\grouping_handler::create();
$handler->restore_instance_data_from_backup($this->task, $data);
}
}
public function process_grouping_group($data) {
@@ -1832,12 +1840,19 @@ class restore_course_structure_step extends restore_structure_step {
protected function define_structure() {
$paths = [];
$course = new restore_path_element('course', '/course');
$category = new restore_path_element('category', '/course/category');
$tag = new restore_path_element('tag', '/course/tags/tag');
$customfield = new restore_path_element('customfield', '/course/customfields/customfield');
$courseformatoptions = new restore_path_element('course_format_option', '/course/courseformatoptions/courseformatoption');
$allowedmodule = new restore_path_element('allowed_module', '/course/allowed_modules/module');
$paths[] = $course;
$paths[] = new restore_path_element('category', '/course/category');
$paths[] = new restore_path_element('tag', '/course/tags/tag');
$paths[] = new restore_path_element('course_format_option', '/course/courseformatoptions/courseformatoption');
$paths[] = new restore_path_element('allowed_module', '/course/allowed_modules/module');
// Custom fields.
if ($this->get_setting_value('customfield')) {
$paths[] = new restore_path_element('customfield', '/course/customfields/customfield');
}
// Apply for 'format' plugins optional paths at course level
$this->add_plugin_structure('format', $course);
@@ -1860,7 +1875,7 @@ class restore_course_structure_step extends restore_structure_step {
// Apply for admin tool plugins optional paths at course level.
$this->add_plugin_structure('tool', $course);
return array($course, $category, $tag, $customfield, $allowedmodule, $courseformatoptions);
return $paths;
}
/**
@@ -4921,6 +4936,12 @@ class restore_create_categories_and_questions extends restore_structure_step {
/** @var array $cachedcategory store a question category */
protected $cachedcategory = null;
/** @var stdClass the last question_bank_entry seen during the restore. Processed when we get to a question. */
protected $latestqbe;
/** @var stdClass the last question_version seen during the restore. Processed when we get to a question. */
protected $latestversion;
protected function define_structure() {
// Check if the backup is a pre 4.0 one.
@@ -5046,45 +5067,25 @@ class restore_create_categories_and_questions extends restore_structure_step {
}
/**
* Process pre 4.0 question data where in creates the record for version and entry table.
* Set up date to allow restore of questions from pre-4.0 backups.
*
* @param array $data the data from the XML file.
* @param stdClass $data the data from the XML file.
*/
protected function process_question_legacy_data($data) {
global $DB;
$this->latestqbe = (object) [
'id' => $data->id,
'questioncategoryid' => $data->category,
'ownerid' => $data->createdby,
'idnumber' => $data->idnumber ?? null,
];
$oldid = $data->id;
// Process question bank entry.
$entrydata = new stdClass();
$entrydata->questioncategoryid = $data->category;
$userid = $this->get_mappingid('user', $data->createdby);
if ($userid) {
$entrydata->ownerid = $userid;
} else {
if (!$this->task->is_samesite()) {
$entrydata->ownerid = $this->task->get_userid();
}
}
// The idnumber if it exists also needs to be unique within a category or reset it to null.
if (isset($data->idnumber) && !$DB->record_exists('question_bank_entries',
['idnumber' => $data->idnumber, 'questioncategoryid' => $data->category])) {
$entrydata->idnumber = $data->idnumber;
}
$newentryid = $DB->insert_record('question_bank_entries', $entrydata);
// Process question versions.
$versiondata = new stdClass();
$versiondata->questionbankentryid = $newentryid;
$versiondata->version = 1;
// Question id is updated after inserting the question.
$versiondata->questionid = 0;
$versionstatus = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY;
if ((int)$data->hidden === 1) {
$versionstatus = \core_question\local\bank\question_version_status::QUESTION_STATUS_HIDDEN;
}
$versiondata->status = $versionstatus;
$newversionid = $DB->insert_record('question_versions', $versiondata);
$this->set_mapping('question_version_created', $oldid, $newversionid);
$this->latestversion = (object) [
'id' => $data->id,
'version' => 1,
'status' => $data->hidden ?
\core_question\local\bank\question_version_status::QUESTION_STATUS_HIDDEN :
\core_question\local\bank\question_version_status::QUESTION_STATUS_READY,
];
}
/**
@@ -5093,37 +5094,9 @@ class restore_create_categories_and_questions extends restore_structure_step {
* @param array $data the data from the XML file.
*/
protected function process_question_bank_entry($data) {
global $DB;
$data = (object)$data;
$oldid = $data->id;
$questioncreated = $this->get_mappingid('question_category_created', $data->questioncategoryid) ? true : false;
$recordexist = $DB->record_exists('question_bank_entries', ['id' => $data->id,
'questioncategoryid' => $data->questioncategoryid]);
// Check we have category created.
if (!$questioncreated && $recordexist) {
return self::SKIP_ALL_CHILDREN;
}
$data->questioncategoryid = $this->get_new_parentid('question_category');
$userid = $this->get_mappingid('user', $data->ownerid);
if ($userid) {
$data->ownerid = $userid;
} else {
if (!$this->task->is_samesite()) {
$data->ownerid = $this->task->get_userid();
}
}
// The idnumber if it exists also needs to be unique within a category or reset it to null.
if (!empty($data->idnumber) && $DB->record_exists('question_bank_entries',
['idnumber' => $data->idnumber, 'questioncategoryid' => $data->questioncategoryid])) {
unset($data->idnumber);
}
$newitemid = $DB->insert_record('question_bank_entries', $data);
$this->set_mapping('question_bank_entry', $oldid, $newitemid);
// We can only determine the right way to process this once we get to
// process_question and have more information, so for now just store.
$this->latestqbe = (object) $data;
}
/**
@@ -5132,16 +5105,9 @@ class restore_create_categories_and_questions extends restore_structure_step {
* @param array $data the data from the XML file.
*/
protected function process_question_versions($data) {
global $DB;
$data = (object)$data;
$oldid = $data->id;
$data->questionbankentryid = $this->get_new_parentid('question_bank_entry');
// Question id is updated after inserting the question.
$data->questionid = 0;
$newitemid = $DB->insert_record('question_versions', $data);
$this->set_mapping('question_versions', $oldid, $newitemid);
// We can only determine the right way to process this once we get to
// process_question and have more information, so for now just store.
$this->latestversion = (object) $data;
}
/**
@@ -5152,17 +5118,19 @@ class restore_create_categories_and_questions extends restore_structure_step {
protected function process_question($data) {
global $DB;
$data = (object)$data;
$data = (object) $data;
$oldid = $data->id;
// Check if the backup is a pre 4.0 one.
// Check we have one mapping for this question.
if (!$questionmapping = $this->get_mapping('question', $oldid)) {
// No mapping = this question doesn't need to be created/mapped.
return;
}
// Check if this is a pre 4.0 backup, then there will not be a question bank entry
// or question version in the file. So, we need to set up that data ready to be used below.
$restoretask = $this->get_task();
if ($restoretask->backup_release_compare('4.0', '<') || $restoretask->backup_version_compare(20220202, '<')) {
// Check we have one mapping for this question.
if (!$questionmapping = $this->get_mapping('question', $oldid)) {
return; // No mapping = this question doesn't need to be created/mapped.
}
// Get the mapped category (cannot use get_new_parentid() because not
// all the categories have been created, so it is not always available
// Instead we get the mapping for the question->parentitemid because
@@ -5206,28 +5174,66 @@ class restore_create_categories_and_questions extends restore_structure_step {
}
}
$newitemid = $DB->insert_record('question', $data);
$this->set_mapping('question', $oldid, $newitemid);
// Also annotate them as question_created, we need
// that later when remapping parents (keeping the old categoryid as parentid).
$parentcatid = $this->get_old_parentid('question_category');
$this->set_mapping('question_created', $oldid, $newitemid, false, null, $parentcatid);
// Now update the question_versions table with the new question id. we dont need to do that for random qtypes.
$legacyquestiondata = $this->get_mappingid('question_version_created', $oldid) ? true : false;
if ($legacyquestiondata) {
$parentitemid = $this->get_mappingid('question_version_created', $oldid);
// With newitemid = 0, let's create the question.
if (!$questionmapping->newitemid) {
// Now we know we are inserting a question, we may need to insert the questionbankentry.
if (empty($this->latestqbe->newid)) {
$this->latestqbe->oldid = $this->latestqbe->id;
$this->latestqbe->questioncategoryid = $this->get_new_parentid('question_category');
$userid = $this->get_mappingid('user', $this->latestqbe->ownerid);
if ($userid) {
$this->latestqbe->ownerid = $userid;
} else {
if (!$this->task->is_samesite()) {
$this->latestqbe->ownerid = $this->task->get_userid();
}
}
// The idnumber if it exists also needs to be unique within a category or reset it to null.
if (!empty($this->latestqbe->idnumber) && $DB->record_exists('question_bank_entries',
['idnumber' => $this->latestqbe->idnumber, 'questioncategoryid' => $this->latestqbe->questioncategoryid])) {
unset($this->latestqbe->idnumber);
}
$this->latestqbe->newid = $DB->insert_record('question_bank_entries', $this->latestqbe);
$this->set_mapping('question_bank_entry', $this->latestqbe->oldid, $this->latestqbe->newid);
}
// Now store the question.
$newitemid = $DB->insert_record('question', $data);
$this->set_mapping('question', $oldid, $newitemid);
// Also annotate them as question_created, we need
// that later when remapping parents (keeping the old categoryid as parentid).
$parentcatid = $this->get_old_parentid('question_category');
$this->set_mapping('question_created', $oldid, $newitemid, false, null, $parentcatid);
// Also insert this question_version.
$oldqvid = $this->latestversion->id;
$this->latestversion->questionbankentryid = $this->latestqbe->newid;
$this->latestversion->questionid = $newitemid;
$newqvid = $DB->insert_record('question_versions', $this->latestversion);
$this->set_mapping('question_versions', $oldqvid, $newqvid);
} else {
$parentitemid = $this->get_new_parentid('question_versions');
// By performing this set_mapping() we make get_old/new_parentid() to work for all the
// children elements of the 'question' one (so qtype plugins will know the question they belong to).
$this->set_mapping('question', $oldid, $questionmapping->newitemid);
// Also create the question_bank_entry and version mappings, if required.
$newquestionversion = $DB->get_record('question_versions', ['questionid' => $questionmapping->newitemid]);
$this->set_mapping('question_versions', $this->latestversion->id, $newquestionversion->id);
if (empty($this->latestqbe->newid)) {
$this->latestqbe->oldid = $this->latestqbe->id;
$this->latestqbe->newid = $newquestionversion->questionbankentryid;
$this->set_mapping('question_bank_entry', $this->latestqbe->oldid, $this->latestqbe->newid);
}
}
$version = new stdClass();
$version->id = $parentitemid;
$version->questionid = $newitemid;
$DB->update_record('question_versions', $version);
// Note, we don't restore any question files yet
// as far as the CONTEXT_MODULE categories still
// haven't their contexts to be restored to
// The {@link restore_create_question_files}, executed in the final step
// The {@see restore_create_question_files}, executed in the final
// step will be in charge of restoring all the question files.
}
@@ -49,7 +49,7 @@ class backup_xml_transformer_test extends \advanced_testcase {
*
* @return array
*/
public function filephp_links_replace_data_provider() {
public static function filephp_links_replace_data_provider(): array {
return array(
array('http://test.test/', 'http://test.test/'),
array('http://test.test/file.php/1', 'http://test.test/file.php/1'),
@@ -37,12 +37,13 @@ class restore_gradebook_structure_step_test extends \advanced_testcase {
*
* @return array
*/
public function rewrite_step_backup_file_for_legacy_freeze_provider() {
public static function rewrite_step_backup_file_for_legacy_freeze_provider(): array {
$fixturesdir = realpath(__DIR__ . '/fixtures/rewrite_step_backup_file_for_legacy_freeze/');
$tests = [];
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($fixturesdir),
\RecursiveIteratorIterator::LEAVES_ONLY);
new \RecursiveDirectoryIterator($fixturesdir),
\RecursiveIteratorIterator::LEAVES_ONLY,
);
foreach ($iterator as $sourcefile) {
$pattern = '/\.test$/';
@@ -556,6 +556,7 @@ abstract class backup_controller_dbops extends backup_dbops {
'backup_general_role_assignments' => 'role_assignments',
'backup_general_activities' => 'activities',
'backup_general_blocks' => 'blocks',
'backup_general_files' => 'files',
'backup_general_filters' => 'filters',
'backup_general_comments' => 'comments',
'backup_general_badges' => 'badges',
@@ -566,6 +567,7 @@ abstract class backup_controller_dbops extends backup_dbops {
'backup_general_questionbank' => 'questionbank',
'backup_general_groups' => 'groups',
'backup_general_competencies' => 'competencies',
'backup_general_customfield' => 'customfield',
'backup_general_contentbankcontent' => 'contentbankcontent',
'backup_general_xapistate' => 'xapistate',
'backup_general_legacyfiles' => 'legacyfiles'
@@ -583,6 +585,7 @@ abstract class backup_controller_dbops extends backup_dbops {
'backup_import_questionbank' => 'questionbank',
'backup_import_groups' => 'groups',
'backup_import_competencies' => 'competencies',
'backup_import_customfield' => 'customfield',
'backup_import_contentbankcontent' => 'contentbankcontent',
'backup_import_legacyfiles' => 'legacyfiles'
);
@@ -606,6 +609,7 @@ abstract class backup_controller_dbops extends backup_dbops {
'backup_auto_role_assignments' => 'role_assignments',
'backup_auto_activities' => 'activities',
'backup_auto_blocks' => 'blocks',
'backup_auto_files' => 'files',
'backup_auto_filters' => 'filters',
'backup_auto_comments' => 'comments',
'backup_auto_badges' => 'badges',
@@ -616,6 +620,7 @@ abstract class backup_controller_dbops extends backup_dbops {
'backup_auto_questionbank' => 'questionbank',
'backup_auto_groups' => 'groups',
'backup_auto_competencies' => 'competencies',
'backup_auto_customfield' => 'customfield',
'backup_auto_contentbankcontent' => 'contentbankcontent',
'backup_auto_xapistate' => 'xapistate',
'backup_auto_legacyfiles' => 'legacyfiles'
@@ -159,6 +159,7 @@ abstract class restore_controller_dbops extends restore_dbops {
'restore_general_questionbank' => 'questionbank',
'restore_general_groups' => 'groups',
'restore_general_competencies' => 'competencies',
'restore_general_customfield' => 'customfield',
'restore_general_contentbankcontent' => 'contentbankcontent',
'restore_general_xapistate' => 'xapistate',
'restore_general_legacyfiles' => 'legacyfiles'
+3 -4
View File
@@ -671,8 +671,7 @@ abstract class restore_dbops {
$questions = self::restore_get_questions($restoreid, $category->id);
// Collect all the questions for this category into memory so we only talk to the DB once.
$questioncache = $DB->get_records_sql_menu('SELECT q.id,
q.stamp
$questioncache = $DB->get_records_sql_menu('SELECT q.stamp, q.id
FROM {question} q
JOIN {question_versions} qv
ON qv.questionid = q.id
@@ -683,8 +682,8 @@ abstract class restore_dbops {
WHERE qc.id = ?', array($matchcat->id));
foreach ($questions as $question) {
if (isset($questioncache[$question->stamp." ".$question->version])) {
$matchqid = $questioncache[$question->stamp." ".$question->version];
if (isset($questioncache[$question->stamp])) {
$matchqid = $questioncache[$question->stamp];
} else {
$matchqid = false;
}
@@ -124,8 +124,7 @@ class restore_dbops_test extends \advanced_testcase {
/**
* Data provider for {@link test_precheck_user()}
*/
public function precheck_user_provider() {
public static function precheck_user_provider(): array {
$emailmultiplier = [
'shortmail' => 'normalusername@example.com',
'longmail' => str_repeat('a', 100) // It's not validated, hence any string is ok.
@@ -135,7 +134,7 @@ class restore_dbops_test extends \advanced_testcase {
foreach ($emailmultiplier as $emailk => $email) {
// Get the related cases.
$cases = $this->precheck_user_cases($email);
$cases = self::precheck_user_cases($email);
// Rename them (keys).
foreach ($cases as $key => $case) {
$providercases[$key . ' - ' . $emailk] = $case;
@@ -150,7 +149,7 @@ class restore_dbops_test extends \advanced_testcase {
*
* @param string $email
*/
private function precheck_user_cases($email) {
private static function precheck_user_cases($email) {
global $CFG;
$baseuserarr = [
@@ -35,22 +35,35 @@ require_once($CFG->dirroot.'/backup/util/xml/parser/processors/grouped_parser_pr
* TODO: Complete phpdocs
*/
class restore_questions_parser_processor extends grouped_parser_processor {
/** @var string XML path in the questions.xml backup file to question categories. */
protected const CATEGORY_PATH = '/question_categories/question_category';
protected $restoreid;
protected $lastcatid;
/** @var string XML path in the questions.xml to question elements within question_category (Moodle 4.0+). */
protected const QUESTION_SUBPATH =
'/question_bank_entries/question_bank_entry/question_version/question_versions/questions/question';
/** @var string XML path in the questions.xml to question elements within question_category (before Moodle 4.0). */
protected const LEGACY_QUESTION_SUBPATH = '/questions/question';
/** @var string identifies the current restore. */
protected string $restoreid;
/** @var int during the restore, this tracks the last category we saw. Any questions we see will be in here. */
protected int $lastcatid;
public function __construct($restoreid) {
$this->restoreid = $restoreid;
$this->lastcatid = 0;
parent::__construct(array());
parent::__construct();
// Set the paths we are interested on
$this->add_path('/question_categories/question_category');
$this->add_path('/question_categories/question_category/questions/question');
$this->add_path(self::CATEGORY_PATH);
$this->add_path(self::CATEGORY_PATH . self::QUESTION_SUBPATH);
$this->add_path(self::CATEGORY_PATH . self::LEGACY_QUESTION_SUBPATH);
}
protected function dispatch_chunk($data) {
// Prepare question_category record
if ($data['path'] == '/question_categories/question_category') {
if ($data['path'] == self::CATEGORY_PATH) {
$info = (object)$data['tags'];
$itemname = 'question_category';
$itemid = $info->id;
@@ -58,7 +71,8 @@ class restore_questions_parser_processor extends grouped_parser_processor {
$this->lastcatid = $itemid;
// Prepare question record
} else if ($data['path'] == '/question_categories/question_category/questions/question') {
} else if ($data['path'] == self::CATEGORY_PATH . self::QUESTION_SUBPATH ||
$data['path'] == self::CATEGORY_PATH . self::LEGACY_QUESTION_SUBPATH) {
$info = (object)$data['tags'];
$itemname = 'question';
$itemid = $info->id;
@@ -53,7 +53,7 @@ class restore_structure_parser_processor_test extends advanced_testcase {
*
* @return array
*/
public function process_cdata_data_provider() {
public static function process_cdata_data_provider(): array {
return array(
array(null, null, true),
array("$@NULL@$", null, true),
@@ -77,8 +77,8 @@ class badges extends system_report {
$this->add_filters();
$this->add_actions();
// Set initial sorting by name.
$this->set_initial_sort_column('badge:namewithlink', SORT_ASC);
$this->set_default_no_results_notice(new lang_string('nomatchingbadges', 'core_badges'));
// Set if report can be downloaded.
$this->set_downloadable(false);
@@ -157,13 +157,12 @@ class badges extends system_report {
* unique identifier
*/
protected function add_filters(): void {
$filters = [
$this->add_filters_from_entities([
'badge:name',
'badge:version',
'badge:status',
'badge:expiry',
];
$this->add_filters_from_entities($filters);
]);
}
/**
@@ -18,8 +18,10 @@ declare(strict_types=1);
namespace core_badges\reportbuilder\local\systemreports;
use core\context\system;
use core_badges\reportbuilder\local\entities\badge;
use core_badges\reportbuilder\local\entities\badge_issued;
use core_reportbuilder\local\helpers\database;
use core_reportbuilder\system_report;
use lang_string;
use moodle_url;
@@ -52,11 +54,18 @@ class course_badges extends system_report {
$this->set_main_table('badge', $entityalias);
$this->add_entity($badgeentity);
$type = $this->get_parameter('type', 0, PARAM_INT);
$courseid = $this->get_parameter('courseid', 0, PARAM_INT);
$paramtype = database::generate_param_name();
$context = $this->get_context();
if ($context instanceof system) {
$type = BADGE_TYPE_SITE;
$this->add_base_condition_sql("{$entityalias}.type = :$paramtype", [$paramtype => $type]);
} else {
$type = BADGE_TYPE_COURSE;
$paramcourseid = database::generate_param_name();
$this->add_base_condition_sql("{$entityalias}.type = :$paramtype AND {$entityalias}.courseid = :$paramcourseid",
[$paramtype => $type, $paramcourseid => $context->instanceid]);
}
$this->add_base_condition_simple('type', $type);
$this->add_base_condition_simple('courseid', $courseid);
$this->add_base_condition_sql("({$entityalias}.status = " . BADGE_STATUS_ACTIVE .
" OR {$entityalias}.status = " . BADGE_STATUS_ACTIVE_LOCKED . ")");
@@ -70,9 +79,12 @@ class course_badges extends system_report {
$this->add_base_fields("{$badgeissuedalias}.uniquehash");
// Now we can call our helper methods to add the content we want to include in the report.
$this->add_columns($badgeissuedalias);
$this->add_columns();
$this->add_filters();
$this->set_initial_sort_column('badge:name', SORT_ASC);
$this->set_default_no_results_notice(new lang_string('nomatchingbadges', 'core_badges'));
// Set if report can be downloaded.
$this->set_downloadable(false);
}
@@ -91,18 +103,17 @@ class course_badges extends system_report {
*
* They are provided by the entities we previously added in the {@see initialise} method, referencing each by their
* unique identifier. If custom columns are needed just for this report, they can be defined here.
*
* @param string $badgeissuedalias
*/
public function add_columns(string $badgeissuedalias): void {
$columns = [
protected function add_columns(): void {
$badgeissuedalias = $this->get_entity('badge_issued')->get_table_alias('badge_issued');
$this->add_columns_from_entities([
'badge:image',
'badge:name',
'badge:description',
'badge:criteria',
'badge_issued:issued',
];
$this->add_columns_from_entities($columns);
]);
$this->get_column('badge_issued:issued')
->set_title(new lang_string('awardedtoyou', 'core_badges'))
@@ -119,8 +130,6 @@ class course_badges extends system_report {
$icon = new pix_icon('i/valid', get_string('dateearned', 'badges', $date));
return $OUTPUT->action_icon($badgeurl, $icon, null, null, true);
});
$this->set_initial_sort_column('badge:name', SORT_ASC);
}
/**
@@ -130,11 +139,9 @@ class course_badges extends system_report {
* unique identifier
*/
protected function add_filters(): void {
$filters = [
$this->add_filters_from_entities([
'badge:name',
'badge_issued:issued',
];
$this->add_filters_from_entities($filters);
]);
}
}
@@ -62,6 +62,9 @@ class recipients extends system_report {
$this->add_filters();
$this->add_actions();
$this->set_initial_sort_column('badge_issued:issued', SORT_DESC);
$this->set_default_no_results_notice(new lang_string('nomatchingawards', 'core_badges'));
// Set if report can be downloaded.
$this->set_downloadable(false);
}
@@ -72,7 +75,9 @@ class recipients extends system_report {
* @return bool
*/
protected function can_view(): bool {
return has_capability('moodle/badges:viewawarded', $this->get_context());
$badgeid = $this->get_parameter('badgeid', 0, PARAM_INT);
$badge = new \core_badges\badge($badgeid);
return has_capability('moodle/badges:viewawarded', $badge->get_context());
}
/**
@@ -81,14 +86,11 @@ class recipients extends system_report {
* They are provided by the entities we previously added in the {@see initialise} method, referencing each by their
* unique identifier. If custom columns are needed just for this report, they can be defined here.
*/
public function add_columns(): void {
$columns = [
protected function add_columns(): void {
$this->add_columns_from_entities([
'user:fullnamewithlink',
'badge_issued:issued',
];
$this->add_columns_from_entities($columns);
$this->set_initial_sort_column('badge_issued:issued', SORT_DESC);
]);
}
/**
@@ -98,12 +100,10 @@ class recipients extends system_report {
* unique identifier
*/
protected function add_filters(): void {
$filters = [
$this->add_filters_from_entities([
'user:fullname',
'badge_issued:issued',
];
$this->add_filters_from_entities($filters);
]);
}
/**
+2 -2
View File
@@ -89,6 +89,8 @@ if (!has_any_capability(array(
}
$PAGE->set_title($hdr);
/** @var core_badges_renderer $output */
$output = $PAGE->get_renderer('core', 'badges');
if ($delete || $archive) {
@@ -159,8 +161,6 @@ if ($msg !== '') {
}
$report = system_report_factory::create(badges::class, $PAGE->context);
$report->set_default_no_results_notice(new lang_string('nobadges', 'badges'));
echo $report->output();
echo $OUTPUT->footer();

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