Compare commits

...

713 Commits

Author SHA1 Message Date
Huong Nguyen e6505da61a Moodle release 5.0.6 2026-02-11 08:44:56 +07:00
Huong Nguyen 55d43fe137 weekly release 5.0.5+ 2026-02-10 08:41:45 +07:00
Shamim Rezaie 8f07ef57be Merge branch 'MDL-87892-500' of https://github.com/HuongNV13/moodle into MOODLE_500_STABLE 2026-02-09 21:07:33 +11:00
Huong Nguyen 8fe771bb9f MDL-87892 admin: Fix MoodleNet check 2026-02-09 16:33:27 +07:00
Shamim Rezaie caaa3a4824 Merge branch 'MDL-87892-500' of https://github.com/HuongNV13/moodle into MOODLE_500_STABLE 2026-02-09 19:36:52 +11:00
Huong Nguyen fb3565e79b MDL-87892 admin: Fix MoodleNet removal warning
Instead of introducing a new optional parameter,
we will make all the changes in the Admin Renderer
2026-02-09 09:05:03 +07:00
Huong Nguyen e1c3872f65 Moodle release 5.0.5 2026-02-06 09:16:50 +07:00
Huong Nguyen cbd5285963 NOBUG: Add upgrade notes 2026-02-06 09:16:50 +07:00
Mihail Geshoski 6dd7b7e490 weekly release 5.0.4+ 2026-02-05 20:23:41 +08:00
Mihail Geshoski 16b222ce6e NOBUG: Add upgrade notes 2026-02-05 20:23:41 +08:00
Mihail Geshoski 244efc0522 Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2026-02-05 20:23:25 +08:00
Paul Holden 503411d6b6 MDL-87870 admin: tighten up validation of colour picker values. 2026-02-05 17:26:33 +07:00
Paul Holden 82f8c9f6c6 MDL-87870 filter_tex: escape background argument content. 2026-02-05 17:26:32 +07:00
Huong Nguyen dc74dfcac4 Merge branch 'MDL-87352-500' of https://github.com/andimendunia/moodle into MOODLE_500_STABLE 2026-02-05 17:26:32 +07:00
Mihail Geshoski f9f0033ce4 Merge branch 'MDL-87258-500' of https://github.com/rjnl/moodle into MOODLE_500_STABLE 2026-02-05 17:26:32 +07:00
Jun Pataleta de33246b7b Merge branch 'MDL-87757-500' of https://github.com/muhammadarnaldo/moodle into MOODLE_500_STABLE 2026-02-05 17:26:32 +07:00
yusufwib01 5d0eab1555 MDL-86785 tiny_equation: Add timeout handling for mimetex execution 2026-02-05 12:03:16 +08:00
Mihail Geshoski 05b4ca7dac Merge branch 'MDL-86437-500' of https://github.com/snake/moodle into MOODLE_500_STABLE 2026-02-05 12:03:16 +08:00
Huong Nguyen 40af5cd52d MDL-87843 filter_tex: Switch to use Colour picker setting
This will allow users to easily choose the background colour
and prevent invalid input values
2026-02-05 12:03:16 +08:00
Paul Holden ea1b0eb4e1 MDL-87612 repository: safer unserializing of file source data. 2026-02-05 12:03:16 +08:00
Mihail Geshoski 071504114a Merge branch 'MDL-87789-500' of https://github.com/snake/moodle into MOODLE_500_STABLE 2026-02-05 12:03:16 +08:00
Shamim Rezaie 77637bfb26 Merge branch 'MDL-86444_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2026-02-05 12:03:15 +08:00
Muhammad Arnaldo ed57a7c2c7 MDL-87757 block_myoverview: Remove navigation role and behat update
- Removal of the navigation role on main and zero-state template
- Add accessibility extra tests for the block_overview
2026-02-04 10:11:46 +07:00
Muhammad Arnaldo 1c17ab4277 MDL-87757 block_myoverview: fix the heading-order 2026-02-04 10:11:46 +07:00
Andi Permana 119cb76523 MDL-87352 admin: Add MoodleNet removal warnings 2026-02-04 10:06:33 +07:00
AMOS bot 2ae0229827 Automatically generated installer lang files 2026-02-04 00:07:38 +00:00
Jun Pataleta 5f7e9e3c6b Merge branch 'MDL-83984_500' of https://github.com/santoshndev/moodle into MOODLE_500_STABLE 2026-02-03 17:06:37 +08:00
Jake Dallimore 77ce015cc4 Merge branch 'MDL-85535-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2026-02-03 16:59:33 +08:00
Jun Pataleta de163f6f42 Merge branch 'MDL-87185-500' of https://github.com/durenadev/moodle into MOODLE_500_STABLE 2026-02-03 16:50:03 +08:00
Jun Pataleta f98ff41818 Merge branch 'MDL-87593-500-enfix' of https://github.com/mudrd8mz/moodle into MOODLE_500_STABLE 2026-02-03 16:47:36 +08:00
Jun Pataleta e03bd88e9a Merge branch 'MDL-77162-filepicker-a11y-tab-order-repository-keyboard-selection-M5.0' of https://github.com/stopfstedt/moodle into MOODLE_500_STABLE 2026-02-03 16:44:05 +08:00
Jun Pataleta bd3bae8b9c Merge branch 'MDL-87694-course-participant-profile-missing-heading-M5.0' of https://github.com/stopfstedt/moodle into MOODLE_500_STABLE 2026-02-03 15:18:08 +08:00
Rajneel Totaram 47a7db0a69 MDL-87258 mod_lti: request access for PNA
Since Chrome 142, public servers accessing resources on local networks
gets blocked by default. Users need to allow access for such requests
to proceed.

This patch introduces a new config setting `ltiallowlocalnetwork`.
This determines if the local-network-access flag should be added to LTI
iframes so that Chrome users get prompted when a local network access
is being made.
2026-02-03 18:49:01 +12:00
Mihail Geshoski cd55b35362 Merge branch 'MDL-87606_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2026-02-03 14:22:36 +08:00
Mihail Geshoski 049c2636c0 Merge branch 'MDL-86609_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2026-02-03 14:10:55 +08:00
Mihail Geshoski 3e2824d0df Merge branch 'MOODLE_500_STABLE_MDL-84966' of https://github.com/niko-hoogeveen/moodle into MOODLE_500_STABLE 2026-02-03 13:44:57 +08:00
Mihail Geshoski 07109510c7 Merge branch 'MDL-85653_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2026-02-03 13:36:38 +08:00
Mihail Geshoski d8372d7ecd Merge branch 'MDL-87029-500' of https://github.com/cameron1729/moodle into MOODLE_500_STABLE 2026-02-03 13:26:55 +08:00
Huong Nguyen 91f05629cd Merge branch 'MDL-87334-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-02-03 11:07:50 +07:00
Huong Nguyen 431138556e Merge branch 'MDL-87289-500' of https://github.com/raortegar/moodle into MOODLE_500_STABLE 2026-02-03 10:43:59 +07:00
Huong Nguyen a7c18aaee7 Merge branch 'MDL-87396-500' of https://github.com/izendegi/moodle into MOODLE_500_STABLE 2026-02-03 10:37:16 +07:00
Huong Nguyen 94bc33b976 Merge branch 'MDL-87520-500-branch-number' of https://github.com/mudrd8mz/moodle into MOODLE_500_STABLE 2026-02-03 10:32:43 +07:00
Huong Nguyen c872aad808 Merge branch 'MDL-86905-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2026-02-03 10:27:12 +07:00
Huong Nguyen 00143faad5 Merge branch 'MDL-87675-500' of https://github.com/nvhai248/moodle into MOODLE_500_STABLE 2026-02-03 10:23:43 +07:00
AMOS bot d268a60e1e Automatically generated installer lang files 2026-02-03 00:07:52 +00:00
Stefan Topfstedt a23bd2ad53 MDL-87694 core: prevent empty heading in context header. 2026-02-02 10:38:14 -08:00
Stefan Topfstedt 4f2deeadf0 MDL-87694 profile: change page title to "Login required".
This realigns the page title with user/view.php.
2026-02-02 10:23:24 -08:00
Stefan Topfstedt 76cb6c49b0 MDL-87694 profile: set top level heading when accessed as guest user. 2026-02-02 10:13:40 -08:00
Jun Pataleta 35b132b2c2 MDL-87694 core: headinglevel display option for $OUTPUT->confirm()
`\core\output\core_renderer::confirm()`'s `$displayoptions` parameter
now also accepts a `headinglevel` option that developers can use to
specify the heading level of the confirmation's heading. If not
specified, the confirmation heading will be rendered in an `h4` tag.
2026-02-02 09:19:34 -08:00
cescobedo d70634a418 Merge branch 'MDL-87761-500' of https://github.com/sarjona/moodle into MOODLE_500_STABLE 2026-02-02 11:15:41 +01:00
Jun Pataleta 389c5e2eb5 MDL-86905 core: Use proper link markup for email links 2026-02-02 18:05:03 +08:00
Huong Nguyen d677363483 Merge branch 'MDL-78342-500' of https://github.com/davewoloszyn/moodle into MOODLE_500_STABLE 2026-02-02 08:50:04 +07:00
Safat 0a1b2845a5 Merge branch 'MDL-86601-adhoc-index-MOODLE_500_STABLE' of https://github.com/bwalkerl/moodle into MOODLE_500_STABLE 2026-02-02 12:13:00 +11:00
Cameron Ball 003fea1634 MDL-87029 quiz: Refetch attempts in overdue task to avoid stale submits
The update_overdue_attempts scheduled task iterated attempts from a recordset
and could act on stale attempt data if the web request finished an attempt
before cron processed it, causing duplicate submissions.

Change get_list_of_overdue_attempts() to return only attempt ids plus computed user
timeclose/timelimit, and refetch each attempt by id inside the task loop before
constructing quiz_attempt. This keeps quiz_attempt APIs unchanged and ensures cron
operates on current state
2026-01-31 15:38:43 +08:00
AMOS bot 24b230e284 Automatically generated installer lang files 2026-01-31 00:07:43 +00:00
David Mudrák 0f61bd060e MDL-87520 core: Fix interpretation of CFG->branch in update API client
Starting in version 3.10, Moodle started to use a different format for
the $CFG->branch that has not been fixed here. This is to make sure that
we request the correct version of the plugin.
2026-01-30 14:20:21 +01:00
Benjamin Walker 226aee577d MDL-86601 core_task: Add index for scheduled task lastruntime 2026-01-30 22:52:20 +10:00
Benjamin Walker 4a2cf5131b MDL-86601 core_task: Add index for large adhoc task queues 2026-01-30 22:52:19 +10:00
Sara Arjona 4f3ecdf095 MDL-87761 course: Add warning for phasing out subsection descriptions
The Description field within the Subsection edit form has been deprecated since Moodle 5.2 onwards (see MDL-87279).
To ensure a smooth transition and avoid data loss for our users, the XD team have prepared a solution to notify them
of this upcoming change in stable versions.
2026-01-30 12:25:55 +01:00
Iñigo Zendegi 12bcb9a569 MDL-87396 mod_assign: Add availability check to notifications 2026-01-30 12:02:12 +01:00
Paul Holden fb3e6c2e8c MDL-87334 course: looser check for empty return field editing course.
When the course format switcher reloads the form, the `$returnto`
parameter is of type string: "0", rather of type integer per initial
load.

In this case the `empty(...)` check is verifying all of empty string,
0 (integer) and "0" (string). Hurrah for PHP type checking.
2026-01-30 10:37:55 +00:00
Huong Nguyen 59fd844136 weekly release 5.0.4+ 2026-01-30 15:39:35 +07:00
Huong Nguyen f0d72a138f Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2026-01-30 15:39:24 +07:00
Andrew Nicols 8c50614860 NOBUG: Bump composer.lock 2026-01-30 13:07:12 +08:00
Daniel Ureña 18192b6ea0 MDL-87185 block_site_main_menu: Add required library 2026-01-29 13:12:52 +01:00
fgo c624f40635 MDL-86437 enrol_lti: Cast scoreGiven to float for LTI compliance
scoreGiven was being passed as a string (e.g. "8.0"), which caused
validation errors in some LMS implementations such as Rustici Engine.
According to the LTI specification, scoreGiven must be numeric if
present.

Co-authored-by: Jake Dallimore <jake@moodle.com>
2026-01-29 14:59:14 +08:00
Jake Dallimore ec28b3530a MDL-87789 libraries: patch lti1p3 for certification support
https://github.com/packbackbooks/lti-1-3-php-library/issues/169 blocks
us from using the new build.1edtech certification tooling. This issue
commits that fix as a library customisation/hack for stables, so the
suite can be used for annual/bi-annual re-certification.
2026-01-29 13:26:32 +08:00
Huong Nguyen bb4d7e6ee4 Merge branch 'MDL-87521_500' of https://github.com/timhunt/moodle into MOODLE_500_STABLE 2026-01-29 11:03:47 +07:00
Huong Nguyen 68398f16c7 Merge branch 'MDL-87087-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2026-01-29 11:01:41 +07:00
Huong Nguyen 68b06af0f8 Merge branch 'MDL-86994-500' of https://github.com/mioyu-ubiq/moodle into MOODLE_500_STABLE 2026-01-29 10:58:30 +07:00
Huong Nguyen 3481a9d19e Merge branch 'MDL-87018-500' of https://github.com/bhect0/moodle into MOODLE_500_STABLE 2026-01-29 10:55:12 +07:00
Huong Nguyen 9db5a7f3fe Merge branch 'MDL-87104-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-29 10:46:38 +07:00
Huong Nguyen 9f5fedee5f Merge branch 'MDL-87323-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-29 10:41:40 +07:00
Huong Nguyen 2d8d1e8dcf Merge branch 'MDL-86988-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-29 10:39:20 +07:00
Angelia Dela Cruz bd27e15147 MDL-87087 tool_dataprivacy: Test data request by authorized user 2026-01-29 11:09:13 +08:00
AMOS bot bcd7b651b8 Automatically generated installer lang files 2026-01-29 00:07:41 +00:00
David Mudrák 85c1213a5e MDL-87593 lang: Fix strings order 2026-01-28 21:45:08 +01:00
Tim Hunt 7ede51f863 MDL-87521 behat: better error reporting if an adhoc task fails 2026-01-28 14:58:49 +00:00
Paul Holden 2cc0ff9b26 Merge branch 'MDL-87437-500' of https://github.com/tasiobg/moodle into MOODLE_500_STABLE 2026-01-28 14:16:28 +00:00
Jun Pataleta 63cb8772ae Merge branch 'MDL-86639-500' of https://github.com/yusufwib01/moodle into MOODLE_500_STABLE 2026-01-28 16:17:18 +08:00
mioyu-ubiq 56ab46e236 MDL-86994 mod_assign: Behat to test permitted users can edit submission 2026-01-28 13:55:21 +08:00
Hai Nguyen Van 2b73a96232 MDL-87675 core: Add delay for displaying the YUI alert dialogue message
* Add a slight delay for displaying the message content of the YUI
alert dialogue's ARIA live container to allow screen readers to
announce the alert message accordingly.
2026-01-28 03:18:14 +00:00
David Mudrák 9b3f75c5c7 MDL-87593 lang: Use the fixed strings in tests 2026-01-27 21:44:46 +01:00
Helen Foster 408a058083 MDL-87593 lang: Import fixed English strings (en_fix) 2026-01-27 21:42:43 +01:00
Mark Johnson 4d89422fc8 MDL-87606 backup: Include child questions in backups
Since MDL-41924, because we are not always including the whole category
of each question being used in a backup, we have been missing some child
questions.

This expands the query selecting questions belonging to categories
where only annotated questions are being included, to also select any
children of those questions.
2026-01-27 14:53:37 +00:00
Paul Holden 215d9d623c MDL-87104 message: remove border from contact request sent profile info. 2026-01-27 10:26:07 +00:00
Raquel Ortega 986a201e6c MDL-87289 mod_forum: Disable mediaplugin filter in emails 2026-01-26 21:33:30 +01:00
Niko Hoogeveen 74c67b4f30 MDL-84966 core_question: Updated question bank tag filter
Fixes a bug where filtering questions by tag the 'NONE'
option was not being respected. Automated testing was also added
to cover tag filtering conditions in the question bank
2026-01-26 11:21:28 -05:00
Huong Nguyen efb090fa3f Merge branch 'MDL-84862-500-test' of https://github.com/yusufwib01/moodle into MOODLE_500_STABLE 2026-01-26 15:32:39 +07:00
Huong Nguyen 94db3eae21 weekly release 5.0.4+ 2026-01-26 10:39:17 +07:00
Huong Nguyen c7511914d4 Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2026-01-26 10:39:05 +07:00
Héctor Benedicte 641bb41063 MDL-87018 qtype_essay: Add unit tests for un_summarise_response(). 2026-01-23 19:25:23 +01:00
AMOS bot 8c0d5df95b Automatically generated installer lang files 2026-01-23 00:07:58 +00:00
Safat 862d57ca12 Merge branch 'MDL-86527-500' of https://github.com/HuongNV13/moodle into MOODLE_500_STABLE 2026-01-22 15:40:02 +11:00
Huong Nguyen ac4a2a427f Merge branch 'MDL-87188-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-22 11:02:53 +07:00
Huong Nguyen f7892080c5 Merge branch 'MDL-87317-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2026-01-22 10:53:05 +07:00
Huong Nguyen 29cc6da010 Merge branch 'MDL-87318-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2026-01-22 10:46:28 +07:00
Huong Nguyen 8de8070c46 Merge branch 'MDL-86797-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-22 10:44:30 +07:00
Huong Nguyen b04d0c86f1 Merge branch 'MDL-87092-500' of https://github.com/Kredelirious/moodle into MOODLE_500_STABLE 2026-01-22 10:37:05 +07:00
Huong Nguyen 9fd37ca5c6 Merge branch 'MDL-87090-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2026-01-22 10:32:56 +07:00
Jun Pataleta 80ced0eddc Merge branch 'MDL-86136_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2026-01-22 08:32:34 +08:00
Jun Pataleta 238eb6b945 Merge branch 'MDL-87478_500' of https://github.com/mohdtahseen1/moodle into MOODLE_500_STABLE 2026-01-22 08:22:33 +08:00
Mark Johnson ca0efffb05 MDL-86136 question: Amend version restore test
Restoring a whole course will now restore the backed-up questions to a
new qbank instance. This means the test to restore versions was not
restoring the deleted versions to the original question bank entires,
but to a new question bank entry in the new qbank.

Updating the test to just backup and restore the quiz resolves this.
2026-01-21 09:30:07 +00:00
Mark Johnson 2785d6f2bd MDL-86136 qbank: Restore entire activity when it is in the backup
When restoring a backup containing a question bank, we were always
trying to match questions to an existing category on the target course
if once existed. This meant that when duplicating a qbank on the same
course, or importing the same qbank to another course multiple times,
only one of the restored qbanks would end up with questions in it.

This adds a mechanism to record any activities in the backup which
support `FEATURE_PUBLISHES_QUESTIONS`. Then when we restore the
questions, we check if we will be restoring the original activity they
belong to, and skip trying to match them to an existing category. This
means a new copy of each question will be created, and moved to the new
copy of the qbank once it is created.
2026-01-21 09:30:06 +00:00
Muhammad Arnaldo 1bf68468ef MDL-86527 behat: Avoid element-click-intercepted failures
Adjusts the window size to accommodate wide tables.
This ensures that columns which were previously clipped
are now visible and accessible to the Behat driver.
2026-01-21 15:05:12 +07:00
Muhammad Arnaldo 38375adf4d MDL-86527 behat: Fix random failures when toggling edit mode 2026-01-21 15:05:12 +07:00
Adrian Greeve 4e1053e6ce Merge branch 'MDL-87625-500' of https://github.com/andrewnicols/moodle into MOODLE_500_STABLE 2026-01-21 14:20:35 +08:00
Adrian Greeve 24c97bd603 Merge branch 'MDL-87659-500' of https://github.com/andrewnicols/moodle into MOODLE_500_STABLE 2026-01-21 13:15:07 +08:00
Andrew Nicols 8be48fd41e MDL-87659 core: Hide "Details" section of checks Table when there are none 2026-01-21 13:01:41 +08:00
Huong Nguyen 64f95b61c1 Merge branch 'MDL-79221-MOODLE_500_STABLE' of https://github.com/PhMemmel/moodle into MOODLE_500_STABLE 2026-01-21 10:14:21 +07:00
Huong Nguyen 014580bbdd Merge branch 'MDL-51447-500' of https://github.com/AnupamaSarjoshi/moodle into MOODLE_500_STABLE 2026-01-21 10:10:50 +07:00
AMOS bot 1bb491d769 Automatically generated installer lang files 2026-01-21 00:08:05 +00:00
Yusuf Wibisono fbc30b007b MDL-86639 groups: Wrap group names in grade report group selector 2026-01-21 03:34:57 +07:00
Ilya Tregubov f245bdaf24 Merge branch 'MDL-76975-500' of https://github.com/yerairogo/moodle into MOODLE_500_STABLE 2026-01-20 19:46:11 +02:00
Paul Holden 2b4d264cb1 MDL-86797 courseformat: account for hidden delegated section info. 2026-01-20 09:56:45 +00:00
Kim Jared Lucas 2a6955e490 MDL-87092 tool_uploaduser: suspend enrolments via CSV upload 2026-01-20 11:20:03 +08:00
Mihail Geshoski 0a30b72921 Merge branch 'MDL-87287_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2026-01-20 10:37:20 +08:00
AMOS bot 173f24702f Automatically generated installer lang files 2026-01-20 00:08:06 +00:00
Anupama Sarjoshi 1944075f31 MDL-51447 block_completionstatus: Show only user-visible activities
This change ensures that the completion details page displays only the
activities that are visible to the user on the course home page.
Activities that are hidden, unavailable or  located in hidden sections
are no longer shown in the completion details view.

Co-authored by: ewallah <info@ewallah.net>
2026-01-19 17:57:01 +05:30
Anupama Sarjoshi c4f303b42a MDL-51447 core_completion: Get visible activities with completion on 2026-01-19 17:57:01 +05:30
Simey Lameze b898bff306 MDL-87090 behat: improve new test 2026-01-19 14:13:16 +08:00
mioyu-ubiq 6b08248cfa MDL-87090 mod_assign : Teacher can override assignment deadlines 2026-01-19 14:13:14 +08:00
David Woloszyn fedc27f80e MDL-78342 core_table: Remove line break conversion in format_text 2026-01-19 13:07:56 +11:00
Mark Johnson 194caa005d MDL-86609 qbank_bulkmove: Select the current category by default 2026-01-16 14:36:20 +00:00
Nicolas Dunand bf73761ff8 MDL-86609 qbank_bulkmove: Target qbank categoryid fix. 2026-01-16 14:35:56 +00:00
Luca Bösch 781cdd65f4 MDL-87318 gradereport_grader: No over-thick table borders with BS 5. 2026-01-16 11:01:31 +01:00
Luca Bösch 0deaaf6e18 MDL-87317 report_progress: Striped hovering table rows with BS 5. 2026-01-16 11:00:37 +01:00
Jake Dallimore 3d8e9b8444 weekly release 5.0.4+ 2026-01-16 16:38:28 +08:00
Jake Dallimore 07c19b9ce7 Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2026-01-16 16:38:22 +08:00
Paul Holden d33164d9c4 MDL-85300 grade: account for tooltip size in bulk move dialogue.
Now that it actually works, it obscures some elements required in
Behat scenarios. Resize the icon, and place it to the right.
2026-01-16 15:26:53 +08:00
Jake Dallimore 0f56b6d72b Merge branch 'MDL-87634-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Huong Nguyen b27b9b4031 Merge branch 'MDL-86802-500' of https://github.com/Jayce0808/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Jake Dallimore 8d12694488 Merge branch 'MDL-86423-500' of https://github.com/martygilbert/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Jake Dallimore fb293a5750 Merge branch 'MDL-87635-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Jake Dallimore 301e373ffa Merge branch 'MDL-86869_500-single-view-overload' of https://github.com/alexkeel/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Paul Holden b8bd4e8604 MDL-50364 forms: consistent access to language strings from JS. 2026-01-16 15:26:53 +08:00
Paul Holden 54b42e04af Merge branch 'MDL-50364-500' of https://github.com/Jayce0808/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Ilya Tregubov 80709ededb Merge branch 'MDL-85300-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Huong Nguyen 8af6c40ab0 Merge branch 'MDL-86017-500' of https://github.com/mijiaa/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Huong Nguyen 2bd3f9f058 Merge branch 'MDL-87070-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Huong Nguyen e9fbd3db48 Merge branch 'MDL-85431_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Huong Nguyen 7ccd3a62d9 Merge branch 'MDL-87443-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-16 15:26:53 +08:00
Huong Nguyen be210d1ed2 Merge branch 'MDL-87229-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2026-01-16 15:26:52 +08:00
Huong Nguyen b9d71a4a47 Merge branch 'MDL-87056-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-16 15:26:52 +08:00
Huong Nguyen 31fd12db29 Merge branch 'MDL-86565-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-16 15:26:52 +08:00
Huong Nguyen cf22cbe371 Merge branch 'MDL-87120-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2026-01-16 15:26:51 +08:00
Mark Johnson 855d0901ea MDL-85653 qbank_editquestion: Display static status when not editable 2026-01-14 15:42:40 +00:00
Mark Johnson 7bd7ca8d83 MDL-86444 questions: Fix question categories with incorrect top parents 2026-01-14 10:11:40 +00:00
Paul Holden ed571424f9 MDL-87634 core: exclude fixtures from Github actions "one-by-one" job.
This is consistent with the PHPUnit general configuration in 20aa9d05.
2026-01-14 09:25:34 +00:00
Yerai Rodríguez 5f075b79be MDL-76975 admin: Move AMD dependencies to data attribute to fix overflow
Since there is a 1024 length limit on arguments passed through
js_call_amd(), we pass it through a HTML element dataset to avoid
this limit.
2026-01-14 08:34:06 +01:00
Guest 5093d3bfe7 MDL-87478 mod_quiz: Make pre-create attempts work with previews 2026-01-13 15:10:45 +05:30
AMOS bot 22e13a4463 Automatically generated installer lang files 2026-01-13 00:08:00 +00:00
Andrew Nicols 072658a276 MDL-87625 core: Use the /r.php basepath to guess routes 2026-01-13 08:06:38 +08:00
Paul Holden d873307bf8 MDL-87635 backup: ensure required test libraries are loaded. 2026-01-12 17:22:26 +00:00
Simey Lameze 602e40f054 MDL-87088 behat: add missing @javascript tags to required tests 2026-01-12 13:37:59 +07:00
Angelia Dela Cruz 8507bc2716 MDL-87070 mod_glossary: Behat to confirm glossary autolinking works 2026-01-12 11:59:14 +08:00
Huong Nguyen 3e398810f2 Merge branch 'MDL-87088-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2026-01-12 09:53:25 +07:00
Huong Nguyen 1352482b39 Merge branch 'MDL-86058-allow-enable-disable-tasks-backport-MOODLE-500-STABLE' of https://github.com/duyhuynhdev/moodle into MOODLE_500_STABLE 2026-01-12 09:44:32 +07:00
Stefan Topfstedt 27a36e6fae MDL-77162 filepicker: default to selecting first repository available. 2026-01-09 08:14:14 -08:00
Paul Holden 4c4e77ba26 MDL-87443 reportbuilder: use Toast selector in Behat scenarios. 2026-01-09 12:08:19 +00:00
Paul Holden fdd9f2e022 MDL-87443 behat: define new Toast message named selector. 2026-01-09 12:08:19 +00:00
Mark Johnson cffa9a1008 MDL-87287 qbank_deletequestion: Update behat test for tag deletion
Now that deleting a tagged question correctly deletes it tag instances,
the tag is no longer available for re-selection after all the tagged
questions are deleted.
2026-01-09 10:42:39 +00:00
Mark Johnson 0ff87413b5 MDL-87287 mod_qbank: De-duplicate tags when migrating questions
In the migration from old-style question banks to mod_qbank, if a
question had the same tag from multiple contexts, when it was moved to
its new question bank context, the migration tried to set multiple tag
instances for the same tag to the same context, which caused a unique
key violation.

This add some checking to the
`question_move_question_tags_to_new_context` function to identify any
tag instances to be moved that will trigger this key violation, and
delte any duplicates before the move so we end up with a single instance
of the tag in the new context. This is done in a transaction that will
only be committed once the remaining tags have been moved.

This required adding the `tiuserid` field to the data returned by
`core_tag_tag::get_items_tag` so we can assemble the unique key without
having to do additional queries.

This also extends the test coverage for the `transfer_questions` task
to ensure tags are moved to the new contexts, and tags on stale questions
are deleted.
2026-01-09 10:42:07 +00:00
Mark Johnson 8bd6c40a0c MDL-87287 qbank_tagquestion: Remove all tags from deleted questions
When we deleted a question, we were including the userid of the user who
performed the delete when checking for question tags. This means that if
user A tagged the question, and user B deleted the question, it might
leave the tags behind.

This fixes the issue by deleting tags regardless of the user, and adds
an upgrade step to find and remove orphaned tag instances.
2026-01-09 10:42:07 +00:00
Tasio e95a118087 MDL-87437 course: Make course cached image entries domain-agnostic 2026-01-09 10:10:23 +01:00
Luca Bösch 80e0d1818a MDL-87229 course: Show nice "Other users" table in courses. 2026-01-09 07:12:42 +01:00
Jayce Birrell a38ed9f2a3 MDL-50364 forms: calendar header renderer uses translated months 2026-01-09 13:52:59 +10:30
Angelia Dela Cruz 3ff7a1a4b7 MDL-87088 core_grades: Behat to view grades from user menu 2026-01-09 10:40:30 +08:00
Huong Nguyen 9699514341 weekly release 5.0.4+ 2026-01-09 08:41:40 +07:00
Huong Nguyen c04d745016 NOBUG: Add upgrade notes 2026-01-09 08:41:40 +07:00
Jun Pataleta 4c2ac777f1 MDL-85535 forum: Render discussion navigation at the bottom only 2026-01-08 11:35:00 +08:00
Jun Pataleta b6f5584c4d MDL-85535 forum: Label discussion navigation 2026-01-08 11:35:00 +08:00
Marty cd80e0ae07 MDL-86423 mod_assign: Reduce duesoon/overdue notifications.
Students shouldn't receive overdue notifications if there is nothing to
submit in Moodle.

Students shouldn't receive due soon notifications if they a) already
have a grade or b) meet activity completion status.
2026-01-07 12:20:51 -05:00
Paul Holden 7a2a319bbd MDL-87120 course: observe activity dates display in course requests.
Upgrade step to ensure the default value for this field in the schema
matches the default value used in the interface itself.
2026-01-07 16:43:26 +00:00
Jun Pataleta f1784eba65 Merge branch 'MDL-86436-navigation-accessibility-page-heading-menu-visible-on-larger-screens-even-if-empty-M5.0' of https://github.com/stopfstedt/moodle into MOODLE_500_STABLE 2026-01-07 11:18:05 +08:00
Jun Pataleta c3114ff21a Merge branch 'MDL-87416-glossary-entry-page-title-missing-M5.0' of https://github.com/stopfstedt/moodle into MOODLE_500_STABLE 2026-01-07 11:13:54 +08:00
Santosh Nagargoje 4c53960c75 MDL-83984 core: Fixed subpanel show/hide issue 2026-01-06 16:19:21 +05:30
Adrian Greeve 9841148790 Merge branch 'MDL-87526-500' of https://github.com/andrewnicols/moodle into MOODLE_500_STABLE 2026-01-06 09:10:36 +08:00
Stefan Topfstedt fe15e9f6c3 MDL-87416 glossary: set page title on glossary entry details page. 2026-01-05 11:31:48 -08:00
Mark Johnson fbf2963387 MDL-85431 questions: Fix access checks on Question banks page
Users who could not manage activities on a course, but did have
permission to access particular question banks, could not access the
Question banks page.

This modifies the permission checks on that page to allow access if the
user can either manage activities, or has access to at least one
activity that publishes questions. Some additional changes to the output
were required to prevent non-editing users adding banks.

It also modifies the navigation hook to add the Question banks
navigation node if the user can access any activitiy that publishes
questions on the course. This is all based on cached modinfo and
permissions data so should remain performant.
2026-01-05 15:20:51 +00:00
Paul Holden fa94598fe0 Merge branch 'MDL-87288-500' of https://github.com/ilyatregubov/moodle into MOODLE_500_STABLE 2026-01-05 09:46:54 +00:00
Huong Nguyen 39ca46780a Merge branch 'MDL-81882-500' of https://github.com/yusufwib01/moodle into MOODLE_500_STABLE 2025-12-29 13:51:48 +07:00
Matt Porritt 926ac9ed31 MDL-84862 AI: Stop provider instance creataion when no provider plugins
Prevents calls to action to create an AI provider instance from
being displayed to users when there are no AI provider plugins
installed in the instance.

Co-Authored-By: Yusuf Wibisono <yusuf.wibisono@moodle.com>
2025-12-29 12:03:43 +07:00
Huong Nguyen 426ffb42da Merge branch 'MDL-87433-500' of https://github.com/muhammadarnaldo/moodle into MOODLE_500_STABLE 2025-12-29 09:54:47 +07:00
yusufwib01 49dcdcadba MDL-81882 core: Optimize block instance deletion with batch processing
Improve upgrade execution by gathering block instance IDs upfront
and processing deletions of related records in context, block_positions, user_preferences, and block_instances tables in batches.
2025-12-29 09:30:48 +07:00
Muhammad Arnaldo 2482ea9af6 MDL-87433 course: Add sorting to get_nearest_editable_subcategory
Add ORDER BY to the query to ensure categories are returned in
consistent order. This fixes random test failures, especially
on PostgreSQL.
2025-12-24 16:14:26 +07:00
Alex Keel 09a7591042 MDL-86869 gradereport_singleview: Raises memory limit 2025-12-23 12:20:20 +00:00
Mihail Geshoski b81abb8578 Merge branch 'MDL-86798_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-12-23 16:11:38 +08:00
Andrew Nicols c9529535bb MDL-87526 core: Specify composer project type 2025-12-23 11:50:05 +08:00
Andrew Nicols 164376014e MDL-87526 core: Moodle provides moodle/lms 2025-12-23 11:50:05 +08:00
Mark Johnson 976456a6f1 MDL-86798 questions: Check original context is on the same site
When checking if the original context exists during a restore, we need
to check that we're looking at the context on the same site, not one on
a different site that happens to have the same ID.
2025-12-19 09:28:23 +00:00
Mark Johnson a364395d8e MDL-86798 questions: Track next version for question bank entries
This adds a new "nextversion" field to `question_bank_entries` to track
which version number the next version of the question should have. This
ensures that version numbers are not re-used if the latest version is
deleted.

To use this field, you must call
`\core_question\versions::get_next_version()`. This will initialise the
field to the correct value if it is currently null.

If you create a new version using this value, you must then call
`\core_question\versions::increment_next_version()` to increment the
counter.
2025-12-19 09:28:23 +00:00
Mark Johnson fb9f3ee58c MDL-86798 questions: Restore backups containing deleted versions
If the latest version of a question is deleted, and then a new one
created, the new one will currently re-use the version number of the
deleted version. If the original version was backed up before it was
deleted, then restored later, we end up with two questions in one
question bank entry that have the same version.

To resolve this, when restoring a question, we check if there is already
a version with the same version number, then bump it and any higher
versions up by 1. We also check for any references specifically using
these versions and bump those up by 1. Any references using "always
latest" will be fine, as the latest version will still be the latest.

Additionally, if deleting a version made it hidden, and the backup
contains the same version in "ready" state, restoring the backup will
restore it to "ready" state.
2025-12-19 09:26:15 +00:00
Huong Nguyen 6e82b46a48 weekly release 5.0.4+ 2025-12-19 09:04:41 +07:00
Ilya Tregubov 29e9471a66 MDL-87288 output: Fix pagination in small containers. 2025-12-18 09:37:49 +01:00
Huong Nguyen 6e1e877bb6 Merge branch 'MDL-87340-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-12-18 11:45:27 +08:00
Huong Nguyen b5d6d847cf Merge branch 'MDL-86420-500' of https://github.com/muhammadarnaldo/moodle into MOODLE_500_STABLE 2025-12-18 11:45:27 +08:00
Huong Nguyen 02a6973793 Merge branch 'MDL-86086-500' of https://github.com/andimendunia/moodle into MOODLE_500_STABLE 2025-12-18 11:45:27 +08:00
Huong Nguyen 2ceffeba8a Merge branch 'MDL-87094-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2025-12-18 11:45:27 +08:00
Mihail Geshoski f77a71f18f Merge branch 'MDL-72833_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-12-18 11:45:27 +08:00
Andi Permana 3df3f8c96c MDL-86086 theme_boost: Add visual distinction for readonly form inputs 2025-12-17 19:07:52 +07:00
Mihail Geshoski 627fdd0bfd Merge branch 'MDL-86416-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-12-17 12:15:05 +08:00
Paul Holden 5355c46c43 MDL-85300 output: ensure Bootstrap tooltips load for dynamic content.
Prior to this change, tooltips would only load for elements in the
initial page DOM without considering those elements subsequently added
dynamically (e.g. via AJAX).

Co-authored-by: Sebastian Gundersen <sebastian@sgundersen.com>
2025-12-16 13:30:20 +00:00
Alex Keel 48020125d1 MDL-86869 gradereport_singleview: Lower the max per page limit
Review actions
2025-12-15 14:48:36 +00:00
Amaia Anabitarte 8a9707b653 Merge branch 'MDL-87436-500' of https://github.com/laurentdavid/moodle into MOODLE_500_STABLE 2025-12-15 13:42:36 +01:00
Mark Johnson 9ad6d20b70 MDL-72833 quiz: Respect locale in maxmark setting
Editing maxmarks in quiz slots was not respecting the decimal separator
from the set language's locale, meaning if your language formats numbers
like 1,10 editing didn't work correctly.

This sets the correct parameter to ensure the locale is respected.
2025-12-15 11:46:52 +00:00
Jun Pataleta 3c56b3b7c0 Merge branch 'MDL-87341_500' of https://github.com/TomoTsuyuki/moodle into MOODLE_500_STABLE 2025-12-15 18:48:35 +08:00
Angelia Dela Cruz d6f5a3fa89 MDL-87094 core_course: Behat to restrict available activities/resources 2025-12-15 12:06:06 +08:00
Huong Nguyen e7f3feac7e Merge branch 'MOODLE_500_STABLE_MDL-73396' of https://github.com/niko-hoogeveen/moodle into MOODLE_500_STABLE 2025-12-15 08:55:46 +07:00
Huong Nguyen 08b7aafce2 Merge branch 'MDL-86679-500' of https://github.com/andimendunia/moodle into MOODLE_500_STABLE 2025-12-15 08:47:53 +07:00
Tomo Tsuyuki 89b2aac22c MDL-87341 javascript: Fix aria label issue for navigation bar 2025-12-15 10:27:41 +11:00
Stefan Topfstedt d3500faa9b MDL-86436 navigation: hide empty page heading menu.
Co-authored-by: Jun Pataleta <jun@moodle.com>
2025-12-12 18:05:36 -08:00
Stefan Topfstedt 61b4aaf199 MDL-87415 profile: set page title when accessed as guest user. 2025-12-12 13:43:38 -08:00
Philipp Memmel 36caae7105 MDL-79221 core_grade: Fix fetching context for disabled mod plugins
Activity plugins that are disabled on the site are not included in
the modinfo cache. That's why their context must not be fetched via
modinfo cache.
2025-12-12 06:43:00 +01:00
Philipp Memmel 9af25198fd MDL-79221 core_completion: Do not update state for disabled plugins 2025-12-12 06:43:00 +01:00
Shamim Rezaie f878d036dd weekly release 5.0.4+ 2025-12-12 14:06:34 +11:00
Shamim Rezaie 9ccb749a18 Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2025-12-12 14:06:24 +11:00
Mihail Geshoski a6d0cb3cc1 MDL-87412 qbank_managecategories: Use single quotes in scenario name 2025-12-12 09:46:25 +07:00
Huong Nguyen 40d438dac1 Merge branch 'MDL-84736-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-12-12 09:46:25 +07:00
Huong Nguyen 94b842021c Merge branch 'MDL-86830-500' of https://github.com/andimendunia/moodle into MOODLE_500_STABLE 2025-12-12 09:46:25 +07:00
Huong Nguyen 7a567ed194 Merge branch 'MDL-86808-500' of https://github.com/muhammadarnaldo/moodle into MOODLE_500_STABLE 2025-12-12 09:46:25 +07:00
Luca Bösch 5e6e675fb9 MDL-86677 mod_quiz: Make the attempt summary table striped 2025-12-12 09:46:24 +07:00
Mihail Geshoski 9054263ecd Merge branch 'MDL-87182-500' of https://github.com/srobotta/moodle into MOODLE_500_STABLE 2025-12-12 09:46:24 +07:00
Mihail Geshoski 0dbb57ece9 Merge branch 'MDL-87121_500' of https://github.com/santoshndev/moodle into MOODLE_500_STABLE 2025-12-12 09:46:24 +07:00
Mihail Geshoski b9be456bc6 Merge branch 'MDL-87412_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-12-12 09:46:24 +07:00
Mihail Geshoski 2c6fd6d4ac Merge branch 'MDL-87142-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-12-12 09:46:24 +07:00
Jun Pataleta 84c34ff230 Merge branch 'MDL-86807-500' of https://github.com/muhammadarnaldo/moodle into MOODLE_500_STABLE 2025-12-12 09:46:24 +07:00
Jun Pataleta 06a0eb182b Merge branch 'MDL-86805-500' of https://github.com/andimendunia/moodle into MOODLE_500_STABLE 2025-12-12 09:46:24 +07:00
Huong Nguyen c0fefda2fc Merge branch 'MDL-86593-500' of https://github.com/christianabila/moodle into MOODLE_500_STABLE 2025-12-12 09:46:24 +07:00
Muhammad Arnaldo be74828054 MDL-86420 enrol_database: avoid duplicate key violations 2025-12-11 10:25:24 +07:00
AMOS bot 984a280583 Automatically generated installer lang files 2025-12-11 00:08:02 +00:00
Niko Hoogeveen fb6a0f6444 MDL-73396 auth_oauth2: link non-suspended account on oauth login
Added checks to link non-suspended user accounts to OAuth2, when logging
in. Also added an additional check to prevent users from using OAuth2
to login if their account is suspended in Moodle.
2025-12-10 14:21:51 -05:00
Niko Hoogeveen 307ed32403 MDL-73396 core_user: prioritize active users when retrieving by email
Updated get_users_by_email() to return active users at the
start of the returned array, suspended users last.
2025-12-10 14:21:51 -05:00
Laurent David e30b97f3b8 MDL-87436 core_courseformat: Fix id collision when testing
* When testing using phpunit/sqlsrv the ids of sections and cm are colliding
so we need to make sure we separate them as a reference to a cm can be the
same as a reference to a section
2025-12-10 12:10:12 +01:00
Simey Lameze 187cc673c9 MDL-84736 behat: add custom step to edit a criterion
This commit also improves the existing tests and add a new scenario to
verify the 'Do not mark for regrade' behavior.
2025-12-09 17:23:21 +08:00
Angelia Dela Cruz 59bd9c5da6 MDL-84736 gradingform : Behat for editing guide with graded submissions 2025-12-09 17:23:20 +08:00
Stefan Topfstedt fa50aa22b9 MDL-86416 navigation: Render the more menu only when it's not empty
Co-authored-by: Jun Pataleta <jun@moodle.com>
2025-12-09 11:15:29 +08:00
Huong Nguyen 917b9a0e32 Merge branch 'MDL-87379_500' of https://github.com/santoshndev/moodle into MOODLE_500_STABLE 2025-12-09 09:28:29 +07:00
Mihail Geshoski 4388a17c2b Merge branch 'MDL-82281-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-12-09 09:45:59 +08:00
Mihail Geshoski 95bce73f7c Merge branch 'MDL-86677-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-12-09 09:29:03 +08:00
Mihail Geshoski a1390072c3 Merge branch 'mdl-87356_500' of https://github.com/james-cnz/moodle into MOODLE_500_STABLE 2025-12-09 09:17:50 +08:00
Simey Lameze 8a3093377a MDL-87340 mod_quiz: make test_question_shuffle more robust
This commit improves test_question_shuffle by retrying if questions
remains in the same order after shuffling.
2025-12-09 07:34:12 +08:00
Stephan Robotta 8137ccc608 MDL-87182 quiz: no CBM metric when no data available 2025-12-08 08:46:02 +01:00
Muhammad Arnaldo becef1c899 MDL-86807 core_courseformat: RTL chevron in move activity modal 2025-12-08 11:50:37 +07:00
Andi Permana e9688d295f MDL-86830 calendar: Fix double encoding in event title attributes 2025-12-08 10:44:07 +07:00
Luca Bösch c3be940177 MDL-87142 question: dropdown-toggle class for question format select 2025-12-07 20:12:44 +01:00
Luca Bösch 9ae5248089 MDL-86677 mod_quiz: let the summary of attempt table be striped 2025-12-07 20:11:49 +01:00
Luca Bösch 580ab8704e MDL-82281 quiz: Amend test to circumvent modinfo cache fails. 2025-12-07 20:10:59 +01:00
Huong Nguyen a5b3ac7e43 Moodle release 5.0.4 2025-12-07 08:06:17 +07:00
Huong Nguyen a7bbd44304 NOBUG: Add upgrade notes 2025-12-07 08:06:16 +07:00
Andi Permana c15d798502 MDL-86805 courseindex: Fix RTL keyboard navigation in tree 2025-12-06 01:09:24 +07:00
Mark Johnson a4d8076384 MDL-87412 qbank_managecategories: Fix "new child" drop target
This fixes the CSS rule that reveals the "as new child of" drop target
shown when dragging a category over another category which has no
children.

We can't behat test the actual drag-drop reordering behaviour with behat
as reactive DragDrop components aren't testable, but we can trigger the
CSS to add a regression test for the drop target's appearance.
2025-12-05 14:18:20 +00:00
Santosh Nagargoje 8a23b61990 MDL-87379 theme_classic: Fixed mobile responsiveness issue 2025-12-05 15:25:33 +05:30
Muhammad Arnaldo e27fe53bc3 MDL-86808 theme_boost: misaligned footer popover in RTL
Limit the fallback placement vertically.
2025-12-05 16:28:00 +07:00
Andi Permana 65008c9e74 MDL-86679 core: Fix MS field mappings in upgrade script 2025-12-05 15:48:31 +07:00
Andi Permana 87eef1669d MDL-86679 oauth2: Support MS personal and work account names 2025-12-05 15:44:23 +07:00
Huong Nguyen 5a34bf72d6 weekly release 5.0.3+ 2025-12-05 08:08:56 +07:00
Huong Nguyen 3cf30be0f1 NOBUG: Add upgrade notes 2025-12-05 08:08:56 +07:00
Huong Nguyen 0c04f1921f MDL-81304 Performance: Add notes for CTE 2025-12-04 21:12:23 +07:00
Huong Nguyen b61eb194ef Merge branch 'MDL-87068-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-12-04 20:59:59 +07:00
Santosh Nagargoje 7cee7c5692 MDL-87121 quiz: Fixed random question performance issue 2025-12-04 17:27:37 +05:30
James C d36616757c MDL-87356 qtype_random: orphaned random questions should be deleted
This patch reinstates the task from MDL-63260 and MDL-66273.
2025-12-04 23:00:49 +13:00
Christian Abila 4d8bcbece8 MDL-86593 Course completion: Disabled modules not returned as criteria
- Filter out disabled modules
- Update get_criteria method signature
- Fix code style
2025-12-04 07:07:18 +01:00
Angelia Dela Cruz 1c9c017fa5 MDL-87068 contentbank_h5p: Behat for restoring course contentbank 2025-12-04 10:33:49 +08:00
Huong Nguyen ae27d04332 Merge branch 'MDL-83485-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-12-04 09:19:07 +07:00
Huong Nguyen 460089df2f Merge branch 'MDL-82232-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-12-04 09:13:09 +07:00
Huong Nguyen b33724c13e MDL-72744 table: Improve PHPUnit test 2025-12-04 08:57:58 +07:00
David Woloszyn 50b527ad2d MDL-72744 core_grades: Escape formulas when exporting spreadsheets 2025-12-04 08:57:58 +07:00
David Woloszyn bcf67dd1cb MDL-72744 dataformat: Escape formulas when exporting spreadsheets
Co-authored-by: Huong Nguyen <huongnv13@gmail.com>
2025-12-04 08:57:58 +07:00
Mihail Geshoski 09a76fcb45 Merge branch 'MDL-85534-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-12-04 09:45:20 +08:00
Huong Nguyen 05b0e7c0eb MDL-86087 core: Use correct required version 2025-12-04 08:36:40 +07:00
Mihail Geshoski 148a0c6459 Merge branch 'MDL-87299-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-12-04 09:22:12 +08:00
Mihail Geshoski 7e131d5b33 Merge branch 'MDL-87245-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-12-03 23:50:18 +08:00
Mihail Geshoski 9afb3db588 Merge branch 'MOODLE_500_STABLE_MDL-81304' of https://github.com/mattporritt/moodle into MOODLE_500_STABLE 2025-12-03 23:38:48 +08:00
Jun Pataleta b63c72dccd MDL-87245 scorm: Indicate when the SCORM package opens in a new window 2025-12-03 23:36:26 +08:00
Jun Pataleta 877e43b6ee MDL-87245 lang: Add a bracketed form of the opensinnewwindow lang string 2025-12-03 23:36:25 +08:00
Mihail Geshoski 18e8714eb4 Merge branch 'MDL-85858-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-12-03 23:28:37 +08:00
Jun Pataleta 1c9f9eed15 MDL-85534 forum: Set appropriate heading levels for the discussion page 2025-12-03 17:33:51 +08:00
Huong Nguyen a2d7d9bd05 Merge branch 'MDL-87091-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-12-03 16:11:33 +07:00
mioyu-ubiq 01ed555cad MDL-87091 behat: Test authloginviaemail setting behavior 2025-12-03 15:55:56 +08:00
Huong Nguyen e27c62ed44 MDL-87353 core: Safer unserializing of file references 2025-12-03 14:17:23 +08:00
Jun Pataleta b9465bbd1d Merge branch 'MDL-86087-500' of https://github.com/HuongNV13/moodle into MOODLE_500_STABLE 2025-12-03 14:10:04 +08:00
Stefan Hanauska 0722f5dc62 MDL-86960 mod_glossary: Check user 2025-12-03 13:42:17 +08:00
Stefan Hanauska 8f7d361597 MDL-86960 mod_data: Check user 2025-12-03 13:42:10 +08:00
Stefan Hanauska c05961c8da MDL-86960 mod_forum: Check user 2025-12-03 13:42:03 +08:00
Huong Nguyen 822dd5aeb7 Merge branch 'MDL-87339-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-12-03 12:15:02 +07:00
Jake Dallimore 60e6410c73 MDL-87286 enrol_lti: prevent suspended user account auth in legacy LTI 2025-12-03 15:50:09 +11:00
Jake Dallimore 6cf403f23e MDL-87286 auth_lti: prevent suspended user account auth in LTI1p3 2025-12-03 15:50:09 +11:00
Matt Porritt fbf71949dc MDL-81304 Performance: Improve performance of my courses.
Refactor get_nearest_editable_subcategory to improve performance.

This refactor maintains functionality and signature of
get_nearest_editable_subcategory but improves perofrmance
for varied datasets. This makes rendering of the
my courses page.
2025-12-03 15:49:41 +11:00
raortegar 83ee815775 MDL-87267 aiplacement_courseassist: Improve response formatting 2025-12-03 11:16:44 +07:00
Mihail Geshoski 672b2a9074 MDL-82808 assign: Use blindid during submission removal in blind marking 2025-12-03 03:14:20 +00:00
Rajneel Totaram bf6fb596dc MDL-82808 mod_assign: replace userid with blindid in anonymous marking 2025-12-03 03:14:20 +00:00
David Woloszyn 8565f480a3 MDL-86544 lib: Adjust checks on local URL params 2025-12-03 03:14:20 +00:00
Eric Merrill 8c9068eb5d MDL-80317 auth_oauth2: Restrict login redirect to local url 2025-12-03 03:14:20 +00:00
Stefan Hanauska 664191aa93 MDL-86507 badge: Check if role is assigned 2025-12-03 03:14:20 +00:00
David Woloszyn 9438f2af46 MDL-85557 tiny_equation: Sanitise equation preview input 2025-12-03 03:14:20 +00:00
yusufwib01 6d2eefe372 MDL-86326 auth: Enhance validation logic in resend_confirmation_email 2025-12-03 03:14:20 +00:00
Mihail Geshoski 545f94bbbc Merge branch 'MDL-86749_500' of https://github.com/santoshndev/moodle into MOODLE_500_STABLE 2025-12-03 11:06:23 +08:00
Huong Nguyen a0e4237954 Merge branch 'MDL-78442-500' of https://github.com/andimendunia/moodle into MOODLE_500_STABLE 2025-12-03 09:55:53 +07:00
Mihail Geshoski a92402e067 Merge branch 'MDL-87066_cleanstring_500' of https://github.com/skodak/moodle into MOODLE_500_STABLE 2025-12-03 09:47:36 +08:00
Jun Pataleta b4a12fcc30 MDL-82232 behat: Fix breadcrumb navigation on Behat 2025-12-02 19:22:10 +08:00
Jun Pataleta 3140d11871 MDL-82232 core: Change the breadcrumb lang string to Breadcrumb 2025-12-02 19:22:10 +08:00
Andi Permana fe98642103 MDL-78442 antivirus_clamav: Try SCAN first, then INSTREAM as fallback 2025-12-02 15:46:43 +07:00
Andi Permana da7ce0c6e2 MDL-78442 tool_moodlenet: Fix directory path passed to antivirus scanner 2025-12-02 15:46:43 +07:00
Mihail Geshoski 9ff7da25f1 Merge branch 'MDL-86806-500' of https://github.com/muhammadarnaldo/moodle into MOODLE_500_STABLE 2025-12-02 15:11:03 +08:00
Mihail Geshoski adbdfc59ca Merge branch 'MDL-86523-MOODLE_500_STABLE_invalidcategoryid' of https://github.com/loewis/moodle into MOODLE_500_STABLE 2025-12-02 15:03:57 +08:00
Mihail Geshoski 4425af045f Merge branch 'MDL-86844-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-12-02 14:50:31 +08:00
Mihail Geshoski 11d65e4c0b MDL-85405 core: Bump version to update cache 2025-12-02 14:27:50 +08:00
Mihail Geshoski 7fd581312c Merge branch 'MDL-85405_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-12-02 14:20:09 +08:00
Huong Nguyen f9ec46708e Merge branch 'MDL-84898-prohibitjoin-50' of https://github.com/leonstr/moodle into MOODLE_500_STABLE 2025-12-02 10:38:24 +07:00
Huong Nguyen bd4730f673 Merge branch 'MDL-86425-500' of https://github.com/sh-csg/moodle into MOODLE_500_STABLE 2025-12-02 10:32:39 +07:00
Huong Nguyen 47f6947f32 Merge branch 'MDL-87218-500-enfix' of https://github.com/mudrd8mz/moodle into MOODLE_500_STABLE 2025-12-02 10:30:59 +07:00
Muhammad Arnaldo 1f68dba5c2 MDL-86806 core_courseformat: Fix RTL keyboard navigation
Ensure consistent navigation experience across LTR and
RTL interfaces in activity chooser.
2025-12-02 10:20:50 +07:00
David Mudrák 64e7610026 MDL-87218 lang: Use the fixed strings in tests, too 2025-12-01 19:46:29 +01:00
Helen Foster 44549616db MDL-87218 lang: Import fixed English strings (en_fix) 2025-12-01 19:46:29 +01:00
Jun Pataleta e3cc7953eb MDL-85858 mod_scorm: Fix Table of Contents toggle button's accessibility
* Set proper label via `aria-label`.
* Instead of changing the button's label to 'Show'/'Hide', set the
button's `aria-expanded` attribute accordingly.
* Remove unnecessary event handling for the toggle button when pressing
Enter or Space key. This is already natively supported and triggers
the click event.
* Adjust Behat tests accordingly.
2025-11-28 21:01:20 +08:00
Jun Pataleta 3902dd9df6 MDL-85858 mod_scorm: Use semantic heading for the Preview mode 2025-11-28 21:01:19 +08:00
Jun Pataleta 8b9a7fdb15 MDL-85858 mod_scorm: Set page and iframe titles for the SCORM player 2025-11-28 21:01:19 +08:00
Luca Bösch fbc330cf89 MDL-86844 qbank: style question bank table as in Moodle 4.5. 2025-11-28 10:40:16 +01:00
Huong Nguyen c4d054cfbf MDL-86087 core: Fix PHPUnit 11.5.43+ compatibility
Adjust tests to comply with updated PHPUnit lifecycle behaviour
 - Initialise typed test properties (e.g. core_session memcached test) or make them nullable
 - Add `isset()` checks to avoid accessing properties before initialisation
 - Ensure resetAfterTest() is called before modifying DB or `$USER`
2025-11-28 09:10:34 +07:00
Huong Nguyen d25846cb41 MDL-86087 core: Define environment requirements for Moodle 5.2 2025-11-28 09:10:34 +07:00
Paul Holden f2ca4d59b2 MDL-87339 hook: ensure cache directory present/writeable for use.
Avoids PHP warnings during Behat initialisation:

- file_put_contents(...): Failed to open stream: No such file or directory;
- rename(...): No such file or directory
2025-11-27 19:06:14 +00:00
Paul Holden 08d0f1021a MDL-87323 report_outline: fix report viewed event URL. 2025-11-27 17:28:56 +00:00
Mark Johnson 4317b656ae MDL-85405 course: Fix indentation and line wrapping 2025-11-27 15:13:46 +00:00
Luca Bösch d0c0e5a635 MDL-85405 modinfo: Don't show modules without FEATURE_CAN_DISPLAY
Question banks were displaying in places they shouldn't, because
FEATURE_CAN_DISPLAY wasn't fully implemented. This broadens its
usage in the following areas:

- Availability info - Not relevant to qbank. However you could feasibly
have some module which isn't shown to students, but the teacher can
use
  it to track completion, so dont display the link.
- Activities block - links to each activity's index page. We already
have
the Question banks page in the secondary nav. No need to have it here
too.
- Overview report - It doesn't make sense to display question banks
here,
  as they're not an activity students can participate in, they wont have
  dates etc.
- Externallib - Return with candisplay = false. The app needs to handle
  this correctly.
- Visibility options, moodleform_mod, modvisible and visibility
selector.
Not relevant for qbank since it doesn't include the standard
coursemodule
  options, but if an activity with without CAN_DISPLAY did display a
  visibility setting, "Hidden" should be the only option.
- Activity names filter - we dont want automatic links to question
banks.
2025-11-27 15:13:45 +00:00
Petr Skoda a16fc54eb3 MDL-87066 core: add upgrade note for clean_string() 2025-11-27 14:59:00 +01:00
Petr Skoda f00eecb062 MDL-87066 core: add clean_string() to solve double encoding in Mustache
The idea is to prevent double escaping in s()
and mustache.escape() by using numeric html
entities to sanitise result of format_string(),
get_string() and similar.
2025-11-27 14:59:00 +01:00
Luca Bösch a36c4548be MDL-87299 qtype_match: Remove Bootstrap 5 table borders. 2025-11-27 13:59:07 +01:00
Mihail Geshoski 299b171191 weekly release 5.0.3+ 2025-11-27 19:40:25 +08:00
Mihail Geshoski 446d364a02 Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2025-11-27 19:40:11 +08:00
Stefan Hanauska 7bce94b05f MDL-86425 backup: Reset nullcontent flag in xml_writer 2025-11-27 06:11:56 +01:00
Jun Pataleta bcba5e2b27 MDL-83485 core: Add bottom margin on preference links
To meet the WCAG 2.2 Level AA requirement for minimum target size,
we need to add a bit of spacing between the links on the user
preferences page.

More information:
https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html
2025-11-27 11:37:04 +08:00
Jun Pataleta 08564c803b MDL-83485 core: Add accessibility Behat coverage to the preferences page 2025-11-27 11:37:03 +08:00
Jun Pataleta 2fac37a527 MDL-83485 core: Fix heading level for preferences groups 2025-11-27 11:37:03 +08:00
Jun Pataleta 0d53dbc128 MDL-83485 core: Render preferences groups as lists 2025-11-27 11:37:03 +08:00
Andrew Nicols 3f64d0da2f Merge branch 'MDL-86255-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-27 11:11:06 +08:00
Andrew Nicols dcec803f0a Merge branch 'MDL-86955-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-27 11:08:30 +08:00
Jake Dallimore 707eef0930 Merge branch 'MDL-86840-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-11-27 09:43:58 +08:00
Paul Holden ae44f84ffa MDL-86988 mod_resource: ensure required library always present.
The `resourcelib` library is explicitly required by the modules
own local library, and neither the add/update methods use it
directly.
2025-11-26 15:11:12 +00:00
Paul Holden 773823a082 MDL-87188 gradereport_grader: prevent overlapping collapsed columns. 2025-11-26 11:40:35 +00:00
Mihail Geshoski 50cfa1884c Merge branch 'MDL-87259-500' of https://github.com/x-iy/moodle into MOODLE_500_STABLE 2025-11-26 18:02:27 +08:00
Mihail Geshoski 19c613902d Merge branch 'MDL-86668-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-11-26 17:51:36 +08:00
Mihail Geshoski 4893a3ca55 Merge branch 'MDL-86975-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-26 17:43:50 +08:00
Mihail Geshoski 09b4598628 Merge branch 'MDL-87149-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-11-26 17:30:00 +08:00
david adamson a9ab17b82e MDL-87259 course: Correct content item user cache key 2025-11-26 14:36:19 +11:00
Paul Holden b01cffa8c7 Merge branch 'MDL-87046-500' of https://github.com/andrewnicols/moodle into MOODLE_500_STABLE 2025-11-25 15:25:23 +00:00
Andrew Nicols 045967e885 MDL-86018 tool_xmldb: Check XML content in reconciler 2025-11-25 15:02:18 +00:00
Paul Holden a158a2043a Merge branch 'MDL-85306-500' of https://github.com/vinod404/moodle into MOODLE_500_STABLE 2025-11-25 14:38:05 +00:00
Andrew Nicols 880f41ef50 Merge branch 'MDL-86656-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-25 21:14:08 +08:00
Andrew Nicols a20783157a Merge branch 'MDL-86419-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-25 21:08:21 +08:00
Andrew Nicols 0edf1c226c Merge branch 'MDL-86279-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-25 21:04:36 +08:00
Andrew Nicols a8c5fd81c9 Merge branch 'MDL-87166-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-25 20:58:19 +08:00
Andrew Nicols e6f215292e Merge branch 'MDL-86765-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-25 20:52:26 +08:00
Leon Stringer d371441c62 MDL-84898 core: Improve prohibit performance
Change the query used to check if a user has a capability but is
assigned a role that prohibits that capability.  This is based on the
query added by Petr Skoda for MDL-57027.
2025-11-25 11:34:46 +00:00
Huong Nguyen 40544a33b5 Merge branch 'MDL-87017-500-frontpage-block-any-page' of https://github.com/danowar2k/moodle into MOODLE_500_STABLE 2025-11-25 10:42:18 +07:00
Huong Nguyen 88e4536aff Merge branch 'MDL-87194-500' of https://github.com/albertgasset/moodle into MOODLE_500_STABLE 2025-11-25 10:40:04 +07:00
Huong Nguyen db8823ef36 Merge branch 'MDL-86161-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-11-25 10:38:13 +07:00
Huong Nguyen 8318a966f5 Merge branch 'MDL-87031_500' of https://github.com/santoshndev/moodle into MOODLE_500_STABLE 2025-11-25 10:35:28 +07:00
Jun Pataleta ea032c7045 Merge branch 'MDL-86547-500' of https://github.com/muhammadarnaldo/moodle into MOODLE_500_STABLE 2025-11-25 11:09:46 +08:00
Huong Nguyen d19fcae54b Merge branch 'MDL-85930-500' of https://github.com/andimendunia/moodle into MOODLE_500_STABLE 2025-11-25 08:51:57 +07:00
Muhammad Arnaldo 53d459e674 MDL-86547 theme_boost: Override the code-color
Increase the contrast by overriding the existing code color to match the one on default.scss
2025-11-24 19:27:36 +07:00
Jun Pataleta 91fbd8048b Merge branch 'MDL-86547-500' of https://github.com/muhammadarnaldo/moodle into MOODLE_500_STABLE 2025-11-24 15:55:19 +08:00
Muhammad Arnaldo 55c2214ee3 MDL-86547 theme_boost: Improve inline code contrast in editor
Changed the background color of highlighted inline code for better accessibility.
2025-11-24 14:26:15 +07:00
AMOS bot 25d176c1bb Automatically generated installer lang files 2025-11-23 00:08:22 +00:00
Santosh Nagargoje 83356beefa MDL-87031 gradereport: Fixed clear button issue 2025-11-21 23:37:09 +05:30
Martin v. Löwis aee6e963f2 MDL-86523 backup: update context only if also updating category. 2025-11-21 15:47:08 +01:00
Luca Bösch bb1926ee95 MDL-86668 course: Support filter in scale names. 2025-11-21 10:46:27 +01:00
Luca Bösch 78629fc48a MDL-86161 groups: Correct picture title and alt text. 2025-11-21 10:46:11 +01:00
Huong Nguyen 91febb5f8e weekly release 5.0.3+ 2025-11-21 14:33:34 +07:00
Huong Nguyen cafdda4428 NOBUG: Add upgrade notes 2025-11-21 14:33:34 +07:00
Mihail Geshoski 3503f27db7 Merge branch 'MDL-86984-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-11-21 08:11:18 +07:00
Mihail Geshoski ed5aa97fc9 Merge branch 'MDL-86069-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-21 08:11:18 +07:00
Mihail Geshoski ec879bb46b Merge branch 'MDL-87011-500' of https://github.com/rjnl/moodle into MOODLE_500_STABLE 2025-11-21 08:11:17 +07:00
Huong Nguyen 7336d00a9d Merge branch 'MDL-86323_500' of https://github.com/PhilippImhof/moodle into MOODLE_500_STABLE 2025-11-21 08:11:17 +07:00
Huong Nguyen f95ba7e3aa Merge branch 'MDL-87048-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-11-21 08:11:17 +07:00
Huong Nguyen 33216607a5 Merge branch 'MDL-84735-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-11-21 08:11:17 +07:00
Andrew Nicols a5a6c1f554 MDL-87046 core: Fix shutdown manager early return
If the `\core_shutdown_manager::initialize` method is called multiple
times, it should only succeed once.

Unfortunately whilst logging existed, the shutdown manager did not
actually exit.
2025-11-21 08:53:03 +08:00
Huong Nguyen d75c674d3a Merge branch 'MDL-85373-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-20 13:30:41 +07:00
Mihail Geshoski 21778ac0c0 Merge branch 'MDL-86967_500' of https://github.com/Chocolate-lightning/moodle into MOODLE_500_STABLE 2025-11-20 13:30:41 +07:00
Huong Nguyen c8cfd00a3f Merge branch 'MDL-86272-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-20 13:30:41 +07:00
Amaia Anabitarte 95a394d41b Merge branch 'MDL-87198-500' of https://github.com/sarjona/moodle into MOODLE_500_STABLE 2025-11-20 13:30:41 +07:00
Huong Nguyen 3fd6c503ce Merge branch 'MDL-82511-cache-cron-MOODLE_500_STABLE' of https://github.com/bwalkerl/moodle into MOODLE_500_STABLE 2025-11-20 13:30:41 +07:00
Huong Nguyen aff6b93390 Merge branch '86320-fix-qr-code-unit-test-500' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_500_STABLE 2025-11-20 13:30:41 +07:00
Huong Nguyen 54683a0468 Merge branch 'MDL-86907-500' of https://github.com/mioyu-ubiq/moodle into MOODLE_500_STABLE 2025-11-20 13:30:41 +07:00
Huong Nguyen cbe8aca481 Merge branch 'MDL-72608-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-20 13:30:40 +07:00
Huong Nguyen f6f24f266d Merge branch 'MDL-85835-500' of https://github.com/plasger-uni-siegen/moodle into MOODLE_500_STABLE 2025-11-20 13:30:40 +07:00
Huong Nguyen fbcefd88b2 Merge branch 'MDL-86998-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-11-20 13:30:40 +07:00
Simey Lameze 0594d87148 MDL-87050 behat: use src for img xpath selector 2025-11-20 13:30:40 +07:00
Mihail Geshoski 00205a5453 Merge branch 'MDL-85049-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-11-20 13:30:40 +07:00
Mihail Geshoski 56d34f5a47 Merge branch 'MDL-86817_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-11-20 13:30:40 +07:00
Angelia Dela Cruz 323458a3a8 MDL-87048 tool_lp: Behat for synchronising cohort with learning plan 2025-11-20 10:10:31 +08:00
Angelia Dela Cruz 071658ba28 MDL-84735 gradingform: Behat for modifying marking guide criterion 2025-11-20 07:50:09 +08:00
Paul Holden c1860dad87 MDL-86272 tool_policy: verify current user before store policy agreed. 2025-11-18 11:47:59 +00:00
Santosh Nagargoje 6f62b7eaa5 MDL-86749 questions: Added index on hashcode column
Identified performance bottlenecks in clear_cached_data() from
mod/quiz/report/statistics/report.php. The delete_records() calls on
question_statistics, question_response_analysis, and quiz_statistics tables
use the hashcode column for filtering, which becomes inefficient with large
datasets.
2025-11-18 16:56:47 +05:30
Paul Holden 4e85aecde8 MDL-86565 courseformat: don't link to sections user cannot see. 2025-11-18 10:32:01 +00:00
Mathew May 0b6ac8dc94 MDL-86967 theme_classic: Correct orange & yellow vars + warning 2025-11-18 15:06:50 +08:00
Mathew May 40f7285bbb MDL-86967 theme_boost: Correct orange & yellow vars + warning 2025-11-18 15:06:45 +08:00
mioyu-ubiq fba03e9ee5 MDL-86907 mod_choice: Behat test for adding multiple choice responses 2025-11-18 15:01:54 +08:00
Mihail Geshoski 9e26d529c4 Merge branch 'MDL-86099_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-11-17 22:28:35 +08:00
Andi Permana b21e7b56a6 MDL-85930 tiny_media: Fix adding video from Youtube repo 2025-11-17 19:10:13 +07:00
Paul Holden f1d0e24258 MDL-86279 core: fix deprecation emitting/annotation in AWS helpers. 2025-11-17 11:01:03 +00:00
Paul Holden 6213577e08 MDL-86955 tool_task: ensure tasks are runnable in adhoc table output. 2025-11-17 10:56:49 +00:00
Huong Nguyen 06a1c95afa Merge branch 'MDL-85235-500' of https://github.com/safatshahin/moodle into MOODLE_500_STABLE 2025-11-17 16:02:01 +07:00
Huong Nguyen d3096b658b Merge branch 'MDL-87050-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2025-11-17 15:58:14 +07:00
Huong Nguyen eb07f79220 Merge branch 'MDL-87111-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-17 15:31:42 +07:00
Huong Nguyen 146c3da68f Merge branch 'MDL-86810-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-17 15:27:42 +07:00
Huong Nguyen c47d471e3b Merge branch 'MDL-86159-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-17 14:56:03 +07:00
Huong Nguyen df3ef9a8e7 Merge branch 'MDL-85764-quiz-notification-MOODLE_500_STABLE' of https://github.com/bwalkerl/moodle into MOODLE_500_STABLE 2025-11-17 14:50:48 +07:00
vinod404 b362a6d1ed MDL-85306 core/toggle: Move tooltip/title to input to show tooltips.
The title and tooltip attributes are now moved to the input element, ensuring tooltips appear.
2025-11-17 12:14:16 +05:30
Jun Pataleta 83d2dc180f MDL-87149 mod_feedback: Accessibility Behat test coverage
* Check the accessibility of the questionnaire, especially when
there are dependent questions.
* Use generators for a more efficient and faster test execution.
2025-11-17 12:45:01 +08:00
Jun Pataleta a14c44374a MDL-87149 mod_feedback: Generate dependent questions
Allow the generator to create questions that depend on other questions.
2025-11-17 12:45:01 +08:00
Jun Pataleta e6d4f54e23 MDL-87149 theme_boost: Remove the .feedback_is_dependent class
It's no longer being used. So, just remove it.
2025-11-17 12:45:00 +08:00
Jun Pataleta ad733468ef MDL-87149 mod_feedback: Do not use .feedback_is_dependent anymore
Making a visual distinction for dependent questions compared to other
questions does not add much value in the perspective of users. We should
just stop adding the `.feedback_is_dependent` class for dependent
questions.
2025-11-17 12:45:00 +08:00
Huong Nguyen 3a7525ed2f Merge branch 'MDL-87107-500' of https://github.com/andrewnicols/moodle into MOODLE_500_STABLE 2025-11-17 09:09:02 +07:00
Mark Johnson 377bce2895 MDL-86099 questions: Check for empty bank names
If we call `question_bank_helper::create_default_open_instance` with an
empty `$bankname` parameter, it will currently create a new instance
with no name. This leads to exceptions being thrown when we try to load
the course it belongs to.

This adds some validation to ensure the name being passed is not empty.
Once the issue is resolved, and the bank is created with a proper name,
the course will work as normal.
2025-11-14 16:51:21 +00:00
Albert Gasset d0fdcd6528 MDL-87194 tool_mobile: Fix subscription requests 2025-11-14 16:17:03 +01:00
Albert Gasset 6e173777e9 MDL-87194 message_airnotifier: Fix access key requests 2025-11-14 16:16:54 +01:00
Sara Arjona 17d26daac7 MDL-87198 course_format: Consider section name visibility in Overview 2025-11-14 15:56:49 +01:00
Daniel Poggenpohl 3dfe385f07 MDL-87017 blocks: Provide page context to page_type_list functions
- The current context may be necessary when deleting a frontpage block displayed on every page with javascript disabled
- The current context may be necessary when a frontpage block is displayed on every page and the question bank is viewed
- Also handle a NULL currentcontext for question_page_type_list() correctly
2025-11-14 15:37:58 +01:00
Paul Holden bada9f3efa MDL-72608 output: define default popover region template lang string. 2025-11-14 13:04:50 +00:00
Paul Holden c0d57476a5 MDL-86419 enrol_ldap: define plugin's own copy of configuration strings.
AMOS BEGIN
 CPY [ignorehiddencourses,enrol_database],[ignorehiddencourses,enrol_ldap]
 CPY [ignorehiddencourses_desc,enrol_database],[ignorehiddencourses_desc,enrol_ldap]
AMOS END
2025-11-14 13:03:56 +00:00
Benjamin Walker 5afac60e42 MDL-85764 mod_quiz: Improve performance of quiz notifications task 2025-11-14 20:04:14 +10:00
Benjamin Walker 724e5b45e3 MDL-82511 cachestore_redis: Reduce blocking when finding keys 2025-11-14 20:03:43 +10:00
Benjamin Walker fd6b14286a MDL-82511 cache: Improve performance of cleanup in cache_cron_task 2025-11-14 20:03:43 +10:00
Paul Holden 2fada9ae2d MDL-86159 mod_bigbluebuttonbn: consistent/correct course name format. 2025-11-14 07:57:59 +00:00
Philipp Imhof edc2f17f54 MDL-86323 editor_tiny: allow svg attributes
Co-authored-by: Petr Skoda <commits@skodak.org>
2025-11-14 08:50:29 +01:00
Luca Bösch 0349b88a58 MDL-86984 book: remove borders in print page top table. 2025-11-13 17:06:59 +01:00
Luca Bösch 19df1c7ea2 MDL-85049 question: complete border around table row for newest question 2025-11-13 17:02:25 +01:00
Mihail Geshoski e6593a6e73 weekly release 5.0.3+ 2025-11-13 18:49:03 +08:00
Mark Johnson 458be6f714 MDL-86817 qbank: Prevent unique key violations during migration
When fixing categories with broken parents, if the resulting changes
would have led to categories with the same stamp or idnumber being in
the same context, the task failed due to violations of the unique keys
on contextid-stamp and contextid-idnumber.

This checks for violations before moving categories, and either
generates a new stamp or nulls the idnumber on the category being moved,
following the method used in MDL-85869.
2025-11-13 10:35:16 +00:00
Angelia Dela Cruz 1d8531f7d5 MDL-87050 mod_folder: Behat for preventing forced file downloads 2025-11-13 15:53:07 +08:00
Mihail Geshoski 1e2310781e Merge branch 'MDL-86397_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-11-13 12:16:20 +08:00
Huong Nguyen 8715e6ddab Merge branch 'MDL-86845-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-11-13 11:12:12 +07:00
Huong Nguyen 86574edf57 Merge branch 'MDL-86895-500' of https://github.com/mioyu-ubiq/moodle into MOODLE_500_STABLE 2025-11-13 10:44:05 +07:00
Huong Nguyen 739d59d8d3 Merge branch 'MDL-79249-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2025-11-13 10:20:36 +07:00
Huong Nguyen d51f19869f Merge branch 'MDL-87047-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2025-11-13 10:16:53 +07:00
Huong Nguyen 1cfae4692b Merge branch 'MDL-78973-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2025-11-13 08:52:54 +07:00
Huong Nguyen 904d4637ef Merge branch 'MDL-84967-M500_recordset-not-closed-in-core_analytics_local_analyser_by_course_get_analysables_iterator' of https://github.com/ziegenberg/moodle into MOODLE_500_STABLE 2025-11-13 08:47:36 +07:00
Huong Nguyen e72988cdf3 Merge branch 'MDL-82867-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-13 08:44:42 +07:00
Mark Johnson 8c35bcb50e MDL-86397 calendar: Filter user courses
In the calendar API, `raw_event_retrieval_strategy` accepts a list of
courses to return events for. If one or more users are also specified,
it will find the courses the are enrolled in, then call
`calendar_set_filters()` to return a sorted list of those courses, and
any groups within those courses that they can see events for. The list
of courses in then filtered to those passed to
`raw_event_retrieval_strategy`.

If the user is enrolled on lots of courses, but is only viewing the
caledar for one course, this results in a lot of redundant work to fetch
group data for their courses which is then not used. This either
involves a lot of extra complex queries, or results in an unncessary
cache hit for each course.

This change re-orders the code so that the list of enrolled courses is
filtered to just those courses being viewed, before it is passed to
`calendar_set_filters()`. This means we are only fetching group data for
those courses we will be showing events for.
2025-11-12 14:25:40 +00:00
Mihail Geshoski b00abeda20 Merge branch 'MDL-87130-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-12 17:26:23 +08:00
Mihail Geshoski c8b6f031cd Merge branch 'MDL-86963-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2025-11-12 17:15:00 +08:00
Mihail Geshoski 31b09beaa8 Merge branch 'MDL-85686-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-11-12 16:59:57 +08:00
Angelia Dela Cruz dca942ad3e MDL-87047 tool_lp: Behat optimisation 2025-11-12 16:37:50 +08:00
Mihail Geshoski eafa526b2b Merge branch 'MDL-86886-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2025-11-12 16:37:26 +08:00
Angelia Dela Cruz eb9e540a7f MDL-87047 tool_lp: Behat to complete a learning plan and alter it 2025-11-12 16:34:53 +08:00
Angelia Dela Cruz be198feadf MDL-86963 tool_lp: Behat to perform CRUD operations on competencies 2025-11-12 10:33:24 +08:00
Luca Bösch 80d90fd53d MDL-86845 admin: Striped hovering plugins + course format table w/ BS 5. 2025-11-12 00:22:01 +01:00
Safat e29cfb15d2 MDL-85235 tool_mobile: Implement the augmentation hooks for apps 2025-11-12 10:11:16 +11:00
Safat 79950edcd1 MDL-85235 tool_mobile: Add extend ios app banner hook 2025-11-12 10:11:03 +11:00
Paul Holden a32e1d6000 MDL-87130 dml: fix SQL debugging test assertions on Windows.
Ensure that the Windows directory separator ('\') isn't confused
for regular expression control character.
2025-11-11 15:50:41 +00:00
Jun Pataleta 8d4bef06c3 MDL-86840 forum: Add accessibility Behat coverage
* Add accessibility Behat coverage on the Advanced forum search page.
2025-11-11 21:14:11 +08:00
Jun Pataleta ccff76264a MDL-86840 forum: Do not use layout table for the search form 2025-11-11 21:14:10 +08:00
Jun Pataleta 73d4148143 MDL-86840 forum: Fix heading structure of search form 2025-11-11 21:14:10 +08:00
Paul Holden 84caa44014 MDL-86765 forms: disable calendar icon if element disabled.
This is similar to change in ec89abc5 which updated the icon state
if the corresponding checkbox was unchecked. Here we're doing the
same if the entire date/time element itself is disabled.
2025-11-11 12:49:46 +00:00
Paul Holden 365649a8b7 MDL-86656 task: remove spurious mtrace parameters in calling code.
Co-authored-by: Jason Lees <jlees@arden.ac.uk>
2025-11-11 12:48:16 +00:00
Paul Holden b6f7d9b192 MDL-87056 enrol: update instance modified date when toggling status. 2025-11-11 12:36:26 +00:00
Paul Holden 24523358c0 MDL-87111 filter_tex: remove border-radius of rendered expression. 2025-11-11 12:18:23 +00:00
Paul Holden 0352940fbf MDL-87166 communication: verify user feature support on user deletion. 2025-11-11 11:45:40 +00:00
Jun Pataleta 89951b89c5 MDL-86998 message: Fix accessibility issues in notification settings
* Fix missing labels for the checkboxes that enable notification plugins
* Add an accessible name for the Default notification preferences table
* Fix missing table header for the preference column of the Default
  notification preferences table.
* Accessibility Behat test coverage for the Notification settings
  admin page
* Remove the unnecessary title attributes for the visually hidden labels
2025-11-11 17:28:49 +08:00
Jun Pataleta 57c4780ead MDL-86998 message: Fix accessibility issues in notification preferences
* Fix missing column heading for the preference column
* Fix incorrect label for the toggle controls
* Make the preference name a table heading with a row scope so that the
  toggle controls will be programmatically associated to it.
* Apply a col scope for the processor column headings to
  programmatically associate the toggle controls to their respective
  columns.
2025-11-11 17:28:49 +08:00
Angelia Dela Cruz 234fd43581 MDL-86886 tool_lp: Behat to move and cross-reference competencies 2025-11-11 15:54:46 +08:00
Simon Plasger ba629c5b41 MDL-85835 TinyMCE: Fix not working tabs on TinyMCE in quiz mode 2025-11-11 07:32:13 +01:00
Angelia Dela Cruz 479738e0ff MDL-78973 Behat: Behat coverage for invalid file upload in data activity 2025-11-11 13:16:49 +08:00
Simey Lameze cd4c824f6e MDL-85686 mod_quiz: unit test coverage for questions shuffle 2025-11-11 11:18:04 +08:00
Mio Yu ccb3653e7e MDL-86895 core_grades: Behat to verify listing and grading submissions 2025-11-11 09:51:55 +08:00
Safat 5637b4f6ed MDL-85235 core: Add extend url hook 2025-11-10 22:07:39 +11:00
Safat 1eb3e7781d MDL-85235 tool_mobile: Make mobile manifest cookieless and cacheable 2025-11-10 22:07:39 +11:00
Huong Nguyen b6a4b81ae8 Merge branch 'MDL-85627-500' of https://github.com/jleyva/moodle into MOODLE_500_STABLE 2025-11-10 10:17:19 +07:00
Huong Nguyen c615ae3949 Merge branch 'MDL-86999-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-11-10 10:13:11 +07:00
Huong Nguyen bf52e60dce Merge branch 'MDL-81604-500' of https://github.com/t-schroeder/moodle into MOODLE_500_STABLE 2025-11-10 10:08:14 +07:00
Shamim Rezaie 04b7ec3506 Merge branch 'MDL-86965-500' of https://github.com/NashTechOpenUniversity/moodle into MOODLE_500_STABLE 2025-11-10 13:44:24 +11:00
Luca Bösch b038b9ad2d MDL-86999 customfield: Striped hovering fields table with BS 5. 2025-11-07 13:11:19 +01:00
Andrew Nicols f3702d06e0 MDL-87107 core: Stop using MUC for hook manager caching 2025-11-07 17:19:09 +08:00
Huong Nguyen 7838e3f247 weekly release 5.0.3+ 2025-11-07 14:49:05 +07:00
Huong Nguyen 6f5c9fdcee NOBUG: Add upgrade notes 2025-11-07 14:49:05 +07:00
Huong Nguyen 758b273d33 Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2025-11-07 14:48:54 +07:00
Huong Nguyen 32824dd691 Merge branch 'MDL-86701-500-fix' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-11-07 08:46:41 +07:00
Juan Leyva 5b1c5c47e5 MDL-85627 mod_bigbluebuttonbn: Remove unused class 2025-11-06 13:14:32 +01:00
Jun Pataleta d603e78896 MDL-86701 behat: Update Behat tests to press edit/delete buttons 2025-11-06 18:40:22 +08:00
Huong Nguyen 8c399ba7f9 MDL-69226 environment: filter extension required for 4.1 2025-11-06 18:21:33 +08:00
hieuvu adf6199966 MDL-86965 core_question: Fix get_bank_instances query. 2025-11-06 16:52:09 +07:00
Mihail Geshoski 2699e5f3c2 Merge branch 'MDL-87073-500' of https://github.com/HuongNV13/moodle into MOODLE_500_STABLE 2025-11-06 17:07:52 +08:00
Huong Nguyen cbe0abe1be MDL-87073 PHPUnit: Use non-DST timezone for comparing
Including in this commit
 - Use America/New_York instead of US/Eastern
2025-11-06 15:47:13 +07:00
Huong Nguyen 54272a7269 Merge branch 'MDL-86908-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2025-11-06 15:42:27 +07:00
Huong Nguyen 525c6541bc Merge branch 'MDL-87049-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-11-06 15:40:31 +07:00
Huong Nguyen b80d614961 Merge branch 'MDL-87079-500' of https://github.com/andrewnicols/moodle into MOODLE_500_STABLE 2025-11-06 15:37:29 +07:00
Jake Dallimore a8ad58cc07 Merge branch 'MDL-86379-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-11-06 14:30:05 +08:00
Mihail Geshoski 37c7760c98 Merge branch 'MDL-86010_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-11-06 11:53:07 +08:00
Huong Nguyen 2ab3f1088f Merge branch 'MDL-87019-redis-bloat-MOODLE_500_STABLE' of https://github.com/bwalkerl/moodle into MOODLE_500_STABLE 2025-11-06 10:35:11 +07:00
Jake Dallimore cfa5f8a60d Merge branch 'MDL-86534-500' of https://github.com/andrewnicols/moodle into MOODLE_500_STABLE 2025-11-06 11:33:50 +08:00
Huong Nguyen 41ad1a67f9 Merge branch 'MDL-86701-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-11-06 10:27:21 +07:00
Huong Nguyen 2d17eeb6c8 Merge branch 'MDL-86332-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-06 10:20:33 +07:00
Huong Nguyen 6ab0bdd7f7 Merge branch 'mdl-85036_500' of https://github.com/james-cnz/moodle into MOODLE_500_STABLE 2025-11-06 10:53:56 +08:00
Jake Dallimore f4f445d54a Merge branch 'MDL-87004_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-11-06 10:53:56 +08:00
Simey Lameze 280a604e4d MDL-87049 behat: read showcampaigncontent setting when running behat 2025-11-06 08:20:52 +08:00
Angelia Dela Cruz 95304962da MDL-87049 core: Behat to toggle campaign content banner display 2025-11-06 08:20:51 +08:00
AMOS bot 323ee9aa02 Automatically generated installer lang files 2025-11-06 00:07:58 +00:00
Angelia Dela Cruz 7ca19e9c32 MDL-86908 core_contentbank: Behat to set supported files of contentbank 2025-11-05 18:00:23 +08:00
Simey Lameze 8de0e64544 MDL-86379 mod_quiz: move create_test_quiz function into generator 2025-11-05 11:50:11 +08:00
Andrew Nicols 7e9255978b MDL-87079 core: Call existing pcntl handlers
Whilst `register_shutdown_function` works as a queue, `pcntl_signal`
does not.

To preserve the behaviour of existing signal handlers, as are typically
found in CLI wrappers like PHPUnit and Behat, we should store any
existing handler
2025-11-05 08:52:34 +08:00
Ilya Tregubov 33483246d1 Merge branch 'MDL-86953-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-04 16:46:33 +01:00
James C 69957f8a3b MDL-85036 completion: Properly initialize cm_info for user completion 2025-11-04 20:53:29 +13:00
Jake Dallimore 5b848f2964 Merge branch 'MDL-85391-m500' of https://github.com/NeillM/moodle into MOODLE_500_STABLE 2025-11-04 14:14:48 +08:00
Jake Dallimore ac3f6fc4d3 Merge branch 'MDL-86855-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-11-04 14:09:54 +08:00
Ilya Tregubov bd132c995d Merge branch 'MDL-86952-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-11-03 12:14:42 +01:00
Jun Pataleta c24afe888c MDL-86701 customfield: Better naming of custom field action buttons
Include the category and field names for accessible names of the delete
and action buttons to help assistive technology users better understand
the buttons' purpose.
2025-11-03 12:12:32 +08:00
Jun Pataleta c11f67bdb4 MDL-86701 customfield: Improve action buttons accessibility
* Use native HTML buttons for the edit and delete buttons. This provides
default button behaviours which helps keyboard users activate the
buttons using either the Space or Enter key.
* Move the accessible label out of the pix icon and to the action button
itself.
* Style buttons to ensure that they have a minimum clickable size of
24x24 pixels to sufficiently meet WCAG 2.2 SC 2.5.8 - Target Size
(Minimum) (Level AA).
2025-11-03 11:59:40 +08:00
Angelia Dela Cruz 2ca2aeaf03 MDL-79249 core_filepicker: Cancel file and folder upload using X button 2025-11-03 10:44:38 +08:00
Huong Nguyen 9a7a484e69 Merge branch 'MDL-69226-M500_verify-that-the-filter-php-extension-is-present' of https://github.com/ziegenberg/moodle into MOODLE_500_STABLE 2025-11-03 09:02:15 +07:00
AMOS bot fdc195ce67 Automatically generated installer lang files 2025-11-01 00:07:57 +00:00
Benjamin Walker 2530e564b1 MDL-87019 redis: Avoid storing userhashkey for non-login users 2025-10-31 16:20:34 +10:00
Huong Nguyen 8449b9ac6f Merge branch 'MDL-86235-500' of https://github.com/andimendunia/moodle into MOODLE_500_STABLE 2025-10-31 09:34:55 +07:00
Mihail Geshoski 8316503864 weekly release 5.0.3+ 2025-10-30 18:11:16 +08:00
Mihail Geshoski 158fa68cdf Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2025-10-30 18:11:00 +08:00
Neill Magill ee5126a88e MDL-85391 course: Handle null course urls
Course urls may be null when navigation is set to true.

The return value from course_get_url being null was not being handled before
this change, which could lead to an exception causing the page not to load.

It also handles null urls in the course index in Boost so that they are
not a link to what ever the current page is.

If either the first or last section in a format did not a
return a url under the Classic theme there would still be
a link displayed with a link to the current page the user
is on.

After this change no link would be displayed in this case.
2025-10-29 08:16:34 +00:00
Huong Nguyen 88b6baa6af Merge branch 'mdl85075-50' of https://github.com/matthewhilton/moodle into MOODLE_500_STABLE 2025-10-29 09:31:20 +07:00
Mihail Geshoski 06463ce66a Merge branch 'MDL-86894-500' of https://github.com/Kredelirious/moodle into MOODLE_500_STABLE 2025-10-29 10:18:31 +08:00
Mihail Geshoski d3d2107e2c Merge branch 'MDL-82190-500' of https://github.com/danghieu1407/moodle into MOODLE_500_STABLE 2025-10-29 10:11:34 +08:00
Daniel Ziegenberg 4eded4dca4 MDL-69226 environment: filter extension required
Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
2025-10-28 19:31:14 +01:00
Kim Jared Lucas f9a738f3cf MDL-86894 mod_forum: Behat to verify default forum RSS settings 2025-10-28 13:02:58 +08:00
AMOS bot aacdf287f5 Automatically generated installer lang files 2025-10-28 00:09:47 +00:00
Rajneel Totaram eb3731e9b2 MDL-87011 mod_assign: Replace deprecated CSS style 2025-10-27 22:25:50 +12:00
Adrian Greeve 5190731af4 Merge branch 'MDL-85774-500-3' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-10-27 09:03:21 +08:00
Daniel Ziegenberg ab33219f38 MDL-84967 analytics: close recordset when it's not needed anymore
Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
2025-10-24 21:02:59 +02:00
ferran 5b5ef5c66f Merge branch 'MDL-86430-Bad-Display-Of-Scale-Grading-500' of https://github.com/birdy1976/moodle into MOODLE_500_STABLE 2025-10-24 12:15:36 +02:00
Andi Permana 2a4b767402 MDL-86235 core: Add table-hover class to admintable and generaltable 2025-10-24 15:50:06 +07:00
Mark Johnson da518313d6 MDL-87004 backup: Ensure backups include all random questions
Backing up quizzes containing random questions from multiple different
categories was only including one of the categories in the backup.

This was due to doing $array + $array instead of array_merge(), meaning
items in the second array with keys that were already present in the
first did not get added to the result.
2025-10-24 09:45:31 +01:00
Jun Pataleta d158fc8819 MDL-86855 qbank_columnsortorder: Render disabled columns as a list
* Lists must be marked up with the proper semantics.
2025-10-24 12:02:54 +08:00
Jun Pataleta 83ffdd7a71 MDL-86855 qbank_columnsortorder: Fix accessibility issues
* Fix empty column heading in admin settings page
* Add accessible labels for the move buttons
* Fix drag and drop Behat test
* Add accessibility Behat coverage
2025-10-24 12:02:54 +08:00
Huong Nguyen 1beae326aa weekly release 5.0.3+ 2025-10-24 11:00:15 +07:00
Huong Nguyen 89cd360c83 NOBUG: Add upgrade notes 2025-10-24 11:00:15 +07:00
Martin Vögeli 719921b93a MDL-86430 theme_boost: Fix display of scale grading when title too long 2025-10-23 17:14:51 +02:00
danghieu1407 9765721e10 MDL-82190 Quiz: Fix quiz preview crash on question version removal 2025-10-23 13:32:47 +07:00
Jun Pataleta 52ec42bb01 MDL-85774 login: Check for username/password fields before moving focus
When the login form is not shown but $CFG->loginautofocus is turned on,
we need to verify first that the username and password fields exist
before we move the focus. Otherwise, the JS will break.
2025-10-23 11:28:48 +08:00
Jun Pataleta 4c66cdde04 MDL-85774 login: Remove visually-hidden links
Visually hidden links on login error/info disrupt tab order. We must
remove them.

Instead, announce the div containing the login error/info messages on
page reload.

The visually hidden signup link has also been removed.
2025-10-23 11:28:48 +08:00
Huong Nguyen 5be6382221 Merge branch 'MDL-86986-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-10-23 09:57:31 +07:00
Huong Nguyen f50b0661ef Merge branch 'MDL-80524-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-23 09:29:27 +07:00
Mihail Geshoski 7b443d6bf0 Merge branch 'MOODLE_500_STABLE' of https://github.com/aneno-m-e/moodle into MOODLE_500_STABLE 2025-10-23 10:23:12 +08:00
Matthew Hilton bd500af20e MDL-85075 files: Use core security helper first 2025-10-23 12:21:17 +10:00
Andrew Nicols a429bfbdac Merge branch 'MDL-81804-500-first' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-10-23 09:12:45 +08:00
Amaia Anabitarte f8cc4eeea9 Merge branch 'MDL-86434-invalidusertitle-500' of https://github.com/leonstr/moodle into MOODLE_500_STABLE 2025-10-22 23:12:54 +02:00
Luca Bösch 635b7f6bdf MDL-81804 dml: Passing parameters with -c key=val on PostgreSQL.
Co-authored-by: Marcos Dos Santos De Oliveira <marcos.s.oliveira@fiesc.com.br>
2025-10-22 16:20:25 +02:00
Jun Pataleta ded6e7e9b2 MDL-86986 core: Add aria-label to the drag handle button 2025-10-22 20:14:38 +08:00
ferran 66a094dc77 Merge branch 'wip_MDL-86435_m50' of https://github.com/gjb2048/moodle into MOODLE_500_STABLE 2025-10-22 12:55:56 +02:00
Mihail Geshoski e9ad1731cb Merge branch 'MDL-85474_500' of https://github.com/jonof/moodle into MOODLE_500_STABLE 2025-10-22 16:46:56 +08:00
Paul Holden a3c171eeb8 MDL-80524 rating: preserve activity idnumber when adding rating.
See also e9a5485f for context regarding similar problem with grade
updates.

Co-authored-by: Julian Tovar
2025-10-22 09:43:39 +01:00
Mihail Geshoski 79cf123335 Merge branch 'MDL-86282-500' of https://github.com/srobotta/moodle into MOODLE_500_STABLE 2025-10-22 16:31:09 +08:00
Noemie Ariste 0fb17449f6 MDL-75764 mod_assign: remove capability check for bulk downloads 2025-10-22 16:50:14 +13:00
Mihail Geshoski 1e44685774 Merge branch 'MDL-86217-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-22 11:41:19 +08:00
Mihail Geshoski 8c2b54410e Merge branch 'MDL-86225-500' of https://github.com/josepico01/moodle into MOODLE_500_STABLE 2025-10-22 11:03:21 +08:00
Mihail Geshoski ba4ffb5881 Merge branch 'MDL-86063-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-22 10:21:45 +08:00
Huong Nguyen 2f4f624b19 Merge branch '83543-xls-form-500' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_500_STABLE 2025-10-22 09:12:55 +07:00
Huong Nguyen c8d7e0cf64 Merge branch '77137-proxybypass-on-multiple-curl-queries-500' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_500_STABLE 2025-10-22 09:07:17 +07:00
Paul Holden 84e9482367 MDL-86975 mod_book: fix alignment of chapter editing delete icon.
Mis-aligned since changes to previously used action icon in df486967.
2025-10-22 00:26:42 +01:00
Amaia Anabitarte 60950923a6 Merge branch 'MDL-85796-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-10-21 19:56:09 +02:00
Paul Holden fd5aa44763 MDL-86255 behat: implement methods to assert date/time field value. 2025-10-21 11:34:43 +01:00
Shamim Rezaie e36f16ec13 Merge branch 'MDL-85592-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-21 17:10:33 +11:00
Huong Nguyen 1125b4ada6 Merge branch 'MDL-85168-MOODLE_500_STABLE' of https://github.com/phmemmel/moodle into MOODLE_500_STABLE 2025-10-21 10:36:34 +07:00
Huong Nguyen 974b18b09e Merge branch 'MDL-85633-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-10-21 09:47:25 +07:00
Huong Nguyen e465d5432f Merge branch 'MDL-85511-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-10-21 09:44:49 +07:00
Huong Nguyen 5194cad1b5 Merge branch 'MDL-85287-m500' of https://github.com/sammarshallou/moodle into MOODLE_500_STABLE 2025-10-21 09:42:07 +07:00
Huong Nguyen 2849cf39dc Merge branch 'MDL-86559-500' of https://github.com/andimendunia/moodle into MOODLE_500_STABLE 2025-10-21 09:39:32 +07:00
Jonathon Fowler 06417ba66a MDL-85474 assign: fix call to undefined 'view_error_page' method
And while doing so, fix $notices parameters that ought to be call-by-
reference to collect notices produced during calls to
process_submit_other_for_grading() and process_submit_for_grading().
2025-10-21 10:30:42 +10:00
Paul Holden cf8d527e11 Merge branch 'MDL-86455-500' of https://github.com/yerairogo/moodle into MOODLE_500_STABLE 2025-10-20 16:51:06 +01:00
Sara Arjona 4be1d94f50 Merge branch 'MDL-86598-500' of https://github.com/aanabit/moodle into MOODLE_500_STABLE 2025-10-20 16:59:08 +02:00
Amaia Anabitarte 50ee96071a MDL-86598 course: Render HTML in activity overview section name mustache 2025-10-20 16:16:52 +02:00
Amaia Anabitarte 7c767af54b Merge branch 'MDL-86011-500' of https://github.com/sarjona/moodle into MOODLE_500_STABLE 2025-10-20 16:01:45 +02:00
Amaia Anabitarte e5f5854999 Merge branch 'MDL-86912-500' of https://github.com/sarjona/moodle into MOODLE_500_STABLE 2025-10-20 13:33:44 +02:00
Luca Bösch 8c7fd86a7d MDL-85633 course: Move away from YUI navigation.
Co-authored-by: Mikel Martín Corrales <mikel@moodle.com>
2025-10-20 11:25:14 +02:00
sam marshall 227e4a4e28 MDL-85287 User tours: Avoid scrolling while backdrop is displayed
If the page scrolls while the backdrop is displayed, it looks
incorrect because the backdrop does not scroll with page content.
To avoid this, don't show the backdrop until scrolling has finished.
2025-10-20 09:58:30 +01:00
Sara Arjona df800f94e2 MDL-86912 assign: Prevent admin submitting unless enrolled as student 2025-10-20 09:47:27 +02:00
Sara Arjona ef2bce431e MDL-86912 assign: Adjust display of Status column in Overview 2025-10-20 09:47:27 +02:00
Luca Bösch 1003a27252 MDL-85511 course: back button for course management course search. 2025-10-20 08:03:57 +02:00
Mihail Geshoski 66ff71cbe8 Merge branch 'MDL-85696-500' of https://github.com/andelacruz/moodle into MOODLE_500_STABLE 2025-10-20 10:28:03 +08:00
Huong Nguyen 96906b853e Merge branch 'mdl-85917_500' of https://github.com/james-cnz/moodle into MOODLE_500_STABLE 2025-10-20 08:48:46 +07:00
Huong Nguyen 514417a376 Merge branch 'MDL-85975_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-10-20 08:45:59 +07:00
Paul Holden f9f4c49fd2 MDL-86063 customfield: internally validate numeric data in persistent.
Move previous validation from the data controller, added in 89dbe63d,
into the persistent class itself so that it can internally validate
itself rather than relying on callers.

This resolves problems with empty/null numeric fields contained within
course backups (e.g. during course copy).
2025-10-19 16:53:17 +01:00
Paul Holden 01a3c146c3 MDL-86217 badges: gracefully handle missing recipient data. 2025-10-19 16:50:16 +01:00
Gareth Barnard cf1e0e962f MDL-86435 course: i/groupn.svg is not the same size as other icons. 2025-10-17 16:49:24 +01:00
Paul Holden 5a3bcf7b82 MDL-86953 blocks: constrain block controls menu on narrow screens.
Extension of work in 93cadaba that constrained the dropdown menu,
we now set a breakpoint to account for overflowing when narrow.
2025-10-17 14:49:48 +01:00
Ilya Tregubov 520ae9c00d Merge branch 'MDL-80422-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-17 15:37:33 +02:00
Paul Holden 70f1993958 MDL-86952 output: truncate long text in drag/drop dialog options. 2025-10-17 14:12:31 +01:00
Paul Holden cdc9d7e3ff MDL-86952 output: truncate long text in modal/dialog title element. 2025-10-17 14:12:10 +01:00
Amaia Anabitarte 0306be834e Merge branch 'MDL-85887-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-17 13:47:48 +02:00
Paul Holden 95c789fc1d MDL-86810 completion: update module completion data correctly.
Ensure we check the correct field to determine form value.
2025-10-17 12:13:01 +01:00
Paul Holden f8f309800c MDL-85373 admin: update site installation page referenced favicon. 2025-10-17 12:06:27 +01:00
Angelia Dela Cruz 123b1a1193 MDL-85696 mod_quiz: Behat to attempt password and time restricted quiz 2025-10-17 16:19:36 +08:00
Huong Nguyen 7518095d59 Merge branch 'MDL-85418-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-17 10:28:04 +07:00
Huong Nguyen dd2de75ad4 Merge branch 'MDL-85312-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-17 10:19:09 +07:00
Andrew Nicols b286e6c65a Merge branch 'm500-86376' of https://github.com/danmarsden/moodle into MOODLE_500_STABLE 2025-10-17 11:04:40 +08:00
Andrew Nicols 611008d6eb Merge branch 'MDL-85366-500' of https://github.com/djarran/moodle into MOODLE_500_STABLE 2025-10-17 08:47:05 +08:00
Andrew Nicols 30a482b220 Merge branch 'MDL-86822-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-17 08:34:39 +08:00
Andrew Nicols 240ea09d61 Merge branch 'MDL-85554-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-17 08:27:42 +08:00
Andrew Nicols 7927f8d058 weekly release 5.0.3+ 2025-10-17 06:50:42 +08:00
Andrew Nicols 2e78b280b8 NOBUG: Add upgrade notes 2025-10-17 06:50:42 +08:00
Andrew Nicols fbfba415e6 Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2025-10-17 06:50:21 +08:00
Paul Holden 39bfcbbc9a MDL-85554 user: fix class attribute spacing for profile categories.
Update to use non-aliased html_writer class.
2025-10-16 22:29:19 +01:00
Yerai Rodríguez 7dfbf9582f MDL-86455 forms: disable all modal submit buttons on button click
To provide visual feedback and prevent multiple clicks
on no-submit buttons, all submit buttons within a modal
form will be disabled once any of them is clicked.
2025-10-16 15:59:36 +02:00
Mihail Geshoski d8577022cd Merge branch 'MDL-85874_500' of https://github.com/cwarwicker/moodle into MOODLE_500_STABLE 2025-10-16 16:53:43 +08:00
Mihail Geshoski 29a1ccdcd0 Merge branch 'MDL-85729-group-images-MOODLE_500_STABLE' of https://github.com/bwalkerl/moodle into MOODLE_500_STABLE 2025-10-16 16:14:09 +08:00
Jun Pataleta 7db7c26280 MDL-85796 core: Remove unnecessary title attribute on profile links
The title attribute with value "View profile" on profile links is
not necessary as the user's name on the link itself is sufficient
to convey the purpose of the link.
2025-10-16 15:51:01 +08:00
Dan Marsden fb9d6e718d MDL-86376 core: Make public static functions more resilient
a
2025-10-16 20:45:50 +13:00
Andrew Nicols 3b0a9293b3 Merge branch 'MDL-85348-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-16 13:48:50 +08:00
Andrew Nicols 209ea54fca Merge branch 'MDL-84745-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-16 13:44:36 +08:00
Andrew Nicols 360cb2d370 Merge branch 'MDL-85736-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-16 13:39:55 +08:00
Andrew Nicols 3b91765090 Merge branch 'MDL-86053-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-16 13:33:22 +08:00
Andrew Nicols 04b2b22112 Merge branch 'MDL-86293-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-16 13:25:01 +08:00
Andrew Nicols 4d135c1c53 Merge branch 'MDL-86648-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-16 13:15:20 +08:00
Mihail Geshoski cd8fbc5af0 Merge branch 'MDL-85988-500' of https://github.com/rjnl/moodle into MOODLE_500_STABLE 2025-10-16 10:38:12 +08:00
Jarad Barker da9daf4437 MDL-84483 core_files: Always fire after_file_created hook 2025-10-16 09:04:09 +07:00
Mihail Geshoski 7956cebf42 Merge branch 'MDL-85618-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-15 23:39:22 +08:00
hieuvu ef3cc1d8b9 MDL-86621 core_question: Add capability checking for question bank node 2025-10-15 23:18:58 +08:00
ferran b6a1859fea Merge branch 'MDL-86003-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-15 15:40:14 +02:00
ferran b820cade16 Merge branch 'MDL-85486-500' of https://github.com/roland04/moodle into MOODLE_500_STABLE 2025-10-15 15:15:21 +02:00
ferran 8dd5b60a81 Merge branch 'MDL-66579-500' of https://github.com/rjnl/moodle into MOODLE_500_STABLE 2025-10-15 15:07:18 +02:00
Andrew Nicols 06c110488b Merge branch 'MDL-86369-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-15 17:12:58 +08:00
Andrew Nicols 2538b7df54 Merge branch 'MDL-86627-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-15 17:03:38 +08:00
Andrew Nicols f92d05c33e Merge branch 'MDL-86645-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-15 17:01:48 +08:00
Sara Arjona de47113316 Merge branch 'MDL-86879-500' of https://github.com/ferranrecio/moodle into MOODLE_500_STABLE 2025-10-15 11:00:04 +02:00
Andrew Nicols e3e6b67b07 Merge branch 'MDL-86646-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-15 16:57:31 +08:00
Andrew Nicols 1d7dc95e25 Merge branch 'MDL-86147-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-15 15:53:18 +08:00
Andrew Nicols 545e742dbf Merge branch 'MDL-86186-500' of https://github.com/lameze/moodle into MOODLE_500_STABLE 2025-10-15 15:49:42 +08:00
Philipp Memmel d80cf37b0e MDL-81263 grunt: Respect local .eslintignore and .stylelintignore 2025-10-15 15:19:48 +08:00
Andrew Nicols 329ed8a83f Merge branch 'MDL-86767-500' of https://github.com/lucaboesch/moodle into MOODLE_500_STABLE 2025-10-15 15:13:29 +08:00
Andrew Nicols 93a62aae94 Merge branch '86322-fix-example-phpdoc-500' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_500_STABLE 2025-10-15 15:10:55 +08:00
Andrew Nicols 7e22374591 Merge branch 'MDL-85495-500' of https://github.com/muhammadarnaldo/moodle into MOODLE_500_STABLE 2025-10-15 15:05:44 +08:00
Andrew Nicols f09e9afaad Merge branch 'MDL-86762-500' of https://github.com/HuongNV13/moodle into MOODLE_500_STABLE 2025-10-15 14:59:11 +08:00
Mihail Geshoski a0622c21ee Merge branch 'MDL-81514_500_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_500_STABLE 2025-10-15 11:05:39 +08:00
Mihail Geshoski b6c07ab1ed Merge branch 'MDL-86621-500' of https://github.com/NashTechOpenUniversity/moodle into MOODLE_500_STABLE 2025-10-15 09:49:09 +08:00
AMOS bot ae942c292a Automatically generated installer lang files 2025-10-15 00:09:33 +00:00
Paul Holden 2a40043b1c MDL-86627 cohort: format name correctly in report entity column. 2025-10-14 15:04:58 +01:00
Mikel Martín 944d37ead3 MDL-85486 theme_boost: Fix single section page inplace editor
When course format is displayed as single section per page, the inplace editable
in the section page heading was incorrectly displaye, and the instructions panel
was not displayed.
Adding some specific styles to fix that behaviour.
2025-10-14 11:40:32 +02:00
Stephan Robotta a6d59403ec MDL-86282 navigation: Main navigation corrected for XMLDB tool 2025-10-14 10:50:14 +02:00
Sara Arjona aefaca7bd7 MDL-86011 feedback: Prevent admin answering unless enrolled as student 2025-10-14 07:09:58 +02:00
Sara Arjona 26eb19151e MDL-86011 feedback: Adjust display of Responded column in Overview 2025-10-13 17:08:11 +02:00
hieuvu d785312c06 MDL-86621 core_question: remove incorrect navigation nodes. 2025-10-13 15:05:26 +07:00
Andi Permana 4ea394146d MDL-86559 filter_activitynames: Fix auto links with double spaces 2025-10-13 11:48:28 +07:00
Julien Boulen 95d763d24f MDL-77137 filelib: Honour proxybypass option for multiple Curl queries 2025-10-12 22:16:58 +02:00
Julien Boulen 157e5af983 MDL-86320 core: Fix unit test qrcode_test 2025-10-12 21:55:21 +02:00
Julien Boulen aeb3794af4 MDL-86322 phpdoc: Fix the given example in the phpdoc 2025-10-12 21:49:15 +02:00
Julien Boulen 50d583d951 MDL-83543 core: Move download complete status handling to Excel library
When a form is validated, all validation buttons are automatically
locked to prevent them from being sent twice by mistake. When the form
returns a file instead of redirecting to a new HTML page, a mechanism
(\core_form\util::form_download_complete()) must be called to
reactivate the form's validation buttons.

This mechanism is called for CSV files (file lib/csvlib.class.php), but
not when downloading xls files. The mechanism is only called when
downloading grades in Excel format (file
grade/export/xls/grade_export_xls.php).

The patch proposes to call this mechanism globally for all Excel file
downloads (file lib/excellib.class.php), and not just for grade
downloads (file grade/export/xls/grade_export_xls.php).
2025-10-12 21:35:03 +02:00
ferran 06fef3b872 MDL-86879 core_course: optimise subsections loading 2025-10-10 14:08:25 +02:00
Jun Pataleta e040a192c0 MDL-85820 lib: Update pear/readme_moodle.txt 2025-10-10 11:01:51 +08:00
Tim Hunt af619f925b MDL-85820 formslib: don't add '-' to client-side valiation 2025-10-10 11:01:51 +08:00
Luca Bösch 8d7e88efff MDL-86767 forum: let forum use standard buttons. 2025-10-09 21:05:32 +02:00
Huong Nguyen 7abebfa820 weekly release 5.0.3+ 2025-10-09 21:59:44 +07:00
Huong Nguyen 9c9a144a7a Merge branch 'install_500_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_500_STABLE 2025-10-09 21:59:03 +07:00
Huong Nguyen 8bf9b64078 Merge branch 'MDL-86777-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-09 08:47:49 +07:00
Huong Nguyen 02b3d90ab1 Merge branch 'MDL-86736-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-09 08:43:52 +07:00
Huong Nguyen 7cdeda9093 Merge branch 'MDL-86654-500' of https://github.com/junpataleta/moodle into MOODLE_500_STABLE 2025-10-09 08:41:33 +07:00
Huong Nguyen 6318c0bf80 Merge branch 'MDL-86575-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-09 08:20:33 +07:00
Huong Nguyen 962cabf1b2 Merge branch 'MDL-86574-500' of https://github.com/paulholden/moodle into MOODLE_500_STABLE 2025-10-09 08:15:21 +07:00
AMOS bot 3972f16c85 Automatically generated installer lang files 2025-10-09 00:09:12 +00:00
Rajneel Totaram 97284b10c7 MDL-85988 mod_book: Fix chapter content overlaps navigation buttons 2025-10-09 11:05:10 +12:00
Rajneel Totaram 86f293fb27 MDL-66579 mod_book: Make chapter numbering consistent 2025-10-09 10:18:59 +12:00
Mihail Geshoski 8e0c904526 Merge branch 'MDL-78495-500_exclude_badges_from_recyclebin' of https://github.com/sharpchi/moodle into MOODLE_500_STABLE 2025-10-08 23:39:26 +08:00
Paul Holden ebc79d11de MDL-82867 output: consistently space external link pixicon. 2025-10-08 16:17:56 +01:00
Mark Sharp 8533b0a132 MDL-78495 Badges: Exclude badges from recycle bin
- co-authored by: Sara Arjona

Add badges to recycle bin test
2025-10-08 11:04:48 +01:00
Mihail Geshoski e558a6bfaf Merge branch 'MDL-86382-MOODLE_500_STABLE' of https://github.com/PhMemmel/moodle into MOODLE_500_STABLE 2025-10-08 13:35:51 +08:00
Mihail Geshoski 0f2443cddb Merge branch 'MDL-86300-500' of https://github.com/sh-csg/moodle into MOODLE_500_STABLE 2025-10-08 13:27:22 +08:00
Mihail Geshoski d2269b1a8b Merge branch 'mdl-83511_500' of https://github.com/james-cnz/moodle into MOODLE_500_STABLE 2025-10-08 13:13:36 +08:00
Paul Holden 37be3e8bdd MDL-86332 completion: remove criteria only from current course on save. 2025-10-07 12:23:42 +01:00
Paul Holden 846b814f94 MDL-86069 blog: verify success state of RSS file before processing.
Avoids subsequent errors in the SimplePie library when trying to
process invalid feed content, triggering numerous PHP deprecation
notices.

See: https://github.com/simplepie/simplepie/issues/810
2025-10-07 12:19:27 +01:00
Jun Pataleta 000468f2d7 Merge branch 'MDL-86450-forum-accessibility-check-boxes-in-advanced-search-form-not-labeled-corrected-M5.0' of https://github.com/stopfstedt/moodle into MOODLE_500_STABLE 2025-10-07 14:07:39 +08:00
james-cnz e2a4283c3e MDL-85917 course: Relocate section title update code 2025-10-07 12:56:20 +13:00
Jun Pataleta ddeec0c02b MDL-86654 customfield: Show drag handles only when necessary
* Show category drag handles when there are 2 or more categories
* Show custom field drag handles when there are a total of 2 or more
fields on the page.
2025-10-06 16:01:46 +08:00
Paul Holden d1394d878b MDL-86777 customfield: show formatted category name in move dialog. 2025-10-06 08:11:12 +01:00
Muhammad Arnaldo 0e7b17b7bf MDL-85495 core_course/activitychooser: consistent starred state 2025-10-06 11:30:25 +07:00
James C 82643aadf9 MDL-83511 course: Add activities by section ID 2025-10-06 12:57:21 +13:00
Mark Johnson b6bb37d133 MDL-85975 backup: Handle nulls and arrays in restored questiondata
unset_excluded_fields() was using isset() to determine if the field
targeted for removal is present in the provided data structure. However,
isset() returns false if the field exists, but contains null. This means
the field will not be unset when it should be.

This resolves this by changing the isset() to a property_exists() check
for objects, and array_key_exists() check for arrays. It also expands
the function to properly handle arrays of arrays, or arrays of values,
which was not fully covered before and is used by some third-party
question types.
2025-10-03 15:48:13 +01:00
Paul Holden 63798cf9f3 MDL-80422 auth_oauth2: honour site/user preferred homepage post-login.
Co-authored-by: Markus Kwaśnicki <markus.kwasnicki@uni-mainz.de>
2025-10-03 14:19:22 +01:00
Paul Holden 31fb5cd4f5 MDL-86822 mod_h5pactivity: fix block page type list method parameters.
Similar was done before in 7a77493b.
2025-10-02 12:13:13 +01:00
Huong Nguyen f9b66b57df MDL-86762 repository_flickr: Fix Flickr fetching and downloading 2025-10-02 17:46:39 +07:00
Jayce Birrell 161837e393 MDL-86802 core: make CURLOPT_USERPWD optional for put()
Microsoft does not always allow an Authorization header when using PUT but the put() method sets one
by default - https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0#remarks.
I've included an optional argument to prevent this, but the default
value will maintain the pre-existing logic to avoid other regressions.
2025-10-02 15:50:55 +09:30
Stefan Topfstedt 828708e376 MDL-86450 Forum: adds missing IDs to advanced search form elements. 2025-09-30 11:44:06 -07:00
Stefan Hanauska 91e676ebde MDL-86300 backup: Save old id of top category
Co-authored-by: Paola Maneggia <paola.maneggia@isb.bayern.de>
2025-09-29 19:22:01 +02:00
Philipp Memmel cd54407e40 MDL-86382 qbank_bulkmove: Fix selecting placeholder in qbank selector
@Co-authored-by: Luca Bösch <luca.boesch@bfh.ch>
2025-09-26 13:54:57 +00:00
Paul Holden 19a794db63 MDL-86736 block_myoverview: remove stray template content.
Changes made in c530e4c4 left some stray elements in the templates,
which manifested themselves as displaying misplaced pipe characters
depending on unrelated site config (`$CFG->courselistshortnames`).
2025-09-26 11:41:49 +01:00
Mark Johnson 8e004afafb MDL-81514 assign: Show non-participation groups in activity menu
This sets the flag in the activity menu for selecting the grade
summaries for each groups, to include non-participation groups as well.
2025-09-25 16:40:20 +01:00
Mark Johnson 7e0d7bf9b5 MDL-81514 assign: Enable filtering by non-participation groups
This adds non-participation groups to the group menu on the Submissions
screen, so that submissions can be filtered by these groups.
2025-09-25 16:40:20 +01:00
Mark Johnson 66328d8428 MDL-81514 groups: Add participationonly option to activity group menu
groups_print_activity_menu() and groups_get_activity_group() now include
an additional $participationonly parameter,
which is true by default. This can be set false when we want the user to
be able to select a non-participation group within
an activity, for example if a teacher wants to filter assignment
submissions by non-participation groups. It should never be
used when the menu is displayed to students, as this may allow them to
participate using non-participation groups.

groups_sort_menu_options() now has a $splitparticipation parameter,
which will split non-participation groups out into their own optgroup at
the end of the menu.
2025-09-25 16:40:20 +01:00
Benjamin Walker 049b172e00 MDL-85729 group: Lazy load group image urls in search box 2025-09-25 14:25:10 +10:00
Paul Holden 3e5d11a046 MDL-86369 mod_scorm: fix attempt deletion behaviour on submit/redirect.
Standard after a POST submission is to redirect back to where user came
from (in this case), to avoid awkward page reload behaviour. Also fix
bug where deleting an attempt for a user, where the attempt didn't exist
would delete all attempts for that user.
2025-09-22 09:06:17 +01:00
Paul Holden d737b9ad07 MDL-86574 tool_cohortroles: format cohort data during privacy export. 2025-09-22 09:00:34 +01:00
Paul Holden 371b19bc2b MDL-86648 mod_assign: refer to selected user when calculating override.
The selected user is either that chosen for a new override, or the saved
value when editing/loading an existing override.
2025-09-17 15:37:43 +01:00
Conn Warwicker 39137cf98f MDL-85874 core_grade: Fix grade category toggle JS error. 2025-09-16 15:43:50 +01:00
Paul Holden d9e0ff18c6 MDL-86646 gradereport_user: ensure table rowspan always populated. 2025-09-16 13:21:38 +01:00
Paul Holden 001d0f72a7 MDL-86645 grade: account for text grade types determining element icon. 2025-09-16 10:07:33 +01:00
Paul Holden 1cdfee56d9 MDL-85418 user: prevent default click event/scroll in user sub-menus. 2025-09-15 10:41:23 +01:00
Paul Holden 1041103f2d MDL-86147 block_myoverview: consistent zero-state view styling.
Make the zero state template consistent with the populated course
template from 6415776d, specifically in regards to borders.
2025-09-15 10:39:36 +01:00
Paul Holden 0a92183a94 MDL-85887 tag: style search form using common Bootstrap controls. 2025-09-12 11:38:49 +01:00
Paul Holden 028ed9c60e MDL-86575 cohort: format cohort names in external service return data. 2025-09-07 19:31:31 +02:00
Paul Holden bd0a861e5d MDL-86003 datafield_textarea: define missing media/subtitle options.
In order to insert multimedia using the editor, we need a "subtitle"
filepicker option.
2025-09-07 10:53:03 +02:00
Leon Stringer 59bbfa4cc0 MDL-86434 core: Page title for invalid user ID 2025-09-03 16:14:01 +02:00
Andrew Nicols f3c89b4ab3 MDL-86534 mod_forum: Only run bulk action JS if they are enabled 2025-09-03 12:46:08 +02:00
Paul Holden 36e4118e2d MDL-85592 output: export missing node sort attribute for template. 2025-08-21 13:06:24 +01:00
Paul Holden 1c4e61ec4a MDL-85618 filter_displayh5p: change regular expression delimeter.
Ensure we don't confuse the expression parser when supplied "Allowed
source" contains coincidental control characters in the URL, e.g. '/'
and '#'.

Note that `preg_quote(...)` isn't appropriate here, because the given
URL may indeed contain genuine control characters already.
2025-08-21 13:00:49 +01:00
Paul Holden 95a76b29a8 MDL-85348 cohort: disable report bulk deletion for managed cohorts. 2025-08-20 09:09:27 +01:00
Paul Holden 8cd752c0df MDL-85736 core: don't double escape page URL in meta refresh tag.
Co-authored-by: Clay Cross <claycross@gmail.com>
2025-08-19 17:11:52 +01:00
Paul Holden 7a3eb1805b MDL-84745 cohort: capability check prior to bulk deletion button. 2025-08-18 08:51:05 +01:00
Paul Holden 2ec1d258ce MDL-86293 communication: queue/execute membership task if appropriate.
Avoid doing so if the current instance does not support user features.
2025-08-15 14:04:49 +01:00
Paul Holden e65ccd7ea3 MDL-86053 mod_assign: account for lack of global scales in settings. 2025-08-13 10:15:08 +01:00
Paul Holden c93da59bb5 MDL-85312 profilefield_menu: remove locked field option formatting.
We shouldn't be formatting the option key when setting constant
value, because that isn't formatted - only the option value is.
2025-08-12 08:34:33 +01:00
Jose Pico e419f36236 MDL-86225 plagiarism: Update data type from object to array 2025-08-11 16:06:26 +10:00
Mark Johnson 223da4833a MDL-86010 tool_lp: Test fetching evidence works after cm deletion 2025-08-08 16:03:11 +01:00
Michael Kotlyar 57b29b7a55 MDL-86010 competency: Delete competency evidence on cm delete
Evidence recorded against course module competencies was not deleted
with the course module. This led to errors when attempting to view the
competency record on a learning plan.

This change will delete associated evidence records with the cm, and
will clean up any existing orphaned records on upgrade.

Co-Authored-By: Mark Johnson <mark.johnson@catalyst-eu.net>
2025-08-08 16:03:11 +01:00
dustinhuynh 29d322526f MDL-86058 core_task: enable disable tasks with a pending upgrade 2025-08-06 15:47:41 +10:00
Simey Lameze cd2c6b7def MDL-86186 behat: enlarge window size before asserting 2025-08-04 11:27:21 +08:00
Mi Jia Looi f3fd9b1836 MDL-86017 mod_folder: Cast customdata to object in folder_cm_info_view() 2025-07-22 13:42:45 +10:00
djarrancotleanu e00381381a MDL-85366 core: Add proper PHPMailer handling of .ics files 2025-07-08 17:07:07 +10:00
Tim Schroeder f95266a84c MDL-81604 Files: Fix broken file serving w/ Apache + PHP-FPM + PHP >=8.1 2025-07-04 20:03:26 +02:00
Philipp Memmel 2304462b47 MDL-85168 lib: Move courseid filter to participants_filter.js 2025-05-09 07:21:02 +02:00
742 changed files with 13089 additions and 2710 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ jobs:
chunk=$(((($count % $chunks)) + 1))
echo "$testname $testfile" >> ./chunk_$chunk.txt
done < <(grep "function test_" "${testfile}" | sed -r "s/^.*function (test_[a-zA-Z0-9_]+).*/\1/")
done < <(find . -name "*_test.php")
done < <(find . -name "*_test.php" -not -path "*/fixtures/*")
# Generate the matrix to run tests.
echo "matrix=$(ls -1 chunk_*.txt | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT
echo "$count individual tests collected in $chunks files"
+41 -2
View File
@@ -58,6 +58,31 @@ module.exports = grunt => {
}) + "\n");
};
/**
* Extracts ignore entries from a local ignore file.
*
* @param {string} componentPath the file path to the component, relative to the code base directory
* @param {string} ignoreFilePath the path to the ignore file
* @return {array} array of ignore paths to be included in the global ignore files
*/
const getEntriesFromLocalIgnoreFile = (componentPath, ignoreFilePath) => {
const ignorePaths = [];
if (grunt.file.exists(ignoreFilePath)) {
const ignoreFile = grunt.file.read(ignoreFilePath);
const entries = ignoreFile.split('\n');
entries.forEach(entry => {
entry = entry.trim();
if (entry.length > 0 && !entry.startsWith('#') && !entry.startsWith('!')) {
while (entry.startsWith('/')) {
entry = entry.substring(1);
}
ignorePaths.push(componentPath + '/' + entry);
}
});
}
return ignorePaths;
};
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
@@ -67,6 +92,20 @@ module.exports = grunt => {
// An array of paths to third party directories.
const thirdPartyPaths = ComponentList.getThirdPartyPaths();
const localStylelintIgnorePaths = [];
const localEslintIgnorePaths = [];
ComponentList.getComponentPaths(process.cwd() + '/').forEach(componentPath => {
const localEslintIgnorePath = process.cwd() + '/' + componentPath + '/.eslintignore';
const localEslintIgnoreEntries = getEntriesFromLocalIgnoreFile(componentPath, localEslintIgnorePath);
if (localEslintIgnoreEntries.length > 0) {
localEslintIgnorePaths.push(...localEslintIgnoreEntries);
}
const localStylelintIgnorePath = process.cwd() + '/' + componentPath + '/.stylelintignore';
const localStylelintIgnoreEntries = getEntriesFromLocalIgnoreFile(componentPath, localStylelintIgnorePath);
if (localStylelintIgnoreEntries.length > 0) {
localStylelintIgnorePaths.push(...localStylelintIgnoreEntries);
}
});
// Generate .eslintignore.
const eslintIgnores = [
@@ -77,7 +116,7 @@ module.exports = grunt => {
// Ignore all yui/src meta directories and build directories.
'*/**/yui/src/*/meta/',
'*/**/build/',
].concat(thirdPartyPaths);
].concat(thirdPartyPaths).concat(localEslintIgnorePaths);
grunt.file.write('.eslintignore', eslintIgnores.join('\n') + '\n');
// Generate .stylelintignore.
@@ -88,7 +127,7 @@ module.exports = grunt => {
'theme/classic/style/moodle.css',
'jsdoc/styles/*.css',
'admin/tool/componentlibrary/hugo/dist/css/docs.css',
].concat(thirdPartyPaths);
].concat(thirdPartyPaths).concat(localStylelintIgnorePaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n') + '\n');
phpcsIgnore(thirdPartyPaths);
+7
View File
@@ -0,0 +1,7 @@
issueNumber: MDL-87443
notes:
core:
- message: >-
There is a new Behat `toast_message` named selector to more easily
assert the presence of Toast messages on the page
type: improved
+80
View File
@@ -6,6 +6,86 @@ More detailed information on key changes can be found in the [Developer update n
The format of this change log follows the advice given at [Keep a CHANGELOG](https://keepachangelog.com).
## 5.0.5
### core
#### Changed
- `\core\output\core_renderer::confirm()`'s `$displayoptions` parameter now also accepts a `headinglevel` option that developers can use to specify the heading level of the confirmation's heading. If not specified, the confirmation heading will be rendered in an `h4` tag.
For more information see [MDL-87694](https://tracker.moodle.org/browse/MDL-87694)
### core_question
#### Fixed
- In order to prevent re-use of question version numbers after a version is deleted, the `nextversion` column was added to `question_bank_entries`. This serves as a counter incremented each time a version is created.
Do not query this field directly. Instead use `core_question\versions::get_next_version()` to read the value, which will initialise it based on the existing versions if it is not set yet. By default, it will increment the version number automatically, unless you pass `increment: false`. Because of this, it is advisable to call it inside a transaction, that is only committed after the version number is used in a `question_versions` record.
For more information see [MDL-86798](https://tracker.moodle.org/browse/MDL-86798)
## 5.0.4
### core
#### Added
- Added clean_string() that prevents double escaping in Mustache templates
For more information see [MDL-87066](https://tracker.moodle.org/browse/MDL-87066)
#### Changed
- The Hook Manager now uses localcache instead of caching via MUC.
For more information see [MDL-87107](https://tracker.moodle.org/browse/MDL-87107)
#### Fixed
- `restore_qtype_plugin::unset_excluded_fields` now returns the modified questiondata structure,
in order to support structures that contain arrays.
If your qtype plugin overrides `restore_qtype_plugin::remove_excluded_question_data` without
calling the parent method, you may need to modify your overridden method to use the returned
value.
For more information see [MDL-85975](https://tracker.moodle.org/browse/MDL-85975)
- When responding to pcntl signals, call existing signal handlers.
For more information see [MDL-87079](https://tracker.moodle.org/browse/MDL-87079)
### core_completion
#### Changed
- The `completion_info::clear_criteria` method takes an optional `$removetypecriteria` to determine whether to remove course type criteria from other courses that refer to the current course
For more information see [MDL-86332](https://tracker.moodle.org/browse/MDL-86332)
### core_course
#### Added
- The external function `core_course_get_course_contents` now includes the `candisplay` property for each returned module. If this is false, the module should not be displayed on the course page (for example, for question banks).
For more information see [MDL-85405](https://tracker.moodle.org/browse/MDL-85405)
### core_group
#### Added
- `groups_print_activity_menu()` and `groups_get_activity_group()` now include an additional `$participationonly` parameter, which is true by default. This can be set false when we want the user to be able to select a non-participation group within an activity, for example if a teacher wants to filter assignment submissions by non-participation groups. It should never be used when the menu is displayed to students, as this may allow them to participate using non-participation groups. Non-participation groups are labeled as such.
For more information see [MDL-81514](https://tracker.moodle.org/browse/MDL-81514)
### mod_glossary
#### Added
- Function mod_glossary_rating_can_see_item_ratings is now implemented for checking permissions to view ratings.
For more information see [MDL-86960](https://tracker.moodle.org/browse/MDL-86960)
## 5.0.3
### core
+2 -2
View File
@@ -119,8 +119,8 @@ foreach ($settingspage->children as $childpage) {
$outputhtml .= html_writer::tag('div', '<!-- -->', array('class' => 'clearer'));
$outputhtml .= $setting->output_html($data);
if ($childpage->has_dependencies()) {
$opts = ['dependencies' => $childpage->get_dependencies_for_javascript()];
$PAGE->requires->js_call_amd('core/showhidesettings', 'init', [$opts]);
$context = ['dependencies' => json_encode($childpage->get_dependencies_for_javascript())];
echo $OUTPUT->render_from_template('core_admin/settings_showhide', $context);
}
}
$outputhtml .= html_writer::end_tag('fieldset');
@@ -0,0 +1,74 @@
<?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/>.
namespace core_admin\admin;
use admin_setting;
/**
* Render a notification as part of other admin settings.
*
* @package core_admin
* @subpackage admin
* @copyright 2025 Matt Porritt <matt.porritt@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_setting_notification extends admin_setting {
/**
* Constructor.
*
* @param string $name The name of the setting.
* @param string $notification The notification to display.
* @param string $type The type of notification.
* @param bool $cancelable Whether the notification can be canceled.
*/
public function __construct(
string $name,
/** @var string The notification to display. */
protected string $notification,
/** @var string The type of notification. */
protected string $type = 'info',
/** @var bool Whether the notification can be canceled. */
protected bool $cancelable = false
) {
$this->nosave = true;
parent::__construct($name, '', '', '');
}
#[\Override]
public function get_setting(): bool {
return true;
}
#[\Override]
public function get_defaultsetting(): bool {
return true;
}
#[\Override]
public function write_setting($data): string {
// Do not write any setting.
return '';
}
#[\Override]
public function output_html($data, $query = ''): string {
global $OUTPUT;
return $OUTPUT->notification($this->notification, $this->type, $this->cancelable);
}
}
+5 -5
View File
@@ -125,11 +125,6 @@ if ($options['list']) {
exit(0);
}
if (moodle_needs_upgrading()) {
mtrace("Moodle upgrade pending, cannot manage tasks.");
exit(1);
}
if ($disable = $options['disable']) {
if (!$task = \core\task\manager::get_scheduled_task($disable)) {
mtrace("Task '$disable' not found");
@@ -157,6 +152,11 @@ if ($disable = $options['disable']) {
exit(1);
}
} else if ($execute = $options['execute']) {
if (moodle_needs_upgrading()) {
mtrace("Moodle upgrade pending, cannot execute tasks.");
exit(1);
}
if (!$task = \core\task\manager::get_scheduled_task($execute)) {
mtrace("Task '$execute' not found");
exit(1);
+209
View File
@@ -3835,6 +3835,7 @@
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="optional"/>
<PHP_EXTENSION name="exif" level="optional"/>
<PHP_EXTENSION name="filter" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
@@ -4411,6 +4412,7 @@
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="required"/>
<PHP_EXTENSION name="exif" level="optional"/>
<PHP_EXTENSION name="filter" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
@@ -4607,6 +4609,7 @@
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="required"/>
<PHP_EXTENSION name="exif" level="optional"/>
<PHP_EXTENSION name="filter" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
@@ -4802,6 +4805,7 @@
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="required"/>
<PHP_EXTENSION name="exif" level="optional"/>
<PHP_EXTENSION name="filter" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
@@ -4997,6 +5001,7 @@
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="required"/>
<PHP_EXTENSION name="exif" level="optional"/>
<PHP_EXTENSION name="filter" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
@@ -5100,4 +5105,208 @@
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="5.2" requires="4.4">
<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="16" />
<VENDOR name="mssql" version="15.0" />
<VENDOR name="auroramysql" version="8.0" />
</DATABASE>
<PHP version="8.3.0" level="required">
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="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_EXTENSION name="filter" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="zend.exception_ignore_args" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingzendexceptionignoreargs" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK function="\core\environment::check_composer_dependencies_installed" level="optional" />
<CUSTOM_CHECK function="\core\environment::check_composer_developer_dependencies_not_installed" level="optional" />
<CUSTOM_CHECK function="\core\environment::check_composer_dependencies_optimised" level="optional" />
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="required">
<FEEDBACK>
<ON_ERROR message="sixtyfourbitsrequired" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
<FEEDBACK>
<ON_CHECK message="iscustomadminwarnings" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_db_prefix_length" level="required">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_async_backup" level="recommended">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_aurora_version" level="optional">
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+1 -1
View File
@@ -121,7 +121,7 @@ $table = new html_table();
$table->head = [get_string('filter'), get_string('isactive', 'filters'),
get_string('order'), get_string('applyto', 'filters'), get_string('settings'), get_string('uninstallplugin', 'core_admin')];
$table->colclasses = array ('leftalign', 'leftalign', 'centeralign', 'leftalign', 'leftalign', 'leftalign');
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$table->id = 'filterssetting';
$table->data = [];
+32 -8
View File
@@ -916,8 +916,14 @@ if (empty($CFG->disabledevlibdirscheck) && (is_dir($CFG->dirroot.'/vendor') || i
// Check if the site is being foced onto ssl.
$overridetossl = !empty($CFG->overridetossl);
// Check if moodle campaign content setting is enabled or not.
$showcampaigncontent = !isset($CFG->showcampaigncontent) || $CFG->showcampaigncontent;
if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) {
// We need to add this in order to be able to verify the showcampaigncontent setting behaviour during behat tests.
$showcampaigncontent = get_config('core', 'showcampaigncontent');
$showcampaigncontent = $showcampaigncontent === 'true';
} else {
// Check if moodle campaign content setting is enabled or not.
$showcampaigncontent = !isset($CFG->showcampaigncontent) || $CFG->showcampaigncontent;
}
// Encourage admins to enable the user feedback feature if it is not enabled already.
$showfeedbackencouragement = empty($CFG->enableuserfeedback);
@@ -935,9 +941,27 @@ admin_externalpage_setup('adminnotifications');
$output = $PAGE->get_renderer('core', 'admin');
echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed, $cronoverdue, $dbproblems,
$maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
$registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir,
$mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent,
$showcampaigncontent, $showfeedbackencouragement, $servicesandsupportcontent,
$xmlrpcwarning);
echo $output->admin_notifications_page(
$maturity,
$insecuredataroot,
$errorsdisplayed,
$cronoverdue,
$dbproblems,
$maintenancemode,
$availableupdates,
$availableupdatesfetch,
$buggyiconvnomb,
$registered,
$cachewarnings,
$eventshandlers,
$themedesignermode,
$devlibdir,
$mobileconfigured,
$overridetossl,
$invalidforgottenpasswordurl,
$croninfrequent,
$showcampaigncontent,
$showfeedbackencouragement,
$servicesandsupportcontent,
$xmlrpcwarning
);
+2 -2
View File
@@ -98,7 +98,7 @@
echo $OUTPUT->header();
?>
<form method="post" action="index.php">
<table align="center" width="635" class="generaltable" border="0" cellpadding="5" cellspacing="0">
<table align="center" width="635" class="generaltable table table-hover" border="0" cellpadding="5" cellspacing="0">
<tr>
<td class="generalboxcontent">
<table cellpadding="9" cellspacing="0" class="table-reboot">
@@ -119,7 +119,7 @@
</table>
</form>
<form method="post" action="index.php">
<table align="center" width="635" class="generaltable" border="0" cellpadding="5" cellspacing="0">
<table align="center" width="635" class="generaltable table table-hover" border="0" cellpadding="5" cellspacing="0">
<tr>
<td class="generalboxcontent">
<table cellpadding="9" cellspacing="0" class="table-reboot">
+1 -1
View File
@@ -54,7 +54,7 @@ $table = new html_table();
$table->head = array($txt->name, $txt->version, $txt->uninstall, $txt->settings);
$table->colclasses = array('mdl-left', 'mdl-align', 'mdl-align', 'mdl-align');
$table->data = array();
$table->attributes['class'] = 'manageplagiarismtable generaltable';
$table->attributes['class'] = 'manageplagiarismtable generaltable table table-hover';
// Iterate through auth plugins and add to the display table.
$authcount = count($plagiarismplugins);
+43 -9
View File
@@ -282,13 +282,30 @@ class core_admin_renderer extends plugin_renderer_base {
*
* @return string HTML to output.
*/
public function admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
$cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch,
$buggyiconvnomb, $registered, array $cachewarnings = array(), $eventshandlers = 0,
$themedesignermode = false, $devlibdir = false, $mobileconfigured = false,
$overridetossl = false, $invalidforgottenpasswordurl = false, $croninfrequent = false,
$showcampaigncontent = false, bool $showfeedbackencouragement = false, bool $showservicesandsupport = false,
$xmlrpcwarning = '') {
public function admin_notifications_page(
$maturity,
$insecuredataroot,
$errorsdisplayed,
$cronoverdue,
$dbproblems,
$maintenancemode,
$availableupdates,
$availableupdatesfetch,
$buggyiconvnomb,
$registered,
array $cachewarnings = [],
$eventshandlers = 0,
$themedesignermode = false,
$devlibdir = false,
$mobileconfigured = false,
$overridetossl = false,
$invalidforgottenpasswordurl = false,
$croninfrequent = false,
$showcampaigncontent = false,
bool $showfeedbackencouragement = false,
bool $showservicesandsupport = false,
$xmlrpcwarning = ''
) {
global $CFG;
$output = '';
@@ -313,6 +330,7 @@ class core_admin_renderer extends plugin_renderer_base {
$output .= $this->mobile_configuration_warning($mobileconfigured);
$output .= $this->forgotten_password_url_warning($invalidforgottenpasswordurl);
$output .= $this->mnet_deprecation_warning($xmlrpcwarning);
$output .= $this->moodlenet_removal_warning();
$output .= $this->userfeedback_encouragement($showfeedbackencouragement);
$output .= $this->services_and_support_content($showservicesandsupport);
$output .= $this->campaign_content($showcampaigncontent);
@@ -1809,6 +1827,7 @@ class core_admin_renderer extends plugin_renderer_base {
$table = new html_table();
$table->id = 'plugins-control-panel';
$table->attributes['class'] = 'generaltable table table-striped table-hover';
$table->head = array(
get_string('displayname', 'core_plugin'),
get_string('version', 'core_plugin'),
@@ -2063,7 +2082,7 @@ class core_admin_renderer extends plugin_renderer_base {
get_string('status'),
);
$servertable->colclasses = array('centeralign name', 'centeralign info', 'leftalign report', 'leftalign plugin', 'centeralign status');
$servertable->attributes['class'] = 'table table-striped admintable environmenttable generaltable table-sm';
$servertable->attributes['class'] = 'table table-striped admintable environmenttable generaltable table-sm table-hover';
$servertable->id = 'serverstatus';
$serverdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
@@ -2076,7 +2095,7 @@ class core_admin_renderer extends plugin_renderer_base {
get_string('status'),
);
$othertable->colclasses = array('aligncenter info', 'alignleft report', 'alignleft plugin', 'aligncenter status');
$othertable->attributes['class'] = 'table table-striped admintable environmenttable generaltable table-sm';
$othertable->attributes['class'] = 'table table-striped admintable environmenttable generaltable table-sm table-hover';
$othertable->id = 'otherserverstatus';
$otherdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
@@ -2325,6 +2344,21 @@ class core_admin_renderer extends plugin_renderer_base {
return $this->warning($xmlrpcwarning);
}
/**
* Display a warning about the removal of MoodleNet integration.
*
* @return string HTML to output.
*/
protected function moodlenet_removal_warning(): string {
$moodlenetenabled = get_config('tool_moodlenet', 'enablemoodlenet');
if (!empty($moodlenetenabled)) {
$moodlenetwarning = get_string('moodlenetremovalwarning', 'admin');
return $this->warning($moodlenetwarning);
}
return '';
}
/**
* Renders the theme selector list.
*
+1 -1
View File
@@ -263,7 +263,7 @@ if (($action == 'edit') || ($action == 'new')) {
$table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
$table->id = 'repositoriessetting';
$table->data = array();
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
// Get list of used plug-ins
$repositorytypes = repository::get_types();
+1 -1
View File
@@ -179,7 +179,7 @@ echo $OUTPUT->header();
<div>
<input type="hidden" name="sesskey" value="<?php p(sesskey()); ?>" />
<table class="generaltable generalbox groupmanagementtable boxaligncenter" summary="">
<table class="generaltable generalbox groupmanagementtable boxaligncenter table table-hover" summary="">
<tr>
<td id='existingcell'>
<p>
+2 -2
View File
@@ -228,7 +228,7 @@ if ($roleid) {
<form id="assignform" method="post" action="<?php echo $assignurl ?>"><div>
<input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" />
<table id="assigningrole" summary="" class="admintable roleassigntable generaltable" cellspacing="0">
<table id="assigningrole" summary="" class="admintable roleassigntable generaltable table table-hover" cellspacing="0">
<tr>
<td id="existingcell">
<p><label for="removeselect"><?php print_string('extusers', 'core_role'); ?></label></p>
@@ -322,7 +322,7 @@ if ($roleid) {
$table->id = 'assignrole';
$table->head = array(get_string('role'), get_string('description'), get_string('userswiththisrole', 'core_role'));
$table->colclasses = array('leftalign role', 'leftalign', 'centeralign userrole');
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
if ($showroleholders) {
$table->headspan = array(1, 1, 2);
$table->colclasses[] = 'leftalign roleholder';
+1 -1
View File
@@ -153,7 +153,7 @@ require('managetabs.php');
$table = new html_table();
$table->colclasses = array('leftalign', 'leftalign', 'leftalign', 'leftalign');
$table->id = 'roles';
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$table->head = array(
get_string('role') . ' ' . $OUTPUT->help_icon('roles', 'core_role'),
get_string('description'),
+2 -4
View File
@@ -165,10 +165,8 @@ if (empty($SITE->fullname)) {
$PAGE->requires->js_call_amd('core_form/changechecker', 'watchFormById', ['adminsettings']);
if ($settingspage->has_dependencies()) {
$opts = [
'dependencies' => $settingspage->get_dependencies_for_javascript()
];
$PAGE->requires->js_call_amd('core/showhidesettings', 'init', [$opts]);
$context = ['dependencies' => json_encode($settingspage->get_dependencies_for_javascript())];
echo $OUTPUT->render_from_template('core_admin/settings_showhide', $context);
}
echo $OUTPUT->footer();
+18 -8
View File
@@ -32,19 +32,29 @@ if ($hassiteconfig) {
$providers->add(new admin_setting_heading('availableproviders',
get_string('availableproviders', 'core_ai'),
get_string('availableproviders_desc', 'core_ai')));
// Add call to action to add a new provider.
$providers->add(new \core_admin\admin\admin_setting_template_render(
name: 'addnewprovider',
templatename: 'core_ai/admin_add_provider',
context: ['addnewproviderurl' => new moodle_url('/ai/configure.php')]
));
$providers->add(new \core_ai\admin\admin_setting_provider_manager(
if (!empty(core_plugin_manager::instance()->get_plugins_of_type("aiprovider"))) {
// Add call to action to add a new provider.
$providers->add(new \core_admin\admin\admin_setting_template_render(
name: 'addnewprovider',
templatename: 'core_ai/admin_add_provider',
context: ['addnewproviderurl' => new moodle_url('/ai/configure.php')]
));
$providers->add(new \core_ai\admin\admin_setting_provider_manager(
'aiprovider',
\core_ai\table\aiprovider_management_table::class,
'manageaiproviders',
new lang_string('manageaiproviders', 'core_ai'),
));
));
} else {
$providers->add(new \core_admin\admin\admin_setting_notification(
name:'noproviderplugins',
notification: get_string('noproviderplugins', 'core_ai'),
type: 'danger'
));
}
$ADMIN->add('ai', $providers);
// Add settings page for AI placement settings.
@@ -0,0 +1,51 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template core_admin/settings_showhide
Passes the necessary data to show/hide dependant settings.
Context variables required for this template:
* dependencies - JSON-serialized data structure describing the dependencies between settings
Example context (json):
{
"dependencies": {
"s__setting1":{
"eq":[
[
"s__setting0"
]
]
},
"s__setting2":{
"eq":[
[
"s__setting1"
]
]
}
}
}
}}
<span id="settings-showhide-{{uniqid}}" data-dependencies="{{dependencies}}"></span>
{{#js}}
require(['core/showhidesettings'], function(ShowHideSettings) {
ShowHideSettings.init("settings-showhide-{{uniqid}}");
});
{{/js}}
+1
View File
@@ -90,6 +90,7 @@ Feature: An administrator can browse user accounts
| username | firstname | lastname | email | confirmed |
| user3 | User | Three | three@example.com | 0 |
And I navigate to "Users > Accounts > Browse list of users" in site administration
And I change window size to "large"
Then I should see "Confirmation pending" in the "User Three" "table_row"
And I press "Resend confirmation email" action in the "User Three" report row
And I should see "Confirmation email sent successfully"
@@ -0,0 +1,17 @@
@core @core_admin
Feature: Toggle campaign banner visibility
In order to control the visibility of the campaign banner content
As an admin
I need to be able to disable the campaign banner display
Scenario Outline: Admin can disable the campaign banner display
Given the following config values are set as admin:
| showcampaigncontent | <showcampaigncontent> |
And I log in as "admin"
When I navigate to "Notifications" in site administration
Then "//iframe[@id='campaign-content']" "xpath_element" <display> exist
Examples:
| showcampaigncontent | display |
| true | should |
| false | should not |
+1 -1
View File
@@ -47,7 +47,7 @@ $table->head = array(
get_string('thirdpartylibrarylocation', 'core_admin'), get_string('license'));
$table->align = array('left', 'left', 'left', 'left');
$table->id = 'thirdpartylibs';
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$table->data = array();
foreach ($files as $component => $xmlpath) {
+1 -1
View File
@@ -140,7 +140,7 @@ function print_report_tree($contextid, $contexts, $allroles) {
// If there are any role overrides here, print them.
if (!empty($contexts[$contextid]->rolecapabilities)) {
$rowcounter = 0;
echo '<table class="generaltable table-striped"><tbody>';
echo '<table class="generaltable table-striped table table-hover"><tbody>';
foreach ($allroles as $role) {
if (isset($contexts[$contextid]->rolecapabilities[$role->id])) {
$permission = $contexts[$contextid]->rolecapabilities[$role->id];
@@ -166,10 +166,12 @@ class provider implements
// Retrieve the tool_cohortroles records created for the user.
$sql = "SELECT cr.id as cohortroleid,
cr.cohortid,
c.name as cohortname,
c.idnumber as cohortidnumber,
c.description as cohortdescription,
c.contextid as contextid,
c.description,
c.descriptionformat,
c.contextid,
r.shortname as roleshortname,
cr.userid as userid,
cr.timecreated as timecreated,
@@ -185,27 +187,39 @@ class provider implements
$cohortroles = $DB->get_records_sql($sql, $params);
foreach ($cohortroles as $cohortrole) {
$context = \context::instance_by_id($cohortrole->contextid);
// The tool_cohortroles data export is organised in:
// {User Context}/Cohort roles management/{cohort name}/{role shortname}/data.json.
$subcontext = [
get_string('pluginname', 'tool_cohortroles'),
$cohortrole->cohortname,
format_string($cohortrole->cohortname, options: ['context' => $context]),
$cohortrole->roleshortname
];
$data = (object) [
'cohortname' => $cohortrole->cohortname,
'cohortname' => format_string($cohortrole->cohortname, options: ['context' => $context]),
'cohortidnumber' => $cohortrole->cohortidnumber,
'cohortdescription' => $cohortrole->cohortdescription,
'cohortdescription' => format_text(
writer::with_context($context)->rewrite_pluginfile_urls(
$subcontext,
'cohort',
'description',
$cohortrole->cohortid,
$cohortrole->description,
),
$cohortrole->descriptionformat,
['context' => $context],
),
'roleshortname' => $cohortrole->roleshortname,
'userid' => transform::user($cohortrole->userid),
'timecreated' => transform::datetime($cohortrole->timecreated),
'timemodified' => transform::datetime($cohortrole->timemodified)
];
$context = \context::instance_by_id($cohortrole->contextid);
writer::with_context($context)->export_data($subcontext, $data);
writer::with_context($context)
->export_area_files($subcontext, 'cohort', 'description', $cohortrole->cohortid)
->export_data($subcontext, $data);
}
}
@@ -162,7 +162,7 @@ class data_requests_table extends table_sql {
*/
public function col_userid($data) {
$user = $data->foruser;
return html_writer::link($user->profileurl, $user->fullname, ['title' => get_string('viewprofile')]);
return html_writer::link($user->profileurl, $user->fullname);
}
/**
@@ -183,7 +183,7 @@ class data_requests_table extends table_sql {
*/
public function col_requestedby($data) {
$user = $data->requestedbyuser;
return html_writer::link($user->profileurl, $user->fullname, ['title' => get_string('viewprofile')]);
return html_writer::link($user->profileurl, $user->fullname);
}
/**
@@ -138,7 +138,7 @@
}}>
<td>{{typename}}</td>
<td>{{#userdate}} {{timecreated}}, {{#str}} strftimedatetime, core_langconfig {{/str}} {{/userdate}}</td>
<td><a href="{{requestedbyuser.profileurl}}" title="{{#str}}viewprofile{{/str}}">{{requestedbyuser.fullname}}</a></td>
<td><a href="{{requestedbyuser.profileurl}}">{{requestedbyuser.fullname}}</a></td>
<td>
<span class="badge {{statuslabelclass}}" title="{{statuslabeltitle}}">{{statuslabel}}</span>
</td>
@@ -62,7 +62,7 @@
</div>
<div class="flex-grow-1 ms-3">
<h4 class="mt-0 mb-1">
<a href="{{foruser.profileurl}}" title="{{#str}}viewprofile{{/str}}">{{foruser.fullname}}</a>
<a href="{{foruser.profileurl}}">{{foruser.fullname}}</a>
</h4>
<a href="mailto:{{foruser.email}}">{{foruser.email}}</a>
<div class="clearfix mt-1 mb-1">
@@ -76,7 +76,7 @@
</span>
<span class="float-start me-1">
<strong>{{#str}}requestbydetail, tool_dataprivacy{{/str}}</strong>
<span><a href="{{requestedbyuser.profileurl}}" title="{{#str}}viewprofile{{/str}}">{{requestedbyuser.fullname}}</a></span>
<span><a href="{{requestedbyuser.profileurl}}">{{requestedbyuser.fullname}}</a></span>
</span>
</div>
{{#canreview}}
@@ -0,0 +1,100 @@
@tool @tool_dataprivacy
Feature: Authorized users can request others personal data
In order to export or access another users data
As a designated role
I need the correct permissions
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| user1 | User1 | One | user1@example.com |
| user2 | User2 | Two | user2@example.com |
| officer1 | Officer1 | One | officer1@example.com |
# Create Privacy Officer Role.
And the following "role" exists:
| shortname | privacyofficer |
| name | Privacy Officer |
| context_system | 1 |
| tool/dataprivacy:managedataregistry | allow |
| tool/dataprivacy:managedatarequests | allow |
| tool/dataprivacy:makedatarequestsforchildren | allow |
| moodle/site:configview | allow |
| moodle/category:viewhiddencategories | allow |
| moodle/course:viewhiddencourses | allow |
| moodle/course:viewhiddenactivities | allow |
| moodle/course:view | allow |
# Create Parent Role.
And the following "role" exists:
| shortname | parentrole |
| name | Parent Role |
| context_user | 1 |
| moodle/user:viewdetails | allow |
| moodle/user:viewalldetails | allow |
| moodle/user:readuserblogs | allow |
| moodle/user:readuserposts | allow |
| moodle/user:viewuseractivitiesreport | allow |
| moodle/user:editprofile | allow |
| tool/policy:acceptbehalf | allow |
| tool/dataprivacy:makedatarequestsforchildren | allow |
# Add permission to allow parent to make requests on behalf of child user.
And the following config values are set as admin:
| contactdataprotectionofficer | 1 | tool_dataprivacy |
And I log in as "admin"
@javascript
Scenario: Privacy officer can request for other user's personal data
Given I navigate to "Users > Permissions > Assign system roles" in site administration
# Assign Privacy Officer role to officer1.
And I follow "Privacy Officer"
And I set the field "addselect_searchtext" to "Officer1"
And I set the field "addselect" to "Officer1 One (officer1@example.com)"
And I press "Add"
# Navigate to home in order to navigate properly to Privacy settings.
And I am on site homepage
# Select Privacy officer in the Orivacy officer role mapping setting.
And I navigate to "Users > Privacy and policies > Privacy settings" in site administration
And I click on "Privacy Officer" "checkbox"
And I press "Save changes"
And I log in as "officer1"
And I navigate to "Users > Privacy and policies > Data requests" in site administration
# Create a new request as the designated privacy officer.
When I follow "New request"
And I set the field "User" to "User1 One"
And I set the field "Comment" to "User One data"
And I press "Save changes"
# Confirm that the new data request is successfully created for selected user with status "Awaiting approval".
Then the following should exist in the "generaltable" table:
| Type | User | Requested by | Status | Message |
| Export | User1 One | Officer1 One | Awaiting approval | User One data |
@javascript
Scenario: Parent user can request data on behalf of child user
Given I navigate to "Users > Accounts > Browse list of users" in site administration
And I follow "User1 One"
And I click on "Preferences" "link" in the ".profile_tree" "css_element"
# Assign user2 as parent for user1.
And I follow "Assign roles relative to this user"
And I follow "Parent"
And I set the field "Potential users" to "User2 Two (user2@example.com)"
And I click on "Add" "button" in the "#page-content" "css_element"
And I log in as "user2"
And I follow "Profile" in the user menu
And I follow "Data requests"
# As parent, create a data request for a child user.
And I follow "New request"
And I click on "User" "field"
When I type "User1 One"
# Confirm that only the parent's child users can be searched and selected.
Then I should see "User1 One"
And I type "User2 Two"
And I should see "No suggestions"
And I type "Officer1 One"
And I should see "No suggestions"
And I set the field "Search" to "User1"
And I set the field "Comment" to "This is a comment"
And I press "Save changes"
# Confirm that data request was successfully made by parent on behalf of child user.
And I should see "Your request has been submitted to the privacy officer"
And the following should exist in the "generaltable" table:
| Type | Requested by | Status | Message |
| Export all of my personal data (User1 One) | User2 Two | Awaiting approval | This is a comment |
@@ -80,7 +80,7 @@ class table implements \renderable {
'text-center',
];
$table->id = 'manage-licenses';
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$table->data = [];
$rownumber = 0;
@@ -137,7 +137,7 @@ class tool_log_setting_managestores extends admin_setting {
$table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign', 'centeralign',
'centeralign');
$table->id = 'logstoreplugins';
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$table->data = array();
// Iterate through store plugins and add to the display table.
@@ -49,7 +49,7 @@
}
}}
<span>
<a href="{{profileurl}}" title="{{#str}}viewprofile{{/str}}">
<a href="{{profileurl}}">
<img height="18" src="{{profileimageurlsmall}}" alt="">
<span>{{fullname}}</span>
{{#hasidentity}}
@@ -0,0 +1,77 @@
@tool @tool_lp @tool_lp_framework
Feature: Manage CRUD operations for competencies
In order to perform CRUD operations on competencies
As a manager
I need to be able to create, read, update and delete competencies
Background:
Given the following "core_competency > frameworks" exist:
| shortname | idnumber |
| CF1 | CF1 |
And the following "core_competency > competencies" exist:
| shortname | competencyframework | idnumber | description |
| C1 | CF1 | C1ID | C1 description |
And I log in as "admin"
And I navigate to "Competencies > Competency frameworks" in site administration
And I click on "CF1 (CF1)" "link"
@javascript
Scenario: Create a new competency
# Targets the `CF1` element to make `Add competency` button visible and accessible to avoid ambiguity with the other 'CF1' element on the screen.
Given I click on "//span[text()='CF1']" "xpath_element"
When I press "Add competency"
And I set the field "Name" to "C2"
And I set the field "Description" to "C2 description"
And I set the field "ID number" to "C2ID"
And I press "Save changes"
# Access the newly created competencies to ensure that correct information was registered.
Then "Competency created" "text" should exist
And "C2" "text" should appear after "C1" "text"
And I select "C2" of the competency tree
And "C2ID" "text" should exist
And "C2 description" "text" should exist
@javascript
Scenario: Read a competency
When I select "C1" of the competency tree
# Confirm that selected competency info displayed matches registered info.
Then "C1ID" "text" should exist
And "C1 description" "text" should exist
# Targets the unique 'Edit' link needed to open the menu, avoiding ambiguity with the other 'Edit' link.
And I click on "//a[@href='#' and text()='Edit']" "xpath_element"
# Similar to the previous step, to avoid ambiguity with the competency framework "Edit", target css element with data-action=edit.
And I click on "[data-action=edit]" "css_element"
# Confirm that the details displayed when accessing edit screen values match registered data.
And the field "Name" matches value "C1"
And the field "Description" matches value "C1 description"
And the field "ID number" matches value "C1ID"
@javascript
Scenario: Update a competency
Given I select "C1" of the competency tree
# Targets the unique 'Edit' link needed to open the menu, avoiding ambiguity with the other 'Edit' link.
And I click on "//a[@href='#' and text()='Edit']" "xpath_element"
# Similar to the previous step, to avoid ambiguity with the competency framework "Edit", target css element with data-action=edit.
When I click on "[data-action=edit]" "css_element"
And I set the field "Name" to "C2"
And I set the field "Description" to "C2 description"
And I set the field "ID number" to "C2ID"
And I press "Save changes"
Then "Competency updated" "text" should exist
And "C1" "text" should not exist
And "C2" "text" should exist
And I select "C2" of the competency tree
And "C2ID" "text" should exist
And "C1ID" "text" should not exist
And "C2 description" "text" should exist
And "C1 description" "text" should not exist
@javascript
Scenario: Delete a competency
Given I select "C1" of the competency tree
# Targets the unique 'Edit' link needed to open the menu, avoiding ambiguity with the other 'Edit' link.
And I click on "//a[@href='#' and text()='Edit']" "xpath_element"
When I click on "Delete" "link"
And I click on "Delete" "button" in the "Confirm" "dialogue"
# Confirm that "C1" competency was successfully deleted.
Then "C1" "text" should not exist
@@ -0,0 +1,63 @@
@tool @tool_lp @tool_lp_framework
Feature: Move and cross-reference competencies
In order to move and cross-reference competencies
As a manager
I need to be open the competency's menu items.
Background:
Given the following "core_competency > frameworks" exist:
| shortname | idnumber |
| CF1 | CF1 |
And the following "core_competency > competencies" exist:
| shortname | competencyframework |
| C1 | CF1 |
| C2 | CF1 |
| C3 | CF1 |
| C4 | CF1 |
And I log in as "admin"
And I navigate to "Competencies > Competency frameworks" in site administration
And I click on "CF1 (CF1)" "link"
@javascript
Scenario: Move a competency using Move up/Move down menu items
Given I select "C1" of the competency tree
# Targets the unique 'Edit' link needed to open the menu, avoiding ambiguity with the other 'Edit' link.
And I click on "//a[@href='#' and text()='Edit']" "xpath_element"
When I click on "Move down" "link"
Then "C1" "text" should appear after "C2" "text"
# Targets the unique 'Edit' link needed to open the menu, avoiding ambiguity with the other 'Edit' link.
And I click on "//a[@href='#' and text()='Edit']" "xpath_element"
And I click on "Move up" "link"
And "C1" "text" should appear before "C2" "text"
@javascript
Scenario: Move a competency using Relocate menu item
Given I select "C3" of the competency tree
# Targets the unique 'Edit' link needed to open the menu, avoiding ambiguity with the other 'Edit' link.
And I click on "//a[@href='#' and text()='Edit']" "xpath_element"
When I click on "Relocate" "link"
And I click on "C1" "text" in the "Move competency" "dialogue"
And I click on "Move" "button" in the "Move competency" "dialogue"
Then "C1" "text" should appear before "C3" "text"
And "C3" "text" should appear before "C2" "text"
And I select "C3" of the competency tree
# Targets the unique 'Edit' link needed to open the menu, avoiding ambiguity with the other 'Edit' link.
And I click on "//a[@href='#' and text()='Edit']" "xpath_element"
# Similar to the previous step, to avoid ambiguity with the competency framework "Edit", target css element with data-action=edit.
And I click on "[data-action=edit]" "css_element"
And "C1" "text" should exist
And "No parent (top-level competency)" "text" should not exist
And I press "Cancel"
And "C1" "text" should appear before "C3" "text"
And "C3" "text" should appear before "C2" "text"
@javascript
Scenario: Cross-reference a competency
Given I select "C1" of the competency tree
# Targets the unique 'Edit' link needed to open the menu, avoiding ambiguity with the other 'Edit' link.
And I click on "//a[@href='#' and text()='Edit']" "xpath_element"
When I click on "Add cross-referenced competency" "link"
And I click on "C2" "text" in the "Competency picker" "dialogue"
And I click on "Add" "button" in the "Competency picker" "dialogue"
Then "Cross-referenced competencies:" "text" should exist
And I should see "C2 cmp2"
+71 -23
View File
@@ -16,16 +16,10 @@ Feature: Manage plan workflow
| usermanageownplan | User manage own plan role | user |
| manageplan | Manager all plans role | manager |
And the following "role capabilities" exist:
| role | moodle/competency:planmanageowndraft | moodle/competency:planmanageown |
| usermanageowndraftplan | allow | |
| usermanageownplan | allow | allow |
| manageplan | allow | allow |
And the following "role capability" exists:
| role | manageplan |
| moodle/competency:planmanage | allow |
| moodle/competency:planview | allow |
| moodle/competency:planreview | allow |
| moodle/competency:planrequestreview | allow |
| role | moodle/competency:planmanageowndraft | moodle/competency:planmanageown | moodle/competency:planmanage | moodle/competency:planview | moodle/competency:planreview | moodle/competency:planrequestreview |
| usermanageowndraftplan | allow | | | | | |
| usermanageownplan | allow | allow | | | | |
| manageplan | allow | allow | allow | allow | allow | allow |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| user1 | usermanageowndraftplan | System | |
@@ -53,8 +47,7 @@ Feature: Manage plan workflow
| lp | System | 1 | my-index | content |
Scenario: User can manages his own plan draft
Given I log in as "user1"
And I follow "Profile" in the user menu
Given I am on the "user1" "user > profile" page logged in as user1
When I follow "Learning plans"
Then I should see "List of learning plans"
And I should see "Test-Plan1"
@@ -63,11 +56,9 @@ Feature: Manage plan workflow
And I should see "Waiting for review"
And I click on "Cancel review" of edit menu in the "Test-Plan1" row
And I should see "Draft"
And I log out
Scenario: User can manages his own plan
Given I log in as "user2"
And I follow "Profile" in the user menu
Given I am on the "user2" "user > profile" page logged in as user2
When I follow "Learning plans"
Then I should see "List of learning plans"
And I should see "Test-Plan2"
@@ -82,11 +73,11 @@ Feature: Manage plan workflow
And I should see "Active"
And I click on "Complete this learning plan" of edit menu in the "Test-Plan2" row
And I click on "Complete this learning plan" "button" in the "Confirm" "dialogue"
And I wait until the page is ready
And I should see "Complete"
And I click on "Reopen this learning plan" of edit menu in the "Test-Plan2" row
And I click on "Reopen this learning plan" "button" in the "Confirm" "dialogue"
And I should see "Active"
And I log out
Scenario: Manager can see learning plan with status waiting for review
Given the following "core_competency > plans" exist:
@@ -96,7 +87,6 @@ Feature: Manage plan workflow
When I log in as "manager1"
Then I should see "Test-Plan3"
And I should not see "Test-Plan4"
And I log out
Scenario: Manager can start review of learning plan with status waiting for review
Given the following "core_competency > plans" exist:
@@ -108,7 +98,6 @@ Feature: Manage plan workflow
And I should see "Test-Plan3"
When I follow "Start review"
Then I should see "In review"
And I log out
Scenario: Manager can reject a learning plan with status in review
Given the following "core_competency > plans" exist:
@@ -121,7 +110,6 @@ Feature: Manage plan workflow
And I should see "In review"
When I follow "Finish review"
Then I should see "Draft"
And I log out
Scenario: Manager can accept a learning plan with status in review
Given the following "core_competency > plans" exist:
@@ -134,7 +122,6 @@ Feature: Manage plan workflow
And I should see "In review"
When I follow "Make active"
Then I should see "Active"
And I log out
Scenario: Manager send back to draft an active learning plan
Given the following "core_competency > plans" exist:
@@ -150,7 +137,6 @@ Feature: Manage plan workflow
And I follow "Learning plans"
Then I should see "Draft"
And I should not see "Active"
And I log out
Scenario: Manager change an active learning plan to completed
Given the following "core_competency > plans" exist:
@@ -169,7 +155,6 @@ Feature: Manage plan workflow
And I follow "Learning plans"
Then I should see "Complete"
And I should not see "Active"
And I log out
Scenario: Manager reopen a complete learning plan
Given the following "core_competency > plans" exist:
@@ -187,4 +172,67 @@ Feature: Manage plan workflow
And I follow "Learning plans"
Then I should see "Active"
And I should not see "Complete"
And I log out
Scenario: Student learning plan derived from templates can be completed
Given the following "core_competency > templates" exist:
| shortname |
| LPT1 |
And the following "core_competency > template_competencies" exist:
| template | competency |
| LPT1 | Test-Comp1 |
And I log in as "admin"
And I navigate to "Competencies > Learning plan templates" in site administration
# Select 1 user to assign to create learning plans for using template.
And I click on ".template-userplans" "css_element" in the "LPT1" "table_row"
And I set the field "Select users" to "user1"
And I press "Create learning plans"
And I click on "LPT1" "link" in the "LPT1" "table_row"
When I click on "Complete this learning plan" "link"
And I click on "Complete this learning plan" "button" in the "Confirm" "dialogue"
# Add a short wait to ensure the page has loaded before checking that "Complete" "text" exists.
And I wait until the page is ready
# Confirm that student's learning plan template is marked as Completed.
Then "Complete" "text" should exist
And "Reopen this learning plan" "link" should exist
Scenario: Learning plan template updates are not reflected on plans already completed
Given the following "core_competency > templates" exist:
| shortname |
| LPT1 |
And the following "core_competency > template_competencies" exist:
| template | competency |
| LPT1 | Test-Comp1 |
And I log in as "admin"
And I navigate to "Competencies > Learning plan templates" in site administration
# Select 2 users to assign to create learning plans for using template.
And I click on ".template-userplans" "css_element" in the "LPT1" "table_row"
And I set the field "Select users" to "user1"
And I press "Create learning plans"
And I set the field "Select users" to "user2"
And I press "Create learning plans"
# Complete the learning plan for User 1.
And I click on "LPT1" "link" in the "User 1" "table_row"
And I click on "Complete this learning plan" "link"
And I click on "Complete this learning plan" "button" in the "Confirm" "dialogue"
# Add another competency to the learning plan template.
And the following "core_competency > template_competencies" exist:
| template | competency |
| LPT1 | Test-Comp2 |
# Navigate back to the list of Learning plan templates in order to access User 1's learning plan.
And I navigate to "Competencies > Learning plan templates" in site administration
And I click on ".template-userplans" "css_element" in the "LPT1" "table_row"
# Confirm that only the first competency is reflected on User 1's learning plan since it's already completed.
When I click on "LPT1" "link" in the "User 1" "table_row"
Then "Test-Comp2" "link" should not exist
And "Test-Comp2" "text" should not exist
And "Test-Comp1" "link" should exist
And "Test-Comp1" "text" should exist
# Navigate back to list of Learning plan templates in order to access User 2's learning plan.
And I navigate to "Competencies > Learning plan templates" in site administration
And I click on ".template-userplans" "css_element" in the "LPT1" "table_row"
# Confirm that both competencies are reflected on User 2's learning plan since it's not yet completed.
And I click on "LPT1" "link" in the "User 2" "table_row"
And "Test-Comp2" "link" should exist
And "Test-Comp2" "text" should exist
And "Test-Comp1" "link" should exist
And "Test-Comp1" "text" should exist
@@ -0,0 +1,60 @@
@tool @tool_lp @core_cohort
Feature: Cohorts can be synchronized with learning plans
In order to create learning plans for cohort members
As an admin
I need to be able to synchronise cohorts with learning plans
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| user1 | User | One | user1@example.com |
| user2 | User | Two | user2@example.com |
And the following "cohorts" exist:
| name | idnumber |
| Cohort 1 | CH1 |
And the following "cohort members" exist:
| user | cohort |
| user1 | CH1 |
| user2 | CH1 |
And the following "core_competency > frameworks" exist:
| shortname | idnumber |
| CF1 | CF1 |
And the following "core_competency > competencies" exist:
| shortname | competencyframework | idnumber |
| C1 | CF1 | C1 |
And the following "core_competency > templates" exist:
| shortname |
| LPT1 |
And the following "core_competency > template_competencies" exist:
| template | competency |
| LPT1 | C1 |
@javascript
Scenario: Cohorts can be synchronised with learning plans
Given I log in as "admin"
# Navigate to the list of learning plan templates in order to add cohorts.
And I navigate to "Competencies > Learning plan templates" in site administration
When I click on "Add cohorts to sync" of edit menu in the "LPT1" row
And I set the field "Select cohorts to sync" to "Cohort 1"
And I press "Add cohorts"
And I wait until the page is ready
# Confirm that 2 learning plans were created for members of the cohort.
Then "2 learning plans were created" "text" should exist
# Confirm current screen is still "Cohorts synced to this learning plan template screen"
And "Cohorts synced to this learning plan template" "text" should exist
# Confirm that the cohort is now added to the learning plan template.
And the following should exist in the "generaltable" table:
| Name | Cohort ID |
| Cohort 1 | CH1 |
# Navigate back to the list of learning plan templates to view updated list.
And I navigate to "Competencies > Learning plan templates" in site administration
# Confirm that the added cohort and learning plans are now reflected on the list of Learning plan templates.
And the following should exist in the "generaltable" table:
| Name | Category | Cohorts | Learning plans |
| LPT1 | System | 1 | 2 |
And I click on ".template-userplans" "css_element" in the "LPT1" "table_row"
# Confirm that learning plans were created for all cohort members.
And the following should exist in the "generaltable" table:
| Name | First name / Last name | Email address |
| LPT1 | User One | user1@example.com |
| LPT1 | User Two | user2@example.com |
+75
View File
@@ -17,6 +17,7 @@
namespace tool_lp;
use core_competency\api;
use core_competency\competency;
use core_external\external_api;
use externallib_advanced_testcase;
@@ -432,6 +433,80 @@ final class externallib_test extends externallib_advanced_testcase {
$this->assertEquals('A', $summary->usercompetencysummary->evidence[1]->gradename);
}
/**
* Evidence stored against a course module competency is deleted if the CM is deleted.
* @covers \tool_lp\external::data_for_user_competency_summary_in_plan
*/
public function test_data_for_user_competency_summary_in_plan_deleted_cm(): void {
$this->setUser($this->creator);
$dg = $this->getDataGenerator();
$lpg = $dg->get_plugin_generator('core_competency');
$f1 = $lpg->create_framework();
$c1 = $lpg->create_competency(['competencyframeworkid' => $f1->get('id')]);
$c2 = $lpg->create_competency(['competencyframeworkid' => $f1->get('id')]);
$tpl = $lpg->create_template();
$lpg->create_template_competency(['templateid' => $tpl->get('id'), 'competencyid' => $c1->get('id')]);
$lpg->create_template_competency(['templateid' => $tpl->get('id'), 'competencyid' => $c2->get('id')]);
$plan = $lpg->create_plan(['userid' => $this->user->id, 'templateid' => $tpl->get('id'), 'name' => 'Evil']);
$course = $dg->create_course();
$assign1 = $dg->create_module('assign', ['course' => $course->id]);
$assign2 = $dg->create_module('assign', ['course' => $course->id]);
$lpg->create_course_module_competency(['competencyid' => $c1->get('id'), 'cmid' => $assign1->cmid]);
$lpg->create_course_module_competency(['competencyid' => $c2->get('id'), 'cmid' => $assign1->cmid]);
api::add_evidence(
$this->user->id,
$c1->get('id'),
\core\context\module::instance($assign1->cmid),
competency::OUTCOME_COMPLETE,
'evidence_competencyrule',
'core_competency',
);
api::add_evidence(
$this->user->id,
$c2->get('id'),
\core\context\module::instance($assign2->cmid),
competency::OUTCOME_COMPLETE,
'evidence_competencyrule',
'core_competency',
);
// Confirm we have evidence for 2 course module competencies.
$summary1 = external::data_for_user_competency_summary_in_plan($c1->get('id'), $plan->get('id'));
$this->assertEquals('Evil', $summary1->plan->name);
$this->assertEquals(
get_string('evidence_competencyrule', 'core_competency'),
$summary1->usercompetencysummary->evidence[0]->description
);
$summary2 = external::data_for_user_competency_summary_in_plan($c2->get('id'), $plan->get('id'));
$this->assertEquals('Evil', $summary2->plan->name);
$this->assertEquals(
get_string('evidence_competencyrule', 'core_competency'),
$summary2->usercompetencysummary->evidence[0]->description
);
// Delete one course module.
course_delete_module($assign1->cmid);
// The evidence for the deleted course module should have been deleted. Other evidence should remain.
$summary1 = external::data_for_user_competency_summary_in_plan($c1->get('id'), $plan->get('id'));
$this->assertEquals('Evil', $summary1->plan->name);
$this->assertFalse(array_key_exists(0, $summary1->usercompetencysummary->evidence));
$summary2 = external::data_for_user_competency_summary_in_plan($c2->get('id'), $plan->get('id'));
$this->assertEquals('Evil', $summary2->plan->name);
$this->assertEquals(
get_string('evidence_competencyrule', 'core_competency'),
$summary2->usercompetencysummary->evidence[0]->description
);
}
public function test_data_for_user_competency_summary(): void {
$this->setUser($this->creator);
+1 -1
View File
@@ -56,7 +56,7 @@ class tool_messageinbound_renderer extends plugin_renderer_base {
$enabled,
$edit,
);
$table->attributes['class'] = 'admintable generaltable messageinboundhandlers';
$table->attributes['class'] = 'admintable generaltable messageinboundhandlers table table-hover';
$yes = get_string('yes');
$no = get_string('no');
+1 -1
View File
@@ -74,7 +74,7 @@ class manager {
get_string('achievedweight', 'tool_mfa'),
get_string('status'),
];
$table->attributes['class'] = 'admintable generaltable table table-bordered';
$table->attributes['class'] = 'admintable generaltable table table-bordered table-hover';
$table->colclasses = [
'text-end',
'',
+4 -4
View File
@@ -174,7 +174,7 @@ class renderer extends \plugin_renderer_base {
$table = new \html_table();
$table->id = 'active_factors';
$table->attributes['class'] = 'generaltable table table-bordered';
$table->attributes['class'] = 'generaltable table table-bordered table-hover';
$table->head = [
$headers->devicename,
$headers->added,
@@ -348,7 +348,7 @@ class renderer extends \plugin_renderer_base {
$table = new \html_table();
$table->head = $displaynames;
$table->align = $colclasses;
$table->attributes['class'] = 'generaltable table table-bordered w-auto';
$table->attributes['class'] = 'generaltable table table-bordered w-auto table-hover';
$table->attributes['style'] = 'width: auto; min-width: 50%; margin-bottom: 0;';
// Manually handle Total users and MFA users.
@@ -461,7 +461,7 @@ class renderer extends \plugin_renderer_base {
$table = new \html_table();
$table->attributes['class'] = 'generaltable table table-bordered w-auto';
$table->attributes['class'] = 'generaltable table table-bordered w-auto table-hover';
$table->attributes['style'] = 'width: auto; min-width: 50%';
$table->head = [
@@ -513,7 +513,7 @@ class renderer extends \plugin_renderer_base {
global $DB;
$table = new \html_table();
$table->attributes['class'] = 'generaltable table table-bordered w-auto';
$table->attributes['class'] = 'generaltable table table-bordered w-auto table-hover';
$table->attributes['style'] = 'width: auto; min-width: 50%';
$table->head = [
'userid' => get_string('userid', 'grades'),
@@ -131,7 +131,7 @@ class admin_setting_managemfa extends \core_admin\table\plugin_management_table
$txt = get_strings(['combination', 'totalweight'], 'tool_mfa');
$table = new \html_table();
$table->id = 'mfacombinations';
$table->attributes['class'] = 'admintable generaltable table table-bordered';
$table->attributes['class'] = 'admintable generaltable table table-bordered table-hover';
$table->head = [$txt->combination, $txt->totalweight];
$table->data = [];
@@ -28,6 +28,6 @@ $string['pluginname'] = 'Authentication type';
$string['privacy:metadata'] = 'The Authentication type factor plugin does not store any personal data.';
$string['settings:description'] = 'Automatically verify users based on their authentication type.';
$string['settings:goodauth'] = 'Factor authentication types';
$string['settings:goodauth_help'] = 'Select all authentication types to use as a factor for MFA. Any types not selected will not be treated as a FAIL in MFA.';
$string['settings:goodauth_help'] = 'Select all authentication types that will gain the points from this factor. Other authentication types will not be treated as a fail in MFA, but will not gain this factor\'s weight points.';
$string['settings:shortdescription'] = 'Allow users to bypass extra authentication steps based on their authentication type.';
$string['summarycondition'] = 'has an authentication type of {$a}';
@@ -195,7 +195,7 @@ class factor extends object_factor_base {
$manualtable = new \html_table();
$manualtable->id = 'manualattributes';
$manualtable->attributes['class'] = 'generaltable table table-bordered table-sm w-auto';
$manualtable->attributes['class'] = 'generaltable table table-bordered table-sm w-auto table-hover';
$manualtable->attributes['style'] = 'width: auto;';
$manualtable->data = [
[get_string('setupfactor:key', 'factor_totp'), $secret],
+1 -1
View File
@@ -817,7 +817,7 @@ class api {
$credentials[] = ['type' => 'airnotifieraccesskey', 'value' => $CFG->airnotifieraccesskey];
}
if (\core\hub\registration::is_registered()) {
$credentials[] = ['type' => 'siteid', 'value' => $CFG->siteidentifier];
$credentials[] = ['type' => 'siteid', 'value' => \core\hub\registration::get_secret()];
}
// Generate a hash key for validating that the request is coming from this site via WS.
$key = complex_random_string(32);
+35 -15
View File
@@ -16,7 +16,10 @@
namespace tool_mobile;
use core\hook\output\extend_url;
use html_writer;
use moodle_url;
use tool_mobile\local\hooks\before_extend_ios_app_banner;
/**
* Allows plugins to add any elements to the footer.
@@ -35,22 +38,39 @@ class hook_callbacks {
\core\hook\output\before_standard_head_html_generation $hook,
): void {
global $CFG, $PAGE;
// Smart App Banners meta tag is only displayed if mobile services are enabled and configured.
if (!empty($CFG->enablemobilewebservice)) {
$mobilesettings = get_config('tool_mobile');
if (!empty($mobilesettings->enablesmartappbanners)) {
if (!empty($mobilesettings->iosappid)) {
$hook->add_html(
'<meta name="apple-itunes-app" content="app-id=' . s($mobilesettings->iosappid) . ', ' .
'app-argument=' . $PAGE->url->out() . '"/>'
);
}
// Only emit mobile app metadata when mobile services are enabled + configured.
if (empty($CFG->enablemobilewebservice)) {
return;
}
$mobilesettings = get_config('tool_mobile');
if (empty($mobilesettings->enablesmartappbanners)) {
return;
}
// IOS with hook-based app id and argument augmentation.
if (!empty($mobilesettings->iosappid)) {
$appid = (string)$mobilesettings->iosappid;
$appargument = $PAGE->url->out();
// Hook to allow modification of ios smart app banner fields.
$ioshook = new before_extend_ios_app_banner($appid, $appargument);
\core\di::get(\core\hook\manager::class)->dispatch($ioshook);
$appid = $ioshook->get_appid();
$appargument = $ioshook->get_appargument();
// Add the meta tag.
$hook->add_html(
'<meta name="apple-itunes-app" content="app-id=' . s($appid) .
', app-argument=' . s($appargument) . '"/>'
);
}
if (!empty($mobilesettings->androidappid)) {
$mobilemanifesturl = "$CFG->wwwroot/$CFG->admin/tool/mobile/mobile.webmanifest.php";
$hook->add_html('<link rel="manifest" href="' . $mobilemanifesturl . '" />');
}
}
// Android with hook-based URL augmentation.
if (!empty($mobilesettings->androidappid)) {
$url = new moodle_url('/admin/tool/mobile/mobile.webmanifest.php');
$urlhook = new extend_url($url);
\core\di::get(\core\hook\manager::class)->dispatch($urlhook);
$url = $urlhook->get_url();
// Add the link tag.
$hook->add_html('<link rel="manifest" href="' . $url->out(false) . '" />');
}
}
@@ -0,0 +1,78 @@
<?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/>.
namespace tool_mobile\local\hooks;
/**
* Allow adjustment of ios smart app banner fields.
*
* @package tool_mobile
* @copyright 2025 Safat Shahin <safat.shahin@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
#[\core\attribute\label('Allow adjustment of ios smart app banner fields')]
#[\core\attribute\tags('mobile')]
final class before_extend_ios_app_banner {
/**
* Create a new instance of the hook.
*
* @param string $appid The app id for the ios smart banner
* @param string $appargument The app argument for the ios smart banner
*/
public function __construct(
/** @var string $appid The app id for the ios smart banner */
private string $appid,
/** @var string $appargument The app argument for the ios smart banner */
private string $appargument,
) {
}
/**
* Get the appid.
*
* @return string
*/
public function get_appid(): string {
return $this->appid;
}
/**
* Set the appid.
*
* @param string $appid
*/
public function set_appid(string $appid): void {
$this->appid = $appid;
}
/**
* Get the appargument.
*
* @return string
*/
public function get_appargument(): string {
return $this->appargument;
}
/**
* Set the appargument.
*
* @param string $appargument
*/
public function set_appargument(string $appargument): void {
$this->appargument = $appargument;
}
}
+3
View File
@@ -28,10 +28,13 @@
*/
define('NO_DEBUG_DISPLAY', true);
define('NO_MOODLE_COOKIES', true);
require_once(__DIR__ . '/../../../config.php');
header('Content-Type: application/json; charset: utf-8');
header('Cache-Control: public, max-age=' . HOURSECS . ', no-transform');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + HOURSECS) . ' GMT');
$mobilesettings = get_config('tool_mobile');
// Display manifest contents only if all the required conditions are met.
@@ -86,7 +86,7 @@ class import_backup_helper {
}
[$filepath, $filename] = $this->remoteresource->download_to_requestdir();
\core\antivirus\manager::scan_file($filepath, $filename, true);
\core\antivirus\manager::scan_file($filepath . DIRECTORY_SEPARATOR . $filename, $filename, true);
// Check the final size of file against the user upload limits.
$localsize = filesize(sprintf('%s/%s', $filepath, $filename));
@@ -78,7 +78,7 @@ class import_strategy_file implements import_strategy {
// Download the file into a request directory and scan it.
[$filepath, $filename] = $resource->download_to_requestdir();
avmanager::scan_file($filepath, $filename, true);
avmanager::scan_file($filepath . DIRECTORY_SEPARATOR . $filename, $filename, true);
// Check the final size of file against the user upload limits.
$localsize = filesize(sprintf('%s/%s', $filepath, $filename));
@@ -38,6 +38,9 @@ $string['defaultmoodlenet_desc'] = 'The URL of the MoodleNet instance available
$string['defaultmoodlenetname'] = "MoodleNet instance name";
$string['defaultmoodlenetnamevalue'] = 'MoodleNet Central';
$string['defaultmoodlenetname_desc'] = 'The name of the MoodleNet instance available via the activity chooser.';
$string['removalwarning_feature'] = 'If you need to continue using MoodleNet, contact your site administrator about setting up a self-hosted MoodleNet instance.';
$string['removalwarning_service'] = 'After the date, you will no longer be able to browse or add content from MoodleNet Central.';
$string['removalwarning_title'] = 'The MoodleNet service will be shut down on 20 April 2026.';
$string['enablemoodlenet'] = 'Enable MoodleNet integration (inbound)';
$string['enablemoodlenet_desc'] = 'If enabled, a user with the capability to create and manage activities can browse MoodleNet via the activity chooser and import MoodleNet resources into their course. In addition, a user with the capability to restore backups can select a backup file on MoodleNet and restore it into Moodle.';
$string['errorduringdownload'] = 'An error occurred while downloading the file: {$a}';
@@ -27,8 +27,16 @@
<div class="content text-start mb-5 px-5 py-4" data-region="chooser-option-summary-content-container">
<div data-region="moodle-net">
<div class="overlay-icon-container z-index-1 d-none" data-region="spinner"></div>
<img class="w-25 mb-4" aria-hidden="true" src="{{{img}}}">
<img class="w-25 mb-4" alt="" aria-hidden="true" src="{{{img}}}">
<p>{{#str}} instancedescription, tool_moodlenet {{/str}}</p>
{{! Removal warning - always visible when MoodleNet integration is enabled }}
<div class="alert alert-warning w-75 mx-auto mb-3" role="alert">
<strong>{{#str}}removalwarning_title, tool_moodlenet{{/str}}</strong>
<p class="mb-1">{{#str}}removalwarning_service, tool_moodlenet{{/str}}</p>
<p class="mb-0">{{#str}}removalwarning_feature, tool_moodlenet{{/str}}</p>
</div>
<p class="w-75 mx-auto mb-1 mt-5">{{#str}} connectandbrowse, tool_moodlenet {{/str}}</p>
<a class="btn btn-secondary d-block w-75 mx-auto mb-4"
data-action="browse"
@@ -60,7 +60,7 @@ class renderer extends plugin_renderer_base {
get_string('systemauthstatus', 'tool_oauth2') . ' ' . $this->help_icon('systemaccountconnected', 'tool_oauth2'),
get_string('edit'),
];
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$data = [];
$index = 0;
@@ -231,7 +231,7 @@ class renderer extends plugin_renderer_base {
get_string('url'),
get_string('edit'),
];
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$data = [];
$index = 0;
@@ -290,7 +290,7 @@ class renderer extends plugin_renderer_base {
get_string('userfieldinternalfield', 'tool_oauth2'),
get_string('edit'),
];
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$data = [];
$index = 0;
@@ -61,7 +61,8 @@ Feature: Basic OAuth2 functionality
And I should see "device_authorization_endpoint"
And I navigate to "Server > OAuth 2 services" in site administration
And I click on "Configure user field mappings" "link" in the "Testing service" "table_row"
And I should see "firstname" in the "givenname" "table_row"
And I should see "firstname" in the "given_name" "table_row"
And I should see "lastname" in the "family_name" "table_row"
And I should see "idnumber" in the "sub" "table_row"
And I should see "email" in the "email" "table_row"
And I should see "lang" in the "locale" "table_row"
+7 -14
View File
@@ -14,15 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Provides {@link tool_policy\output\renderer} class.
*
* @package tool_policy
* @category output
* @copyright 2018 David Mudrák <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_policy;
use coding_exception;
@@ -33,13 +24,12 @@ use core\session\manager;
use stdClass;
use tool_policy\event\acceptance_created;
use tool_policy\event\acceptance_updated;
use user_picture;
defined('MOODLE_INTERNAL') || die();
/**
* Provides the API of the policies plugin.
*
* @package tool_policy
* @category output
* @copyright 2018 David Mudrak <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -1038,9 +1028,12 @@ class api {
// MDL-80973: At this point, the policyagreed value in DB could be 0 but $user->policyagreed could be 1 (as it was copied from $USER).
// So we need to ensure that the value in DB is set true if all policies were responded.
if ($user->policyagreed != $allresponded || $allresponded) {
$userpolicyagreed = (bool) ($user->policyagreed ?? false);
if ($userpolicyagreed !== $allresponded || $allresponded) {
$user->policyagreed = $allresponded;
$DB->set_field('user', 'policyagreed', $allresponded, ['id' => $user->id]);
if (!isguestuser($user)) {
$DB->set_field('user', 'policyagreed', $user->policyagreed, ['id' => $user->id]);
}
}
}
@@ -145,6 +145,12 @@ class course_bin extends base_bin {
return;
}
// We never need badge information here.
if ($plan->setting_exists('badges')) {
$badges = $plan->get_setting('badges');
$badges->set_value(false);
}
$controller->execute_plan();
// We don't need the forced setting anymore, hence restore previous settings.
@@ -39,11 +39,19 @@ Feature: Basic recycle bin functionality
| student2 | G1 |
| student2 | G2 |
And the following config values are set as admin:
| coursebinenable | 1 | tool_recyclebin |
| categorybinenable | 1 | tool_recyclebin |
| coursebinexpiry | 604800 | tool_recyclebin |
| coursebinenable | 1 | tool_recyclebin |
| categorybinenable | 1 | tool_recyclebin |
| coursebinexpiry | 604800 | tool_recyclebin |
| categorybinexpiry | 1209600 | tool_recyclebin |
| autohide | 0 | tool_recyclebin |
| autohide | 0 | tool_recyclebin |
And the following "core_badges > Badges" exist:
| name | course | description | image | status | type |
| My course 1 badge | C1 | Badge description | badges/tests/behat/badge.png | active | 2 |
| My course 2 badge | C2 | Badge description | badges/tests/behat/badge.png | active | 2 |
And the following "core_badges > Criterias" exist:
| badge | role |
| My course 1 badge | editingteacher |
| My course 2 badge | editingteacher |
Scenario: Restore a deleted assignment
Given I log in as "teacher1"
@@ -58,6 +66,14 @@ Feature: Basic recycle bin functionality
And I wait to be redirected
And I am on "Course 1" course homepage
And I should see "Test assign 1" in the "Section 1" "section"
# Check badges were not duplicated.
And I navigate to "Badges" in current page administration
And the following should exist in the "reportbuilder-table" table:
| Name | Badge status |
| My course 1 badge | Available |
And the following should not exist in the "reportbuilder-table" table:
| Name | Badge status |
| My course 1 badge | Not available |
@javascript
Scenario: Restore a deleted course
@@ -83,6 +99,11 @@ Feature: Basic recycle bin functionality
And "Student 1" "text" should exist in the "Group A" "table_row"
And "Student 2" "text" should exist in the "Group A" "table_row"
And "Student 2" "text" should exist in the "Group B" "table_row"
# Check badges are restored.
And I navigate to "Badges" in current page administration
And the following should exist in the "reportbuilder-table" table:
| Name | Badge status |
| My course 2 badge | Not available |
@javascript
Scenario: Deleting a single item from the recycle bin
+10 -6
View File
@@ -58,7 +58,7 @@ class tool_task_renderer extends plugin_renderer_base {
get_string('nextruntime', 'tool_task'),
];
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$table->colclasses = [];
// For each task entry (row) show action buttons/logs link depending on the user permissions.
@@ -200,8 +200,9 @@ class tool_task_renderer extends plugin_renderer_base {
});
}
return html_writer::table($table)
. html_writer::div(
$output = html_writer::table($table);
if ($canruntasks) {
$output .= html_writer::div(
html_writer::link(
new moodle_url(
$adhocrunurl,
@@ -210,7 +211,10 @@ class tool_task_renderer extends plugin_renderer_base {
get_string('runclassname', 'tool_task')
),
'task-runnow'
)
);
}
return $output
. html_writer::div(
html_writer::link(
new moodle_url(
@@ -259,7 +263,7 @@ class tool_task_renderer extends plugin_renderer_base {
get_string('actions','tool_task'),
];
$table->attributes['class'] = 'generaltable';
$table->attributes['class'] = 'generaltable table table-hover';
$table->colclasses = [];
// For each task entry (row) show action buttons/logs link depending on the user permissions.
@@ -384,7 +388,7 @@ class tool_task_renderer extends plugin_renderer_base {
get_string('default', 'tool_task'),
];
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$table->colclasses = [];
if (!$showloglink) {
+1 -1
View File
@@ -64,7 +64,7 @@ class preview extends \html_table {
$this->previewrows = $previewrows;
$this->id = "uupreview";
$this->attributes['class'] = 'generaltable';
$this->attributes['class'] = 'generaltable table table-hover';
$this->tablealign = 'center';
$this->summary = get_string('uploaduserspreview', 'tool_uploaduser');
$this->head = array();
+2 -1
View File
@@ -94,7 +94,8 @@ class uu_progress_tracker {
*/
public function start() {
$ci = 0;
echo '<table id="uuresults" class="generaltable boxaligncenter flexible-wrap" summary="'.get_string('uploadusersresult', 'tool_uploaduser').'">';
echo '<table id="uuresults" class="generaltable boxaligncenter flexible-wrap table table-hover" ' .
'summary="' . get_string('uploadusersresult', 'tool_uploaduser') . '">';
echo '<tr class="heading r0">';
foreach ($this->headers as $key => $header) {
echo '<th class="header c'.$ci++.'" scope="col">'.$header.'</th>';
@@ -0,0 +1,41 @@
@tool @tool_uploaduser @_file_upload
Feature: Admin can suspend user course enrolment via CSV upload
In order to manage enrolments in bulk
As an administrator
I need to be able to enrol and suspend users using CSV upload
Background:
Given the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
| Course 2 | C2 |
| Course 3 | C3 |
@javascript
Scenario: Admin uploads enrol and suspend CSVs and verifies enrolment status
Given I log in as "admin"
And I navigate to "Users > Accounts > Upload users" in site administration
When I upload "lib/tests/fixtures/QA_user_enrol.txt" file to "File" filemanager
And I press "Upload users"
And I press "Upload users"
And I press "Continue"
And I upload "lib/tests/fixtures/QA_user_suspend.txt" file to "File" filemanager
And I press "Upload users"
And I set the field "Upload type" to "Update existing users only"
And I press "Upload users"
And I press "Continue"
And I am on the "Course 1" "enrolled users" page
Then the following should exist in the "participants" table:
| First name | Status |
| Learner One | Active |
| Learner Two | Active |
And I am on the "Course 2" "enrolled users" page
And the following should exist in the "participants" table:
| First name | Status |
| Learner One | Active |
| Learner Two | Suspended |
And I am on the "Course 3" "enrolled users" page
And the following should exist in the "participants" table:
| First name | Status |
| Learner One | Suspended |
| Learner Two | Active |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -3
View File
@@ -808,9 +808,6 @@ const Tour = class {
targetNode.data('flexitour', 'target');
// Add the backdrop.
this.positionBackdrop(stepConfig);
$(document.body).append(currentStepNode);
this.currentStepNode = currentStepNode;
@@ -826,6 +823,7 @@ const Tour = class {
.animate({
scrollTop: this.calculateScrollTop(stepConfig),
}).promise().then(function() {
this.positionBackdrop(stepConfig);
this.positionStep(stepConfig);
this.revealStep(stepConfig);
pendingPromise.resolve();
@@ -90,7 +90,7 @@ abstract class XMLDBCheckAction extends XMLDBAction {
// If not confirmed, show confirmation box
if (!$confirmed) {
$o = '<table class="generaltable" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o = '<table class="generaltable table table-hover" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o.= ' <tr><td class="generalboxcontent">';
$o.= ' <p class="centerpara">' . $this->str[$this->introstr] . '</p>';
$o .= ' <table class="table-reboot w-100" cellpadding="20"><tr><td class="text-end">';
@@ -99,7 +99,8 @@ class check_bigints extends XMLDBCheckAction {
$dbman = $DB->get_manager();
$s = '';
$r = '<table class="generaltable boxaligncenter boxwidthwide" border="0" cellpadding="5" cellspacing="0" id="results">';
$r = '<table class="generaltable boxaligncenter boxwidthwide table table-hover" ' .
'border="0" cellpadding="5" cellspacing="0" id="results">';
$r.= ' <tr><td class="generalboxcontent">';
$r.= ' <h2 class="main">' . $this->str['searchresults'] . '</h2>';
$r.= ' <p class="centerpara">' . $this->str['wrongints'] . ': ' . count($wrong_fields) . '</p>';
@@ -147,7 +147,8 @@ class check_defaults extends XMLDBCheckAction {
$dbman = $DB->get_manager();
$s = '';
$r = '<table class="generaltable boxaligncenter boxwidthwide" border="0" cellpadding="5" cellspacing="0" id="results">';
$r = '<table class="generaltable boxaligncenter boxwidthwide table table-hover" ' .
'border="0" cellpadding="5" cellspacing="0" id="results">';
$r .= ' <tr><td class="generalboxcontent">';
$r .= ' <h2 class="main">' . $this->str['searchresults'] . '</h2>';
$r .= ' <p class="centerpara">' . $this->str['wrongdefaults'] . ': ' . count($wrongfields) . '</p>';
@@ -159,7 +159,8 @@ class check_foreign_keys extends XMLDBCheckAction {
}
protected function display_results(array $violatedkeys) {
$r = '<table class="generaltable boxaligncenter boxwidthwide" border="0" cellpadding="5" cellspacing="0" id="results">';
$r = '<table class="generaltable boxaligncenter boxwidthwide table table-hover" ' .
'border="0" cellpadding="5" cellspacing="0" id="results">';
$r.= ' <tr><td class="generalboxcontent">';
$r.= ' <h2 class="main">' . $this->str['searchresults'] . '</h2>';
$r.= ' <p class="centerpara">' . $this->str['violatedforeignkeys'] . ': ' . count($violatedkeys) . '</p>';
@@ -154,7 +154,8 @@ class check_indexes extends XMLDBCheckAction {
}
$s = '';
$r = '<table class="generaltable boxaligncenter boxwidthwide" border="0" cellpadding="5" cellspacing="0" id="results">';
$r = '<table class="generaltable boxaligncenter boxwidthwide table table-hover" ' .
'border="0" cellpadding="5" cellspacing="0" id="results">';
$r.= ' <tr><td class="generalboxcontent">';
$r.= ' <h2 class="main">' . $this->str['searchresults'] . '</h2>';
$r .= ' <p class="centerpara">' . $this->str['missingindexes'] . ': ' . count($missingindexes) . '</p>';
@@ -73,7 +73,7 @@ class delete_field extends XMLDBAction {
// If not confirmed, show confirmation box
if (!$confirmed) {
$o = '<table width="60" class="generaltable" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o = '<table width="60" class="generaltable table table-hover" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o.= ' <tr><td class="generalboxcontent">';
$o.= ' <p class="centerpara">' . $this->str['confirmdeletefield'] . '<br /><br />' . $fieldparam . '</p>';
$o .= ' <table class="table-reboot w-100" cellpadding="20"><tr><td class="text-end">';
@@ -73,7 +73,7 @@ class delete_index extends XMLDBAction {
// If not confirmed, show confirmation box
if (!$confirmed) {
$o = '<table width="60" class="generaltable" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o = '<table width="60" class="generaltable table table-hover" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o.= ' <tr><td class="generalboxcontent">';
$o.= ' <p class="centerpara">' . $this->str['confirmdeleteindex'] . '<br /><br />' . $indexparam . '</p>';
$o .= ' <table class="table-reboot w-100" cellpadding="20"><tr><td class="text-end">';
@@ -73,7 +73,7 @@ class delete_key extends XMLDBAction {
// If not confirmed, show confirmation box
if (!$confirmed) {
$o = '<table width="60" class="generaltable" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o = '<table width="60" class="generaltable table table-hover" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o.= ' <tr><td class="generalboxcontent">';
$o.= ' <p class="centerpara">' . $this->str['confirmdeletekey'] . '<br /><br />' . $keyparam . '</p>';
$o .= ' <table class="table-reboot w-100" cellpadding="20"><tr><td class="text-end">';
@@ -72,7 +72,7 @@ class delete_table extends XMLDBAction {
// If not confirmed, show confirmation box
if (!$confirmed) {
$o = '<table width="60" class="generaltable" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o = '<table width="60" class="generaltable table table-hover" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o.= ' <tr><td class="generalboxcontent">';
$o.= ' <p class="centerpara">' . $this->str['confirmdeletetable'] . '<br /><br />' . $tableparam . '</p>';
$o .= ' <table class="table-reboot w-100" cellpadding="20"><tr><td class="text-end">';
@@ -71,7 +71,7 @@ class delete_xml_file extends XMLDBAction {
// If not confirmed, show confirmation box
if (!$confirmed) {
$o = '<table width="60" class="generaltable" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o = '<table width="60" class="generaltable table table-hover" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o.= ' <tr><td class="generalboxcontent">';
$o.= ' <p class="centerpara">' . $this->str['confirmdeletexmlfile'] . '<br /><br />' . $dirpath . '/install.php</p>';
$o .= ' <table class="table-reboot w-100" cellpadding="20"><tr><td class="text-end">';
@@ -119,7 +119,7 @@ class main_view extends XMLDBAction {
// Display list of DB directories if everything is ok
if ($result && !empty($XMLDB->dbdirs)) {
$o .= '<table id="listdirectories" border="0" cellpadding="5" cellspacing="1"' .
' class="table-striped table-sm admintable generaltable">';
' class="table-striped table-sm admintable generaltable table table-hover">';
$row = 0;
foreach ($XMLDB->dbdirs as $key => $dbdir) {
// Detect if this is the lastused dir
@@ -90,8 +90,15 @@ class reconcile_files extends XMLDBAction {
// Generate the XML contents from the loaded structure.
$xmlcontents = $xmldb->getStructure()->xmlOutput();
$correctdom = new \DOMDocument();
$correctdom->loadXML($xmlcontents);
$correct = $correctdom->saveXML();
if ($rawcontents != $xmlcontents) {
$currentdom = new \DOMDocument();
$currentdom->loadXML($rawcontents);
$current = $currentdom->saveXML();
if ($current !== $correct) {
$relpath = str_replace($CFG->dirroot . '/', '', $key) . '/install.xml';
$needfix[] = $relpath;
// Left here on purpose, as a quick way to fix problems. To be
@@ -71,7 +71,8 @@ class revert_changes extends XMLDBAction {
// If not confirmed, show confirmation box
if (!$confirmed) {
$o = '<table width="60" class="generaltable boxaligncenter" border="0" cellpadding="5" cellspacing="0" id="notice">';
$o = '<table width="60" class="generaltable boxaligncenter table table-hover" ' .
'border="0" cellpadding="5" cellspacing="0" id="notice">';
$o.= ' <tr><td class="generalboxcontent">';
$o.= ' <p class="centerpara">' . $this->str['confirmrevertchanges'] . '<br /><br />' . $dirpath . '</p>';
$o .= ' <table class="table-reboot w-100" cellpadding="20"><tr><td class="text-end">';
+1
View File
@@ -50,6 +50,7 @@ if (!isset($SESSION->xmldb)) {
// Some previous checks
$site = get_site();
$PAGE->set_primary_active_tab('siteadminnode');
// Body of the script, based on action, we delegate the work
$action = optional_param ('action', 'main_view', PARAM_ALPHAEXT);
+6
View File
@@ -72,6 +72,12 @@ $PAGE->set_pagelayout('admin');
$PAGE->set_title($title);
$PAGE->set_heading($title);
// Explode if there are no provider plugins installed.
$plugins = core_plugin_manager::instance()->get_plugins_of_type('aiprovider');
if (empty($plugins)) {
throw new moodle_exception('noproviderplugins', 'core_ai');
}
// Provider instance form processing.
$mform = new \core_ai\form\ai_provider_form(customdata: $data);
if ($mform->is_cancelled()) {
@@ -92,10 +92,11 @@ class explain_text extends external_api {
// Send the action to the AI manager.
$manager = \core\di::get(\core_ai\manager::class);
$response = $manager->process_action($action);
$generatedcontent = $response->get_response_data()['generatedcontent'] ?? '';
// Return the response.
return [
'success' => $response->get_success(),
'generatedcontent' => $response->get_response_data()['generatedcontent'] ?? '',
'generatedcontent' => \core_external\util::format_text($generatedcontent, FORMAT_PLAIN, $contextid)[0],
'finishreason' => $response->get_response_data()['finishreason'] ?? '',
'errorcode' => $response->get_errorcode(),
'error' => $response->get_errormessage(),
@@ -92,10 +92,11 @@ class summarise_text extends external_api {
// Send the action to the AI manager.
$manager = \core\di::get(\core_ai\manager::class);
$response = $manager->process_action($action);
$generatedcontent = $response->get_response_data()['generatedcontent'] ?? '';
// Return the response.
return [
'success' => $response->get_success(),
'generatedcontent' => $response->get_response_data()['generatedcontent'] ?? '',
'generatedcontent' => \core_external\util::format_text($generatedcontent, FORMAT_PLAIN, $contextid)[0],
'finishreason' => $response->get_response_data()['finishreason'] ?? '',
'errorcode' => $response->get_errorcode(),
'error' => $response->get_errormessage(),
+8
View File
@@ -40,15 +40,23 @@ Feature: An administrator can manage AI subsystem settings
And I navigate to "AI > AI providers" in site administration
And I should see "OpenAI API test"
And I should see "Azure AI API test"
And I hover "Enable OpenAI API test" "field"
And "Enable OpenAI API test" "text" should be visible
And I toggle the "Enable OpenAI API test" admin switch "on"
And I should see "OpenAI API test enabled."
And I hover "Enable Azure AI API test" "field"
And "Enable Azure AI API test" "text" should be visible
And I toggle the "Enable Azure AI API test" admin switch "on"
And I should see "Azure AI API test enabled."
And I reload the page
And I should see "Disable OpenAI API test"
And I should see "Disable Azure AI API test"
And I hover "Disable OpenAI API test" "field"
And "Disable OpenAI API test" "text" should be visible
And I toggle the "Disable OpenAI API test" admin switch "off"
And I should see "OpenAI API test disabled."
And I hover "Disable Azure AI API test" "field"
And "Disable Azure AI API test" "text" should be visible
And I toggle the "Disable Azure AI API test" admin switch "off"
Then I should see "Azure AI API test disabled."
@@ -53,6 +53,7 @@ abstract class by_course extends base {
if (!$recordset->valid()) {
$this->add_log(get_string('nocourses', 'analytics'));
$recordset->close();
return new \ArrayIterator([]);
}
+1 -34
View File
@@ -54,7 +54,7 @@ final class model_test extends \advanced_testcase {
public function setUp(): void {
parent::setUp();
$this->resetAfterTest();
$this->setAdminUser();
$target = \core_analytics\manager::get_target('test_target_shortname');
@@ -68,8 +68,6 @@ final class model_test extends \advanced_testcase {
}
public function test_enable(): void {
$this->resetAfterTest(true);
$this->assertEquals(0, $this->model->get_model_obj()->enabled);
$this->assertEquals(0, $this->model->get_model_obj()->trained);
$this->assertEquals('', $this->model->get_model_obj()->timesplitting);
@@ -81,8 +79,6 @@ final class model_test extends \advanced_testcase {
}
public function test_create(): void {
$this->resetAfterTest(true);
$target = \core_analytics\manager::get_target('\core_course\analytics\target\course_dropout');
$indicators = array(
\core_analytics\manager::get_indicator('\core\analytics\indicator\any_write_action'),
@@ -194,7 +190,6 @@ final class model_test extends \advanced_testcase {
*/
public function test_clear_static(): void {
global $DB;
$this->resetAfterTest();
$statictarget = new \test_static_target_shortname();
$indicators['test_indicator_max'] = \core_analytics\manager::get_indicator('test_indicator_max');
@@ -211,8 +206,6 @@ final class model_test extends \advanced_testcase {
}
public function test_model_manager(): void {
$this->resetAfterTest(true);
$this->assertCount(3, $this->model->get_indicators());
$this->assertInstanceOf('\core_analytics\local\target\binary', $this->model->get_target());
@@ -225,8 +218,6 @@ final class model_test extends \advanced_testcase {
}
public function test_output_dir(): void {
$this->resetAfterTest(true);
$dir = make_request_directory();
set_config('modeloutputdir', $dir, 'analytics');
@@ -237,9 +228,6 @@ final class model_test extends \advanced_testcase {
public function test_unique_id(): void {
global $DB;
$this->resetAfterTest(true);
$originaluniqueid = $this->model->get_unique_id();
// Same id across instances.
@@ -283,8 +271,6 @@ final class model_test extends \advanced_testcase {
* @return void
*/
public function test_exists(): void {
$this->resetAfterTest(true);
$target = \core_analytics\manager::get_target('\core_course\analytics\target\no_teaching');
$this->assertTrue(\core_analytics\model::exists($target));
@@ -302,9 +288,6 @@ final class model_test extends \advanced_testcase {
*/
public function test_model_timelimit(): void {
global $DB;
$this->resetAfterTest(true);
set_config('modeltimelimit', 2, 'analytics');
$courses = array();
@@ -365,8 +348,6 @@ final class model_test extends \advanced_testcase {
* Test model_config::get_class_component.
*/
public function test_model_config_get_class_component(): void {
$this->resetAfterTest(true);
$this->assertEquals('core',
\core_analytics\model_config::get_class_component('\\core\\analytics\\indicator\\read_actions'));
$this->assertEquals('core',
@@ -387,8 +368,6 @@ final class model_test extends \advanced_testcase {
$this->markTestSkipped('mlbackend_python is not configured.');
}
$this->resetAfterTest(true);
$this->model->enable('\\core\\analytics\\time_splitting\\quarters');
$zipfilepath = $this->model->export_model('yeah-config.zip');
@@ -408,8 +387,6 @@ final class model_test extends \advanced_testcase {
* Test can export configuration
*/
public function test_can_export_configuration(): void {
$this->resetAfterTest(true);
// No time splitting method.
$this->assertFalse($this->model->can_export_configuration());
@@ -433,8 +410,6 @@ final class model_test extends \advanced_testcase {
$this->markTestSkipped('mlbackend_python is not configured.');
}
$this->resetAfterTest(true);
$this->model->enable('\\core\\analytics\\time_splitting\\quarters');
$modelconfig = new \core_analytics\model_config($this->model);
@@ -463,8 +438,6 @@ final class model_test extends \advanced_testcase {
public function test_inplace_editable_name(): void {
global $PAGE;
$this->resetAfterTest();
$output = new \core_renderer($PAGE, RENDERER_TARGET_GENERAL);
// Check as a user with permission to edit the name.
@@ -489,8 +462,6 @@ final class model_test extends \advanced_testcase {
public function test_get_name_and_rename(): void {
global $PAGE;
$this->resetAfterTest();
$output = new \core_renderer($PAGE, RENDERER_TARGET_GENERAL);
// By default, the model exported for template uses its target's name in the name inplace editable element.
@@ -518,8 +489,6 @@ final class model_test extends \advanced_testcase {
* Tests model::get_potential_timesplittings()
*/
public function test_potential_timesplittings(): void {
$this->resetAfterTest();
$this->assertArrayNotHasKey('\core\analytics\time_splitting\no_splitting', $this->model->get_potential_timesplittings());
$this->assertArrayHasKey('\core\analytics\time_splitting\single_range', $this->model->get_potential_timesplittings());
$this->assertArrayHasKey('\core\analytics\time_splitting\quarters', $this->model->get_potential_timesplittings());
@@ -531,8 +500,6 @@ final class model_test extends \advanced_testcase {
* @return null
*/
public function test_get_samples(): void {
$this->resetAfterTest();
if (!PHPUNIT_LONGTEST) {
$this->markTestSkipped('PHPUNIT_LONGTEST is not defined');
}
+1 -8
View File
@@ -39,7 +39,7 @@ final class stats_test extends \advanced_testcase {
*/
public function setUp(): void {
parent::setUp();
$this->resetAfterTest();
$this->setAdminUser();
}
@@ -47,9 +47,6 @@ final class stats_test extends \advanced_testcase {
* Test the {@link \core_analytics\stats::enabled_models()} implementation.
*/
public function test_enabled_models(): void {
$this->resetAfterTest(true);
// By default, sites have {@link \core_course\analytics\target\no_teaching} and
// {@link \core_user\analytics\target\upcoming_activities_due} enabled.
$this->assertEquals(4, \core_analytics\stats::enabled_models());
@@ -77,8 +74,6 @@ final class stats_test extends \advanced_testcase {
$this->markTestSkipped('mlbackend_python is not configured.');
}
$this->resetAfterTest(true);
$model = \core_analytics\model::create(
\core_analytics\manager::get_target('test_target_shortname'),
[
@@ -127,8 +122,6 @@ final class stats_test extends \advanced_testcase {
$this->markTestSkipped('mlbackend_python is not configured.');
}
$this->resetAfterTest(true);
$model = \core_analytics\model::create(
\core_analytics\manager::get_target('test_target_shortname'),
[
+13 -6
View File
@@ -370,7 +370,7 @@ class core_auth_external extends external_api {
* @throws moodle_exception
*/
public static function resend_confirmation_email($username, $password, $redirect = '') {
global $PAGE;
global $PAGE, $CFG;
$warnings = array();
$params = self::validate_parameters(
@@ -387,20 +387,27 @@ class core_auth_external extends external_api {
$username = trim(core_text::strtolower($params['username']));
$password = $params['password'];
$user = core_user::get_user_by_username($username);
if (!empty($user) && $user->confirmed) {
if (!empty($CFG->protectusernames)) {
throw new moodle_exception('invalidlogin');
}
throw new moodle_exception('alreadyconfirmed');
}
if (is_restored_user($username)) {
if (!empty($CFG->protectusernames)) {
throw new moodle_exception('invalidlogin');
}
throw new moodle_exception('restoredaccountresetpassword', 'webservice');
}
$user = authenticate_user_login($username, $password);
if (empty($user)) {
throw new moodle_exception('invalidlogin');
}
if ($user->confirmed) {
throw new moodle_exception('alreadyconfirmed');
}
// Check if we should redirect the user once the user is confirmed.
$confirmationurl = null;
if (!empty($params['redirect'])) {
+1 -11
View File
@@ -14,18 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Sync users task
* @package auth_db
* @author Guy Thomas <gthomas@moodlerooms.com>
* @copyright Copyright (c) 2017 Blackboard Inc.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_db\task;
defined('MOODLE_INTERNAL') || die();
/**
* Sync users task class
* @package auth_db
@@ -49,7 +39,7 @@ class sync_users extends \core\task\scheduled_task {
*/
public function execute() {
if (!is_enabled_auth('db')) {
mtrace('auth_db plugin is disabled, synchronisation stopped', 2);
mtrace('auth_db plugin is disabled, synchronisation stopped');
return;
}
+14
View File
@@ -104,6 +104,7 @@ class auth_plugin_lti extends \auth_plugin_base {
* @param int $provisioningmode the desired account provisioning mode, which controls the auth flow for unbound users.
* @param array $legacyconsumersecrets an array of secrets used by the legacy consumer if a migration claim exists.
* @throws coding_exception if the specified provisioning mode is invalid.
* @throws \core\exception\moodle_exception if user authentication fails.
*/
public function complete_login(array $launchdata, moodle_url $returnurl, int $provisioningmode,
array $legacyconsumersecrets = []): void {
@@ -112,6 +113,19 @@ class auth_plugin_lti extends \auth_plugin_base {
if ($this->get_user_binding($launchdata['iss'], $launchdata['sub'])) {
$user = $this->find_or_create_user_from_launch($launchdata);
if ($user->suspended) {
$failurereason = AUTH_LOGIN_SUSPENDED;
$event = \core\event\user_login_failed::create([
'userid' => $user->id,
'other' => [
'username' => $user->username,
'reason' => $failurereason
]
]);
$event->trigger();
throw new \core\exception\moodle_exception('invalidlogin', 'core');
}
if (isloggedin()) {
// If a different user is currently logged in, authenticate the linked user instead.
global $USER;
+2 -6
View File
@@ -197,9 +197,7 @@ class api {
$data->link = $confirmationurl->out(false);
$message = get_string('confirmlinkedloginemail', 'auth_oauth2', $data);
$data->link = $confirmationurl->out();
$messagehtml = text_to_html(get_string('confirmlinkedloginemail', 'auth_oauth2', $data), false, false, true);
$messagehtml = text_to_html(get_string('confirmlinkedloginemail', 'auth_oauth2', $data), false, false);
$user->mailformat = 1; // Always send HTML version as well.
@@ -339,9 +337,7 @@ class api {
$data->link = $confirmationurl->out(false);
$message = get_string('confirmaccountemail', 'auth_oauth2', $data);
$data->link = $confirmationurl->out();
$messagehtml = text_to_html(get_string('confirmaccountemail', 'auth_oauth2', $data), false, false, true);
$messagehtml = text_to_html(get_string('confirmaccountemail', 'auth_oauth2', $data), false, false);
$user->mailformat = 1; // Always send HTML version as well.
+53 -19
View File
@@ -34,9 +34,11 @@ use stdClass;
use core\oauth2\issuer;
use core\oauth2\client;
global $CFG;
require_once($CFG->libdir.'/authlib.php');
require_once($CFG->dirroot.'/user/lib.php');
require_once($CFG->dirroot.'/user/profile/lib.php');
require_once($CFG->dirroot.'/login/lib.php');
/**
* Plugin for oauth2 authentication.
@@ -175,12 +177,12 @@ class auth extends \auth_plugin_base {
public function loginpage_idp_list($wantsurl) {
$providers = \core\oauth2\api::get_all_issuers(true);
$result = [];
if (empty($wantsurl)) {
$wantsurl = '/';
}
foreach ($providers as $idp) {
if ($idp->is_available_for_login()) {
$params = ['id' => $idp->get('id'), 'wantsurl' => $wantsurl, 'sesskey' => sesskey()];
$params = ['id' => $idp->get('id'), 'sesskey' => sesskey()];
if (!empty($wantsurl)) {
$params['wantsurl'] = $wantsurl;
}
$url = new moodle_url('/auth/oauth2/login.php', $params);
$icon = $idp->get('image');
$result[] = ['url' => $url, 'iconurl' => $icon, 'name' => $idp->get_display_name()];
@@ -465,18 +467,31 @@ class auth extends \auth_plugin_base {
$mappeduser = get_complete_user_data('id', $linkedlogin->get('userid'));
if ($mappeduser && $mappeduser->suspended) {
$failurereason = AUTH_LOGIN_SUSPENDED;
$event = \core\event\user_login_failed::create([
'userid' => $mappeduser->id,
'other' => [
'username' => $userinfo['username'],
'reason' => $failurereason
]
]);
$event->trigger();
$SESSION->loginerrormsg = get_string('invalidlogin');
$client->log_out();
redirect(new moodle_url('/login/index.php'));
// Check if there's another user with the same email that is not suspended.
$moodleuser = \core_user::get_user_by_email($userinfo['email'], '*', null, IGNORE_MULTIPLE);
if ($moodleuser->id == $mappeduser->id) {
$failurereason = AUTH_LOGIN_SUSPENDED;
$event = \core\event\user_login_failed::create([
'userid' => $mappeduser->id,
'other' => [
'username' => $userinfo['username'],
'reason' => $failurereason,
],
]);
$event->trigger();
$SESSION->loginerrormsg = get_string('invalidlogin');
$client->log_out();
redirect(new moodle_url('/login/index.php'));
} else if ($moodleuser && !$moodleuser->suspended) {
// Update the OAuth2 linked login to point to the active user account.
$linkedlogin->set('userid', $moodleuser->id);
$linkedlogin->set('timemodified', time());
$linkedlogin->update();
// Update user fields and continue with login.
$userinfo = $this->update_user($userinfo, $moodleuser);
$userwasmapped = true;
}
} else if ($mappeduser && ($mappeduser->confirmed || !$issuer->get('requireconfirmation'))) {
// Update user fields.
$userinfo = $this->update_user($userinfo, $mappeduser);
@@ -506,7 +521,6 @@ class auth extends \auth_plugin_base {
redirect(new moodle_url('/login/index.php'));
}
if (!$issuer->is_valid_login_domain($oauthemail)) {
// Trigger login failed event.
$failurereason = AUTH_LOGIN_UNAUTHORISED;
@@ -522,8 +536,24 @@ class auth extends \auth_plugin_base {
if (!$userwasmapped) {
// No defined mapping - we need to see if there is an existing account with the same email.
$moodleuser = \core_user::get_user_by_email($userinfo['email'], '*', null, IGNORE_MULTIPLE);
// Ensure we don't link a login for a suspended user.
if (!empty($moodleuser) && $moodleuser->suspended) {
$failurereason = AUTH_LOGIN_SUSPENDED;
$event = \core\event\user_login_failed::create([
'userid' => $moodleuser->id,
'other' => [
'username' => $userinfo['email'],
'reason' => $failurereason,
],
]);
$event->trigger();
$SESSION->loginerrormsg = get_string('invalidlogin');
$client->log_out();
redirect(new moodle_url('/login/index.php'));
}
$moodleuser = \core_user::get_user_by_email($userinfo['email']);
if (!empty($moodleuser)) {
if ($issuer->get('requireconfirmation')) {
$PAGE->set_url('/auth/oauth2/confirm-link-login.php');
@@ -620,7 +650,11 @@ class auth extends \auth_plugin_base {
complete_user_login($user, $this->get_extrauserinfo());
$this->update_picture($user);
redirect($redirecturl);
if (empty($redirecturl)) {
$redirecturl = core_login_get_return_url();
}
redirect(new moodle_url($redirecturl));
}
/**
+1 -1
View File
@@ -55,7 +55,7 @@ class renderer extends plugin_renderer_base {
get_string('info', 'auth_oauth2'),
get_string('edit'),
];
$table->attributes['class'] = 'admintable generaltable';
$table->attributes['class'] = 'admintable generaltable table table-hover';
$data = [];
$index = 0;
+7 -16
View File
@@ -27,19 +27,14 @@ $string['auth_oauth2description'] = 'OAuth 2 standards based authentication';
$string['auth_oauth2settings'] = 'OAuth 2 authentication settings.';
$string['confirmaccountemail'] = 'Hi {$a->firstname},
A new account has been requested at \'{$a->sitename}\'
using your email address.
A new account has been requested at \'{$a->sitename}\' using your email address.
To confirm your new account, please go to this web address:
To confirm your new account, please click the link below:
{$a->link}
<a href="{$a->link}">Confirm your account</a>
In most mail programs, this should appear as a blue link
which you can just click on. If that doesn\'t work,
then cut and paste the address into the address
line at the top of your web browser window.
If you need help, please contact the site administrator,
If you need help, please contact the site administrator.
{$a->admin}
If you did not do this, someone else could be trying to compromise your account.
@@ -53,16 +48,12 @@ A request has been made to link the {$a->issuername} login
{$a->linkedemail} to your account at \'{$a->sitename}\'
using your email address.
To confirm this request and link these logins, please go to this web address:
To confirm this request and link these logins, please click the link below:
{$a->link}
<a href="{$a->link}">Link your accounts</a>
In most mail programs, this should appear as a blue link
which you can just click on. If that doesn\'t work,
then cut and paste the address into the address
line at the top of your web browser window.
If you need help, please contact the site administrator,
If you need help, please contact the site administrator.
{$a->admin}
If you did not do this, someone else could be trying to compromise your account.
+1 -1
View File
@@ -25,7 +25,7 @@
require_once('../../config.php');
$issuerid = required_param('id', PARAM_INT);
$wantsurl = new moodle_url(optional_param('wantsurl', '', PARAM_URL));
$wantsurl = optional_param('wantsurl', '', PARAM_LOCALURL);
$PAGE->set_context(context_system::instance());
$PAGE->set_url(new moodle_url('/auth/oauth2/login.php', ['id' => $issuerid]));
+3 -1
View File
@@ -96,13 +96,15 @@ Feature: Test if the login form provides the correct feedback
And I follow "Log in"
Then the focused element is "Password" "field"
@accessibility
Scenario: Test the login page focus after error feature
Given I follow "Log in"
And I set the field "Username" to "admin"
And I set the field "Password" to "wrongpassword"
And I press "Log in"
And I press the tab key
And I wait until the page is ready
Then the focused element is "Username" "field"
And the page should meet accessibility standards with "best-practice" extra tests
Scenario: Display the password visibility toggle icon
Given the following config values are set as admin:
+9
View File
@@ -182,6 +182,7 @@ final class external_test extends externallib_advanced_testcase {
$this->assertTrue($result['success']);
$this->assertEmpty($result['warnings']);
set_config('protectusernames', 0);
$_SERVER['HTTP_USER_AGENT'] = 'no browser'; // Hack around missing user agent in CLI scripts.
$this->expectException('\moodle_exception');
$this->expectExceptionMessage('error/invalidlogin');
@@ -205,6 +206,7 @@ final class external_test extends externallib_advanced_testcase {
$this->assertTrue($result['success']);
$this->assertEmpty($result['warnings']);
set_config('protectusernames', 0);
$_SERVER['HTTP_USER_AGENT'] = 'no browser'; // Hack around missing user agent in CLI scripts.
$this->expectException('\moodle_exception');
$this->expectExceptionMessage('error/invalidlogin');
@@ -235,6 +237,13 @@ final class external_test extends externallib_advanced_testcase {
$result = external_api::clean_returnvalue(core_auth_external::confirm_user_returns(), $result);
$this->assertTrue($result['success']);
// Keep protectusernames enabled so the call returns invalidlogin exception.
$this->expectException('\moodle_exception');
$this->expectExceptionMessage('error/invalidlogin');
core_auth_external::resend_confirmation_email($username, $password);
// Now disable protectusernames and expect an exception.
set_config('protectusernames', 0);
$this->expectException('\moodle_exception');
$this->expectExceptionMessage('error/alreadyconfirmed');
core_auth_external::resend_confirmation_email($username, $password);
+5 -1
View File
@@ -746,7 +746,11 @@ abstract class info {
$modulename = format_string($cm->get_name(), true, ['context' => $context]);
// We make sure that we add a data attribute to the name so we can change it later if the
// original module name changes.
if ($cm->has_view() && $cm->get_user_visible()) {
if (
\course_modinfo::is_mod_type_visible_on_course($cm->modname)
&& $cm->has_view()
&& $cm->get_user_visible()
) {
// Help student by providing a link to the module which is preventing availability.
return \html_writer::link($cm->get_url(), $modulename, ['data-cm-name-for' => $cm->id]);
} else {
@@ -32,7 +32,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I click on "Item name displayed with access restriction information if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save and return to course"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -58,7 +58,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I click on "Item name displayed with access restriction information if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save and return to course"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -83,7 +83,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I click on "Item name displayed with access restriction information if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save and return to course"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -112,7 +112,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I click on "Item name displayed with access restriction information if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save changes"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -138,7 +138,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I click on "Item name displayed with access restriction information if student doesn't meet this condition Click to hide" "link"
Then the "Activity or resource" select box should not contain "Previous activity with completion"
# Set Page2 restriction to Previous Activity with completion and delete Page1.
@@ -148,7 +148,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I click on "Item name displayed with access restriction information if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save and return to course"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -170,7 +170,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I click on "Item name displayed with access restriction information if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save changes"
Then I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -184,7 +184,7 @@ Feature: Confirm that availability_completion works with previous activity setti
And I expand all fieldsets
And I click on "Add restriction..." "button"
And I click on "Activity completion" "button" in the "Add restriction..." "dialogue"
And I click on "Displayed if student doesn't meet this condition Click to hide" "link"
And I click on "Item name displayed with access restriction information if student doesn't meet this condition Click to hide" "link"
And I set the field "Activity or resource" to "Previous activity with completion"
And I press "Save changes"
And I should see "Not available unless: The previous activity with completion" in the "region-main" "region"
@@ -180,4 +180,4 @@ Feature: Display availability for activities and sections
And I should not see "Date" in the "Restrict access" "fieldset"
And I press "Add restriction..."
And I click on "Grade" "button" in the "Add restriction..." "dialogue"
And the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Displayed if student"
And the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Item name displayed"
@@ -89,13 +89,13 @@ Feature: edit_availability
And I should see "Date" in the "Restrict access" "fieldset"
And ".availability-item .availability-eye img" "css_element" should be visible
And ".availability-item .availability-delete img" "css_element" should be visible
And the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Displayed if student"
And the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Item name displayed"
# Toggle the eye icon.
When I click on ".availability-item .availability-eye img" "css_element"
Then the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Hidden entirely"
When I click on ".availability-item .availability-eye img" "css_element"
Then the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Displayed if student"
Then the "alt" attribute of ".availability-item .availability-eye img" "css_element" should contain "Item name displayed"
# Click the delete button.
When I click on ".availability-item .availability-delete img" "css_element"
+10 -3
View File
@@ -310,7 +310,10 @@ trait backup_question_set_reference_trait {
foreach ($setreferenceconditions as $setreferencecondition) {
$conditions = json_decode($setreferencecondition, true);
$conditions = question_reference_manager::convert_legacy_set_reference_filter_condition($conditions);
$setreferencequestionids += array_keys($randomloader->get_filtered_questions($conditions['filter'], 0));
$setreferencequestionids = array_merge(
$setreferencequestionids,
array_keys($randomloader->get_filtered_questions($conditions['filter'], 0)),
);
}
if (empty($setreferencequestionids)) {
return;
@@ -2642,6 +2645,7 @@ class backup_questions_structure_step extends backup_structure_step {
'questioncategoryid',
'idnumber',
'ownerid',
'nextversion',
]);
$questionversions = new backup_nested_element('question_version');
@@ -2718,7 +2722,7 @@ class backup_questions_structure_step extends backup_structure_step {
WHERE bi.backupid = ?
AND bi.itemname = 'question_categoryfinal'", [backup::VAR_BACKUPID]);
// Add all question bank entries from "complete" categories, plus annotated question bank entires
// Add all question bank entries from "complete" categories, plus annotated question bank entires and their children
// from "partial" categories.
$questionbankentry->set_source_sql(
"
@@ -2730,8 +2734,11 @@ class backup_questions_structure_step extends backup_structure_step {
UNION
SELECT qbe.*
FROM {question_bank_entries} qbe
JOIN {question_versions} qv ON qv.questionbankentryid = qbe.id
JOIN {question} q ON q.id = qv.questionid
LEFT JOIN {question_versions} parentqv ON parentqv.questionid = q.parent
JOIN {question_category_partial_temp} qcp ON qcp.itemid = qbe.questioncategoryid
JOIN {backup_ids_temp} biq ON biq.itemid = qbe.id
JOIN {backup_ids_temp} biq ON biq.itemid = qbe.id OR biq.itemid = parentqv.questionbankentryid
WHERE qcp.itemid = ?
AND qcp.backupid = ?
AND biq.backupid = ?
+48 -14
View File
@@ -568,8 +568,7 @@ abstract class restore_qtype_plugin extends restore_plugin {
foreach ($excludefields as $excludefield) {
$pathparts = explode('/', ltrim($excludefield, '/'));
$data = $questiondata;
self::unset_excluded_fields($data, $pathparts);
$questiondata = self::unset_excluded_fields($questiondata, $pathparts);
}
return $questiondata;
@@ -581,25 +580,60 @@ abstract class restore_qtype_plugin extends restore_plugin {
* If any of the elements in the path is an array, this is called recursively on each element in the array to unset fields
* in each child of the array.
*
* @param stdClass|array $data The questiondata object, or a subsection of it.
* @param stdClass|array $data The questiondata structure, or a subsection of it.
* @param array $pathparts The remaining elements in the path to the excluded field.
* @return void
* @return stdClass|array The $data structure with excluded fields removed.
*/
private static function unset_excluded_fields(stdClass|array $data, array $pathparts): void {
private static function unset_excluded_fields(stdClass|array $data, array $pathparts): stdClass|array {
$element = array_shift($pathparts);
if (!isset($data->{$element})) {
// This element is not present in the data structure, nothing to unset.
return;
$unset = false;
// Get the current element from the data structure.
if (is_object($data)) {
if (!property_exists($data, $element)) {
// This element is not present in the data structure, nothing to unset.
return $data;
}
$dataelement = $data->{$element};
} else { // It's an array.
if (!array_key_exists($element, $data)) {
return $data;
}
$dataelement = $data[$element];
}
if (is_object($data->{$element})) {
self::unset_excluded_fields($data->{$element}, $pathparts);
} else if (is_array($data->{$element})) {
foreach ($data->{$element} as $item) {
self::unset_excluded_fields($item, $pathparts);
// Check if we need to recur, or unset this element.
if (is_object($dataelement)) {
$dataelement = self::unset_excluded_fields($dataelement, $pathparts);
} else if (is_array($dataelement)) {
foreach ($dataelement as $key => $item) {
if (is_object($item) || is_array($item)) {
// This is an array of objects or arrays, recur.
$dataelement[$key] = self::unset_excluded_fields($item, $pathparts);
} else {
// This is an associative array of values, check if they should be removed.
$subelement = reset($pathparts);
if ($key == $subelement) {
unset($dataelement[$key]);
}
}
}
} else if (empty($pathparts)) {
// This is the last element of the path and it's a scalar value, unset it.
unset($data->{$element});
$unset = true;
}
// Write the modified element back to the data structure, or unset it.
if (is_object($data)) {
if ($unset) {
unset($data->{$element});
} else {
$data->{$element} = $dataelement;
}
} else {
if ($unset) {
unset($data[$element]);
} else {
$data[$element] = $dataelement;
}
}
return $data;
}
}

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