Compare commits

..

775 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) ec58cefefb Moodle release 3.10 2020-11-07 17:24:12 +01:00
Eloy Lafuente (stronk7) e4cda88e76 Moodle release 3.10rc2 2020-11-06 22:56:08 +01:00
Víctor Déniz 8752df87ed Merge branch 'MDL-70137-310-2' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-11-06 19:16:52 +00:00
Andrew Nicols 511dab1cd3 MDL-70137 cache: Write config to temp file and move into place 2020-11-06 19:16:51 +00:00
Andrew Nicols b26a5e5e08 MDL-70137 cache: Use sensible default when reading MUC config
When we read the MUC configuration, a file which exists but is empty
will not error, but will cause all configuration to be empty.

We already perform an {{is_array()}} check on the {{$configuration}}
variable, but the default value for {{$configuration}} is an empty
array. In the case where the file exists, but is empty, no errors occur
when the file is loaded, and the initial {{$configuration}} value is
not overwritten, leading to the file being replaced with an empty copy.
2020-11-06 19:16:44 +00:00
Eloy Lafuente (stronk7) fcb699808c Merge branch 'MDL-70143-310' of git://github.com/marinaglancy/moodle into MOODLE_310_STABLE 2020-11-06 19:51:54 +01:00
Eloy Lafuente (stronk7) f9dc16ca05 Merge branch 'MDL-70139-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE 2020-11-06 18:56:00 +01:00
Marina Glancy a350376b65 MDL-70143 tool_uploaduser: fix wrong cache reference 2020-11-06 18:07:24 +01:00
Sara Arjona 29f7a9a210 MDL-70139 core_badges: fix invalid request when sending to backpack
Having mixed $data in badge exporters is causing some issues.
As all these exporters are using $data as an object, $data can be
converted to object in the constructor, to avoid errors and get
the expected behaviour always.
2020-11-06 16:36:52 +01:00
Jun Pataleta 022a019637 Merge branch 'MDL-70130-310' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-11-06 11:27:54 +08:00
Andrew Nicols 50f5563c1f MDL-70130 core: Compare realpaths for file attachment checks
Rather than using the provided path, the `realpath` must be used to
ensure that the use of symlinks in paths is normalised.
2020-11-06 11:00:30 +08:00
Andrew Nicols 1c0b8f8c50 MDL-70130 core: Simplify attachment handling in email_to_suer 2020-11-06 11:00:29 +08:00
Marina Glancy c879cb24df MDL-70130 core: allow to attach files from localrequestdir to emails
Co-authored-by: Paul Holden <paulh@moodle.com>
2020-11-06 11:00:29 +08:00
Andrew Nicols 6890ad18e3 Merge branch 'MDL-70131-310' of git://github.com/marinaglancy/moodle into MOODLE_310_STABLE 2020-11-06 09:27:33 +08:00
Andrew Nicols b88679e3a1 Merge branch 'MDL-70120-assign-stamp-expires-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-11-06 09:26:01 +08:00
Marina Glancy 8c1917588d MDL-70131 cli: only allow to negate existing keys 2020-11-05 18:10:13 +01:00
Eloy Lafuente (stronk7) c50c904c9e Moodle release 3.10rc1 2020-11-05 12:16:53 +01:00
Jun Pataleta 9023021ae0 Merge branch 'MDL-70075-310-2' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-11-05 12:51:23 +08:00
Andrew Nicols 919ead58fe Merge branch 'MDL-70066-310' of git://github.com/lameze/moodle into MOODLE_310_STABLE 2020-11-05 10:01:18 +08:00
Andrew Nicols 27de77007b MDL-70075 core: Autocomplete selection should always have an active item
Ensure that there is always one active element in the list of selected
autocomplete elements.

Without this we have issues beacuse clicking on the link makes the first
one active if one is not already active, and this turns a click event
into a drag event, which means that it is not deleted.
2020-11-05 09:05:38 +08:00
Andrew Nicols 34d1c23668 MDL-70075 core: Do not return a value in an event handler
Returning a value of `false` in an event handler has the effect of
calling event.preventDefault() and event.stopPropagation().

This is neither obvious, nor desirable in this situation.
2020-11-05 09:05:38 +08:00
Andrew Nicols dc7ca062ca MDL-70075 core: jQuery.attr() does not accept a bool value
The documented values that jQuery.attr() accepts are String, Number, or
null. For some reason, when we pass a Boolean value, the subsequent
click handler does not work in some situations.

Changing this to take a Number, and unsetting it when empty, resolves
this issue.
2020-11-05 09:05:38 +08:00
Andrew Nicols 8100d46f85 MDL-70075 core: Listen for change in accessibleChange event
The accessibleChange custom interaction event was only listening for
blur and focus, however some OS/browser combinations do not emit these
events until the element is explicitly blurred. This is notably
different on Firefox on some Operating Systems.

Recent changes in MDL-68167 explicitly moved the user participants page
filter module to use the accessibleChange event, which means that the
selections are now only triggered on an explicit blur when using
Firefox. This highlight a bug whereby, when the mouse is used to make a
selection, the event is not triggered until the element is blurred.

This change modifies the accessibleChange event to ignore the `change`
event where it was triggered by the keyboard and where that keybaord
event was not a [return] or [escape] keypress, but to otherwise respect
the native change event.
2020-11-05 09:05:38 +08:00
Andrew Nicols f4dfe66ea8 MDL-70075 core: Listen for the focus and blur events again
The `blur` event does not bubble, but the `focusout` events are not
available in all supported versions of Firefox.

Rather than switching event, this patch using event capture to
effectively achieve the same result and bubble the event up through the
DOM to the delegated listener.

There should be no functional change with this patch, except to support
Firefox fully.
2020-11-05 09:05:38 +08:00
Eloy Lafuente (stronk7) e92c6b19b8 Merge branch 'MDL-70100-310' of git://github.com/bmbrands/moodle into MOODLE_310_STABLE 2020-11-04 22:40:54 +01:00
Víctor Déniz fa79a1876c Merge branch 'MDL-70112_310' of https://github.com/timhunt/moodle into MOODLE_310_STABLE 2020-11-04 19:17:34 +00:00
Sara Arjona c9ab02b0cc Merge branch 'MDL-70114-310' of git://github.com/bmbrands/moodle into MOODLE_310_STABLE 2020-11-04 20:15:04 +01:00
Víctor Déniz 9c2241dee4 Merge branch 'MDL-68749-310-2' of git://github.com/mickhawkins/moodle into MOODLE_310_STABLE 2020-11-04 15:24:08 +00:00
Sara Arjona 8028bf10dc Merge branch 'MDL-70119-310' of git://github.com/ferranrecio/moodle into MOODLE_310_STABLE 2020-11-04 15:19:44 +01:00
Bas Brands 04704c2108 MDL-70114 mod_data: add border for to textarea 2020-11-04 13:30:11 +00:00
Brendan Heywood fbe13d55f3 MDL-70120 assignfeedback_editpdf: Stamp files should be cached 2020-11-04 23:06:02 +11:00
Ferran Recio 75d6582fef MDL-70119 core_badges: fix tab names 2020-11-04 12:57:30 +01:00
Simey Lameze 7ca4fd97d9 MDL-70066 badges: change usages of array_key_exists to isset 2020-11-04 16:05:45 +08:00
Jun Pataleta 940ed72017 Merge branch 'MDL-70089_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-11-04 13:05:47 +08:00
Jake Dallimore 477cd8b5fe Merge branch 'MOODLE_310_MDL-70093' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-11-04 09:00:26 +08:00
Tim Hunt a8efb07714 MDL-70112 drag-drop qtypes: fix form preview 2020-11-03 21:36:00 +00:00
Eloy Lafuente (stronk7) 51c9ea5194 MDL-70089 versions: main version bump 2020-11-03 19:38:27 +01:00
Eloy Lafuente (stronk7) b0a1b4ce8b MDL-70089 versions: bump all versions and requires near release
version = 2020110900 release version
requires= 2020110300 current beta+ (week6roll1) version

Note that, because we are under parallel development period,
this is being done in the branch that is going to be released
(MOODLE_310_STABLE already existing) for Moodle 3.10.0 and
not in master, that is the one getting the bump under normal
(non-parallel) periods.
2020-11-03 19:34:52 +01:00
Mihail Geshoski 3d9175f6f1 MDL-67837 backup: Add unit tests 2020-11-03 12:34:28 +01:00
Mihail Geshoski fd2427746f MDL-67837 backup: Verify caps before unenrolling users on course restore 2020-11-03 12:34:28 +01:00
andreasschenkel 49afa008f4 MDL-69844 user: Fix no email in download_participants_table
Only include eMail in download_participants_table 
if selected in showuseridentity 
($identityfieldsselect)
2020-11-03 12:34:28 +01:00
Juan Leyva 551892e2a7 MDL-67015 mod_data: Prevent users adding entries to other groups 2020-11-03 12:34:28 +01:00
Amaia Anabitarte 45c339ef09 MDL-69046 core_contentbank: Escape quotes when showing name 2020-11-03 12:34:28 +01:00
Ferran Recio e9fe9f4ae3 MDL-69378 tool_uploadcourse: fix enrolment methods uploads 2020-11-03 12:34:28 +01:00
Peter Dias 1d1b148ca9 MDL-56310 restore: Confirm user has permission to change capabilities 2020-11-03 12:34:28 +01:00
Eloy Lafuente (stronk7) 15b4174a9f on-demand release 3.10beta+ 2020-11-03 12:23:48 +01:00
Bas Brands 99ab172211 MDL-70100 theme_boost: quiztimer zindex fix 2020-11-03 10:36:11 +01:00
Michael Hawkins 5cc9f3448c MDL-68749 theme: Fix bootstrap toggle switches in RTL layout
Co-authored-by: Bas Brands <bas@moodle.com>
2020-11-03 14:47:58 +08:00
Andrew Nicols 4dd870de20 Merge branch 'MDL-70059-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE 2020-11-03 12:05:19 +08:00
Jun Pataleta c353963ef8 Merge branch 'MDL-70033-310-2' of git://github.com/mickhawkins/moodle into MOODLE_310_STABLE 2020-11-03 12:01:33 +08:00
Michael Hawkins 60585523ad MDL-70033 course: Update download content event handling for Classic 2020-11-03 11:54:56 +08:00
Michael Hawkins eeaf19eb5c MDL-70033 core: Update tree.js event handlers to replace stopPropagation
Also added support to allow links to override action keys (enter/space)

Co-authored-by: Andrew Nicols <andrew@nicols.co.uk>
2020-11-03 11:54:56 +08:00
Juan Leyva 63da614e4f MDL-70081 airnotifier: Add missing device type in token registration 2020-11-03 01:25:57 +01:00
Jun Pataleta 73372330a9 Merge branch 'MDL-69975_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-11-03 00:00:25 +08:00
Sara Arjona 5f3de24306 Merge branch 'MDL-69973_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-11-02 15:44:54 +01:00
Mikhail Golenkov c15eac212b MDL-70093 dataformat_pdf: Fix row height calculation with high cells 2020-11-02 22:25:24 +11:00
Sara Arjona 01c8c8828b MDL-70059 core_badges: avoid duplicate key error
When 2 or more backpack were created without credentials,
a "Duplicate key value violates unique constraint" error
was raised because externalbackpackid was not taking the
correct value.
Other improvements have been done to the code too in order
to make it more readable.
2020-11-02 10:48:06 +01:00
Jake Dallimore 2dbe5f54f1 Merge branch 'MDL-70073-310' of git://github.com/peterRd/moodle into MOODLE_310_STABLE 2020-11-02 13:57:35 +08:00
Jun Pataleta bcf59d235b Merge branch 'MDL-70074-add-authendpoint-310' of https://github.com/cengage/moodle into MOODLE_310_STABLE 2020-11-02 10:04:31 +08:00
Peter Dias 32574e9cae MDL-70073 badges: Fix the backpack-add to match current master 2020-11-01 22:33:28 +08:00
Brendan Heywood 256f8a261c MDL-69975 core: Fix paths longer than 260 chars on windows
Also, ensure that remove_dir() only processes directories,
because sometimes it was being called by shutdown managers
with files, leading to PHP warnings.

Co-authored-by: Eloy Lafuente (stronk7) <stronk7@moodle.org>
Co-authored-by: Jun Pataleta <jun@moodle.com>
2020-11-01 11:09:39 +01:00
Claude Vervoort 60232d2b9b MDL-70074 mod_lti: add authorization_endpoint 2020-10-30 18:08:18 -04:00
Eloy Lafuente (stronk7) 864ddb77c5 MDL-69973 xmldb: Ensure all reports use fresh metadata (not cached) 2020-10-30 19:27:14 +01:00
Eloy Lafuente (stronk7) 462fe3e925 MDL-69973 xmldb: Fix problem with MariaDB >= 10.2.7 metadata defaults
With MariaDB 10.2.7 the driver was incorrectly returning '' (empty
string) as default for all the columns having null (meaning, no
default).

Also, cover the case in unit tests, it seems that we were already
testing other defaults but not the null case.
2020-10-30 19:27:14 +01:00
Eloy Lafuente (stronk7) 6bb7478e8d on-demand release 3.10beta+ 2020-10-30 13:49:20 +01:00
Jun Pataleta 03960b96cb Merge branch 'MDL-68167-310' of git://github.com/rezaies/moodle into MOODLE_310_STABLE 2020-10-30 13:16:55 +08:00
Shamim Rezaie 4d00ebae7a MDL-68167 lib: autocomplete focos should not be removed on blur
See https://www.w3.org/TR/wai-aria-practices-1.1/examples/listbox/listbox-rearrangeable.html
2020-10-30 16:08:56 +11:00
Shamim Rezaie 352e2f7787 MDL-68167 lib: Do not set aria-expanded if it should not be set 2020-10-30 16:08:56 +11:00
Shamim Rezaie 2d2b8d9170 MDL-68167 user: Fix missing label for participants filter input fields 2020-10-30 16:08:56 +11:00
Shamim Rezaie 53f2acb263 MDL-68167 lib: Clear single-select autocomplete elements with keyboard
Following MDL-57680, it should be possible to clear the selected option
using keyboard as well.
2020-10-30 16:08:56 +11:00
Shamim Rezaie 3ea25c3b77 MDL-68167 user: Fix a hardcoded string to be read from lang pack 2020-10-30 16:08:55 +11:00
Shamim Rezaie 7931148cbb MDL-68167 lib: Fix label for autocomplete selection/suggestion box
The content of the autocomplete selection div is purged by javascript
so we have to move its label outside of it. aria-labeledby is the way
to go.

Each time the suggestion box is expanded, autocomplete js renders the
autocomplete suggestions template. So the label cannot be outside the
suggestions ul.
2020-10-30 16:08:40 +11:00
Shamim Rezaie 1031836d89 MDL-68167 user: filter elements should listen to accessibleChange event 2020-10-30 15:01:39 +11:00
Shamim Rezaie ec1e1fd01a MDL-68167 lib: The accessibleChange custom event now supports bubbling
The change event bubbles so the accessibleChange shoud bubble as well.
2020-10-30 15:01:39 +11:00
Shamim Rezaie b5a04a9fe2 MDL-68167 theme_boost: make focus outline accessible for autocompletes 2020-10-30 15:01:39 +11:00
Shamim Rezaie be7b73a24b MDL-68167 lib: Autocomplete selection to use listbox aria role
The aria-selected state cannot be used for the listitem role. The
autocomplete widget highly uses the aria-selected state internally.
2020-10-30 14:59:50 +11:00
Shamim Rezaie 0c438b4d3e MDL-68167 user: Improve keyboard navigation on autocomplete fields 2020-10-30 14:59:50 +11:00
Shamim Rezaie 3f0373cb7e Merge branch 'MDL-69390-310' of git://github.com/bmbrands/moodle into MDL-69390-310-test 2020-10-30 14:59:34 +11:00
Andrew Nicols 6a64b9c5b7 Merge branch 'MDL-69156_310' of https://github.com/ffhs/moodle into MOODLE_310_STABLE 2020-10-30 11:52:07 +08:00
Víctor Déniz 04569f819f Merge branch 'MDL-70032-310-2' of git://github.com/junpataleta/moodle into MOODLE_310_STABLE 2020-10-29 22:26:35 +00:00
Paul Holden a850fa5de8 MDL-69156 backup: correct behaviour of course copy idnumber field.
When a given user doesn't have the capability to change the idnumber
field during course copy, freeze the field value.
2020-10-29 14:15:04 +01:00
Adrian Perez 8d0d0b1f59 MDL-69156 course_copy: set defaults for idnumber when not permitted 2020-10-29 14:15:00 +01:00
Jun Pataleta 8ea746fa79 MDL-70032 qtype_multichoice: Use custom partial named selector
* With the removal of the label element, Behat now has to click on the
answer text. In order to achieve this, the custom partial named selector
"qtype_multichoice > Answer" was now added and have replaced the
instances where the label of the answer's checkbox/radio button is
being clicked.
2020-10-29 16:21:53 +08:00
Jun Pataleta 5d7bd0208a MDL-70032 qtype_multichoice: Fix answer labelling
* Discard the use of the label element in order to be able to render
multiple choice answers as they are and have these act as the radio
button/checkbox' label through the aria-labelledby attribute.
* New JS module qtype_multichoice/answers that listens for click events
on the answer text container and selects the appropriate answer radio
button/checkbox.
2020-10-29 16:21:53 +08:00
Andrew Nicols 52ad601de1 Merge branch 'MDL-68722-310' of https://github.com/matt-catalyst/moodle into MOODLE_310_STABLE 2020-10-29 14:03:15 +08:00
Jake Dallimore 2e02b4d678 Merge branch 'MDL-69716-310' of git://github.com/aanabit/moodle into MOODLE_310_STABLE 2020-10-29 12:40:06 +08:00
Jake Dallimore 859578b0d5 Merge branch 'MDL-70041-310' of git://github.com/mihailges/moodle into MOODLE_310_STABLE 2020-10-29 11:49:20 +08:00
Adrian Greeve 761b8a95f9 Merge branch 'm310_MDL-70042_Progress_Bar_Upgrade_Message_Popup' of https://github.com/scara/moodle into MOODLE_310_STABLE 2020-10-29 08:33:33 +08:00
Matteo Scaramuccia 4ca3d0a0ae MDL-70042 message_popup: Trivial savepoint comment cleanup 2020-10-28 23:00:48 +01:00
Matteo Scaramuccia 75c793f830 MDL-70042 message_popup: progress bar on upgrade only when necessary 2020-10-28 23:00:32 +01:00
Jun Pataleta d546f308d2 Merge branch 'MDL-69390-310' of git://github.com/bmbrands/moodle into MOODLE_310_STABLE 2020-10-28 22:44:08 +08:00
Bas Brands 74f37f98ad MDL-69390 theme_boost: dropdown menu accessibility
- display a dot before the active element
- use the active colour for the hover colour
2020-10-28 14:03:06 +01:00
Jun Pataleta aead807ce6 Merge branch 'MDL-69815-310' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-10-28 14:19:23 +08:00
Andrew Nicols f7ad3eaca3 Merge branch 'MDL-70004-310' of git://github.com/junpataleta/moodle into MOODLE_310_STABLE 2020-10-28 13:14:12 +08:00
Jake Dallimore da4fc1e256 Merge branch 'MDL-64723-310' of git://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-28 12:10:47 +08:00
Mihail Geshoski 35364e22fc MDL-70041 filepicker: Make sure the user has a recently used license 2020-10-28 12:06:34 +08:00
Jake Dallimore b1ef67ba62 Merge branch 'MDL-65792-310' of git://github.com/bmbrands/moodle into MOODLE_310_STABLE 2020-10-28 12:00:16 +08:00
Jake Dallimore 461bf54590 Merge branch 'MDL-70010_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-10-28 11:07:52 +08:00
Andrew Nicols 6ba76c0097 MDL-69815 core: Bump Node to v14.15.0 (LTS/Fermium) 2020-10-28 09:34:31 +08:00
Eloy Lafuente (stronk7) 323ea697c3 Merge branch 'MDL-69998-310-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_310_STABLE 2020-10-28 00:42:05 +01:00
Eloy Lafuente (stronk7) 46f6bae002 Moodle release 3.10beta 2020-10-27 23:48:46 +01:00
Eloy Lafuente (stronk7) 8aacc3fa2b NOBUG: Fixed file access permissions 2020-10-27 23:48:45 +01:00
Eloy Lafuente (stronk7) 0715960dd8 NOBUG: Fixed SVG browser compatibility 2020-10-27 23:48:43 +01:00
Sara Arjona 65084e7371 MDL-69166 enrol_fee: fix behat string from fee to enrolment by payment 2020-10-27 15:01:47 +01:00
Sara Arjona da4b94e012 MDL-69166 enrol_fee: define default value to currency setting 2020-10-27 15:01:47 +01:00
David Mudrák 05679468c5 MDL-69998 lang: Fix reworded strings in Behat test scenarios 2020-10-27 11:20:03 +01:00
Helen Foster 0a64b2ed99 MDL-69998 lang: Import fixed English strings (en_fix) 2020-10-27 11:20:03 +01:00
Andrew Nicols e243810142 Merge branch 'MDL-69166-310-4' of git://github.com/rezaies/moodle into MOODLE_310_STABLE 2020-10-27 16:35:58 +08:00
Bas Brands a5fa563757 MDL-65792 mod_forum: show release time on timed posts 2020-10-27 08:41:28 +01:00
Shamim Rezaie f018e92334 MDL-69166 core: Fix missing lang strings 2020-10-27 18:15:09 +11:00
Andrew Nicols 46e3cfa354 Merge branch 'MDL-69166-310-4' of git://github.com/rezaies/moodle into MOODLE_310_STABLE 2020-10-27 12:59:25 +08:00
Shamim Rezaie 25cf4fa5ca MDL-69166 core_payment: Add privacy implementation 2020-10-27 15:45:25 +11:00
Shamim Rezaie 0fb7847e09 MDL-69166 core_payment: Use promises instead of callbacks 2020-10-27 15:45:25 +11:00
Shamim Rezaie b63f17b5f1 MDL-69166 core_payment: Addressing various integration points
- Add help for 'payment account' field in the enrol instance form
- Remove MOODLE_INTERNALs when not necessary
- Add $userid to deliver_order
- Check if provider classes implement the provider interface
- Rename get_cost to get_payable
- get_payable returns payable object
- Improve registerEventListeners and added init
- Rename payment\provider to payment\service_provider
2020-10-27 15:45:25 +11:00
Shamim Rezaie 52305c9a2e MDL-69166 core_payment: Rename componentid to itemid 2020-10-27 15:45:25 +11:00
Shamim Rezaie 6b3d163a56 MDL-69166 core_payment: Renamed plugintype name from pg to paygw 2020-10-27 15:45:23 +11:00
Marina Glancy efc576fc5c MDL-69166 core_payment: addressing integration review 2020-10-27 15:45:00 +11:00
Marina Glancy 90fbc58de6 MDL-69166 core_payment: rename some functions 2020-10-27 15:45:00 +11:00
Shamim Rezaie 087845bb30 MDL-69166 Replace all upgrade steps with just "create_table" steps 2020-10-27 15:45:00 +11:00
Shamim Rezaie 7d10f35278 MDL-69166 core_payment: Add paymentarea to the payment subsystem 2020-10-27 15:45:00 +11:00
Marina Glancy 9476b48942 MDL-69166 core_payment: archiving accounts, triggering events, tests 2020-10-27 15:45:00 +11:00
Shamim Rezaie 7e11261633 MDL-69166 core_payment: Show cost on the modal when no gateway is chosen 2020-10-27 15:45:00 +11:00
Marina Glancy 15a4e4c87c MDL-69166 core_payment: improvements to api, small fixes 2020-10-27 15:45:00 +11:00
Marina Glancy 895f38cc76 MDL-69166 core_payment: add payment accounts 2020-10-27 15:45:00 +11:00
Shamim Rezaie acd1c82403 MDL-69166 enrol_fee: Show a warning when no currency is supported 2020-10-27 15:44:59 +11:00
Shamim Rezaie c9271eba7c MDL-69166 enrol_fee: Prevent adding instance if no currency is supported 2020-10-27 15:44:59 +11:00
Shamim Rezaie 0cf4bb2afc MDL-69166 pg_paypal: only prevent closing during autorisation 2020-10-27 15:44:59 +11:00
Shamim Rezaie 58a89a46e4 MDL-69166 core-payment: Autoselect gateway when there is only one 2020-10-27 15:44:59 +11:00
Shamim Rezaie 1882bb4792 MDL-69166 core_payment: payment gateways can have a surcharge 2020-10-27 15:44:59 +11:00
Shamim Rezaie bb7d679395 MDL-69166 core_payment: show cost on the modal 2020-10-27 15:44:59 +11:00
Shamim Rezaie 048a652106 MDL-69166 pg_paypal: capture payment directly 2020-10-27 15:44:59 +11:00
Shamim Rezaie 23e24a504e MDL-69166 pg_paypal: New helper to get order details from PayPal 2020-10-27 15:44:59 +11:00
Marina Glancy 761898c876 MDL-69166 core_form: allow modals to prevent closing on accidental click 2020-10-27 15:44:59 +11:00
Shamim Rezaie dc976fba1e MDL-69166 core_payment: ES6-ifying modal_gateways 2020-10-27 15:44:59 +11:00
Shamim Rezaie e2faf67247 MDL-69166 core_payment: Use a custom modal type for gateway selector 2020-10-27 15:44:59 +11:00
Shamim Rezaie b97899634c MDL-69166 pg_paypal: Support multiple currencies on the same page 2020-10-27 15:44:59 +11:00
Shamim Rezaie 2427b92114 MDL-69166 enrol_fee: use template for payment btn & properly format cost 2020-10-27 15:44:59 +11:00
Shamim Rezaie 34770016ee MDL-69166 core_payment: es6-ify 2020-10-27 15:44:59 +11:00
Shamim Rezaie d00c00dd4f MDL-69166 core_payment: add a callback for when payment is done 2020-10-27 15:44:59 +11:00
Shamim Rezaie ed1cc02522 MDL-69166 pg_paypal: Display PayPal buttons in a modal 2020-10-27 15:44:59 +11:00
Shamim Rezaie e1151bf6f5 MDL-69166 pg_paypal: handle paypal checkout callbacks 2020-10-27 15:44:59 +11:00
Shamim Rezaie bbb887f6ae MDL-69166 pg_paypal: Ability to connect to sandbox or live environment 2020-10-27 15:44:59 +11:00
Shamim Rezaie 4403b8f60d MDL-69166 pg_paypal: Process after payment 2020-10-27 15:44:59 +11:00
Shamim Rezaie 3c3b43a58c MDL-69166 core_payment: Save general payment information 2020-10-27 15:44:59 +11:00
Shamim Rezaie 04e2dc7c3b MDL-69166 pg_paypal: paypal helper class to work with API 2020-10-27 15:44:59 +11:00
Shamim Rezaie 05574af1a6 MDL-69166 enrol_fee: Implement callback functions for payment subsystem 2020-10-27 15:44:59 +11:00
Shamim Rezaie 5337ca485c MDL-69166 core_payment: helper methods to get cost and to deliver order
Also create the infrastructure to let components know when they have to
deliver what they sold. We are going to use namespace functions instead
of traditional callbacks.
2020-10-27 15:44:59 +11:00
Shamim Rezaie 3b0034cc91 MDL-69166 enrol_fee: set a description for enrolment 2020-10-27 15:44:59 +11:00
Shamim Rezaie ab6ca27571 MDL-69166 core_payment: send a purchase description to payment gateways
We truncate description to 127 chars as per PayPal requirement
2020-10-27 15:44:59 +11:00
Shamim Rezaie 149e530cc1 MDL-69166 pg_paypal: render PayPal buttons and set up transaction
We truncate brand_name to 127 chars as per PayPal requirement.
2020-10-27 15:44:59 +11:00
Shamim Rezaie 9a7aed4a25 MDL-69166 pg_paypal: WS and AMD to return some settings to be used in js 2020-10-27 15:44:59 +11:00
Shamim Rezaie ed04c3824c MDL-69166 core_payment: post to process payment 2020-10-27 15:44:59 +11:00
Shamim Rezaie 97e8cb0de4 MDL-69166 core_payment: display an image for each gateway 2020-10-27 15:44:59 +11:00
Shamim Rezaie a435c63e16 MDL-69166 core_payment: some basic styling 2020-10-27 15:44:59 +11:00
Shamim Rezaie c2321a263b MDL-69166 core_payment: display the gateways modal 2020-10-27 15:44:58 +11:00
Shamim Rezaie f3d7526419 MDL-69166 core_payment: WS to get list of gateways supporting a currency 2020-10-27 15:44:58 +11:00
Shamim Rezaie d3432a883c MDL-69166 enrol_fee: An enrolment plugin that supports payments 2020-10-27 15:44:58 +11:00
Shamim Rezaie e1cab8e18e MDL-69166 pg_paypal: A new payment gateway is born 2020-10-27 15:44:56 +11:00
Shamim Rezaie bc28c05995 MDL-69166 core: list settings page in the admin tree 2020-10-27 15:05:23 +11:00
Shamim Rezaie 4865d2a0ae MDL-69166 core_payment: basic gateway skeleton 2020-10-27 15:05:23 +11:00
Shamim Rezaie 8317134779 MDL-69166 core: define payment as a subsystem and pg as a plugin type 2020-10-27 15:05:23 +11:00
Michael Hawkins fbac2e9296 MDL-69559 course: Fix course download cap checks when creating courses 2020-10-27 12:01:09 +08:00
Jun Pataleta c978fa26e2 MDL-70004 qtype_multichoice: Set appropriate clear my choice role 2020-10-27 09:57:32 +08:00
Michael Hawkins 599eed0f95 MDL-69559 core: Removed stopPropagation from tree click handling
It was preventing JS click event handlers being reached on some
elements, such as course admin items in Classic
(eg download course content for teachers).
2020-10-27 08:02:20 +08:00
Michael Hawkins 7d52d5def6 MDL-69559 course: Fixed behat navigation in download course content 2020-10-27 08:01:48 +08:00
Paul Holden 8813318d61 MDL-64723 tool_mobile: workaround for invalid certificate parsing.
This is to account for specific server configuration that are affected
by one of the following issues, which results in certificate signature
algorithms being incorrectly parsed:

 * https://bugs.php.net/bug.php?id=77548
 * https://github.com/curl/curl/issues/3706
2020-10-26 23:04:43 +00:00
Sara Arjona 0459910b53 MDL-65959 core_badges: fix unique index in upgrade.php
There was an error when creating the unique index. Apart from that,
the code has been reorganised to copy data in the new structure only
if password field hasn't been removed.
2020-10-26 23:56:46 +01:00
Matt Clarkson adeaafd59d MDL-68722 atto_equation: fix for form elements with special characters
Element id's containing characters such as ':' would break the tab
selector in bootstrap.

This specifically affects the essay question type.
2020-10-27 11:10:58 +13:00
Sara Arjona 0dd7bb8374 Merge branch 'MDL-65959-310' of git://github.com/peterRd/moodle into MOODLE_310_STABLE 2020-10-26 22:44:05 +01:00
Peter Dias bcba1347f8 MDL-65959 badges: Allow cross domain/protocol functionality - obv2 2020-10-26 18:36:26 +08:00
Peter Dias b0e1edd427 MDL-65959 badge: Enable OB2.1 *connection* with cross domain ability 2020-10-26 18:36:26 +08:00
Peter Dias b0007a154c MDL-65959 badge: Reset external_identifiers if backpack details modified 2020-10-26 18:36:26 +08:00
Peter Dias 8c9d3695e3 MDL-65959 badge: Confirm assertion data is updated before awarding 2020-10-26 18:36:26 +08:00
Peter Dias 184944ce6a MDL-65959 badges: Unit and Behat tests 2020-10-26 18:36:26 +08:00
Peter Dias ad9f9e54a3 MDL-65959 badges: Do not use badge user preference after verification 2020-10-26 18:36:26 +08:00
Peter Dias 943b261760 MDL-65959 badges: Update the implementation to use admin set backpack 2020-10-26 18:36:25 +08:00
Peter 8dbc7c6532 MDL-65959 core_badges: Allow ability to upload badges cross domain. 2020-10-26 18:35:36 +08:00
Peter 6f7fe5df9c MDL-65959 core_badges: Unrestricted user's badger account
* Restructure the email to be backpack specific
* Amended table defintion and functions
2020-10-26 18:35:35 +08:00
Eloy Lafuente (stronk7) 7e5f0e1fe6 MDL-70010 core: reconcile MOODLE_310_STABLE and master
There are some unexpected differences between 310 and master,
better reconcile them now. Note this is not 100% critical but,
as far as nothing exclusively for 4.0 has landed to master yet
only branch/version differences should exist.
2020-10-26 11:03:40 +01:00
Eloy Lafuente (stronk7) 11b6df58db Merge branch 'MDL-69993-310' of git://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-26 10:42:51 +01:00
Andrew Nicols 36beec930e Merge branch 'MDL-69995-310' of git://github.com/lucaboesch/moodle into MOODLE_310_STABLE 2020-10-26 16:00:38 +08:00
Adrian Greeve 750fe24949 MDL-69559 core_course: Fix to bad behat test formatting. 2020-10-26 13:28:10 +08:00
Adrian Greeve cc718b59d0 Merge branch 'MDL-69559-310-7' of git://github.com/mickhawkins/moodle into MOODLE_310_STABLE 2020-10-26 13:05:33 +08:00
Jun Pataleta 4dcc2d37c6 Merge branch 'MDL-67301-dynreg-squashed-310' of https://github.com/cengage/moodle into MOODLE_310_STABLE 2020-10-26 12:40:23 +08:00
Michael Hawkins d358b91e2b MDL-69559 course: Add course setting and cap to control course downloads 2020-10-26 10:25:37 +08:00
Michael Hawkins c053b93f0c MDL-69559 course: Add course content download UI and execution page 2020-10-26 10:19:39 +08:00
Michael Hawkins cdf91cc236 MDL-69559 course: Add capability and access checks for course download 2020-10-26 10:19:33 +08:00
Michael Hawkins fab34222ca MDL-69559 admin: Add course download admin settings and lang strings 2020-10-26 10:19:27 +08:00
Luca Bösch a9f5f8094c MDL-69995 backup: padding before activity icons. 2020-10-25 02:07:26 +02:00
Claude Vervoort 10e16c69c8 MDL-67301 mod_lti: dynamic registration 2020-10-24 09:28:32 -04:00
Amaia Anabitarte e66e3740a7 MDL-69716 mod_quiz: No timestamp for in progress attempts 2020-10-23 16:02:25 +02:00
Eloy Lafuente (stronk7) 6594c54b2e on-demand release 3.10dev+ 2020-10-23 14:41:20 +02:00
Paul Holden 6dc336a5d4 MDL-69993 output: correct navigation node type for user reports. 2020-10-23 08:25:40 +01:00
Adrian Greeve 39128991d7 Merge branch 'MDL-67650-forced-checkbox-textarea-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-10-23 09:01:59 +08:00
Víctor Déniz e1990f2f33 Merge branch 'MDL-68664-310' of git://github.com/lameze/moodle into MOODLE_310_STABLE 2020-10-22 12:25:51 +01:00
Sara Arjona 1ce223c7e1 Merge branch 'MDL-69553-m310' of https://github.com/NeillM/moodle into MOODLE_310_STABLE 2020-10-22 08:56:05 +02:00
Brendan Heywood 6694715840 MDL-67650 admin: Consistently show forced config settings 2020-10-22 13:17:49 +11:00
Jake Dallimore 0a43a459ba Merge branch 'MDL-68438_310' of https://github.com/t-schroeder/moodle into MOODLE_310_STABLE 2020-10-22 09:30:48 +08:00
Adrian Greeve 7e0bcbfb19 Merge branch 'MDL-69788-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-22 09:07:54 +08:00
Eloy Lafuente (stronk7) eaf89f7754 Merge branch 'MDL-66392-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-21 19:45:26 +02:00
Paul Holden 5bbfcc25c0 MDL-66392 analytics: make model output directory default to empty.
Falling back to path within $CFG->dataroot/models.
2020-10-21 18:04:20 +01:00
Sara Arjona 4a495d66b8 Merge branch 'm310_MDL-68536_Notice_Undefined_Property_CFG_branch' of https://github.com/scara/moodle into MOODLE_310_STABLE 2020-10-21 18:32:47 +02:00
Sara Arjona b13ec3c353 Merge branch 'MDL-67673_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-10-21 17:38:16 +02:00
Víctor Déniz 5903054142 Merge branch 'MDL-69392-310' of git://github.com/junpataleta/moodle into MOODLE_310_STABLE 2020-10-21 16:26:44 +01:00
Víctor Déniz 2dd9b53fd6 Merge branch 'MDL-69513-dkim-settings-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-10-21 11:56:54 +01:00
Eloy Lafuente (stronk7) 7f20e2071c MDL-67673 phpunit: Document all the changes in upgrade.txt
This includes:

- Breaking changes (return void + PHP 7.1 min requirement).
- Deprecations and removals.
- Specifically DbUnit and its replacement.
- Printer showing how to rerun tests removed.
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) 0ab106f41c MDL-67673 phpunit: Remove the rerun hint on failed test cases
That custom printer was using some hacks to be able to intercept
configuration switches, reflection and other tricks to be able to
print the:

To re-run:
 vendor/bin/phpunit --verbose "core_setuplib_testcase" lib/tests/setuplib_test.php

line on every failed/exceptional/skipped test. After some internal
discussion it was agreed that the normal phpunit output:

1) core_setuplib_testcase::test_localcachedir
Time is lower that allowed start value
Failed asserting that 1601976686 is equal to 1601976687 or is greater than 1601976687.

/var/www/html/lib/phpunit/classes/advanced_testcase.php:446
/var/www/html/lib/tests/setuplib_test.php:170
/var/www/html/lib/phpunit/classes/advanced_testcase.php:80

has already all the information at hand about how to rerun a test:

- vendor/bin/phpunit lib/tests/setuplib_test.php
- vendor/bin/phpunit --filter core_setuplib_testcase::test_localcachedir
- vendor/bin/phpunit --filter ::test_localcachedir
- vendor/bin/phpunit --testsuite componentname_testsuite
- vendor/bin/phpunit --config <<compoenent directory>>
- use --cache-result to get failed tests rerun with ease.
- ...

So better, let's use standard phpunit output and done. Also, note that,
with the upgrade to phpunit 8.5, the printer was not working correctly
any more, causing some switches, like --verbose ... to be ignored. Sure
it could have been fixed but, as commented above, no real need for all
that "parapheranlia" to print the rerun information.
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) 9f82c9aece MDL-67673 phpunit: deprecate old phpunit/dbunit stuff
Apply the standard deprecation procedure to the old APIs, to
be removed in Moodle 4.2 (MDL-69882). Existing unit tests
cover the deprecation debugging.

Originally MDL-64600
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) 1f13dff1a7 MDL-67673 phpunit: Move tests to use new phpunit_dataset
- Make advanced_testcase old methods to use new ones internally.
- Fix advanced_testcase, statslib, mod/quiz and mod/data tests.

Originally MDL-64600
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) be396eddf0 MDL-67673 phpunit: Introduce a new, lightweight phpunit_dataset
In charge of taking over the, now removed/archived, phpunit/dbunit
package. It supports loading of CSV/XML files and strings and
PHP arrays, allowing to send the loaded information to database.

Perform some basic controls about the consistency of information,
surely not super-exhaustive but fair enough.

100% covered with unit test.

Planned like an "interim" replacement for phpunit/dbunit uses in
core that, ideally, should be moved to generators stuff at some
point.

Note, expect a few tests in core to fail with this commit, I've
changed some fixtures around. Next commit will fix existing uses.

Originally MDL-64600
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) 4af4d709a4 MDL-67673 phpunit: Disable phpunit results cache by default
It can be enabled if desired from CLI using the --cache-result
option (or modifying the phpunit.xml cacheResult to true).

That will create the .phpunit.result.cache files that,
later, can be used to easily repeat failed (defects) tests or
run the slow ones first and more. See the --order-by option
to know more about all the available criteria. For example:

./vendor/bin/phpunit --order-by=defects --stop-on-defect

(will run all the failed ones first, stopping on problem, useful
for TDD and other scenarios, not so much for complete runs or CI).

Also, added to .gitignore so they won't be committed ever.
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) 46606b3ddd MDL-67673 phpunit: Remove deprecated assertEquals() params
The optional parameters of assertEquals() and assertNotEquals()
are deprecated in PHPUnit 8 (to be removed in PHPUnit 9):

- delta => use assertEqualsWithDelta()
- canonicalize => use assertEqualsCanonicalizing()
- ignoreCase => use assertEqualsIgnoringCase
- maxDepth => removed without replacement.

More info @ https://github.com/sebastianbergmann/phpunit/issues/3341

Initial search done with:

ag 'assert(Not)?Equals\(.*,.*,' --php

Then, running tests and fixing remaining cases.
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) 35bc26b516 MDL-67673 phpunit: Remove deprecated assertContains() uses on strings
Both assertContains() and assertNotContains() are deprecated in PHPUnit 8
for operations on strings. Also the optional case parameter is. All uses
must be changed to one of:

- assertStringContainsString()
- assertStringContainsStringIgnoringCase()
- assertStringNotContainsString()
- assertStringNotContainsStringIgnoringCase()

More info: https://github.com/sebastianbergmann/phpunit/issues/3422

Regexp to find all uses:

ag 'assert(Not)?Contains\('
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) 106c64ac24 MDL-67673 phpunit: Remove deprecated non-public attribute assertions
With PHPUnit 8 a good number of assertions, all them related with
operations on non-public attributes have been deprecated. And will
be removed with PHPUnit 9.

The main point is that unit tests shouldn't be testing non-public
APIs (good practice) and those assertions were an error originally.

See https://github.com/sebastianbergmann/phpunit/issues/3338 for
the complete list and other details.

When possible (the attributes being checked are public), the change
is simple, just switching to normal assertions.

When the attributes are not public we need to find a workaround
to be able to test the same using public APIs, or use Reflection,
or remove the tests.

For the records, this is the regexp used to find all the cases:

ag '>(assertAttribute|attribute\(|readAttributte|getStaticAttribute| \
    getObjectAttribute)' -G "test.php"
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) ddf72dd60d MDL-67673 phpunit: Remove expectedException annotations
While this is not strictly required, because removal will
happen in PHPUnit 9.0, we are already getting rid of all
uses in core.

From release notes:https://phpunit.de/announcements/phpunit-8.html

The annotations `@expectedException`, `@expectedExceptionCode`,
`@expectedExceptionMessage`, and `@expectedExceptionMessageRegExp`
are now deprecated.
Using these annotations will trigger a deprecation warning
in PHPUnit 8 and in PHPUnit 9 these annotations will be removed.

Also, all uses of expectExceptionMessageRegExp() has been moved
to expectExceptionMessageMatches(). See https://github.com/sebastianbergmann/phpunit/issues/3957

TODO: Various weirdness found while doing the changes with these tests:
- vendor/bin/phpunit lib/tests/exporter_test.php (created MDL-69700)
- vendor/bin/phpunit competency/tests/external_test.php (same issue than prev one)
- vendor/bin/phpunit question/engine/tests/questionengine_test.php (created MDL-69624)
- vendor/bin/phpunit lib/tests/event_test.php (created MDL-69688)
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) 0ae27225f5 MDL-67673 phpunit: Remove deprecated assertArraySubset()
While this is not strictly required, because removal will
happen in PHPUnit 9.0, we are already getting rid of all
uses in core.

From release notes:https://phpunit.de/announcements/phpunit-8.html

assertArraySubset() is deprecated and will be removed in PHPUnit 9.
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) a6674bf8a4 MDL-67673 phpunit: Remove deprecated assertInternalType()
While this is not strictly required, because removal will
happen in PHPUnit 9.0, we are already getting rid of all
uses in core.

From release notes:https://phpunit.de/announcements/phpunit-8.html

assertInternalType() is deprecated and will be removed in
PHPUnit 9. Refactor your test to use assertIsArray(), assertIsBool(),
assertIsFloat(), assertIsInt(), assertIsNumeric(), assertIsObject(),
assertIsResource(), assertIsString(), assertIsScalar(),
assertIsCallable(), or assertIsIterable() instead.
2020-10-21 12:46:05 +02:00
Eloy Lafuente (stronk7) dc87fd4b3f MDL-67673 phpunit: phpunit_constraint_object_is_equal_with_exceptions
Constraints are now declared final, so we cannot extend them anymore.

Hence, instead of extending PHPUnit\Framework\Constraint\IsEqual we
are just wrapping it into our constraint.
2020-10-21 12:46:04 +02:00
Eloy Lafuente (stronk7) d81a94807b MDL-67673 phpunit: Fix the return type of template methods
All the setup/teardown/pre/post/conditions template methods
now are required to return void. This was warned with phpunit 7
and now is enforced.

At the same time, fix a few wrong function names,
provider data and param types, return statements...
2020-10-21 12:46:04 +02:00
Eloy Lafuente (stronk7) c611109ed7 MDL-67673 phpunit: Bump to PHPUnit 8.5 and remove DBunit
This makes everything to break, but it's what we'll be fixing
in the next commits, heh. :-)

Generated with php72 (min version supported), following the
instructions @ https://docs.moodle.org/dev/Composer
2020-10-21 12:46:04 +02:00
Paul Holden 74ef7dc5b1 MDL-69788 admin: validate language menu configuration. 2020-10-21 11:24:22 +01:00
Jun Pataleta 8996ed98c7 Merge branch 'MDL-37226-310' of git://github.com/lucaboesch/moodle into MOODLE_310_STABLE 2020-10-21 17:46:48 +08:00
Tim Schroeder 3fcba4be5e MDL-68438 message: fixed email format change with messaging disabled 2020-10-21 11:29:15 +02:00
Neill Magill 55d463b9f2 MDL-69553 output: Handle pre-loading multiline string defines
Before this patch strings that were declared over multiple lines in
a template would not be parsed correctly.

{{#str}}value,
mod_forum{{/str}}

would have been been parsed to get_string('value', 'core')

{{#str}}
value, mod_forum
{{/str}}

would have been been parsed to get_string('', 'core')
2020-10-21 10:06:26 +01:00
Neill Magill bbb58b10ad MDL-69553 output: Unit tests for loading multiline string defines 2020-10-21 10:06:25 +01:00
Jun Pataleta f266c852c3 Merge branch 'MDL-69945-310' of git://github.com/lucaboesch/moodle into MOODLE_310_STABLE 2020-10-21 16:03:14 +08:00
Jun Pataleta b14daeaa9a MDL-69392 mod_forum: Colour contrast check for locked discussions 2020-10-21 14:54:25 +08:00
Jun Pataleta 8e083da3d5 MDL-69392 block_myoverview: Basic contrast check for the dashboard 2020-10-21 14:54:25 +08:00
Jun Pataleta 8312eeacb0 MDL-69392 question: Fix Try again button styling 2020-10-21 14:54:24 +08:00
Jun Pataleta 0ce40927cf MDL-69392 theme_boost: Improve question colour contrast
* Lighten info container.
* Fix colour contrast for the question container by
  - Lightening the background a bit
  - Darkening the text colour a bit
  - Making sure the link colour has good colour contrast against the
  question text.
* Fix colour contrast for the comments container by
  - Lightening the text colour a bit
  - Darkening the link colour a bit for better colour contrast against
  the feedback text.
2020-10-21 14:54:05 +08:00
Jun Pataleta 0cdfaccd4e MDL-69392 theme_classic: Darken red, blue and green colours
The current red, blue, and green colours achieve the minimum colour
contrast against a white background. However, when they're against
coloured background, text with these colours will easily fail the
4.5:1 contrast ratio requirement for Level AA.
The updated colours now have the following contrast ratio against a
white background:
* Blue  - #0f6fc5 (5.12:1, from 4.58:1)
* Green - #357a32 (5.27:1, from 4.63:1)
* Red   - #ca3120 (5.29:1, from 4.59:1)
2020-10-21 14:54:03 +08:00
Jun Pataleta d386d21360 MDL-69392 theme_boost: Darken red, blue and green colours
The current red, blue, and green colours achieve the minimum colour
contrast against a white background. However, when they're against
coloured background, text with these colours will easily fail the
4.5:1 contrast ratio requirement for Level AA.
The updated colours now have the following contrast ratio against a
white background:
* Blue  - #0f6fc5 (5.12:1, from 4.58:1)
* Green - #357a32 (5.27:1, from 4.63:1)
* Red   - #ca3120 (5.29:1, from 4.59:1)
2020-10-21 14:53:44 +08:00
Adrian Greeve 5429ece3f8 Merge branch 'MDL-69807-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-21 14:18:02 +08:00
Adrian Greeve 32f99bc4d1 Merge branch 'MDL-68766-M310' of https://github.com/michael-milette/moodle into MOODLE_310_STABLE 2020-10-21 12:54:02 +08:00
Jake Dallimore df0df3110d Merge branch 'MDL-68983-recent-session-lock-ro-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-10-21 12:45:55 +08:00
Jake Dallimore 2ced8c6674 Merge branch 'MDL-69902-310' of https://github.com/marinaglancy/moodle into MOODLE_310_STABLE 2020-10-21 10:57:35 +08:00
Jake Dallimore 17056bf206 Merge branch 'MDL-69751-310' of git://github.com/mihailges/moodle into MOODLE_310_STABLE 2020-10-21 10:02:47 +08:00
Eloy Lafuente (stronk7) 27b09acf75 on-demand release 3.10dev+ 2020-10-21 00:51:10 +02:00
Luca Bösch d159c32b84 MDL-65448 block_site_main_menu: Restyle moving. 2020-10-20 17:26:14 +02:00
Jake Dallimore 221f0e16d0 Merge branch 'MDL-67695-MOODLE_310_STABLE_get_lti_proxies' of https://github.com/andrewmadden/moodle into MOODLE_310_STABLE 2020-10-20 11:08:46 +08:00
Adrian Greeve 55189def65 Merge branch 'MOODLE_310_STABLE-MDL-68284' of https://github.com/yao9394/moodle into MOODLE_310_STABLE 2020-10-20 08:49:06 +08:00
Mihail Geshoski 086a2adc35 MDL-69751 core: Restore deleted guest user and add missing context
This upgrade step fixes the cases where the current guest user is
labelled as 'deleted' and the related user context is missing.
2020-10-20 08:41:35 +08:00
Mihail Geshoski 3c315a874a MDL-69751 course: Handle missing guest user context
Makes sure the guest user context exists when fetching
the recommended modules. If the context does not exist
an exception is being thrown describing the problem.
2020-10-20 08:39:17 +08:00
Simey Lameze b4a8a99898 MDL-68664 theme: remove right margin from form-inline class 2020-10-20 08:32:45 +08:00
Katie Ransom 08e8205d6f MDL-69962 tool_usertours: Fix increase in included files 2020-10-20 01:29:47 +01:00
Andrew Nicols 0a54a501eb Merge branch 'MDL-69687-m310' of https://github.com/sammarshallou/moodle into MOODLE_310_STABLE 2020-10-20 08:02:22 +08:00
Jenkins Automation 213ea00afe MDL-69726 calendar: fix raw event fetcher under postgres
Without this, there's a code path that under the right circumstances is hit and
results in a query with `FROM (mdl_event) ev` in it - which is not valid syntax
under postgres.
2020-10-20 07:46:00 +08:00
Paul Holden 9428e33d55 MDL-69807 blocks: remove redundant sesskey loading edit/delete page. 2020-10-19 22:40:45 +01:00
Eloy Lafuente (stronk7) 31a98b3fb2 Merge branch 'MDL-69906-310-searchsimpledb' of git://github.com/mudrd8mz/moodle into MOODLE_310_STABLE 2020-10-19 22:56:31 +02:00
Eloy Lafuente (stronk7) ae6da7d6a0 Merge branch 'MDL-57756-text-customparams-310' of https://github.com/cengage/moodle into MOODLE_310_STABLE 2020-10-19 22:32:02 +02:00
Andrew Madden 4d5bc273ce MDL-67695 mod_lti: Use correct return structure for get_tool_proxies.
* Deprecated serialise_tool_proxy() as no longer used.
* Use tool_proxy_return_structure for each proxy.
* Added tests for getting all proxies and orphaned proxies.
2020-10-20 04:09:44 +11:00
Sara Arjona 33c7881448 Merge branch 'MDL-69897-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-19 18:14:54 +02:00
Sara Arjona b7146b655a Merge branch 'MDL-69900-310' of git://github.com/mihailges/moodle into MOODLE_310_STABLE 2020-10-19 13:41:59 +02:00
sam marshall 178d5a0e23 MDL-69687 Course: remove_course_contents orphaned completion data
The remove_course_contents function did not delete data from
course_module_completion table in most cases, resulting in large
quantities of orphaned data.
2020-10-19 10:24:44 +01:00
Sara Arjona f576390bd2 Merge branch 'MOODLE_310_MDL-69791' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-10-19 10:07:21 +02:00
Andrew Nicols 7ed7afad98 Merge branch 'MDL-65448-310' of git://github.com/lucaboesch/moodle into MOODLE_310_STABLE 2020-10-19 15:54:36 +08:00
Luca Bösch a7e12a77b1 MDL-65448 block_social_activities: Restyle moving. 2020-10-19 09:50:20 +02:00
Luca Bösch 09e02634d4 MDL-65448 core_course: Restyle non-JS activity moving. 2020-10-19 09:50:20 +02:00
Luca Bösch be019636d1 MDL-65448 gradebook: Remove erraneous dev .movehere class left over. 2020-10-19 09:50:19 +02:00
Luca Bösch 7789be4030 MDL-65448 core_course: Restyle non-JS activity moving. 2020-10-19 09:50:19 +02:00
Luca Bösch 91c9ca0f49 MDL-65448 block_site_main_menu: Restyle moving. 2020-10-19 09:50:18 +02:00
Luca Bösch 7c0923a3e4 MDL-65448 block_social_activities: Restyle moving. 2020-10-19 09:50:18 +02:00
Luca Bösch 83cba7b9b0 MDL-65448 gradebook: Restyle moving. 2020-10-19 09:50:18 +02:00
Sara Arjona cb4418bc5b Merge branch 'MDL-69736-310' of git://github.com/ferranrecio/moodle into MOODLE_310_STABLE 2020-10-19 09:03:51 +02:00
Brendan Heywood 4db3403481 MDL-69513 email: Add support for email DKIM signatures 2020-10-19 16:20:42 +11:00
Andrew Nicols 9296086653 Merge branch 'MDL-69687-m310' of https://github.com/sammarshallou/moodle into MOODLE_310_STABLE 2020-10-19 13:19:28 +08:00
Andrew Nicols 38d4a1b75f Merge branch 'MDL-65448-310' of git://github.com/lucaboesch/moodle into MOODLE_310_STABLE 2020-10-19 10:07:45 +08:00
Michael Milette 1b4ef7cd88 MDL-68766 auth: Login form: 'Log in using...' should be h3, not h6 2020-10-17 03:59:35 -04:00
sam marshall 3576eb4835 MDL-69687 Course: Improve removal of completion data on MySQL 2020-10-16 18:22:51 +01:00
sam marshall 39eb58c754 MDL-69687 DB: Add API for deleting data based on subquery
The new API works on normal databases (by deleting data based on the
subquery) and also on MySQL (by deleting the data using a weird join
on the subquery).
2020-10-16 18:22:51 +01:00
Luca Bösch c6731f8045 MDL-37226 assign: align select all header checkbox 2020-10-16 16:08:58 +02:00
Paul Holden 252f95e1b7 MDL-69788 lang: fallback to all translations if misconfigured.
If given translation list contains only invalid entries, fallback
to returning the complete list of available language translations.
2020-10-16 14:38:03 +01:00
Luca Bösch c24c9e174b MDL-65448 block_site_main_menu: Restyle moving. 2020-10-16 14:50:11 +02:00
Luca Bösch 199333208d MDL-65448 block_social_activities: Restyle moving. 2020-10-16 14:50:10 +02:00
Luca Bösch 91557080d7 MDL-65448 core_course: Restyle non-JS activity moving. 2020-10-16 14:50:10 +02:00
Luca Bösch 3370b20e3c MDL-65448 gradebook: Restyle moving. 2020-10-16 14:50:10 +02:00
Luca Bösch 2c98bfc4f4 MDL-69945 core_calendar: let circles appear as circles 2020-10-16 14:22:47 +02:00
Sara Arjona 36f0c3d531 on-demand release 3.10dev+ 2020-10-16 13:18:54 +02:00
Sagar Ghimire 1ebbd18b82 MDL-68284 gradebook: Prevent exposing hidden quiz grade item 2020-10-16 15:06:34 +11:00
Jake Dallimore 04a02b5bd9 Merge branch 'MOODLE_310_MDL-47178' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-10-16 11:52:29 +08:00
Jun Pataleta 506df9bdbd Merge branch 'MDL-69266-310' of https://github.com/HuongNV13/moodle into MOODLE_310_STABLE 2020-10-16 10:09:40 +08:00
Huong Nguyen 873b4847f5 MDL-69266 qtype_ddwtos: 'unlimited' options fail in 3.9 2020-10-15 20:05:52 +07:00
Adrian Greeve a2aa548af7 Merge branch 'MDL-69549-310-7' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-10-15 15:11:29 +08:00
Jun Pataleta d0c89df9ee Merge branch 'MDL-69583-310' of git://github.com/ferranrecio/moodle into MOODLE_310_STABLE 2020-10-15 13:56:58 +08:00
Jun Pataleta 30eccfabaa Merge branch 'MDL-69520-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE 2020-10-15 13:53:36 +08:00
Simey Lameze 63e2c543ae MDL-69549 mod_resource: content export implementation 2020-10-15 13:46:25 +08:00
Andrew Nicols a69b38d604 MDL-69549 mod_page: Content export implementation 2020-10-15 13:46:25 +08:00
Andrew Nicols 0ea391d1eb MDL-69549 mod_folder: Content export implementation 2020-10-15 13:46:25 +08:00
Andrew Nicols 17d4bc49f6 MDL-69549 core: Add context export API 2020-10-15 13:46:25 +08:00
Katie Ransom 57a13a5971 MDL-69739 tool_usertours: Add tour-level CSS selector 2020-10-15 13:35:32 +08:00
Eloy Lafuente (stronk7) 12fce2a4bd Merge branch 'MDL-69813-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-14 22:47:12 +02:00
Eloy Lafuente (stronk7) b68dd3a121 Merge branch 'MDL-63805-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-10-14 21:22:08 +02:00
Eloy Lafuente (stronk7) eb4c7963c0 MDL-68070 messaging: Ensure that error is shown on first messages
Before there is a conversation, messages between users are sent
using core_message_send_instant_messages instead of
core_message_send_messages_to_conversation.

That method had an undefined $errormessage variable, ultimately
causing the problem detected on message_post_message()/message_send()
to never been returned by the external.

This just adds the same error than already existing conversations do,
but returning it as warning, for BC, JS will show it.
2020-10-14 18:57:29 +02:00
Sara Arjona dde0818f6c MDL-69520 core_h5p: unit tests for covering example and tutorial 2020-10-14 18:35:52 +02:00
Sara Arjona ad28920d0b MDL-69520 core_h5p: add example and tutorial links 2020-10-14 18:35:50 +02:00
Eloy Lafuente (stronk7) a5cde22a26 MDL-68070 messaging: Amend lang string to be clearer for any user.
Credit goes to Helen Foster for the improvement, thanks!
2020-10-14 16:54:26 +02:00
Víctor Déniz 44719d2ad9 Merge branch 'MDL-68900-m310' of https://github.com/sumitnegi933/moodle into MOODLE_310_STABLE 2020-10-14 12:22:22 +01:00
Juan Leyva 784c09c834 MDL-63805 glossary: New WS mod_glossary_prepare_entry_for_edition 2020-10-14 12:57:33 +02:00
Juan Leyva 004be78003 MDL-63805 glossary: New WS mod_glossary_update_entry 2020-10-14 12:56:52 +02:00
Juan Leyva 7fae5f61ef MDL-63805 glossary: Glossary API refactor 2020-10-14 12:56:43 +02:00
Ferran Recio d7cadcc244 MDL-69583 tool_customlang: add CLI import 2020-10-14 11:59:33 +02:00
Jake Dallimore 2cb45addb1 Merge branch 'MOODLE_310_MDL-69848' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-10-14 09:42:43 +08:00
Víctor Déniz 5ea92799c4 Merge branch 'MDL-69779-better-x-redirect-by-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-10-13 23:41:59 +01:00
Víctor Déniz 55c9482171 Merge branch 'MDL-68440-310' of https://github.com/Peterburnett/moodle into MOODLE_310_STABLE 2020-10-13 23:15:48 +01:00
Simon Mok 1a7928173b MDL-68070 messaging: Fix error when personal notification is disabled 2020-10-13 23:40:46 +02:00
Eloy Lafuente (stronk7) c3299761f7 Merge branch 'MDL-63806-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-10-13 22:26:35 +02:00
Sara Arjona 9aeb59af73 on-demand release 3.10dev+ 2020-10-13 13:25:30 +02:00
Ferran Recio 3759daa952 MDL-69583 tool_customlang: add customization import 2020-10-13 12:33:13 +02:00
Brendan Heywood 15044cea7f MDL-68983 cache: Fix bug with readonly session combined with lock debug 2020-10-13 14:53:26 +11:00
Andrew Nicols 1170a8b694 Merge branch 'MDL-66928-request-dir-purge-bug-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-10-13 11:49:10 +08:00
Brendan Heywood 69959c371f MDL-66928 core: Move request dirs to system tmp instead of localcache 2020-10-13 14:29:30 +11:00
Andrew Nicols ec46b18e13 Merge branch 'MDL-67654-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-13 07:58:20 +08:00
Paul Holden f1acce7bef MDL-67654 mod_forum: formchangechecker for discussion inline replies. 2020-10-12 23:32:44 +01:00
Adrian Greeve 1c6e578db4 Merge branch 'MOODLE_310_MDL-69818' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-10-12 14:48:48 +08:00
Jake Dallimore a7ea95030c Merge branch 'MDL-68292-admin-sesskey-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-10-12 14:37:07 +08:00
Brendan Heywood 3f04dbee09 MDL-68292 core: Remove sesskey leakage on module pages 2020-10-12 17:11:59 +11:00
Adrian Greeve 6a91117d4a Merge branch 'MDL-65743-310' of git://github.com/lameze/moodle into MOODLE_310_STABLE 2020-10-12 13:41:44 +08:00
Simey Lameze cfe9f53e91 MDL-65743 lib: update moodle library docs 2020-10-12 13:10:12 +08:00
Simey Lameze decd480c42 MDL-65743 lib: add XMPPHP namespace and update calls 2020-10-12 13:10:12 +08:00
Simey Lameze d947f53d4c MDL-65743 lib: upgrade XMPPHP library to v2.2 2020-10-12 13:10:12 +08:00
Andrew Nicols 00877bf283 Merge branch 'MDL-69776-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-10-12 12:33:51 +08:00
Adrian Greeve 6f86e933ed Merge branch 'MDL-69649-310' of git://github.com/rezaies/moodle into MOODLE_310_STABLE 2020-10-12 10:15:41 +08:00
Jake Dallimore 6d7b36da59 Merge branch 'MDL-69910-calendar-protectusername-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-10-12 10:05:43 +08:00
Jake Dallimore 7924191691 Merge branch 'MDL-69707-redis-avoid-write-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-10-12 09:57:46 +08:00
Peter Burnett 0628d11380 MDL-68440 cache: Added counting of default mappings 2020-10-12 11:57:17 +10:00
Jake Dallimore 151a63b4cc Merge branch 'MDL-68406-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-10-12 09:51:51 +08:00
Adrian Greeve 4ebfbfe88c Merge branch 'MDL-69825-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-12 08:09:47 +08:00
Brendan Heywood 93a60507fc MDL-69779 core: Improved the X-Redirect-By header when debugging is on 2020-10-11 09:50:21 +11:00
Brendan Heywood 0a8371c690 MDL-69910 calendar: Fix export exception when both params are sent 2020-10-10 19:28:45 +11:00
Paul Holden 604f19afd6 MDL-69825 admin: externalpage class using a callback for access check.
Co-Authored-By: Marina Glancy <marina@moodle.com>
2020-10-09 15:09:05 +01:00
David Mudrák bda1473afa MDL-69906 admin: Display Setup search engine as link only if it is valid
We use auto-generated admin section name here so we need to check that
the target section actually exists.
2020-10-09 14:16:29 +02:00
Sara Arjona d70cfda576 on-demand release 3.10dev+ 2020-10-09 11:12:48 +02:00
Juan Leyva 3dc820a057 MDL-68406 tool_mobile: Allow users to log-out from the app
In this commit, we also reorganised how the Mobile box is displayed in the user profile.
We are allowing now site admins to see the user last access time.
2020-10-09 09:59:43 +02:00
Juan Leyva 4b64516b0e MDL-63806 glossary: New WS mod_glossary_delete_entry 2020-10-09 09:50:38 +02:00
Juan Leyva e8496407e9 MDL-63806 glossary: Return user permissions for entries in WS 2020-10-09 09:49:59 +02:00
Juan Leyva 0ab3fd7958 MDL-63806 glossary: Move delete code to API function 2020-10-09 09:49:59 +02:00
Marina Glancy d103bdba3d MDL-69902 core_search: fix error in the custom fields indexing 2020-10-09 08:52:47 +02:00
Adrian Greeve cf1d32e9c5 Merge branch 'MDL-68384-fix-spec-violations-310' of https://github.com/cengage/moodle into MOODLE_310_STABLE 2020-10-09 12:05:34 +08:00
Jun Pataleta b5fe033b18 Merge branch 'MDL-69740_310' of https://github.com/timhunt/moodle into MOODLE_310_STABLE 2020-10-09 11:56:44 +08:00
Jun Pataleta 05a3e35677 Merge branch 'MDL-69257-310' of git://github.com/mihailges/moodle into MOODLE_310_STABLE 2020-10-09 11:12:16 +08:00
Mihail Geshoski 03058394f2 MDL-69257 core_h5p: Move $maxsize outside the foreach loop
There is no reason to repeatedly obtain the maximum size for uploading
files as a part of foreach loop.
2020-10-09 10:36:01 +08:00
Martin Gauk 1a80427018 MDL-69257 H5P: Check size of uploaded files and virus scan 2020-10-09 10:36:01 +08:00
Stephen Bourget a2b727d7bc MDL-69900 core_backup: Allow IMSCC v1.0 restore to finish 2020-10-09 09:06:26 +08:00
Eloy Lafuente (stronk7) b2a382016f Merge branch 'MDL-69582-310' of git://github.com/ferranrecio/moodle into MOODLE_310_STABLE 2020-10-08 22:44:29 +02:00
Paul Holden 31efbf2e0e MDL-69897 repository: add heading to delete file modal. 2020-10-08 20:29:48 +01:00
Thomas Wedekind 3540343ceb MDL-69582 tool_customlang: export cli script 2020-10-08 19:30:26 +02:00
Thomas Wedekind 78076a621f MDL-69582 tool_customlang: add export langstring feature 2020-10-08 19:30:26 +02:00
Eloy Lafuente (stronk7) ca80e9a68d Merge branch 'MDL-69810-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-10-08 16:58:34 +02:00
Eloy Lafuente (stronk7) 9b9b38f44e Merge branch 'MDL-69712-310' of git://github.com/aanabit/moodle into MOODLE_310_STABLE 2020-10-08 16:25:35 +02:00
Sara Arjona 8e5b007c3e Merge branch 'MDL-64657-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-10-08 14:15:38 +02:00
Sara Arjona d487ee2240 Merge branch 'MDL-69146_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-10-08 12:43:29 +02:00
Sumit Negi 300e4aef4c MDL-68900 mod_forum: permission check for user who is viewing timed post
Pass current user object to post builder as argument, so that the permission to view timed post
will check with current user, who is viewing the posts instead of user who made that post.
2020-10-08 12:46:17 +05:30
Adrian Greeve eefa5c928f Merge branch 'MDL-69805-310' of https://github.com/dravek/moodle into MOODLE_310_STABLE 2020-10-08 15:00:29 +08:00
Adrian Greeve 407dcd4922 Merge branch 'MDL-69798_310' of https://github.com/timhunt/moodle into MOODLE_310_STABLE 2020-10-08 13:34:30 +08:00
Jake Dallimore 8d9a36fb8a Merge branch 'MDL-69192-310-behat' of https://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-10-08 09:22:40 +08:00
Andrew Nicols b2d43a7db1 MDL-68665 assignfeedback_editpdf: Coding style fixes 2020-10-08 08:24:07 +08:00
Andrew Nicols 876a5c143b Merge branch 'MDL-68665-310-assign-stamp-cache' of https://github.com/jamie-catalyst/moodle into MOODLE_310_STABLE 2020-10-08 08:23:36 +08:00
Andrew Nicols c562848596 MDL-69192 mod_assign: Stop clicking OK on non-existent modal 2020-10-08 08:04:43 +08:00
Eloy Lafuente (stronk7) 74efdb135d Merge branch 'MDL-69760-MOODLE_310_STABLE' of https://github.com/inkjet2000/moodle into MOODLE_310_STABLE 2020-10-08 00:25:14 +02:00
Víctor Déniz 46d1546c6e Merge branch 'MDL-69759-m310' of https://github.com/sammarshallou/moodle into MOODLE_310_STABLE 2020-10-07 22:24:58 +01:00
Jamie Stamp c2ba78902c MDL-68665 assignfeedback_editpdf: Fix systemsstamp URLs 2020-10-07 16:23:18 +01:00
Jamie Stamp 12fb5964f2 MDL-68665 assignfeedback_editpdf: Add filearea to persist stamps 2020-10-07 16:21:18 +01:00
Justin Merrill 52a84caaaa MDL-69760 core: add mdl_event index for assign adhoc tasks 2020-10-07 09:18:24 -04:00
Sara Arjona 524f6a656b Merge branch 'MDL-65451-310' of https://github.com/marinaglancy/moodle into MOODLE_310_STABLE 2020-10-07 09:39:58 +02:00
Andrew Nicols 86e69ea7b2 Merge branch 'MDL-69192-310' of https://github.com/willob99/moodle into MOODLE_310_STABLE 2020-10-07 13:18:41 +08:00
Andrew Nicols 12820e3a56 Merge branch 'MDL-67275-310-post_noun_verb' of git://github.com/mudrd8mz/moodle into MOODLE_310_STABLE 2020-10-07 12:38:02 +08:00
Victor Deniz Falcon 36905f42b8 MDL-52407 travis: use Travis default notifications(email) 2020-10-07 10:45:54 +08:00
Adrian Greeve fd532533dd Merge branch 'MDL-59510-310' of https://github.com/snake/moodle into MOODLE_310_STABLE 2020-10-07 09:58:52 +08:00
Víctor Déniz d6806beb3e Merge branch 'MDL-62678-core-fetch-notifications-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-10-06 22:58:45 +01:00
Eloy Lafuente (stronk7) 9ab387d707 Merge branch 'MDL-69746-MOODLE_310_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_310_STABLE 2020-10-06 23:53:22 +02:00
Marina Glancy 2a4d1c64bf MDL-65451 tool_uploaduser: move code away from index.php, add CLI script 2020-10-06 15:53:13 +02:00
Ferran Recio a0999ab66f MDL-69736 core_h5p: enable player reporting 2020-10-06 13:05:33 +02:00
Paul Holden 7e3f7e3d7c MDL-69813 h5p: fix undefined addon ordering in framework test. 2020-10-06 10:48:06 +01:00
Eloy Lafuente (stronk7) 823bc36276 on-demand release 3.10dev+ 2020-10-06 10:21:14 +02:00
Mikhail Golenkov 1f3aacf8fc MDL-47178 question: Retain question authors when restoring backups. 2020-10-06 09:33:56 +11:00
Eloy Lafuente (stronk7) 38bcf316ee Merge branch 'MDL-69772-310-allcountrycodes' of git://github.com/mudrd8mz/moodle into MOODLE_310_STABLE 2020-10-06 00:04:05 +02:00
Eloy Lafuente (stronk7) f993881244 Merge branch 'MDL-65074-310' of https://github.com/hitteshahuja/moodle into MOODLE_310_STABLE 2020-10-05 23:12:25 +02:00
Víctor Déniz 3277fc9db6 Merge branch 'MDL-69625-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-05 19:21:12 +01:00
Sara Arjona ef3720efbd Merge branch 'MDL-69355-310-filebuffer' of git://github.com/mudrd8mz/moodle into MOODLE_310_STABLE 2020-10-05 18:33:45 +02:00
Jun Pataleta 41bc6b9400 Merge branch 'MDL-69704-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE 2020-10-05 23:12:57 +08:00
Paul Holden b9f8e3e114 MDL-69625 course: return raw custom field value in external method.
For clients that wish to consume the original value of the custom
field (e.g. timestamps for date fields), rather than the formatted
version, add a new "valueraw" property to the returned data.
2020-10-05 10:40:33 +01:00
Eloy Lafuente (stronk7) 355d07e0b4 Merge branch 'MOODLE_310-MDL-69752' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-10-05 10:54:56 +02:00
Amaia Anabitarte 5af206ad2a MDL-69712 core_h5p: Remove 'whitelist' key uses 2020-10-05 10:28:07 +02:00
Jun Pataleta 5ec265b48d Merge branch 'MOODLE_310_MDL-53966' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-10-05 13:24:04 +08:00
Mikhail Golenkov 35b29ce7d9 MDL-69791 gradereport: Fix error message when invalid grade is entered 2020-10-05 14:59:41 +11:00
Mikhail Golenkov bec49592ce MDL-69848 upgrade: Delete notifications in chunks 2020-10-05 13:13:51 +11:00
Jake Dallimore 57bb99edd4 MDL-59510 core_oauth2: autorefresh google drive, nextcloud and onedrive
Request additional offline access, allowing the repository to sign in
automatically each time, including across different user sessions, until
either the refresh token is invalidated or the user logs out of the
repository.
2020-10-05 09:17:14 +08:00
Jake Dallimore eb6b828b81 MDL-59510 core: report oauth2_refresh_token table in core provider 2020-10-05 09:17:14 +08:00
Jake Dallimore 8b09853319 MDL-59510 core_oauth2: add autorefresh mode to oauth2\client
Changes:
- The client can now be instantiated with the new mode enabled.
- A user refresh token will be stored if returned as part of the
authorization_code grant but only if the user is authenticated and only
if the mode is enabled.
- If the mode permits it, attempt to exchange a stored refresh token for
a new access token during login checks, allowing access to continue
across sessions without the need to re-grant consent every time.
- Purge all refresh tokens for a given user, issuer and scope on client
log out. This makes sure logout persists across logins.
2020-10-05 09:17:14 +08:00
Jake Dallimore fe1031244b MDL-59510 core_oauth2: add oauth2_refresh_token table 2020-10-05 09:17:14 +08:00
Mikhail Golenkov 03de8ed6d9 MDL-69818 mod_feedback: Fix item dependency during activity restoration 2020-10-04 18:27:32 +11:00
Mikhail Golenkov 6fae5e65e9 MDL-69752 mod_data: Format module intro on Database activities page 2020-10-04 13:46:32 +11:00
Mikhail Golenkov d7157063c3 MDL-53966 lesson: Allow maximum number of attempts to be unlimited 2020-10-04 13:18:45 +11:00
Tim Hunt 477fb6c9d6 MDL-69740 Behat init: more progress info at the end of the install 2020-10-02 23:16:23 +01:00
Juan Leyva c50b024463 MDL-69810 tool_mobile: Return support contact information via WS 2020-10-02 21:02:37 +02:00
Eloy Lafuente (stronk7) fadd2915eb MDL-69146 composer: bump to moodle-behat-extension 3.310.0
Generated following the instructions @:

https://docs.moodle.org/dev/Composer#How_to_prepare_and_submit_composer_changes

(using php72)

Note that here we are jumping to 3-digit branches (for all branches > 39),
exactly how we have done for moodle.git branches (310, 311, 400, 401...)
2020-10-02 15:07:01 +02:00
Sara Arjona c71355941b on-demand release 3.10dev+ 2020-10-02 13:44:05 +02:00
Nathan Nguyen 18871c74e2 MDL-69746 tool_replace: additional skip tables 2020-10-02 15:00:18 +10:00
Víctor Déniz 5cffc7f78b Merge branch 'MDL-69087-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE 2020-10-01 23:42:20 +01:00
Nathan Nguyen 946159a554 MDL-69572 mod_book : add bookid index to book_chapters 2020-10-01 23:28:21 +01:00
Eloy Lafuente (stronk7) 8d371859dc Merge branch 'MDL-69758-m310' of https://github.com/sammarshallou/moodle into MOODLE_310_STABLE 2020-10-01 23:44:15 +02:00
Claude Vervoort aad6afe979 MDL-57756 mod_lti: params change to text type 2020-10-01 17:32:44 -04:00
Sara Arjona d12c1406df MDL-69704 course: catch exception when calling get_course_content_items
When plugins are removed from disk, an exception is thrown when
calling component_callback_exists.
This exception should be catched here in order to load properly
the activity chooser (otherwise, the exception will be displayed
and no activity will appear).
2020-10-01 19:56:34 +02:00
Víctor Déniz 5130127a3e Merge branch 'MDL-69613-MOODLE_310_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_310_STABLE 2020-10-01 17:39:51 +01:00
Tim Hunt 651dbb729c MDL-69798 XML question export: excape special chars in idnumbers 2020-10-01 17:10:28 +01:00
Jamie Stamp 2c8db06e7a MDL-68665 assignfeedback_editpdf: Improve caching on stamps 2020-10-01 16:52:48 +01:00
Eloy Lafuente (stronk7) e98d18241f Merge branch 'MDL-69672-310' of git://github.com/aanabit/moodle into MOODLE_310_STABLE 2020-10-01 17:49:15 +02:00
Eloy Lafuente (stronk7) 3e460f45ac Merge branch 'MDL-69586-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-10-01 17:12:43 +02:00
Sara Arjona d5e30e0108 Merge branch 'MDL-69638_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-10-01 15:01:56 +02:00
Sara Arjona 7db1a61a72 Merge branch 'MDL-69050-310-allowlist' of git://github.com/mudrd8mz/moodle into MOODLE_310_STABLE 2020-10-01 14:51:12 +02:00
David Mudrák d335530a28 MDL-69772 admin: Better validation for the allcountrycodes setting
The patch introduces a new admin_setting fiela type that can be used for
specifying comma separated list of countries. The field has inbuilt
validation so that only valid country codes can be inserted.
2020-10-01 13:38:48 +02:00
Sara Arjona 6fe5bb1b96 MDL-69050 lang: Fix few remaining places spotted during integration 2020-10-01 13:01:58 +02:00
Sara Arjona e2a73965ca Merge branch 'MDL-68098-310' of git://github.com/dpalou/moodle into MOODLE_310_STABLE 2020-10-01 12:56:23 +02:00
Ferran Recio ccd0b96591 MDL-69582 tool_customlang: fix options layout 2020-10-01 11:04:10 +02:00
Ferran Recio 851f0d3354 MDL-69582 tool_customlang: add label to textarea 2020-10-01 11:04:10 +02:00
Sara Arjona 5576a97713 Merge branch 'MDL-67473-multipledeeplinking-squashed-310' of https://github.com/cengage/moodle into MOODLE_310_STABLE 2020-10-01 10:28:12 +02:00
Jake Dallimore b235c3a5a7 Merge branch 'MDL-69573-MOODLE_310_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_310_STABLE 2020-10-01 12:20:29 +08:00
Adrian Greeve c00b8b7cab Merge branch 'MDL-54956-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-10-01 11:17:44 +08:00
willob99 b19f178e0d MDL-69192 mod_assign: replace grading confirmation popup 2020-09-30 11:08:11 -07:00
David Matamoros 56b28e8e0b MDL-69805 mod_data: Freeze comment field if comments disabled 2020-09-30 15:51:02 +02:00
Matteo Scaramuccia 6658d9fba1 MDL-68536 core: Fix notice about undefined prop 'branch' in $CFG 2020-09-30 14:43:42 +02:00
Claude Vervoort 09dabe003a MDL-67473 mod_lti: deeplinking multiple support
AMOS BEGIN
 CPY [contentitem_help,mod_lti],[contentitem_deeplinking_help,mod_lti]
AMOS END
2020-09-30 08:04:53 -04:00
Nathan Nguyen 85f136094b MDL-69573 core_course: Make MAX_COURSES_IN_CATEGORY configurable 2020-09-30 16:04:55 +10:00
Adrian Greeve 1c55d84794 Merge branch 'MDL-37802-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-30 13:51:31 +08:00
Brendan Heywood 3ac504fd3d MDL-62678 core: Improve efficiency of notifications and avoid ajax call 2020-09-30 13:56:29 +10:00
Jake Dallimore 1f25df48b1 Merge branch 'MDL-68845-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-09-30 11:45:43 +08:00
Adrian Greeve 64ba1753a8 Merge branch 'MDL-68562_310' of https://github.com/mkassaei/moodle into MOODLE_310_STABLE 2020-09-30 11:12:34 +08:00
Eloy Lafuente (stronk7) 0e8d14f4e9 MDL-69638 install: update the list of stale files for 3.10 2020-09-29 22:37:56 +02:00
Víctor Déniz 9c28e07d31 Merge branch 'MDL-67841-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-09-29 18:33:48 +01:00
Sara Arjona 4ea44f96e5 Merge branch 'MDL-69342-310_profile_picture_deletion' of https://github.com/vtos/moodle into MOODLE_310_STABLE 2020-09-29 19:01:05 +02:00
Amaia Anabitarte c5c1b8b121 MDL-69672 core_contentbank: is_context_allowed unit tests 2020-09-29 17:47:37 +02:00
Amaia Anabitarte 3490f29ad9 MDL-69672 core_contentbank: Check used context level 2020-09-29 17:47:36 +02:00
Jun Pataleta 3b03a3da47 Merge branch 'MDL-69600-divertemails-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-09-29 20:27:36 +08:00
Sara Arjona a6aefe15f0 Merge branch 'MDL-65976-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-09-29 14:09:26 +02:00
Juan Leyva b294665c21 MDL-65976 completion: New course completion message provider 2020-09-29 13:41:49 +02:00
Brendan Heywood 2b50abffa2 MDL-69707 session: Avoid redis writes if the session is unchanged 2020-09-29 20:46:25 +10:00
Brendan Heywood acb848cdce MDL-69600 core: Expose divertallemails config in UI 2020-09-29 20:30:09 +10:00
Jun Pataleta 7cd362b873 Merge branch 'MDL-41492-310' of https://github.com/peterburnett/moodle into MOODLE_310_STABLE 2020-09-29 18:07:18 +08:00
Juan Leyva cc16de4ccc MDL-68845 calendar: New WS get_calendar_export_token 2020-09-29 10:56:29 +02:00
Juan Leyva c0af823086 MDL-68845 calendar: Move duplicated code to function 2020-09-29 10:54:05 +02:00
Eloy Lafuente (stronk7) 8b026809c5 on-demand release 3.10dev+ 2020-09-29 10:48:59 +02:00
Jun Pataleta 2dbc9a5005 Merge branch 'MDL-69283-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-09-29 13:53:53 +08:00
Claude Vervoort d224506353 MDL-68384 mod_lti: fix spec violations bo claim name and dl value type 2020-09-28 17:02:40 -04:00
Juan Leyva 0d1187b052 MDL-67841 tool_mobile: Inform about last access with the app 2020-09-28 21:40:54 +02:00
Víctor Déniz a2e3aa6806 Merge branch 'MDL-69644-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-28 20:34:01 +01:00
Shamim Rezaie adac2a9e55 MDL-69649 form: Fix labels for defaultcustom form elements 2020-09-28 23:43:01 +10:00
Shamim Rezaie 2fca843e49 MDL-69649 backup: Fix missing labels
- The backup details page uses a table to show a sumary of the backup
  content. Used role attribute to denote the tabular format of the
  summary.
- The backup details page displays activity name next to each activity
  icon. Therefore the icons are only decorative and do not need to have
  any title or even alt text.
- Form labels should be associated with form controls.  A div element is
  not a form control.
- The from attribute of the form labels should be equal to the id
  attribute of an element. Therefore, we first create a label and an
  input elements and associate them to each other, and then pass them to
  backup_detail_pair() when a label is needed.
2020-09-28 23:43:01 +10:00
Sara Arjona 157a497a3e Merge branch 'MDL-69695-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-28 13:03:21 +02:00
sam marshall 4f0fc4f45b MDL-69759 Web services: app checks to token.php cause log errors 2020-09-28 11:55:14 +01:00
Sara Arjona 27b1425eb2 Merge branch 'MDL-68935-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-09-28 11:41:01 +02:00
Peter Burnett 40e41c1997 MDL-41492 cache: Added ability for alternate cache config 2020-09-28 15:14:30 +10:00
Nathan Nguyen 89ce0b387e MDL-69613 gradereport: confirm message if override none is selected 2020-09-28 10:40:06 +10:00
Juan Leyva 9b64c178dd MDL-69283 webservice: New external setting for forcing timezone 2020-09-25 19:09:50 +02:00
Hittesh Ahuja 69cc1d1dd5 MDL-65074 mod_quiz: Quiz navigation buttons shouldnt use btn-secondary
Removing .btn-secondary as plain.scss and default.scss in bootstrap hide the button from view.
2020-09-25 15:14:06 +01:00
Juan Leyva 39c8e99e67 MDL-69776 files: New WS core_files_delete_draft_files 2020-09-25 10:38:25 +02:00
Paul Holden 833ab0ea9f MDL-37802 repository: return error if unzipping files fails.
For instance, when a user tried to unzip a password protected zip
archive using the file manager.
2020-09-25 09:33:54 +01:00
Paul Holden 2b87250347 MDL-69586 tool_usertours: use specified user in privacy prefs export. 2020-09-25 09:13:28 +01:00
Mahmoud Kassaei 95d1f1f18d MDL-68562 Qtype_essay: Adding file-size limit to the attachment files 2020-09-25 08:52:59 +01:00
Sara Arjona d23f05828f MDL-69087 core_h5p: add renderer to let personalize styles
Existing mod_hvp pluging has a renderer to let Moodle instances
alter styles, Javascript, semantics (fields in the editor) and
content: https://github.com/h5p/moodle-mod_hvp/blob/stable/renderer.php

The approach for core_h5p is exactly the same, to let people
to reuse their existing code.
2020-09-24 19:56:42 +02:00
David Mudrák 972340b678 MDL-69050 lang: Stop using the term blacklist in mustache output engine 2020-09-24 19:39:36 +02:00
David Mudrák 3971892bd3 MDL-69050 lang: Fix the variable name in the admin/cli/svgtool.php 2020-09-24 19:33:36 +02:00
David Mudrák b18b714165 MDL-69050 lang: Fix variable name and comment in core-notification YUI 2020-09-24 19:33:36 +02:00
David Mudrák 781545d34d MDL-69050 lang: Rename and deprecate filetypes_util methods 2020-09-24 19:33:32 +02:00
David Mudrák 19fe7f27a8 MDL-69050 lang: Improve the wording of the comments
Stop using the terms whitelist/blacklist when used to allow/deny things.
2020-09-24 19:32:40 +02:00
David Mudrák bd686af064 MDL-69050 lang: Fix the variable name in the Essay question type 2020-09-24 19:32:40 +02:00
David Mudrák fd18dc14ff MDL-69050 lang: Rename the filetypesnotwhitelisted string
Rename the string identifier to filetypesnotallowed, copy all the
existing translations in AMOS and deprecate the original string to be
eventually removed.

AMOS BEGIN
 CPY [filetypesnotwhitelisted,core_form],[filetypesnotallowed,core_form]
AMOS END
2020-09-24 19:32:40 +02:00
David Mudrák e840b14f4c MDL-69050 lang: Fix the variable name in the TeX filter library 2020-09-24 19:32:39 +02:00
David Mudrák 730aa1dcb0 MDL-69050 lang: Rename the whitelist variable in the Workshop locallib 2020-09-24 19:32:39 +02:00
David Mudrák 9ef6492e5d MDL-69050 lang: Fix variables and methods names in curl_security_helper
The code has been using terms that were found exclusive and potentially
derogatory. Fixing the terms and making the variables and methods
consistent with the related admin settings.
2020-09-24 19:32:39 +02:00
David Mudrák 41ad54e182 MDL-69050 lang: Fix placeholder in the err_wrongfileextension string
The name of the placeholder has been found exclusive and potentially
derogatory. Also the name of variable that was used to populate the
placeholder value. That was not the intention.
2020-09-24 19:32:39 +02:00
David Mudrák 2a1fb5b5e7 MDL-69772 admin: Fix legacy coding style on Location settings admin page
No actual change here. Just polishing the coding style and adding
fulltree check.
2020-09-24 18:14:29 +02:00
David Mudrák 56adf1f3d8 MDL-69772 lang: Ignore misconfigured allcountrycodes filter
If the allcountrycodes filter contains only invalid values, ignore the
whole filter setting and make get_list_of_countries() return the full
list of all known countries, rather than empty list.
2020-09-24 18:14:29 +02:00
Víctor Déniz a36870c175 weekly release 3.10dev 2020-09-24 16:27:15 +01:00
Eloy Lafuente (stronk7) a0f377cf2b Merge branch 'MDL-69698-310-licensecache' of git://github.com/mudrd8mz/moodle into MOODLE_310_STABLE 2020-09-24 16:50:39 +02:00
Eloy Lafuente (stronk7) 7905d70497 Merge branch 'MDL-69718-display-size-MOODLE_310_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_310_STABLE 2020-09-24 16:39:26 +02:00
Paul Holden d0a55062f9 MDL-69644 tool_dataprivacy: fix focus outline of contact DPO link.
The link class attribute is a leftover from 7258bf0b, which was mostly
removed in 3b2f691f. It no longer serves a purpose and interferes with
the element focus outline.
2020-09-24 11:53:29 +01:00
Vitaly 7f177d440c MDL-69342 core_user: fixed user picture updating
When editing a user and checking the 'Delete picture' checkbox to delete
the old picture and uploading a new one at a time, the new one didn't appear
in the user profile. This happened due to the 'if/else' statement
in the 'core_user::update_picture()' method which allowed either to delete
the old picture or to upload a new one.
The fix removes the 'else' part of the 'if/else' statement to force
checking for a new uploaded picture no matter if a user checked
the 'Delete picture' checkbox or not.
2020-09-24 10:29:31 +03:00
Bas Brands 8730ffcbe1 MDL-66587 mod_quiz: visible quiz timer 2020-09-24 11:32:18 +08:00
Bas Brands 486aa319c2 MDL-69454 core_search: consistent backup search 2020-09-23 17:36:15 +02:00
Bas Brands 6fa8e1c86f MDL-69454 core_search: consistent cohort search 2020-09-23 17:36:15 +02:00
Bas Brands dcfb713ca6 MDL-69454 core_search: consistent content bank search 2020-09-23 17:36:15 +02:00
Bas Brands 9d82cdb62e MDL-69454 core_search: consistent activity chooser search 2020-09-23 17:36:15 +02:00
Bas Brands a88f50d1b2 MDL-69454 core_search: consistent template library search 2020-09-23 17:36:15 +02:00
Bas Brands 94adb3429b MDL-69454 core_search: consistent capability search 2020-09-23 17:36:15 +02:00
Bas Brands bd516bf05c MDL-69454 core_search: consistent tag search 2020-09-23 17:36:15 +02:00
Bas Brands 02829c03c1 MDL-69454 core_search: message search 2020-09-23 17:36:14 +02:00
Bas Brands e9435e8f6d MDL-69454 core_search: consistent mod searches 2020-09-23 17:36:14 +02:00
Bas Brands 6a750d283d MDL-69454 core_search: consistent block searches 2020-09-23 17:36:14 +02:00
Bas Brands b5e39191fc MDL-69454 core_search: consistent course management search 2020-09-23 17:36:14 +02:00
Bas Brands 42c1cf3b03 MDL-69454 core_search: consistent frontpage course search 2020-09-23 17:36:14 +02:00
Bas Brands a5cd815635 MDL-69454 core_search: consistent admin search 2020-09-23 17:36:14 +02:00
Bas Brands 1fdb4fda4a MDL-69454 core_search: consistent navbar search 2020-09-23 17:36:14 +02:00
Juan Leyva 61772eb89b MDL-54956 quiz: Fix WS to support files submission 2020-09-23 12:52:45 +02:00
Juan Leyva e49ccc92c4 MDL-54956 quiz: Return response files in attempts 2020-09-23 12:52:45 +02:00
Dani Palou f9f289f69d MDL-68098 tests: Reset FILTERLIB_PRIVATE after tests 2020-09-23 12:09:08 +02:00
Dani Palou e16b858ff9 MDL-68098 ws: Add unit tests to test mathjax in WS 2020-09-23 12:08:52 +02:00
Dani Palou f4bdb898c7 MDL-68098 ws: Fix WebServices broken by filters HTML 2020-09-23 12:08:40 +02:00
Eloy Lafuente (stronk7) 2d502fd749 Merge branch 'MDL-68229-310' of git://github.com/jleyva/moodle into MOODLE_310_STABLE 2020-09-23 11:51:16 +02:00
Eloy Lafuente (stronk7) b552d604ff Merge branch 'MDL-69014-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-22 23:04:57 +02:00
Eloy Lafuente (stronk7) 6d73afb2bf Merge branch 'MDL-66934-coursehistory-310' of https://github.com/cengage/moodle into MOODLE_310_STABLE 2020-09-22 14:40:12 +02:00
Juan Leyva 0ad2d843d7 MDL-64657 course: Return hidden section names when configured 2020-09-22 11:53:04 +02:00
Eloy Lafuente (stronk7) 82a1e8fae7 Merge branch 'MDL-66648-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-21 23:36:22 +02:00
Eloy Lafuente (stronk7) a2c1a20055 Merge branch 'MDL-69667-MOODLE_310_STABLE' of https://github.com/comete-upn/moodle into MOODLE_310_STABLE 2020-09-21 23:20:05 +02:00
David Mudrák 76c3dc5f6b MDL-67275 forum: Fix language and accessibility issues with buttons
There were inconsistencies with the text shown on the submit button,
depending on the where the button was shown.

* Inline reply forum displayed general "Submit".
* Experimental nested discussion view reply form displayed "Post"
  (post/core string) which acts as a noun in other contexts and cannot
  be used as such in many non-English languages.
* Advanced reply form displayed "Post to forum".

The patch fixes this and starts to show "Post to forum" in all three
places consistently.

While working on this, two more issues were noticed and fixed:

* Inline reply textarea's title was hard-coded English "post" text.
  Changed to "Message" to provide advisory information related to the
  element.
* Buttons contained title attribute with the same value as the explicit
  button text. This goes against accessibility guidelines.
2020-09-21 22:50:43 +02:00
sam marshall 62ea8b1cae MDL-69758 Web services: core_get_course_contents PHP warnings
Calls to core_get_course_contents can cause PHP warnings in the server
log if there are any URL instances in the course with sketchy URLs.
This is because url_export_contents incorrectly returns null instead
of an empty array if there is an error.
2020-09-21 15:28:11 +01:00
Brendan Heywood c36d5093e3 MDL-69718 core: Added support for TB and PT to display_size 2020-09-21 12:55:44 +10:00
Claude Vervoort fae57261e7 MDL-66934 mod_lti: support context history param 2020-09-18 14:06:58 -04:00
Juan Leyva 11a49b08e7 MDL-68229 tool_mobile: Add missing option to disable tags in the app 2020-09-18 15:31:03 +02:00
Sara Arjona a730c334c7 MDL-69548 grunt: build ignorefiles 2020-09-18 09:56:22 +02:00
Sara Arjona fb5e3957be Merge branch 'MDL-69548-310' of git://github.com/mickhawkins/moodle into MOODLE_310_STABLE 2020-09-18 09:41:10 +02:00
Michael Hawkins 54524f1ff0 MDL-69548 core: Adding the http-message library
This is a dependency of ZipStream
2020-09-18 10:03:22 +08:00
Michael Hawkins bbfbe8e260 MDL-69548 core: Adding the php-enum library
This is a dependency of ZipStream
2020-09-18 10:03:22 +08:00
Michael Hawkins cfe02e4d3e MDL-69548 core: Adding the ZipStream library
This allows downloading of zip files as a stream, and will be used by
the Download course content project (MDL-69540).
2020-09-18 10:03:22 +08:00
Eloy Lafuente (stronk7) 611399214b weekly release 3.10dev 2020-09-17 19:04:13 +02:00
David Mudrák 321de29e93 MDL-69355 file: Do not attempt to set headers after output started
It was found out that in certain situations there may be some content
in to output handlers buffers. Let's allow that to happen given that:

* default handler's buffer is not sent as a part of the file and an
  error is reported into the server log.
* other handlers' buffer is sent with the assumption that it is required
  for the correct serving of the file.
2020-09-17 17:37:28 +02:00
Eloy Lafuente (stronk7) f200ba55f8 Merge branch 'MDL-69395_310' of github.com:stronk7/moodle into MOODLE_310_STABLE 2020-09-17 17:02:08 +02:00
Eloy Lafuente (stronk7) 8d791e12ba MDL-69395 theme_classic: remove superfluous selector already in boost 2020-09-17 13:05:40 +02:00
Jun Pataleta 8923308d47 Merge branch 'MDL-69630-310' of git://github.com/mihailges/moodle into MOODLE_310_STABLE 2020-09-17 09:17:23 +02:00
Eloy Lafuente (stronk7) 0e97e40e5a Merge branch 'MDL-62387-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-17 09:17:23 +02:00
Eloy Lafuente (stronk7) 7254648363 Merge branch 'MDL-68909-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE
Bump version to 2020091000.02 (01 was already current)
2020-09-17 09:17:20 +02:00
Eloy Lafuente (stronk7) c3176af430 Merge branch 'MDL-69664-310' of git://github.com/junpataleta/moodle into MOODLE_310_STABLE 2020-09-17 09:16:52 +02:00
Eloy Lafuente (stronk7) cb82c4d901 Merge branch 'MDL-69395-310' of git://github.com/bmbrands/moodle into MOODLE_310_STABLE 2020-09-17 09:16:52 +02:00
Sara Arjona bf127517b3 Merge branch 'MDL-68688-310' of git://github.com/aanabit/moodle into MOODLE_310_STABLE 2020-09-17 09:16:52 +02:00
Jun Pataleta 29e56fef72 Merge branch 'MDL-69663-m310' of https://github.com/sammarshallou/moodle into MOODLE_310_STABLE 2020-09-17 09:16:52 +02:00
Sara Arjona b249ab9df4 Merge branch 'MDL-68564_before_footer' of git://github.com/davosmith/moodle into MOODLE_310_STABLE 2020-09-17 09:16:52 +02:00
Sara Arjona 7805d0bb44 MDL-68909 h5p: move temporary editor files to draft area 2020-09-17 09:16:51 +02:00
Sara Arjona 6fcc509ed1 MDL-68909 h5p: upgrade step to remove files in editor filearea
As temporary editor files have been moved from core_h5p/editor to
user/draft, they can be removed (to clean unused DB entries).
2020-09-17 09:16:49 +02:00
Mihail Geshoski ebd136ca12 MDL-69630 format_social: Fix behat tests 2020-09-17 12:24:39 +08:00
Stephen Bourget c96a155937 MDL-69630 format_social: Add ajax support 2020-09-17 12:24:39 +08:00
Juan Leyva fdb7f85140 MDL-68935 course: Return context data in get_content WS 2020-09-16 12:43:53 +02:00
David Mudrák fbae45d7c9 MDL-69698 licenses: Improve the performance of the licenses cache
The cache uses a single simple key and there is no need to hash it.
2020-09-15 10:35:34 +02:00
David Mudrák a398a60092 MDL-69698 licenses: Do not cache the localised licenses fullnames
The localisation must happen only after loading the list of licenses
from cache so that the name is displayed in the current user's preferred
language, not in the language of the user who initiated the cache
rebuild.
2020-09-15 10:35:34 +02:00
Paul Holden de0e594a10 MDL-62387 tool_lp: switch to core 'cohort' form element.
The autocomplete AJAX is identical to the version in tool_lp, but also
includes support for excluding suggestions (i.e. cohorts already
synced with the current learning plan).
2020-09-15 08:08:11 +01:00
comete-upn 93097192e6 MDL-69667 competencies: fix competencies count always 0 in frameworks. 2020-09-15 08:37:53 +02:00
Jun Pataleta 1427573cde Merge branch 'MDL-68702-MOODLE_310_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_310_STABLE 2020-09-15 11:56:28 +08:00
Jun Pataleta 28790a42ad Merge branch 'MDL-42012-310-alt' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-09-15 11:52:56 +08:00
Andrew Nicols e5f0085cdb MDL-42012 cache: Fix missing return value 2020-09-15 11:46:31 +08:00
Eloy Lafuente (stronk7) 682593054d Merge branch 'MDL-42012-310-alt' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-09-14 23:28:54 +02:00
Eloy Lafuente (stronk7) 8fba6189fe Merge branch 'MDL-69658-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-14 22:56:42 +02:00
Paul Holden 31188e93d6 MDL-69695 mod_folder: use forcedownload setting during inline display. 2020-09-14 21:40:38 +01:00
Paul Holden 9bc368f71c MDL-69014 tool_usertours: clean up user preferences of deleted tours. 2020-09-14 20:36:28 +01:00
Paul Holden 1aa7c68c6f MDL-66648 user: consistent checks for linking to full profile.
The access checks for displaying a link to a users' full profile
now match the checks performed on the full profile page itself.
2020-09-14 20:22:05 +01:00
Davo Smith 23efc7337a MDL-68564 outputrenderers: extend before_footer hook to allow output 2020-09-14 11:00:36 +01:00
Nathan Nguyen cf4b6c8c94 MDL-68702 core_backup: exclude legacy course files 2020-09-11 10:59:28 +10:00
Amaia Anabitarte abb2037b0f MDL-68688 core_contentbank: Empty content bank notification 2020-09-10 11:58:53 +02:00
sam marshall c94b6b2ab7 MDL-69663 Web services: override_webservice_execution not honoured
If two different plugin types (e.g. theme, local) implement
override_webservice_execution callbacks, then all of them except
the 'last' plugin type do not work correctly.
2020-09-10 09:50:50 +01:00
Sara Arjona ab5d361c80 weekly release 3.10dev 2020-09-10 08:52:01 +02:00
Jun Pataleta 334333b6c7 MDL-69664 mod_lti: Apply correct badge class to tool card 2020-09-09 23:34:39 +08:00
Bas Brands 3d08cd2272 MDL-69395 theme_boost: improve colour contrast for form input fields
- for this issue the atto styles.css was moved into theme boost so
we can use our preset variable for $gray-500
2020-09-09 13:41:32 +02:00
Sara Arjona 83a5ed90ce Merge branch 'MDL-69466-3.10' of https://github.com/JBThong/moodle into MOODLE_310_STABLE 2020-09-09 11:39:16 +02:00
Sara Arjona d945333b47 Merge branch 'MDL-69645-310' of git://github.com/lucaboesch/moodle into MOODLE_310_STABLE 2020-09-09 11:00:49 +02:00
Jun Pataleta da84b731c7 Merge branch 'MDL-57682-310-fix' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-09-09 16:06:02 +08:00
Andrew Nicols 36f3b1e418 MDL-57682 mediaplayer_videojs: Improve in-page caching of lang strings 2020-09-09 15:37:54 +08:00
Andrew Nicols a3cc6898e9 MDL-57682 mediaplayer_videojs: Login not required for lang fetch 2020-09-09 15:37:52 +08:00
Thong Bui fcbca18c7b MDL-69466 Autocomplete widget: Improve keyboard accessibility 2020-09-09 13:44:23 +07:00
Tien Nguyen c0280f4405 MDL-68797 Administration: Add auto complete setting 2020-09-09 14:37:34 +08:00
Sara Arjona c83543095a Merge branch 'MDL-69521_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-09-09 08:08:29 +02:00
Andrew Nicols 13e34fb428 MDL-42012 cache: Valid definitions are required even when disabled 2020-09-09 14:05:03 +08:00
Andrew Nicols c705434a62 MDL-42012 cache: Fully disable cache for disabled cache factory 2020-09-09 14:05:03 +08:00
Andrew Nicols cfe1a9a8d8 MDL-42012 cache: Allow data sources to work when caching is disabled 2020-09-09 14:05:03 +08:00
Andrew Nicols 94d05a5bfb MDL-68797 tool_mobile: Version bump 2020-09-09 12:43:55 +08:00
Tien Nguyen 2562b9f3a3 MDL-68797 Administration: Setting for mobile file type exclusion list 2020-09-09 12:29:06 +08:00
Andrew Nicols e8b05c6cb4 Merge branch 'MDL-57682-310' of git://github.com/rezaies/moodle into MOODLE_310_STABLE 2020-09-09 12:23:33 +08:00
Eloy Lafuente (stronk7) 8f0297915c Merge branch 'MDL-69116-310' of git://github.com/rezaies/moodle into MOODLE_310_STABLE 2020-09-08 23:16:24 +02:00
Paul Holden b25763e875 MDL-69658 quizaccess_seb: progress bar on install only when necessary. 2020-09-08 19:32:24 +01:00
Eloy Lafuente (stronk7) 84bcfbb0d5 MDL-69521 core: Move all comments in code from 4.4 to 4.2 2020-09-08 19:01:42 +02:00
Eloy Lafuente (stronk7) e419e7acba MDL-69521 core: Move all comments in code from 4.3 to 4.1 2020-09-08 19:01:41 +02:00
Eloy Lafuente (stronk7) 309aad5a82 MDL-69521 core: Move all comments in code from 4.2 to 4.0 2020-09-08 19:01:41 +02:00
Eloy Lafuente (stronk7) 8452418666 MDL-69521 core: Move all comments in code from 4.1 to 3.11 2020-09-08 19:01:36 +02:00
Eloy Lafuente (stronk7) 5ba67416e6 Merge branch 'MDL-69510-310' of https://github.com/snake/moodle into MOODLE_310_STABLE 2020-09-08 15:28:33 +02:00
Sara Arjona bd0de2d965 Merge branch 'MDL-69525-310-1' of git://github.com/mihailges/moodle into MOODLE_310_STABLE 2020-09-08 14:21:46 +02:00
Sara Arjona db54910ce2 Merge branch 'MDL-28501-310' of https://github.com/mackensen/moodle into MOODLE_310_STABLE 2020-09-08 13:28:51 +02:00
Michael Hawkins 9d356676c3 MDL-69340 tag: Correct the filter input HTML in the tag manager 2020-09-08 08:54:33 +02:00
Mihail Geshoski a9d3f4b96c MDL-69048 book: Sanitize previous chapter value in add new chapter page 2020-09-08 08:54:33 +02:00
Andrew Nicols ca6cf0bd21 MDL-68974 calendar: Use page context for block check 2020-09-08 08:54:33 +02:00
Andrew Nicols 7d990ee185 MDL-68974 blocks: Check permission before generating content 2020-09-08 08:54:33 +02:00
Mihail Geshoski e2a11dc2aa MDL-65115 repository: Prevent unzipping if it will exceed allowed quota 2020-09-08 08:54:33 +02:00
Mihail Geshoski a2a6303397 MDL-65115 core_files: Add get_total_content_size() in stored_file class
New function get_total_content_size() is introduced in the stored_file
class. The puprose of this function is to calculate and return the
total size (in bytes) of the content of an archive file.
2020-09-08 08:54:33 +02:00
Andrew Nicols 6c4cdd6d96 MDL-68974 admin: Unit tests for context parent/child test 2020-09-08 08:54:33 +02:00
Andrew Nicols 4bb41b4e5a MDL-68974 admin: Unit tests for loginas 2020-09-08 08:54:33 +02:00
Andrew Nicols a937d4d807 MDL-68974 admin: Prevent login as outside of the desired context 2020-09-08 08:54:33 +02:00
Thong Bui 2301f9bfaa MDL-68344 filepicker: File Picker focus lost on upload 2020-09-08 08:45:09 +02:00
Jun Pataleta 0e9c755896 Merge branch 'MDL-69492-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-08 12:56:38 +08:00
Eloy Lafuente (stronk7) 3452156e6e Merge branch 'MDL-69262-310-2' of git://github.com/junpataleta/moodle into MOODLE_310_STABLE 2020-09-07 23:42:53 +02:00
Eloy Lafuente (stronk7) 6ef1780225 Merge branch 'MDL-69448-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-07 23:26:08 +02:00
Eloy Lafuente (stronk7) a8c60a4c31 Merge branch 'MDL-69577-310' of git://github.com/crazyserver/moodle into MOODLE_310_STABLE 2020-09-07 23:09:37 +02:00
Luca Bösch b2995f7a29 MDL-69645 quizaccess: Set allowPreferencesWindow to false in manual conf
Signed-off-by: Luca Bösch <luca.boesch@bfh.ch>
2020-09-07 22:40:58 +02:00
Charles Fulton 51201bc672 MDL-28501 mod_folder: make force downloading behavior configuable 2020-09-07 14:40:40 -04:00
Mathew May aa13890df0 MDL-69240 tool_moodlenet: Clean MoodleNet profile field
Amended by: Eloy Lafuente (stronk7) <stronk7@moodle.org>
- adjust versions for every branch.
- modify verify_webfinger->profileurl external to PARAM_NOTAGS.
2020-09-07 17:36:22 +02:00
Sara Arjona 644b80410d Merge branch 'MDL-69632-310-adminserversettings' of git://github.com/mudrd8mz/moodle into MOODLE_310_STABLE 2020-09-07 13:44:03 +02:00
Sara Arjona b36a28b37a Merge branch 'MDL-67468-MOODLE_310_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_310_STABLE 2020-09-07 13:19:56 +02:00
Mathew May 386223bd86 MDL-62609 lang: Final removal of deprecated strings 2020-09-07 08:06:32 +02:00
Sara Arjona 95359bf9e7 Merge branch 'MDL-63261-310' of https://github.com/Chocolate-lightning/moodle into MOODLE_310_STABLE 2020-09-07 07:30:17 +02:00
Mathew May 1bc2a3b345 MDL-63261 messaging: Final 3.6 deprecations 2020-09-07 09:09:07 +08:00
Eloy Lafuente (stronk7) 709b46dbfd MDL-69521 core: Move all comments in code from 4.0 to 3.10 2020-09-06 17:23:58 +02:00
Shamim Rezaie 94c19e0fea MDL-57682 media_videojs: Cache videojs languages in the localstorage 2020-09-04 18:55:16 +10:00
Shamim Rezaie 4a60349a8a MDL-57682 media_videojs: webservice to get the language pack of videojs 2020-09-04 18:51:37 +10:00
Shamim Rezaie 2189db9c86 MDL-57682 media_videojs: convert videojs loader to es6 2020-09-04 18:51:37 +10:00
David Mudrák f54cb0c257 MDL-69632 admin: Fix the legacy coding style at the server section
No actual changes to the file made, only reformatted and cleaned up to
follow the recent coding guidelines.
2020-09-04 10:23:06 +02:00
Paul Holden 95e0ff974c MDL-69492 auth_ldap: normalise member distinguished name config. 2020-09-04 08:25:58 +01:00
Paul Holden db361e09e7 MDL-69492 auth_cas: normalise member distinguished name config. 2020-09-04 08:25:58 +01:00
Paul Holden f2b1242364 MDL-69448 backup: fix capability checks when unable to copy user data.
When a given user doesn't have the capability to "Include user data"
during course copying, freeze the form element rather than not adding
it at all.

This caused problems as the element was required before preceding with
the course copy.
2020-09-04 08:20:04 +01:00
Nathan Nguyen d0fd7bc58c MDL-67468 filter_activitynames: use MUC 2020-09-04 15:41:52 +10:00
Sara Arjona 916809d995 weekly release 3.10dev 2020-09-03 17:09:17 +02:00
Sara Arjona e22ac10067 NOBUG: Fixed SVG browser compatibility 2020-09-03 17:09:12 +02:00
Andrew Nicols f558127d0e MDL-69391 behat: Grammar correction in feature 2020-09-03 11:35:08 +08:00
Andrew Nicols fc1d22ea70 Merge branch 'MDL-69391-310' of git://github.com/junpataleta/moodle into MOODLE_310_STABLE 2020-09-03 11:35:04 +08:00
Jun Pataleta 5d1979c911 MDL-69391 calendar: Accessibility tests for calendar 2020-09-03 11:11:29 +08:00
Jun Pataleta fe346f0afb MDL-69391 auth: Colour contrast accessibility test for login page 2020-09-03 11:11:29 +08:00
Jun Pataleta 8d5470145d MDL-69391 theme: Darken course selector text colour
Use $gray-600 for a darker text colour in the course select box.
This also makes the colour consistent with the view selector which
also uses $gray-600.
2020-09-03 11:11:29 +08:00
Jun Pataleta 61d32ad081 MDL-69391 theme: Darken navbar-light colour
Increase the opacity for the sass variable $navbar-light-color a
little bit in order to achieve an acceptable colour contrast against
the white background.
2020-09-03 11:11:29 +08:00
Dmitrii Metelkin 558ef4f778 MDL-69418 backup: attach data to grade items 2020-09-03 11:08:00 +08:00
Andrew Nicols c8221dedcd Merge branch 'MDL-69360-310' of git://github.com/NoelDeMartin/moodle into MOODLE_310_STABLE 2020-09-03 10:52:02 +08:00
Andrew Nicols 5265491a8f Merge branch 'MDL-69246_310' of https://github.com/timhunt/moodle into MOODLE_310_STABLE 2020-09-03 10:39:58 +08:00
Jake Dallimore b96e85feac MDL-69510 admin: make ldap configuration warnings clear 2020-09-03 10:26:00 +08:00
Andrew Nicols 817d6dcdbb Merge branch 'MDL-55340-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE 2020-09-03 10:13:49 +08:00
Andrew Nicols de1a942280 Merge branch 'MDL-69069-310' of git://github.com/bmbrands/moodle into MOODLE_310_STABLE 2020-09-03 09:33:05 +08:00
Andrew Nicols 3e1c856bd9 MDL-69117 output: Correct remove_dir usage 2020-09-03 09:01:43 +08:00
Bas Brands cce23499e6 MDL-69117 theme_boost: themedesigner source maps 2020-09-03 08:40:41 +08:00
Bas Brands 74160de2cb MDL-69117 theme_boost: deprecate the autoprefixer 2020-09-03 08:40:41 +08:00
Eloy Lafuente (stronk7) 4ca7232b1f Merge branch 'MDL-55971-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-03 00:51:33 +02:00
Peter Burnett ded581156a MDL-67306 webservices: Added webservice for Grade category creation 2020-09-03 00:21:44 +02:00
Marina Glancy 4cfc74d176 MDL-69608 core_form: frozen forms do not have form tag 2020-09-02 23:48:39 +02:00
Sara Arjona 893cf77d33 Merge branch '67278-moodle-310-categories-selector' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_310_STABLE 2020-09-02 17:37:24 +02:00
Sara Arjona e66f450c8f Merge branch 'MDL-68680-MOODLE_310_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_310_STABLE 2020-09-02 17:16:01 +02:00
Julien Boulen f9f41f5061 MDL-67278 course: Use autocomplete widget for course category selector 2020-09-02 16:00:20 +02:00
Eloy Lafuente (stronk7) 76e2d15794 Merge branch 'MDL-69174-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE 2020-09-02 13:14:34 +02:00
Sara Arjona 31d3fd27fc MDL-69174 mod_h5pactivity: component passed always
The $component = 'mod_h5pactivity' will be passed always to the H5P
player because it's required for being able to call these activities
from outside using embed code. The xAPI implementation checks whether
the information should be tracked or not.
2020-09-02 12:12:25 +02:00
Sara Arjona 2874c6d5a1 MDL-69174 h5p: add component to the embed H5P code
When the Moodle component is passed to the player, xAPI tracking
is enabled so, if the component implements required xAPI API methods
(for instance, mod_h5pactivity does), grades and responses are sent.
Adding this component to the embed code will help to add
the embed code from a mod_h5pactivity to any other place (such as label,
page or book), and being able to track the responses to the original
mod_h5pactivity.
2020-09-02 12:12:25 +02:00
Noel De Martin d8892dcca3 MDL-69360 behat: Fix js ready checks for non-moodle sites 2020-09-02 10:20:28 +02:00
Andrew Nicols 85a1c2c99e Merge branch 'MDL-68892-310' of git://github.com/ferranrecio/moodle into MOODLE_310_STABLE 2020-09-02 09:48:59 +08:00
Dan Marsden 58bf730494 MDL-69190 grade: fix slow query. 2020-09-02 09:31:28 +08:00
Farhan Karmali d179137f1b MDL-67419 admin: New admin setting for lang during user creation 2020-09-02 08:54:47 +08:00
Eloy Lafuente (stronk7) 8eafd115cc Merge branch 'wip_MDL-69491_m310' of git://github.com/gjb2048/moodle into MOODLE_310_STABLE 2020-09-02 00:27:36 +02:00
Eloy Lafuente (stronk7) 3b111cf8a0 Merge branch 'MDL-69174-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE 2020-09-02 00:21:55 +02:00
Sara Arjona a244344e2e Merge branch 'MDL-63387-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-01 16:58:15 +02:00
Pau Ferrer Ocaña 23fed91412 MDL-69577 forum: Add courseid, forumid on get_discussion_posts response 2020-09-01 14:26:08 +02:00
Sara Arjona dee4097c9d Merge branch 'MDL-64525-m310' of https://github.com/NeillM/moodle into MOODLE_310_STABLE 2020-09-01 14:18:05 +02:00
Paul Holden 7665c701fd MDL-63387 course: use renamed role names, update Behat tests.
Specify that we want both role names (renamed course role plus
original).
2020-09-01 12:05:26 +01:00
Paul Holden 3827cbe523 MDL-63387 user: show both role names on course participants page. 2020-09-01 12:05:26 +01:00
Paul Holden f6a2d57b3e MDL-63387 enrol_cohort: show both roles names in instance config form. 2020-09-01 12:05:25 +01:00
Paul Holden 35a5c1adda MDL-63387 enrol_manual: show both role names in enrol users dialog. 2020-09-01 12:05:25 +01:00
Paul Holden e4d86a6ec4 MDL-63387 access: add parameter to define how role names are returned. 2020-09-01 12:04:47 +01:00
Sara Arjona 8d2229db48 Merge branch 'MDL-51709-310' of git://github.com/lucaboesch/moodle into MOODLE_310_STABLE 2020-09-01 09:04:13 +02:00
Mihail Geshoski 4d6b3406c5 MDL-69525 core: Publish a single event when toggling slave checkboxes 2020-09-01 14:53:54 +08:00
Sara Arjona 11a58dd4b0 Merge branch 'MDL-69394-310' of git://github.com/junpataleta/moodle into MOODLE_310_STABLE 2020-09-01 06:45:12 +02:00
Andrew Nicols 0713666486 Merge branch 'MDL-69507_310' of https://github.com/timhunt/moodle into MOODLE_310_STABLE 2020-09-01 11:15:55 +08:00
Andrew Nicols 260e9753d4 Merge branch 'MDL-69387-310-2' of git://github.com/junpataleta/moodle into MOODLE_310_STABLE 2020-09-01 10:59:37 +08:00
Sara Arjona e83fad7382 Merge branch 'MDL-38350-m310' of https://github.com/sammarshallou/moodle into MOODLE_310_STABLE 2020-09-01 07:28:40 +08:00
Andrew Nicols c7e5431086 Merge branch 'MDL-69505-310' of https://github.com/snake/moodle into MOODLE_310_STABLE 2020-09-01 07:28:27 +08:00
Andrew Nicols 10ba6d0aa1 Merge branch 'MDL-69270-310' of git://github.com/ferranrecio/moodle into MOODLE_310_STABLE 2020-09-01 07:28:27 +08:00
Andrew Nicols a4f4cbf095 MDL-69269 contentbank: Fix issues identified in integration 2020-09-01 07:28:27 +08:00
Andrew Nicols 66c757f689 Merge branch 'MDL-69269-310' of git://github.com/sarjona/moodle into MOODLE_310_STABLE 2020-09-01 07:28:27 +08:00
Andrew Nicols 2f7236aa3c Merge branch 'MDL-68569-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-01 07:28:26 +08:00
Andrew Nicols a704b87f8b Merge branch 'MDL-56595-310' of https://github.com/paulholden/moodle into MOODLE_310_STABLE 2020-09-01 07:28:26 +08:00
Luca Bösch 59f48908aa MDL-51709 gradebook: Name display in single view. 2020-08-31 17:58:53 +02:00
Shamim Rezaie e6f0b5a3a3 MDL-69116 qtype_multichoice: accessibility improvement
- Screen-readers should not see 'clear my choice' when it is not visible
- 'clear my choice' option should only become visible when a choice is
selected
2020-08-31 23:53:54 +10:00
Shamim Rezaie 7a85cc6d2e MDL-69116 qtype_mutichoice: Use label for the "clear my choice" link 2020-08-31 23:53:54 +10:00
Bas Brands 3d08c7d396 MDL-69069 theme_boost: color contrast for custom alerts 2020-08-31 08:21:27 +02:00
Nathan Nguyen f809bca508 MDL-33981 repository_equella: support internal copy 2020-08-31 10:39:49 +08:00
Jake Dallimore fbcc91236e MDL-69505 core_form: fix js min/max date restriction in dateselector
This was using the yui2-calendar attribute, not the yui 3 attribute.
2020-08-31 07:57:50 +08:00
Ferran Recio 2dab18e681 MDL-69270 contentbank: replace content with file 2020-08-28 17:59:18 +02:00
Ferran Recio 3565a77362 MDL-68892 mod_h5pactivity: add required to package 2020-08-28 17:50:40 +02:00
Gareth Barnard cbecc140f7 MDL-69491 themes: No 'fontsize' setting in Boost causes unit conflict. 2020-08-28 14:14:38 +01:00
Sara Arjona c3a4859c7d MDL-69269 contentbank: add support to download content 2020-08-28 12:29:03 +02:00
Sara Arjona 330ba8cb10 MDL-69174 h5p: add component to the embed H5P code
When the Moodle component is passed to the player, xAPI tracking
is enabled so, if the component implements required xAPI API methods
(for instance, mod_h5pactivity does), grades and responses are sent.
Adding this component to the embed code will help to add
the embed code from a mod_h5pactivity to any other place (such as label,
page or book), and being able to track the responses to the original
mod_h5pactivity.
2020-08-28 12:26:38 +02:00
Marina Glancy 4e32add0ac MDL-55340 mod_feedback: export question labels
This was present in export in 3.0 but got lost during export
refactoring in 3.1
2020-08-28 12:25:09 +02:00
Eric Merrill e48fecc679 MDL-69112 assign: Improve parsing of uploaded feedback names 2020-08-28 13:29:20 +08:00
Nathan Nguyen d7113bee4e MDL-68680 core_grades: check grade item before trigger delete event 2020-08-28 11:40:31 +10:00
Paul Holden 61ce84f178 MDL-56595 tool_usertours: set page params when configuring tours/steps. 2020-08-27 23:08:15 +01:00
Tim Hunt e3bfcb1cde MDL-69246 questions: allow for float issues when validating manual marks
As well as fixing the bug, I also rewrote the test to use
data providers, which should lead to more useful failure messages.

And, I moved the magic number we used as the float tolerence to
be a named constant.
2020-08-27 17:39:15 +01:00
Sara Arjona 4a6a2636a0 weekly release 3.10dev 2020-08-27 17:36:21 +02:00
Jun Pataleta 09646d7b53 MDL-69262 core: Use core/action_menu_link in core/action_menu_trigger
* Introduce the "actionmenulinkclasses" block in the action_menu_link
template so other templates importing it can have the option to override
its classes.
* Have the action menu trigger template use the action menu link
template to reduce code duplication.
2020-08-27 13:30:32 +08:00
Jun Pataleta 9211552660 MDL-69262 core: Make instance count variable as a static class variable
With the static function variable $instance, calls to
\action_menu_link::export_for_template() from its subclasses are stored
in different variables. This causes duplicate IDs when different
implementations of action menu links are rendered on the action menu
trigger/link template. (e.g. action_menu_link and
action_menu_link_secondary both rendered on the same page).
To make the incrementing uniform for the action_menu_link class and its
implementations, the $instance variable is moved out of the
export_to_template() method and is now made to a static class variable.
2020-08-27 13:30:32 +08:00
Andrew Nicols f51678c56a Merge branch 'MOODLE_310_MDL-67211_v6' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-08-27 12:48:33 +08:00
Mihail Geshoski fa3b387185 MDL-69458 report_insights: Respect perpage value in pagination bar 2020-08-27 12:42:57 +08:00
Adrian Greeve dddff390da Merge branch 'MDL-69479-310' of git://github.com/mihailges/moodle into MOODLE_310_STABLE 2020-08-27 11:40:11 +08:00
Andrew Nicols 6bcc070827 Merge branch 'MDL-69501-310-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_310_STABLE 2020-08-27 11:30:53 +08:00
eWallah e1e362b7ff MDL-67413 competencies: do nothing upon activity completion 2020-08-27 11:11:08 +08:00
Mikhail Golenkov ae12edc741 MDL-67211 phpunit: Do not test the order of the running adhoc tasks. 2020-08-27 13:03:49 +10:00
Mikhail Golenkov 5934444b27 MDL-69358 backup: Do not clean up records for incomplete adhoc tasks.
Co-authored-by: Heena Agheda <heenaagheda@catalyst-au.net>
2020-08-27 10:57:48 +08:00
Andrew Nicols c187594e5b Merge branch 'MDL-66810-310' of git://github.com/peterRd/moodle into MOODLE_310_STABLE 2020-08-27 10:23:25 +08:00
Justin Hunt f9f0f1cc26 MDL-66810 mod_lti: Reinstate deprecated default permissions on iframe
microphone, webcam, camera, midi, encrypted-media, geolocation
2020-08-27 09:44:47 +08:00
Andrew Nicols f0b7948c96 MDL-66222 report_antivirus: Correct version number 2020-08-27 09:44:24 +08:00
Andrew Nicols 3114d04721 Merge branch 'MDL-66222-antivirus-reporting' of https://github.com/Peterburnett/moodle into MOODLE_310_STABLE 2020-08-27 09:36:33 +08:00
Adrian Greeve e78b9f9574 Merge branch 'MDL-69419-310' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-08-27 08:08:07 +08:00
Sara Arjona b0d96c297b Merge branch 'MDL-69389-310' of git://github.com/junpataleta/moodle into MOODLE_310_STABLE 2020-08-26 18:02:55 +02:00
Bas Brands 54d32ce4a9 MDL-69114 theme_boost: improve the color contrast for .*-info classes 2020-08-26 16:28:34 +02:00
Andrew Nicols 71f44b0611 Merge branch 'MOODLE_310_MDL-69307_v4' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-08-26 15:03:01 +08:00
Mikhail Golenkov b8a0258357 MDL-69307 restore: Add CLI script to restore a course.
Co-authored-by: Matt Porritt <mattp@catalyst-au.net>
2020-08-26 14:39:41 +10:00
Jun Pataleta db8fea04f5 MDL-69389 auth: Add wcag141 test for the login page accessibility test 2020-08-26 11:05:27 +08:00
Jun Pataleta 227281d355 MDL-69389 theme_classic: Make default body font colour darker
Links and normal text should have at least a colour contrast ratio
of 3:1. To achieve this, $body-color will be using the darker
shade of gray $gray-900 (#212529).
2020-08-26 11:05:27 +08:00
Jun Pataleta fb6460ca98 MDL-69389 theme_boost: Make default body font colour darker
Links and normal text should have at least a colour contrast ratio
of 3:1. To achieve this, $body-color will be using the darker
shade of gray $gray-900 (#212529).
2020-08-26 11:05:27 +08:00
Jun Pataleta 424c5df1eb MDL-69387 pix: Create PNG versions of the darkened completion icons
Thanks to Barbara Ramiro <barbara@moodle.com> for the help in
generating these PNG versions of the darkened completion icons!
2020-08-26 11:03:06 +08:00
Jun Pataleta 64c4074699 MDL-69387 pix: Darken completion icons
Darkened the fills of completion icons in order to meet the required
minimum contrast ratio of 3:1.
* Changed gray fills (#999) to #949494.
* Changed blue fills (#76A1F0) to #6393ee
* Changed green fills (#9C3) to #79a128

Thanks to Barbara Ramiro <barbara@moodle.com> for the help in
updating the SVG icons!
2020-08-26 11:03:06 +08:00
Jun Pataleta b4ab127434 MDL-69394 calendar: Fix event colour indicator contrast
* Darkened the link and clickable icon colours inside coloured events.
* Added borders around event colour indicators inside the month-view of
  the calendar for better contrast against the white background.
2020-08-26 11:00:22 +08:00
Andrew Nicols 4d03cc37b2 MDL-69419 core: Task reset tests cannot use random test times
If a scheduled task which uses a 'R' field is picked, then the reset of
updated task times will not necessarily be correctly determined as the
randomisation is picked during reset.

This can lead to some random test failures.

Actively specifying a test which does not make use of the 'R' random
field time addresses this issue.
2020-08-26 09:58:22 +08:00
Andrew Nicols 195e7c9cf1 Merge branch 'MOODLE_310_MDL-67211_v6' of https://github.com/golenkovm/moodle into MOODLE_310_STABLE 2020-08-26 09:41:07 +08:00
Paul Holden 1ffb6b09ee MDL-55971 dataformat: method to write exports to file storage. 2020-08-25 17:30:51 +01:00
Paul Holden 06411e3689 MDL-68569 customfield_select: get field options via instance method.
Deprecate the previous static method, which was only called from
instantiated field classes.
2020-08-25 15:08:12 +01:00
Mikhail Golenkov e419e18f0d MDL-67211 Tasks: Add cron_enabled setting.
Co-authored-by: Sam Marshall <s.marshall@open.ac.uk>
2020-08-25 17:01:00 +10:00
Mikhail Golenkov 3263daba84 MDL-67211 Tasks: Front-end to display currently running tasks.
Co-authored-by: Sam Marshall <s.marshall@open.ac.uk>
2020-08-25 17:00:46 +10:00
Mikhail Golenkov 59a5923924 MDL-67211 Tasks: Record when a task is running.
Co-authored-by: Sam Marshall <s.marshall@open.ac.uk>
2020-08-25 16:59:47 +10:00
Andrew Nicols f2602288eb MDL-69464 core_output: Whitespace fix 2020-08-25 13:22:36 +08:00
Marina Glancy 4413ca209f MDL-69464 core_output: allow to avoid formatting in page->set_heading 2020-08-25 13:22:36 +08:00
Adrian Greeve 427f046cff Merge branch 'MDL-68921-310' of git://github.com/vmdef/moodle into MOODLE_310_STABLE 2020-08-25 09:43:31 +08:00
Victor Deniz Falcon e29edbe89e MDL-68921 core_h5p: Add H5P libraries metadata settings
An upgrade step updates installed H5P libraries
2020-08-25 00:30:02 +01:00
Helen Foster e9df0c43bc MDL-69501 lang: Import fixed English strings (en_fix) 2020-08-24 09:53:02 +02:00
Neill Magill d71659dd6d MDL-64525 comments: Should not be able to delete frozen comments
Before this change in a frozen context a user would be able to delete
their own comments.

After this change a user will only be able to delete their own comments
if they still have the capability to post new comments or the capability
to delete comments from any user.
2020-08-24 08:00:10 +01:00
Neill Magill fb6c682850 MDL-64525 comments: Tests for deleting frozen comments 2020-08-24 08:00:10 +01:00
Mihail Geshoski 356a8ee948 MDL-69479 core: Change 4.0 to 3.10 in theme/upgrade.txt 2020-08-24 14:08:46 +08:00
Eloy Lafuente (stronk7) fe9ecef92b MDL-69479 upgrade: Change all 4.0 occurrences to 3.10
Under parallel development, when something is worth being commented
in upgrade.txt notes, it will be applied to all the development branches
using the "earliest" one to be released. So, if something changes
in 3.10 (and also is applied to master), the upgrade.txt notes will
show 3.10 in both branches.

Of course, if something only goes to one dev branch (say master), then the
master version will be used in the notes (4.0 in this case).
2020-08-24 14:08:46 +08:00
Paul Holden 9c1f7874d8 MDL-69493 cohort: remove escaping of return URL params. 2020-08-22 17:09:23 +02:00
Eloy Lafuente (stronk7) 96fac6d9ce weekly release 3.10dev 2020-08-21 20:42:59 +02:00
Adrian Greeve 4b327e1109 MDL-68683 competencies: Update previous bad bump update.
I made a mistake with the previous version bump and updated the
line below what I should have changed. This fixes it to the
intended version numbers.
2020-08-21 14:41:09 +08:00
Jun Pataleta f649cd722f Merge branch 'MDL-66818-310' of git://github.com/andrewnicols/moodle into MOODLE_310_STABLE 2020-08-21 11:32:21 +08:00
Andrew Nicols 03e84b68a1 MDL-66818 mod_forum: Use cap manager to check exportability 2020-08-21 08:17:01 +08:00
Andrew Nicols 51dc7d230f MDL-42434 chat: Disable stylelint important check 2020-08-21 07:39:24 +08:00
Sara Arjona 1044e94507 MDL-42434 mod_chat: styles for chat themes to view help-icon properly
The styles for the bubble and the compact themes have been reviewed
because there weren't enough contrast for the help icon.
2020-08-20 23:44:48 +01:00
Sara Arjona c4303bba51 MDL-42434 mod_chat: display the whole help text
When testing this issue was raised that the help text was cut-off.
This patch should fix this issue changing the placement from
right/left to top.
2020-08-20 23:44:47 +01:00
Andrew Nicols 9d32114bf6 MDL-68705 testing: New CLI args to disable composer features
This commit introduces the following new flags:

  --no-composer-self-update   Disable composer self-update of the
                              composer.phar utility

  --no-composer-upgrade       Disable upgrade of development
                              dependencies using Composer.

  --disable-composer          Disable both composer self-update and
                              composer upgrade
2020-08-20 20:14:54 +02:00
Andrew Nicols 8ddb17b641 MDL-68705 testing: Allow composer updates to be disabled 2020-08-20 20:14:50 +02:00
sam marshall 30990ac512 MDL-38350 Lib: Rename directory before removing it, to reduce races 2020-08-20 16:57:06 +01:00
Tim Hunt 0c6f661def MDL-69507 duration form field: should return an int number of seconds 2020-08-20 11:31:28 +01:00
Tim Hunt 24d0335a0a MDL-69507 duration form field: modernise coding style 2020-08-20 11:31:28 +01:00
Sara Arjona 52836faa5b MDL-69055 core_badges: display password/oauth fields properly 2020-08-20 12:01:49 +08:00
Peter Burnett 64f64e44d8 MDL-69486 webservices: Added user and grade idnumber to grade items 2020-08-20 11:59:41 +08:00
carlos a133b89976 MDL-69375 mod_lti: Fix Names and Roles Link header format
- Changed line 469 of memberships.php to build Link header according to the Web Linking specification RFC8288.
2020-08-20 11:50:54 +08:00
Ferran Recio 93fec2c58c MDL-68964 mod_chat: fix theme param 2020-08-20 11:41:10 +08:00
Sara Arjona 3db6d44feb MDL-42434 mod_chat: add again the usingchat help icon
In Moodle 2.4 the help icon displayed in the chat window was
removed. It has been added to gui_ajax and gui_basic in order to help users.
2020-08-20 11:23:03 +08:00
Adrian Greeve 83aa08c7e1 MDL-68683 competencies: Fix bad version bump. 2020-08-20 11:01:31 +08:00
Simey Lameze 79082f8b6b MDL-68683 competencies: fix query to delete stale files 2020-08-20 10:21:00 +08:00
Paul Holden 544c7d68b6 MDL-69449 block_timeline: use dayslimit context data in template.
Ensures the correct value is used when initially rendering the
course timeline.
2020-08-20 09:24:46 +08:00
Bas Brands 699a82df1a MDL-68889 block_recentlyaccessedcourses: small viewport issues
- on small devices the recentlyaccessedcourses does not show any courses
2020-08-20 09:16:38 +08:00
Peter Burnett d369c098be MDL-69170 task: Added timecreated field to adhoc task table 2020-08-20 08:50:42 +08:00
Sara Arjona 191448afc5 MDL-68975 contentbank: add author field to file details view 2020-08-20 08:42:20 +08:00
Eloy Lafuente (stronk7) 606fbca6b4 MDL-67415 environment: change requirements
- mysql requirement up to 5.7
- postgres requirement up to 9.6
2020-08-20 08:29:43 +08:00
Eloy Lafuente (stronk7) 050eb97c33 MDL-67415 environment: 3.10 base information
This is a direct copy of the 3.9 branch to have
changes under control easier for next commits.
2020-08-20 08:29:43 +08:00
Simey Lameze f6f824597a MDL-66818 mod_forum: remove unnecessary behat steps 2020-08-20 08:16:49 +08:00
gthomas2 f2b4fba61e MDL-66818 mod_forum: hide portfolio export button based on caps 2020-08-20 08:16:49 +08:00
Paul Holden 3a394dd671 MDL-66900 course: don't clean category description when editing. 2020-08-20 07:54:13 +08:00
Sara Arjona 98480b3932 MDL-69473 contentbank: change incorrect ref to size in type column 2020-08-20 07:43:56 +08:00
Eloy Lafuente (stronk7) e010b2e75c MDL-69271 auth_ldap: Don't assume any ordering, just verify matches
Both ldap or the DB can return information in a non-consistent
ordering leading to events to be generated in different order.

And current tests are, right now, assuming a given order.

Note this is a rare random, but it's happening, so better
fix it, see the issue for some more details.

So we just do the tests ordering immune, verifying that all the
expected events have been triggered and done. Irrespectively of their order.
2020-08-20 07:35:59 +08:00
Sara Arjona aa3a9c7895 MDL-69054 core_badges: allow editing OBv1.0 backpacks 2020-08-20 07:31:48 +08:00
Sara Arjona f075ec01ca MDL-61215 core_user: use the new optimised_image filetype group
For the user profile picture (instead of the web_image which includes
SVG files).
2020-08-20 07:16:41 +08:00
Sara Arjona c4c770f48c MDL-61215 core_badges: use the new optimised_image filetype group
For the badge picture (instead of the web_image which includes
SVG files).
2020-08-20 07:16:41 +08:00
Sara Arjona 24ce9b8a10 MDL-61215 core_files: add new optimised_image group
Currently, PHP getimagesize method doesn't support SVG images.
As some features, such as badges, processs and optimise the images
before using them, a new filetype group has been created to exclude
SVG from there: optimised_image.
SVG can't be removed from web_image because then users won't be
able to add SVG images to their courses using labels, pages...
2020-08-20 07:16:41 +08:00
Mihail Geshoski adebc5f811 MDL-69401 book: Limit character length in chapter title 2020-08-20 07:03:24 +08:00
Peter Dias afc19a201c MDL-69297 assign: Check whether there is content for a submission
Confirm there is some content to be submitted for an assignment when processing it.
2020-08-19 23:42:27 +01:00
Peter Dias aa7707cd52 MDL-66665 assign: Check whether a modified user could actually grade 2020-08-19 14:27:59 +08:00
Simey Lameze 676c840c5c MDL-68683 competencies: step to delete orphaned evidence files 2020-08-19 12:55:53 +08:00
Simey Lameze 1222c2125e MDL-68683 core: fix DML exception on upgrade step 2020-08-19 12:55:35 +08:00
Simey Lameze 776b4a85d1 MDL-26401 group: add delimiter and encoding fields to import 2020-08-19 11:11:14 +08:00
Amaia Anabitarte 29fe254b17 MDL-69089 core_contentbank: Empty content names are not allowed 2020-08-19 10:51:58 +08:00
Adrian Greeve bf84a08900 Merge branch 'MDL-69475_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-08-19 10:42:51 +08:00
Simey Lameze 97043c76b7 MDL-26401 group: change import to use csv_import_reader class 2020-08-19 08:51:32 +08:00
Andrew Nicols c1813ed818 MDL-67735 theme_boost: Fix incorrect whitespace 2020-08-19 08:39:15 +08:00
Bas Brands 49f1803c9d MDL-67735 theme_boost: remove bs2 and bs4alpha compatibility css 2020-08-19 08:29:50 +08:00
Amaia Anabitarte 157f8a87b4 MDL-69089 core_contentbank: Tests for empty content names 2020-08-19 08:19:44 +08:00
Leon Stringer c66bf80bd8 MDL-65847 auth_db: user_update() handle errors
The external database authentication plugin (auth_db) can update the
external database if mapped fields are set to Update external: On
update.  This change adds error handling in case this update fails.
2020-08-19 00:36:21 +02:00
Juan Leyva ad25efc776 MDL-69095 tool_mobile: Display warning if not allowed to use qr login 2020-08-19 00:20:54 +02:00
Juan Leyva 1019a2b5ba MDL-69095 tool_mobile: Avoid non-https sites using qrlogin by default 2020-08-19 00:20:54 +02:00
Matt Davidson 7404858689 MDL-63375 workshop: fix rubric grid view 2020-08-19 00:13:54 +02:00
Shamim Rezaie 7b313f407a MDL-68444 calendar: Improve how screenreaders say week titles
Also removed the scope attribute from the mini-calendar table
because according to https://www.w3.org/TR/WCAG20-TECHS/H63.html
it was not needed:
  Note 1: For simple tables that have the headers in the first row
  or column then it is sufficient to simply use the TH elements without
  scope.
2020-08-18 19:13:37 +02:00
Shamim Rezaie 931fc89e13 MDL-68444 calendar: Improve how screenreaders read day titles
Screenreaders now know if each day has any event or not
2020-08-18 19:13:27 +02:00
Mathew May fbbfe9aa00 MDL-68928 core_course: Select activity chooser footer 2020-08-18 19:02:25 +02:00
Victor Deniz Falcon b81952a23d Merge branch 'MDL-69477_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-08-18 12:48:09 +01:00
Eloy Lafuente (stronk7) 12ffcc5097 MDL-69475 backup: Proper handling of backup::RELEASE versions
1) Remove any floatval() casting. They are breaking / killing
   .10 versions (converting them to .1). Since Moodle 2.0 all the
   backup::RELEASE have been 100% numerical values.
2) Use version_compare() always to compare backup::RELEASE values.
   They are always versions and the function is aware of versions
   > .9, able to clean/ignore alpha chars... and everything else.

Note that I've also changed a couple of cases in formats (topics and
weeks) that were correct, but just added the same comment and used
the same version_compare() comparison parameters style, so all uses
in core are consistent (and safe to be copied out there).
2020-08-18 12:49:20 +02:00
Andrew Nicols bd1eaea02b MDL-69273 travis: Use exttests for https too 2020-08-18 10:59:13 +02:00
Andrew Nicols 99a8358b85 MDL-69273 travis: Move exttests check to after_script
The result of the final command `script` phase determines the build
result.

The cleanup belongs in the `after_script` phase.
2020-08-18 10:59:13 +02:00
Eloy Lafuente (stronk7) 0a352c4790 MDL-69477 install: Ensure CFG variables are set before using them
On installation (or also phpunit/behat unit) some CFG variables
were being used (on setting validation) before being set.

So this commit just verifies they are set before using them. Note that,
strictly speaking, only one of them ($CFG->searchenginequeryonly)
required the extra check, but I think it's better to apply it to all
them, as a reference and in case validations are run in any other order.
2020-08-17 10:53:38 +02:00
Nadav Kavalerchik 67dfb55d49 MDL-69414 qtype/ddimageortext: Fix dropzones display in RTL mode 2020-08-17 14:53:20 +08:00
Mihail Geshoski 12bd4bc5ad MDL-67943 core: Update timezone list in core_date 2020-08-17 10:36:01 +08:00
Adrian Greeve 22ec6995ea Merge branch 'MDL-69475_310' of https://github.com/stronk7/moodle into MOODLE_310_STABLE 2020-08-17 09:49:54 +08:00
Eloy Lafuente (stronk7) ae3af1d860 MDL-69475 install: Version, env. and minimal changes before branching
- Also bump travis to get builds against 310_STABLE.
- And backup release to match 3.10

Note this doesn't aim to be a complete change-set, but just the
minimum to switch to 3-digit $branches and keep installation, checks
and tests running and passing.
2020-08-17 00:12:30 +02:00
12880 changed files with 481119 additions and 786134 deletions
+95
View File
@@ -0,0 +1,95 @@
# Generated by "grunt ignorefiles"
*/**/yui/src/*/meta/
*/**/build/
node_modules/
vendor/
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
auth/cas/CAS/
cache/stores/mongodb/MongoDB/
enrol/lti/ims-blti/
filter/algebra/AlgParser.pm
filter/tex/mimetex.*
h5p/h5plib/v124/joubel/core/
h5p/h5plib/v124/joubel/editor/
lib/editor/atto/plugins/html/yui/src/codemirror/
lib/editor/atto/plugins/html/yui/src/beautify/
lib/editor/atto/yui/src/rangy/js/*.*
lib/editor/tinymce/plugins/pdw/tinymce/
lib/editor/tinymce/plugins/spellchecker/rpc.php
lib/editor/tinymce/tiny_mce/
lib/mlbackend/php/phpml/
lib/adodb/
lib/behat/axe/
lib/bennu/
lib/evalmath/
lib/phpspreadsheet/
lib/google/
lib/htmlpurifier/
lib/jabber/
lib/minify/matthiasmullie-minify/
lib/minify/matthiasmullie-pathconverter/
lib/pear/HTML/Common.php
lib/pear/HTML/QuickForm.php
lib/pear/HTML/QuickForm/
lib/pear/PEAR.php
lib/phpmailer/
lib/simplepie/
lib/tcpdf/
lib/typo3/
lib/yuilib/
lib/yuilib/gallery/
lib/jquery/
lib/html2text/
lib/markdown/
lib/xhprof/
lib/horde/
lib/requirejs/
lib/amd/src/loglevel.js
lib/mustache/
lib/amd/src/mustache.js
lib/graphlib.php
lib/php-css-parser/
lib/rtlcss/
lib/scssphp/
lib/spout/
lib/amd/src/chartjs-lazy.js
lib/maxmind/GeoIp2/
lib/maxmind/MaxMind/
lib/ltiprovider/
lib/amd/src/truncate.js
lib/fonts/
lib/amd/src/adapter.js
lib/validateurlsyntax.php
lib/amd/src/popper.js
lib/geopattern-php/
lib/php-jwt/
lib/babel-polyfill/
lib/polyfills/
lib/emoji-data/
lib/plist/
lib/zipstream/
lib/php-enum/
lib/http-message/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
media/player/videojs/amd/src/videojs-flash-lazy.js
media/player/videojs/videojs/video-js.swf
mod/assign/feedback/editpdf/fpdi/
repository/s3/S3.php
theme/boost/scss/bootstrap/
theme/boost/amd/src/bootstrap/alert.js
theme/boost/amd/src/bootstrap/button.js
theme/boost/amd/src/bootstrap/carousel.js
theme/boost/amd/src/bootstrap/collapse.js
theme/boost/amd/src/bootstrap/dropdown.js
theme/boost/amd/src/bootstrap/index.js
theme/boost/amd/src/bootstrap/modal.js
theme/boost/amd/src/bootstrap/popover.js
theme/boost/amd/src/bootstrap/tools/sanitizer.js
theme/boost/amd/src/bootstrap/scrollspy.js
theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/scss/fontawesome/
+11 -74
View File
@@ -2,14 +2,9 @@
'plugins': [
'babel',
'promise',
'jsdoc',
],
'env': {
'browser': true,
// Enable ES6+ features by default.
// See http://eslint.org/docs/user-guide/configuring#specifying-environments
// Note: The YUI override must exactly match this when disabling the ES6+ version because those features are not supported by Shifter.
'es2020': true,
'amd': true
},
'globals': {
@@ -87,7 +82,6 @@
'no-octal-escape': 'error',
'no-proto': 'error',
'no-redeclare': 'warn',
'no-restricted-globals': ['error', { 'name': 'Notification' }],
'no-return-assign': 'error',
'no-script-url': 'error',
'no-self-assign': 'error',
@@ -197,42 +191,27 @@
'property': 'str',
'message': 'Use AMD module "core/str" or M.util.get_string()'
}],
},
overrides: [
{
files: ["**/yui/src/**/*.js"],
'env': {
// Disable ES6+ for YUI files.
'es2020': false,
},
// Disable some rules which we can't safely define for YUI rollups.
rules: {
'no-undef': 'off',
'no-unused-vars': 'off',
'no-unused-expressions': 'off',
// === JSDocs ===
"jsdoc/check-access": 'off',
"jsdoc/check-alignment": 'off',
"jsdoc/check-param-names": 'off',
"jsdoc/check-property-names": 'off',
"jsdoc/empty-tags": 'off',
"jsdoc/implements-on-classes": 'off',
"jsdoc/multiline-blocks": 'off',
"jsdoc/require-jsdoc": 'off',
"jsdoc/require-param": 'off',
"jsdoc/require-param-name": 'off',
"jsdoc/require-param-type": 'off',
"jsdoc/require-property": 'off',
"jsdoc/require-property-name": 'off',
"jsdoc/require-property-type": 'off',
'no-unused-expressions': 'off'
}
},
{
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile.js", ".grunt/*.js", ".grunt/tasks/*.js", "jsdoc.conf.js"],
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile*.js", "babel-plugin-add-module-to-define.js"],
// We support es6 now. Woot!
env: {
es6: true
},
// We're using babel transpiling so use their parser
// for linting.
parser: '@babel/eslint-parser',
parser: 'babel-eslint',
// Check AMD with some slightly stricter rules.
rules: {
'no-unused-vars': 'error',
@@ -259,53 +238,11 @@
// === Promises ===
// We have Promise now that we're using ES6.
'promise/no-native': 'off',
'promise/avoid-new': 'off',
// === JSDocs ===
"jsdoc/check-access": [
'error',
],
"jsdoc/check-alignment": 1, // Recommended.
"jsdoc/check-param-names": [
'error',
],
"jsdoc/check-property-names": [
'error',
],
"jsdoc/empty-tags": [
'error',
],
"jsdoc/implements-on-classes": [
'error',
],
"jsdoc/multiline-blocks": [
'error',
],
"jsdoc/require-jsdoc": [
'error',
],
"jsdoc/require-param": [
'error',
],
"jsdoc/require-param-name": [
'error',
],
"jsdoc/require-param-type": [
'error',
],
"jsdoc/require-property": [
'error',
],
"jsdoc/require-property-name": [
'error',
],
"jsdoc/require-property-type": [
'error',
],
'promise/avoid-new': 'off'
},
parserOptions: {
'sourceType': 'module',
'requireConfigFile': false,
'ecmaVersion': 9,
'sourceType': 'module'
}
}
]
-71
View File
@@ -1,71 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Template configuraton file for github actions CI/CD.
*
* @package core
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com}
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This cannot be used out from a github actions workflow, so just exit.
getenv('GITHUB_WORKFLOW') || die; // phpcs:ignore moodle.Files.MoodleInternal.MoodleInternalGlobalState
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->dbtype = getenv('dbtype');
$CFG->dblibrary = 'native';
$CFG->dbhost = '127.0.0.1';
$CFG->dbname = 'test';
$CFG->dbuser = 'test';
$CFG->dbpass = 'test';
$CFG->prefix = 'm_';
$CFG->dboptions = ['dbcollation' => 'utf8mb4_bin'];
$host = 'localhost';
$CFG->wwwroot = "http://{$host}";
$CFG->dataroot = realpath(dirname(__DIR__)) . '/moodledata';
$CFG->admin = 'admin';
$CFG->directorypermissions = 0777;
// Debug options - possible to be controlled by flag in future.
$CFG->debug = (E_ALL | E_STRICT); // DEBUG_DEVELOPER.
$CFG->debugdisplay = 1;
$CFG->debugstringids = 1; // Add strings=1 to url to get string ids.
$CFG->perfdebug = 15;
$CFG->debugpageinfo = 1;
$CFG->allowthemechangeonurl = 1;
$CFG->passwordpolicy = 0;
$CFG->cronclionly = 0;
$CFG->pathtophp = getenv('pathtophp');
$CFG->phpunit_dataroot = realpath(dirname(__DIR__)) . '/phpunitdata';
$CFG->phpunit_prefix = 't_';
define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://localhost:8080');
define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://localhost:8080');
define('TEST_SESSION_REDIS_HOST', 'localhost');
define('TEST_CACHESTORE_REDIS_TESTSERVERS', 'localhost');
// TODO: add others (solr, mongodb, memcached, ldap...).
// Too much for now: define('PHPUNIT_LONGTEST', true); // Only leaves a few tests out and they are run later by CI.
require_once(__DIR__ . '/lib/setup.php');
-117
View File
@@ -1,117 +0,0 @@
name: Core
on:
push:
branches-ignore:
- master
- MOODLE_[0-9]+_STABLE
tags-ignore:
- v[0-9]+.[0-9]+.[0-9]+*
env:
php: 8.0
jobs:
Grunt:
runs-on: ubuntu-22.04
steps:
- name: Checking out code
uses: actions/checkout@v3
- name: Configuring node & npm
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- name: Installing node stuff
run: npm install
- name: Running grunt
run: npx grunt
- name: Looking for uncommitted changes
# Add all files to the git index and then run diff --cached to see all changes.
# This ensures that we get the status of all files, including new files.
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
run: |
git add .
git reset -- npm-shrinkwrap.json
git diff --cached --exit-code
PHPUnit:
runs-on: ${{ matrix.os }}
services:
exttests:
image: moodlehq/moodle-exttests
ports:
- 8080:80
redis:
image: redis
ports:
- 6379:6379
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
php: 7.3
extensions:
db: mysqli
- os: ubuntu-22.04
php: 8.0
db: pgsql
extensions: xmlrpc-beta
steps:
- name: Setting up DB mysql
if: ${{ matrix.db == 'mysqli' }}
uses: moodlehq/mysql-action@v1
with:
collation server: utf8mb4_bin
mysql version: 5.7
mysql database: test
mysql user: test
mysql password: test
use tmpfs: true
tmpfs size: '1024M'
extra conf: --skip-log-bin
- name: Setting up DB pgsql
if: ${{ matrix.db == 'pgsql' }}
uses: m4nu56/postgresql-action@v1
with:
postgresql version: 10
postgresql db: test
postgresql user: test
postgresql password: test
- name: Configuring git vars
uses: rlespinasse/github-slug-action@v4
- name: Setting up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: ${{ matrix.extensions }}
ini-values: max_input_vars=5000
coverage: none
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
uses: actions/checkout@v3
- name: Setting up PHPUnit
env:
dbtype: ${{ matrix.db }}
run: |
echo "pathtophp=$(which php)" >> $GITHUB_ENV # Inject installed pathtophp to env. The template config needs it.
cp .github/workflows/config-template.php config.php
mkdir ../moodledata
sudo locale-gen en_AU.UTF-8
php admin/tool/phpunit/cli/init.php --no-composer-self-update
- name: Running PHPUnit tests
env:
dbtype: ${{ matrix.db }}
phpunit_options: ${{ secrets.phpunit_options }}
run: vendor/bin/phpunit $phpunit_options
-10
View File
@@ -26,7 +26,6 @@
/cscope.*
/.patches/
/.idea/
.phpstorm.*
/nbproject/
CVS
.DS_Store
@@ -47,12 +46,3 @@ composer.phar
atlassian-ide-plugin.xml
/node_modules/
/.vscode/
moodle-plugin-ci.phar
.eslintignore
.stylelintignore
/jsdoc
/admin/tool/componentlibrary/docs
/admin/tool/componentlibrary/hugo/site/data/my-index.json
.hugo_build.lock
phpcs.xml
jsconfig.json
-244
View File
@@ -1,244 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Helper functions for working with Moodle component names, directories, and sources.
*
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
/* eslint-env node */
/** @var {Object} A list of subsystems in Moodle */
const componentData = {};
/**
* Load details of all moodle modules.
*
* @returns {object}
*/
const fetchComponentData = () => {
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const gruntFilePath = process.cwd();
if (!Object.entries(componentData).length) {
componentData.subsystems = {};
componentData.pathList = [];
// Fetch the component definiitions from the distributed JSON file.
const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`));
// Build the list of moodle subsystems.
componentData.subsystems.lib = 'core';
componentData.pathList.push(process.cwd() + path.sep + 'lib');
for (const [component, thisPath] of Object.entries(components.subsystems)) {
if (thisPath) {
// Prefix "core_" to the front of the subsystems.
componentData.subsystems[thisPath] = `core_${component}`;
componentData.pathList.push(process.cwd() + path.sep + thisPath);
}
}
// The list of components incldues the list of subsystems.
componentData.components = componentData.subsystems;
// Go through each of the plugintypes.
Object.entries(components.plugintypes).forEach(([pluginType, pluginTypePath]) => {
// We don't allow any code in this place..?
glob.sync(`${pluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${pluginType}_${componentName}`;
componentData.components[`${pluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
// Look for any subplugins.
const subPluginConfigurationFile = `${componentPath}/db/subplugins.json`;
if (fs.existsSync(subPluginConfigurationFile)) {
const subpluginList = JSON.parse(fs.readFileSync(fs.realpathSync(subPluginConfigurationFile)));
Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => {
glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${subpluginType}_${componentName}`;
componentData.components[`${subpluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
});
});
}
});
});
}
return componentData;
};
/**
* Get the list of component paths.
*
* @param {string} relativeTo
* @returns {array}
*/
const getComponentPaths = (relativeTo = '') => fetchComponentData().pathList.map(componentPath => {
return componentPath.replace(relativeTo, '');
});
/**
* Get the list of paths to build AMD sources.
*
* @returns {Array}
*/
const getAmdSrcGlobList = () => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
globList.push(`${componentPath}/amd/src/*.js`);
globList.push(`${componentPath}/amd/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to build YUI sources.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getYuiSrcGlobList = relativeTo => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
const relativeComponentPath = componentPath.replace(relativeTo, '');
globList.push(`${relativeComponentPath}/yui/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to thirdpartylibs.xml.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getThirdPartyLibsList = relativeTo => {
const fs = require('fs');
const path = require('path');
return fetchComponentData().pathList
.map(componentPath => path.relative(relativeTo, componentPath) + '/thirdpartylibs.xml')
.map(componentPath => componentPath.replace(/\\/g, '/'))
.filter(path => fs.existsSync(path))
.sort();
};
/**
* Get the list of thirdparty library paths.
*
* @returns {array}
*/
const getThirdPartyPaths = () => {
const DOMParser = require('@xmldom/xmldom').DOMParser;
const fs = require('fs');
const path = require('path');
const xpath = require('xpath');
const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./'));
const libs = ['node_modules/', 'vendor/'];
const addLibToList = lib => {
if (!lib.match('\\*') && fs.statSync(lib).isDirectory()) {
// Ensure trailing slash on dirs.
lib = lib.replace(/\/?$/, '/');
}
// Look for duplicate paths before adding to array.
if (libs.indexOf(lib) === -1) {
libs.push(lib);
}
};
thirdpartyfiles.forEach(function(file) {
const dirname = path.dirname(file);
const xmlContent = fs.readFileSync(file, 'utf8');
const doc = new DOMParser().parseFromString(xmlContent);
const nodes = xpath.select("/libraries/library/location/text()", doc);
nodes.forEach(function(node) {
let lib = path.posix.join(dirname, node.toString());
addLibToList(lib);
});
});
return libs;
};
/**
* Find the name of the component matching the specified path.
*
* @param {String} path
* @returns {String|null} Name of matching component.
*/
const getComponentFromPath = path => {
const componentList = fetchComponentData().components;
if (componentList.hasOwnProperty(path)) {
return componentList[path];
}
return null;
};
/**
* Check whether the supplied path, relative to the Gruntfile.js, is in a known component.
*
* @param {String} checkPath The path to check. This can be with either Windows, or Linux directory separators.
* @returns {String|null}
*/
const getOwningComponentDirectory = checkPath => {
const path = require('path');
// Fetch all components into a reverse sorted array.
// This ensures that components which are within the directory of another component match first.
const pathList = Object.keys(fetchComponentData().components).sort().reverse();
for (const componentPath of pathList) {
// If the componentPath is the directory being checked, it will be empty.
// If the componentPath is a parent of the directory being checked, the relative directory will not start with ..
if (!path.relative(componentPath, checkPath).startsWith('..')) {
return componentPath;
}
}
return null;
};
module.exports = {
fetchComponentData,
getAmdSrcGlobList,
getComponentFromPath,
getComponentPaths,
getOwningComponentDirectory,
getYuiSrcGlobList,
getThirdPartyLibsList,
getThirdPartyPaths,
};
-19
View File
@@ -1,19 +0,0 @@
# Moodle JavaScript Documentation
```
.-..-.
_____ | || |
/____/-.---_ .---. .---. .-.| || | .---.
| | _ _ |/ _ \/ _ \/ _ || |/ __ \
* | | | | | || |_| || |_| || |_| || || |___/
|_| |_| |_|\_____/\_____/\_____||_|\_____)
Moodle - the world's open source learning platform
```
## About
This generated documentation includes API documentation for JavaScript written in the AMD and ES2015 module formats within Moodle.
## Related information
See [https://docs.moodle.org/dev](https://docs.moodle.org/dev) for other related Developer Documentation.
-131
View File
@@ -1,131 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Helper functions for working with Moodle component names, directories, and sources.
*
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
/* eslint-env node */
// Do not include any plugins as stanard.
const plugins = [];
plugins.push('plugins/markdown');
/**
* Get the source configuration.
*
* @return {Object}
*/
const getSource = () => {
const glob = require('glob');
const path = require('path');
const ComponentList = require(path.resolve('.grunt/components.js'));
const thirdPartyPaths = ComponentList.getThirdPartyPaths();
const source = {
include: [],
includePattern: ".+\\.js$",
};
let includeList = [];
ComponentList.getAmdSrcGlobList().forEach(async pattern => {
includeList.push(...glob.sync(pattern));
});
const cwdLength = process.cwd().length + 1;
includeList.forEach(path => {
if (source.include.indexOf(path) !== -1) {
// Ensure no duplicates.
return;
}
const relPath = path.substring(cwdLength);
if (thirdPartyPaths.indexOf(relPath) !== -1) {
return;
}
source.include.push(path);
});
source.include.push('.grunt/jsdoc/README.md');
return source;
};
const tags = {
// Allow the use of unknown tags.
// We have a lot of legacy uses of these.
allowUnknownTags: true,
// We make use of jsdoc and closure dictionaries as standard.
dictionaries: [
'jsdoc',
'closure',
],
};
// Template configuraiton.
const templates = {
cleverLinks: false,
monospaceLinks: false,
};
module.exports = {
opts: {
destination: "./jsdoc/",
template: "node_modules/docdash",
},
plugins,
recurseDepth: 10,
source: getSource(),
sourceType: 'module',
tags,
templates,
docdash: {
collapse: true,
search: true,
sort: true,
sectionOrder: [
"Namespaces",
"Modules",
"Events",
"Classes",
"Externals",
"Mixins",
"Tutorials",
"Interfaces"
],
"menu": {
"Developer Docs": {
href: "https://docs.moodle.org/dev",
target: "_blank",
"class": "menu-item",
id: "devdocs"
},
"MDN Docs": {
href: "https://developer.mozilla.org/en-US/docs/Web/JavaScript",
target: "_blank",
"class": "menu-item",
id: "mdndocs",
},
},
typedefs: true,
},
};
-140
View File
@@ -1,140 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* Component Library build tasks.
*
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Get a child path of the component library.
*
* @param {string} path
* @returns {string}
*/
const getCLPath = path => `admin/tool/componentlibrary/${path}`;
/**
* Get a spawn handler.
*
* This is a generic function to write the spawn output, and then to exit if required and mark the async task as
* complete.
*
* @param {Promise} done
* @returns {function}
*/
const getSpawnHandler = done => (error, result, code) => {
grunt.log.write(result);
if (error) {
process.exit(code);
}
done();
};
/**
* Spawn a function against Node with the provided args.
*
* @param {array} args
* @returns {object}
*/
const spawnNodeCall = args => grunt.util.spawn({
cmd: 'node',
args,
}, getSpawnHandler(grunt.task.current.async()));
/**
* Build the docs using Hugo.
*
* @returns {Object} Reference to the spawned task
*/
const docsBuild = () => spawnNodeCall([
'node_modules/hugo-bin/cli.js',
'--config', getCLPath('config.yml'),
'--cleanDestinationDir',
]);
/**
* Build the docs index using the hugo-lunr-indexer.
*
* @returns {Object} Reference to the spawned task
*/
const indexBuild = () => spawnNodeCall([
'node_modules/hugo-lunr-indexer/bin/hli.js',
'-i', getCLPath('content/**'),
'-o', getCLPath('hugo/site/data/my-index.json'),
'-l', 'yaml',
'-d', '---',
]);
/**
* Build the hugo CSS.
*
* @returns {Object} Reference to the spawned task
*/
const cssBuild = () => spawnNodeCall([
'node_modules/node-sass/bin/node-sass',
'--output-style', 'expanded',
'--source-map', true,
'--source-map-contents', true,
'--precision', 6,
getCLPath('hugo/scss/docs.scss'),
'-o', getCLPath('hugo/dist/css/'),
]);
// Register the various component library tasks.
grunt.registerTask('componentlibrary:docsBuild', 'Build the component library', docsBuild);
grunt.registerTask('componentlibrary:cssBuild', 'Build the component library', cssBuild);
grunt.registerTask('componentlibrary:indexBuild', 'Build the component library', indexBuild);
grunt.registerTask('componentlibrary', 'Build the component library', [
'componentlibrary:docsBuild',
'componentlibrary:cssBuild',
'componentlibrary:indexBuild',
]);
grunt.config.merge({
watch: {
componentLibraryDocs: {
files: [
getCLPath('content/**/*.md'),
getCLPath('hugo'),
],
tasks: ['componentlibrary:docsBuild', 'componentlibrary:indexBuild'],
},
componentLibraryCSS: {
files: [
getCLPath('hugo/scss/**/*.scss'),
'hugo',
],
tasks: ['componentlibrary:cssBuild'],
},
},
});
// Add the 'componentlibrary' task as a startup task.
grunt.moodleEnv.startupTasks.push('componentlibrary');
return {
docsBuild,
cssBuild,
indexBuild,
};
};
-64
View File
@@ -1,64 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
const files = grunt.moodleEnv.files;
// Project configuration.
grunt.config.merge({
eslint: {
// Even though warnings dont stop the build we don't display warnings by default because
// at this moment we've got too many core warnings.
// To display warnings call: grunt eslint --show-lint-warnings
// To fail on warnings call: grunt eslint --max-lint-warnings=0
// Also --max-lint-warnings=-1 can be used to display warnings but not fail.
options: {
quiet: (!grunt.option('show-lint-warnings')) && (typeof grunt.option('max-lint-warnings') === 'undefined'),
maxWarnings: ((typeof grunt.option('max-lint-warnings') !== 'undefined') ? grunt.option('max-lint-warnings') : -1)
},
// Check AMD src files.
amd: {src: files ? files : grunt.moodleEnv.amdSrc},
// Check YUI module source files.
yui: {src: files ? files : grunt.moodleEnv.yuiSrc},
},
});
grunt.loadNpmTasks('grunt-eslint');
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
let changedFiles = Object.create(null);
const onChange = grunt.util._.debounce(function() {
const files = Object.keys(changedFiles);
grunt.config('eslint.amd.src', files);
grunt.config('eslint.yui.src', files);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', (action, filepath) => {
changedFiles[filepath] = action;
onChange();
});
};
-92
View File
@@ -1,92 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Get the list of feature files to pass to the gherkin linter.
*
* @returns {Array}
*/
const getGherkinLintTargets = () => {
if (grunt.moodleEnv.files) {
// Specific files were requested. Only check these.
return grunt.moodleEnv.files;
}
if (grunt.moodleEnv.inComponent) {
return [`${grunt.moodleEnv.runDir}/tests/behat/*.feature`];
}
return ['**/tests/behat/*.feature'];
};
const handler = function() {
const done = this.async();
const options = grunt.config('gherkinlint.options');
// Grab the gherkin-lint linter and required scaffolding.
const linter = require('gherkin-lint/dist/linter.js');
const featureFinder = require('gherkin-lint/dist/feature-finder.js');
const configParser = require('gherkin-lint/dist/config-parser.js');
const formatter = require('gherkin-lint/dist/formatters/stylish.js');
// Run the linter.
return linter.lint(
featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
configParser.getConfiguration(configParser.defaultConfigFileName)
)
.then(results => {
// Print the results out uncondtionally.
formatter.printResults(results);
return results;
})
.then(results => {
// Report on the results.
// The done function takes a bool whereby a falsey statement causes the task to fail.
return results.every(result => result.errors.length === 0);
})
.then(done); // eslint-disable-line promise/no-callback-in-promise
};
grunt.registerTask('gherkinlint', 'Run gherkinlint against the current directory', handler);
grunt.config.set('gherkinlint', {
options: {
files: getGherkinLintTargets(),
}
});
grunt.config.merge({
watch: {
gherkinlint: {
files: [grunt.moodleEnv.inComponent ? 'tests/behat/*.feature' : '**/tests/behat/*.feature'],
tasks: ['gherkinlint'],
},
},
});
// Add the 'gherkinlint' task as a startup task.
grunt.moodleEnv.startupTasks.push('gherkinlint');
return handler;
};
-100
View File
@@ -1,100 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Generate the PHPCS configuration.
*
* @param {Object} thirdPartyPaths
*/
const phpcsIgnore = (thirdPartyPaths) => {
const {toXML} = require('jstoxml');
const config = {
_name: 'ruleset',
_attrs: {
name: "MoodleCore",
},
_content: [
{
rule: {
_attrs: {
ref: './phpcs.xml.dist',
},
},
},
],
};
thirdPartyPaths.forEach(library => {
config._content.push({
'exclude-pattern': library,
});
});
grunt.file.write('phpcs.xml', toXML(config, {
header: true,
indent: ' ',
}) + "\n");
};
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
const handler = function() {
const path = require('path');
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
// An array of paths to third party directories.
const thirdPartyPaths = ComponentList.getThirdPartyPaths();
// Generate .eslintignore.
const eslintIgnores = [
'# Generated by "grunt ignorefiles"',
// Do not ignore the .grunt directory.
'!/.grunt',
// Ignore all yui/src meta directories and build directories.
'*/**/yui/src/*/meta/',
'*/**/build/',
].concat(thirdPartyPaths);
grunt.file.write('.eslintignore', eslintIgnores.join('\n') + '\n');
// Generate .stylelintignore.
const stylelintIgnores = [
'# Generated by "grunt ignorefiles"',
'**/yui/build/*',
'theme/boost/style/moodle.css',
'theme/classic/style/moodle.css',
'jsdoc/styles/*.css',
'admin/tool/componentlibrary/hugo/dist/css/docs.css',
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n') + '\n');
phpcsIgnore(thirdPartyPaths);
};
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', handler);
return handler;
};
-227
View File
@@ -1,227 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Function to generate the destination for the uglify task
* (e.g. build/file.min.js). This function will be passed to
* the rename property of files array when building dynamically:
* http://gruntjs.com/configuring-tasks#building-the-files-object-dynamically
*
* @param {String} destPath the current destination
* @param {String} srcPath the matched src path
* @return {String} The rewritten destination path.
*/
const babelRename = function(destPath, srcPath) {
destPath = srcPath.replace(`amd/src`, `amd/build`);
destPath = destPath.replace(/\.js$/, '.min.js');
return destPath;
};
module.exports = grunt => {
// Load the Ignorefiles tasks.
require('./ignorefiles')(grunt);
// Load the Shifter tasks.
require('./shifter')(grunt);
// Load ESLint.
require('./eslint')(grunt);
// Load jsconfig.
require('./jsconfig')(grunt);
// Load JSDoc.
require('./jsdoc')(grunt);
const path = require('path');
// Register JS tasks.
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
grunt.registerTask('amd', ['ignorefiles', 'eslint:amd', 'rollup']);
grunt.registerTask('js', ['amd', 'yui']);
// Register NPM tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-rollup');
const babelTransform = require('@babel/core').transform;
const babel = (options = {}) => {
return {
name: 'babel',
transform: (code, id) => {
grunt.log.debug(`Transforming ${id}`);
options.filename = id;
const transformed = babelTransform(code, options);
return {
code: transformed.code,
map: transformed.map
};
}
};
};
// Note: We have to use a rate limit plugin here because rollup runs all tasks asynchronously and in parallel.
// When we kick off a full run, if we kick off a rollup of every file this will fork-bomb the machine.
// To work around this we use a concurrent Promise queue based on the number of available processors.
const rateLimit = () => {
const queue = [];
let queueRunner;
const startQueue = () => {
if (queueRunner) {
return;
}
queueRunner = setTimeout(() => {
const limit = Math.max(1, require('os').cpus().length / 2);
grunt.log.debug(`Starting rollup with queue size of ${limit}`);
runQueue(limit);
}, 100);
};
// The queue runner will run the next `size` items in the queue.
const runQueue = (size = 1) => {
queue.splice(0, size).forEach(resolve => {
resolve();
});
};
return {
name: 'ratelimit',
// The options hook is run in parallel.
// We can return an unresolved Promise which is queued for later resolution.
options: async() => {
return new Promise(resolve => {
queue.push(resolve);
startQueue();
});
},
// When an item in the queue completes, start the next item in the queue.
buildEnd: () => {
runQueue();
},
};
};
const terser = require('rollup-plugin-terser').terser;
grunt.config.merge({
rollup: {
options: {
format: 'esm',
dir: 'output',
sourcemap: true,
treeshake: false,
context: 'window',
plugins: [
rateLimit(),
babel({
sourceMaps: true,
comments: false,
compact: false,
plugins: [
'transform-es2015-modules-amd-lazy',
'system-import-transformer',
// This plugin modifies the Babel transpiling for "export default"
// so that if it's used then only the exported value is returned
// by the generated AMD module.
//
// It also adds the Moodle plugin name to the AMD module definition
// so that it can be imported as expected in other modules.
path.resolve('.grunt/babel-plugin-add-module-to-define.js'),
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-syntax-import-meta',
['@babel/plugin-proposal-class-properties', {'loose': false}],
'@babel/plugin-proposal-json-strings'
],
presets: [
['@babel/preset-env', {
targets: {
browsers: [
">0.3%",
"last 2 versions",
"not ie >= 0",
"not op_mini all",
"not Opera > 0",
"not dead"
]
},
modules: false,
useBuiltIns: false
}]
]
}),
terser({
// Do not mangle variables.
// Makes debugging easier.
mangle: false,
}),
],
},
dist: {
files: [{
expand: true,
src: grunt.moodleEnv.files ? grunt.moodleEnv.files : grunt.moodleEnv.amdSrc,
rename: babelRename
}],
},
},
});
grunt.config.merge({
watch: {
amd: {
files: grunt.moodleEnv.inComponent
? ['amd/src/*.js', 'amd/src/**/*.js']
: ['**/amd/src/**/*.js'],
tasks: ['amd']
},
},
});
// Add the 'js' task as a startup task.
grunt.moodleEnv.startupTasks.push('js');
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
let changedFiles = Object.create(null);
const onChange = grunt.util._.debounce(function() {
const files = Object.keys(changedFiles);
grunt.config('rollup.dist.files', [{expand: true, src: files, rename: babelRename}]);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
return {
babelRename,
};
};
-53
View File
@@ -1,53 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
const configuration = {
compilerOptions: {
baseUrl: ".",
paths: {
},
target: "es2015",
allowSyntheticDefaultImports: false,
},
exclude: [
"node_modules",
],
include: [],
};
module.exports = (grunt) => {
const handler = () => {
const jsconfigData = Object.assign({}, configuration);
const path = require('path');
const {fetchComponentData} = require(path.join(process.cwd(), '.grunt', 'components.js'));
const componentData = fetchComponentData().components;
for (const [thisPath, component] of Object.entries(componentData)) {
jsconfigData.compilerOptions.paths[`${component}/*`] = [`${thisPath}/amd/src/*`];
jsconfigData.include.push(`${thisPath}/amd/src/**/*`);
}
grunt.file.write('jsconfig.json', JSON.stringify(jsconfigData, null, " ") + "\n");
};
grunt.registerTask('jsconfig', 'Generate a jsconfig configuration compatible with the LSP', handler);
};
-36
View File
@@ -1,36 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
// Project configuration.
grunt.config.merge({
jsdoc: {
dist: {
options: {
configure: ".grunt/jsdoc/jsdoc.conf.js",
},
},
},
});
grunt.loadNpmTasks('grunt-jsdoc');
};
-40
View File
@@ -1,40 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
grunt.loadNpmTasks('grunt-sass');
grunt.config.merge({
sass: {
dist: {
files: {
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss",
"theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss"
}
},
options: {
implementation: require('node-sass'),
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
}
},
});
};
-155
View File
@@ -1,155 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/* eslint-env node */
module.exports = grunt => {
/**
* Shifter task. Is configured with a path to a specific file or a directory,
* in the case of a specific file it will work out the right module to be built.
*
* Note that this task runs the invidiaul shifter jobs async (becase it spawns
* so be careful to to call done().
*/
const handler = function() {
const done = this.async();
const options = grunt.config('shifter.options');
const async = require('async');
const path = require('path');
// Run the shifter processes one at a time to avoid confusing output.
async.eachSeries(options.paths, function(src, filedone) {
var args = [];
args.push(path.normalize(process.cwd() + '/node_modules/shifter/bin/shifter'));
// Always ignore the node_modules directory.
args.push('--excludes', 'node_modules');
// Determine the most appropriate options to run with based upon the current location.
if (grunt.file.isMatch('**/yui/**/*.js', src)) {
// When passed a JS file, build our containing module (this happen with
// watch).
grunt.log.debug('Shifter passed a specific JS file');
src = path.dirname(path.dirname(src));
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src', src)) {
// When in a src directory --walk all modules.
grunt.log.debug('In a src directory');
args.push('--walk');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*', src)) {
// When in module, only build our module.
grunt.log.debug('In a module directory');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*/js', src)) {
// When in module src, only build our module.
grunt.log.debug('In a source directory');
src = path.dirname(src);
options.recursive = false;
}
if (grunt.option('watch')) {
grunt.fail.fatal('The --watch option has been removed, please use `grunt watch` instead');
}
// Add the stderr option if appropriate
if (grunt.option('verbose')) {
args.push('--lint-stderr');
}
if (grunt.option('no-color')) {
args.push('--color=false');
}
var execShifter = function() {
grunt.log.ok("Running shifter on " + src);
grunt.util.spawn({
cmd: "node",
args: args,
opts: {cwd: src, stdio: 'inherit', env: process.env}
}, function(error, result, code) {
if (code) {
grunt.fail.fatal('Shifter failed with code: ' + code);
} else {
grunt.log.ok('Shifter build complete.');
filedone();
}
});
};
// Actually run shifter.
if (!options.recursive) {
execShifter();
} else {
// Check that there are yui modules otherwise shifter ends with exit code 1.
if (grunt.file.expand({cwd: src}, '**/yui/src/**/*.js').length > 0) {
args.push('--recursive');
execShifter();
} else {
grunt.log.ok('No YUI modules to build.');
filedone();
}
}
}, done);
};
// Register the shifter task.
grunt.registerTask('shifter', 'Run Shifter against the current directory', handler);
// Configure it.
grunt.config.set('shifter', {
options: {
recursive: true,
// Shifter takes a relative path.
paths: grunt.moodleEnv.files ? grunt.moodleEnv.files : [grunt.moodleEnv.runDir]
}
});
grunt.config.merge({
watch: {
yui: {
files: grunt.moodleEnv.inComponent
? ['yui/src/*.json', 'yui/src/**/*.js']
: ['**/yui/src/**/*.js'],
tasks: ['yui']
},
},
});
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
let changedFiles = Object.create(null);
const onChange = grunt.util._.debounce(function() {
const files = Object.keys(changedFiles);
grunt.config('shifter.options.paths', files);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', (action, filepath) => {
changedFiles[filepath] = action;
onChange();
});
return handler;
};
-46
View File
@@ -1,46 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
const handler = function() {
const path = require('path');
// Are we in a YUI directory?
if (path.basename(path.resolve(grunt.moodleEnv.cwd, '../../')) == 'yui') {
grunt.task.run('yui');
// Are we in an AMD directory?
} else if (grunt.moodleEnv.inAMD) {
grunt.task.run('amd');
} else {
// Run all of the requested startup tasks.
grunt.moodleEnv.startupTasks.forEach(taskName => grunt.task.run(taskName));
}
};
// Register the startup task.
grunt.registerTask('startup', 'Run the correct tasks for the current directory', handler);
return handler;
};
-35
View File
@@ -1,35 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
// Load the ignorefiles tasks.
require('./ignorefiles')(grunt);
// Load the Style Lint tasks.
require('./stylelint')(grunt);
// Load the SASS tasks.
require('./sass')(grunt);
// Add the 'css' task as a startup task.
grunt.moodleEnv.startupTasks.push('css');
};
-183
View File
@@ -1,183 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
const getCssConfigForFiles = files => {
return {
stylelint: {
css: {
// Use a fully-qualified path.
src: files,
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
}
}
}
},
},
};
};
const getScssConfigForFiles = files => {
return {
stylelint: {
scss: {
options: {syntax: 'scss'},
src: files,
},
},
};
};
/**
* Register any stylelint tasks.
*
* @param {Object} grunt
* @param {Array} files
* @param {String} fullRunDir
*/
const registerStyleLintTasks = () => {
const glob = require('glob');
// The stylelinters do not handle the case where a configuration was provided but no files were included.
// Keep track of whether any files were found.
let hasCss = false;
let hasScss = false;
// The stylelint processors do not take a path argument. They always check all provided values.
// As a result we must check through each glob and determine if any files match the current directory.
const scssFiles = [];
const cssFiles = [];
const requestedFiles = grunt.moodleEnv.files;
if (requestedFiles) {
// Grunt was called with a files argument.
// Check whether each of the requested files matches either the CSS or SCSS source file list.
requestedFiles.forEach(changedFilePath => {
let matchesGlob;
// Check whether this watched path matches any watched SCSS file.
matchesGlob = grunt.moodleEnv.scssSrc.some(watchedPathGlob => {
return glob.sync(watchedPathGlob).indexOf(changedFilePath) !== -1;
});
if (matchesGlob) {
scssFiles.push(changedFilePath);
hasScss = true;
}
// Check whether this watched path matches any watched CSS file.
matchesGlob = grunt.moodleEnv.cssSrc.some(watchedPathGlob => {
return glob.sync(watchedPathGlob).indexOf(changedFilePath) !== -1;
});
if (matchesGlob) {
cssFiles.push(changedFilePath);
hasCss = true;
}
});
} else {
// Grunt was called without a list of files.
// The start directory (runDir) may be a child dir of the project.
// Check each scssSrc file to see if it's in the start directory.
// This means that we can lint just mod/*/styles.css if started in the mod directory.
grunt.moodleEnv.scssSrc.forEach(path => {
if (path.startsWith(grunt.moodleEnv.runDir)) {
scssFiles.push(path);
hasScss = true;
}
});
grunt.moodleEnv.cssSrc.forEach(path => {
if (path.startsWith(grunt.moodleEnv.runDir)) {
cssFiles.push(path);
hasCss = true;
}
});
}
// Register the tasks.
const scssTasks = ['sass'];
if (hasScss) {
grunt.config.merge(getScssConfigForFiles(scssFiles));
scssTasks.unshift('stylelint:scss');
}
scssTasks.unshift('ignorefiles');
const cssTasks = ['ignorefiles'];
if (hasCss) {
grunt.config.merge(getCssConfigForFiles(cssFiles));
cssTasks.push('stylelint:css');
}
// The tasks must be registered, even if empty to ensure a consistent command list.
// They jsut won't run anything.
grunt.registerTask('scss', scssTasks);
grunt.registerTask('rawcss', cssTasks);
};
// Register CSS tasks.
grunt.loadNpmTasks('grunt-stylelint');
// Register the style lint tasks.
registerStyleLintTasks();
grunt.registerTask('css', ['scss', 'rawcss']);
const getCoreThemeMatches = () => {
const scssMatch = 'scss/**/*.scss';
if (grunt.moodleEnv.inTheme) {
return [scssMatch];
}
if (grunt.moodleEnv.runDir.startsWith('theme')) {
return [`*/${scssMatch}`];
}
return [`theme/*/${scssMatch}`];
};
// Add the watch configuration for rawcss, and scss.
grunt.config.merge({
watch: {
rawcss: {
files: [
'**/*.css',
],
excludes: [
'**/moodle.css',
'**/editor.css',
'jsdoc/styles/*.css',
],
tasks: ['rawcss']
},
scss: {
files: getCoreThemeMatches(),
tasks: ['scss']
},
},
});
};
-272
View File
@@ -1,272 +0,0 @@
/**
* This is a wrapper task to handle the grunt watch command. It attempts to use
* Watchman to monitor for file changes, if it's installed, because it's much faster.
*
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
* watcher for backwards compatibility.
*/
/* eslint-env node */
module.exports = grunt => {
/**
* This is a wrapper task to handle the grunt watch command. It attempts to use
* Watchman to monitor for file changes, if it's installed, because it's much faster.
*
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
* watcher for backwards compatibility.
*/
const watchHandler = function() {
const async = require('async');
const watchTaskDone = this.async();
let watchInitialised = false;
let watchTaskQueue = {};
let processingQueue = false;
const watchman = require('fb-watchman');
const watchmanClient = new watchman.Client();
// Grab the tasks and files that have been queued up and execute them.
var processWatchTaskQueue = function() {
if (!Object.keys(watchTaskQueue).length || processingQueue) {
// If there is nothing in the queue or we're already processing then wait.
return;
}
processingQueue = true;
// Grab all tasks currently in the queue.
var queueToProcess = watchTaskQueue;
// Reset the queue.
watchTaskQueue = {};
async.forEachSeries(
Object.keys(queueToProcess),
function(task, next) {
var files = queueToProcess[task];
var filesOption = '--files=' + files.join(',');
grunt.log.ok('Running task ' + task + ' for files ' + filesOption);
// Spawn the task in a child process so that it doesn't kill this one
// if it failed.
grunt.util.spawn(
{
// Spawn with the grunt bin.
grunt: true,
// Run from current working dir and inherit stdio from process.
opts: {
cwd: grunt.moodleEnv.fullRunDir,
stdio: 'inherit'
},
args: [task, filesOption]
},
function(err, res, code) {
if (code !== 0) {
// The grunt task failed.
grunt.log.error(err);
}
// Move on to the next task.
next();
}
);
},
function() {
// No longer processing.
processingQueue = false;
// Once all of the tasks are done then recurse just in case more tasks
// were queued while we were processing.
processWatchTaskQueue();
}
);
};
const originalWatchConfig = grunt.config.get(['watch']);
const watchConfig = Object.keys(originalWatchConfig).reduce(function(carry, key) {
if (key == 'options') {
return carry;
}
const value = originalWatchConfig[key];
const taskNames = value.tasks;
const files = value.files;
let excludes = [];
if (value.excludes) {
excludes = value.excludes;
}
taskNames.forEach(function(taskName) {
carry[taskName] = {
files,
excludes,
};
});
return carry;
}, {});
watchmanClient.on('error', function(error) {
// We have to add an error handler here and parse the error string because the
// example way from the docs to check if Watchman is installed doesn't actually work!!
// See: https://github.com/facebook/watchman/issues/509
if (error.message.match('Watchman was not found')) {
// If watchman isn't installed then we should fallback to the other watch task.
grunt.log.ok('It is recommended that you install Watchman for better performance using the "watch" command.');
// Fallback to the old grunt-contrib-watch task.
grunt.renameTask('watch-grunt', 'watch');
grunt.task.run(['watch']);
// This task is finished.
watchTaskDone(0);
} else {
grunt.log.error(error);
// Fatal error.
watchTaskDone(1);
}
});
watchmanClient.on('subscription', function(resp) {
if (resp.subscription !== 'grunt-watch') {
return;
}
resp.files.forEach(function(file) {
grunt.log.ok('File changed: ' + file.name);
var fullPath = grunt.moodleEnv.fullRunDir + '/' + file.name;
Object.keys(watchConfig).forEach(function(task) {
const fileGlobs = watchConfig[task].files;
var match = fileGlobs.some(function(fileGlob) {
return grunt.file.isMatch(`**/${fileGlob}`, fullPath);
});
if (match) {
// If we are watching a subdirectory then the file.name will be relative
// to that directory. However the grunt tasks expect the file paths to be
// relative to the Gruntfile.js location so let's normalise them before
// adding them to the queue.
var relativePath = fullPath.replace(grunt.moodleEnv.gruntFilePath + '/', '');
if (task in watchTaskQueue) {
if (!watchTaskQueue[task].includes(relativePath)) {
watchTaskQueue[task] = watchTaskQueue[task].concat(relativePath);
}
} else {
watchTaskQueue[task] = [relativePath];
}
}
});
});
processWatchTaskQueue();
});
process.on('SIGINT', function() {
// Let the user know that they may need to manually stop the Watchman daemon if they
// no longer want it running.
if (watchInitialised) {
grunt.log.ok('The Watchman daemon may still be running and may need to be stopped manually.');
}
process.exit();
});
// Initiate the watch on the current directory.
watchmanClient.command(['watch-project', grunt.moodleEnv.fullRunDir], function(watchError, watchResponse) {
if (watchError) {
grunt.log.error('Error initiating watch:', watchError);
watchTaskDone(1);
return;
}
if ('warning' in watchResponse) {
grunt.log.error('warning: ', watchResponse.warning);
}
var watch = watchResponse.watch;
var relativePath = watchResponse.relative_path;
watchInitialised = true;
watchmanClient.command(['clock', watch], function(clockError, clockResponse) {
if (clockError) {
grunt.log.error('Failed to query clock:', clockError);
watchTaskDone(1);
return;
}
// Generate the expression query used by watchman.
// Documentation is limited, but see https://facebook.github.io/watchman/docs/expr/allof.html for examples.
// We generate an expression to match any value in the files list of all of our tasks, but excluding
// all value in the excludes list of that task.
//
// [anyof, [
// [allof, [
// [anyof, [
// ['match', validPath, 'wholename'],
// ['match', validPath, 'wholename'],
// ],
// [not,
// [anyof, [
// ['match', invalidPath, 'wholename'],
// ['match', invalidPath, 'wholename'],
// ],
// ],
// ],
var matchWholeName = fileGlob => ['match', fileGlob, 'wholename'];
var matches = Object.keys(watchConfig).map(function(task) {
const matchAll = [];
matchAll.push(['anyof'].concat(watchConfig[task].files.map(matchWholeName)));
if (watchConfig[task].excludes.length) {
matchAll.push(['not', ['anyof'].concat(watchConfig[task].excludes.map(matchWholeName))]);
}
return ['allof'].concat(matchAll);
});
matches = ['anyof'].concat(matches);
var sub = {
expression: matches,
// Which fields we're interested in.
fields: ["name", "size", "type"],
// Add our time constraint.
since: clockResponse.clock
};
if (relativePath) {
/* eslint-disable camelcase */
sub.relative_root = relativePath;
}
watchmanClient.command(['subscribe', watch, 'grunt-watch', sub], function(subscribeError) {
if (subscribeError) {
// Probably an error in the subscription criteria.
grunt.log.error('failed to subscribe: ', subscribeError);
watchTaskDone(1);
return;
}
grunt.log.ok('Listening for changes to files in ' + grunt.moodleEnv.fullRunDir);
});
});
});
};
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
grunt.renameTask('watch', 'watch-grunt');
// Register the new watch handler.
grunt.registerTask('watch', 'Run tasks on file changes', watchHandler);
grunt.config.merge({
watch: {
options: {
nospawn: true // We need not to spawn so config can be changed dynamically.
},
},
});
return watchHandler;
};
+1 -1
View File
@@ -1 +1 @@
lts/gallium
v14.15.0
+96
View File
@@ -0,0 +1,96 @@
# Generated by "grunt ignorefiles"
**/yui/build/*
theme/boost/style/moodle.css
theme/classic/style/moodle.css
node_modules/
vendor/
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
auth/cas/CAS/
cache/stores/mongodb/MongoDB/
enrol/lti/ims-blti/
filter/algebra/AlgParser.pm
filter/tex/mimetex.*
h5p/h5plib/v124/joubel/core/
h5p/h5plib/v124/joubel/editor/
lib/editor/atto/plugins/html/yui/src/codemirror/
lib/editor/atto/plugins/html/yui/src/beautify/
lib/editor/atto/yui/src/rangy/js/*.*
lib/editor/tinymce/plugins/pdw/tinymce/
lib/editor/tinymce/plugins/spellchecker/rpc.php
lib/editor/tinymce/tiny_mce/
lib/mlbackend/php/phpml/
lib/adodb/
lib/behat/axe/
lib/bennu/
lib/evalmath/
lib/phpspreadsheet/
lib/google/
lib/htmlpurifier/
lib/jabber/
lib/minify/matthiasmullie-minify/
lib/minify/matthiasmullie-pathconverter/
lib/pear/HTML/Common.php
lib/pear/HTML/QuickForm.php
lib/pear/HTML/QuickForm/
lib/pear/PEAR.php
lib/phpmailer/
lib/simplepie/
lib/tcpdf/
lib/typo3/
lib/yuilib/
lib/yuilib/gallery/
lib/jquery/
lib/html2text/
lib/markdown/
lib/xhprof/
lib/horde/
lib/requirejs/
lib/amd/src/loglevel.js
lib/mustache/
lib/amd/src/mustache.js
lib/graphlib.php
lib/php-css-parser/
lib/rtlcss/
lib/scssphp/
lib/spout/
lib/amd/src/chartjs-lazy.js
lib/maxmind/GeoIp2/
lib/maxmind/MaxMind/
lib/ltiprovider/
lib/amd/src/truncate.js
lib/fonts/
lib/amd/src/adapter.js
lib/validateurlsyntax.php
lib/amd/src/popper.js
lib/geopattern-php/
lib/php-jwt/
lib/babel-polyfill/
lib/polyfills/
lib/emoji-data/
lib/plist/
lib/zipstream/
lib/php-enum/
lib/http-message/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
media/player/videojs/amd/src/videojs-flash-lazy.js
media/player/videojs/videojs/video-js.swf
mod/assign/feedback/editpdf/fpdi/
repository/s3/S3.php
theme/boost/scss/bootstrap/
theme/boost/amd/src/bootstrap/alert.js
theme/boost/amd/src/bootstrap/button.js
theme/boost/amd/src/bootstrap/carousel.js
theme/boost/amd/src/bootstrap/collapse.js
theme/boost/amd/src/bootstrap/dropdown.js
theme/boost/amd/src/bootstrap/index.js
theme/boost/amd/src/bootstrap/modal.js
theme/boost/amd/src/bootstrap/popover.js
theme/boost/amd/src/bootstrap/tools/sanitizer.js
theme/boost/amd/src/bootstrap/scrollspy.js
theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/scss/fontawesome/
+78 -45
View File
@@ -10,20 +10,36 @@ language: php
os: linux
dist: bionic
dist: xenial
services:
- mysql
- docker
addons:
postgresql: "10"
php:
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
- 7.4
- 7.2
branches:
except:
- master
- /MOODLE_[0-9]+_STABLE/
- /^v[0-9]+\.[0-9]+\.[0-9]+.*/
addons:
postgresql: "9.6"
env:
# Although we want to run these jobs and see failures as quickly as possible, we also want to get the slowest job to
# start first so that the total run time is not too high.
#
# We only run MySQL on PHP 7.2, so run that first.
# CI Tests should be second-highest in priority as these only take <= 60 seconds to run under normal circumstances.
# Postgres is significantly is pretty reasonable in its run-time.
# Run CI Tests without running PHPUnit.
- DB=none TASK=CITEST
# Run unit tests on Postgres
- DB=pgsql TASK=PHPUNIT
# Perform an upgrade test too.
- DB=pgsql TASK=UPGRADE
jobs:
# Enable fast finish.
@@ -32,35 +48,12 @@ jobs:
fast_finish: true
include:
# First all the lowest php ones (7.3)
- php: 7.3
env: DB=none TASK=CITEST
- php: 7.3
env: DB=none TASK=GRUNT NVM_VERSION='lts/gallium'
- if: env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present
php: 7.3
env: DB=pgsql TASK=PHPUNIT
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
php: 7.3
env: DB=mysqli TASK=PHPUNIT
# Then, conditionally, all the highest php ones (8.0)
- if: env(MOODLE_PHP) = "all"
php: 8.0
env: DB=none TASK=CITEST
- if: env(MOODLE_PHP) = "all"
php: 8.0
env: DB=none TASK=GRUNT NVM_VERSION='lts/gallium'
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present)
php: 8.0
env: DB=pgsql TASK=PHPUNIT
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
php: 8.0
# Run mysql only on highest - it's just too slow
- php: 7.4
env: DB=mysqli TASK=PHPUNIT
# Run grunt/npm install on highest version too ('node' is an alias for the latest node.js version.)
- php: 7.4
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
cache:
directories:
@@ -81,8 +74,7 @@ install:
sudo service mysql stop
sudo mv /var/lib/mysql /mnt/ramdisk
sudo ln -s /mnt/ramdisk/mysql /var/lib/mysql
echo -e "[mysqld]\nskip-log-bin" | sudo tee -a /etc/mysql/my.cnf
sudo service mysql start
sudo service mysql restart
fi
- >
if [ "$DB" = 'pgsql' ];
@@ -93,7 +85,6 @@ install:
sudo mv /var/lib/postgresql /mnt/ramdisk
sudo ln -s /mnt/ramdisk/postgresql /var/lib/postgresql
sudo service postgresql start 9.6
sh -c 'until pg_isready -p 5432; do echo "Waiting for the DB to be up..."; sleep 2; done'
fi
- >
if [ "$TASK" = 'PHPUNIT' ];
@@ -120,11 +111,9 @@ install:
fi
before_script:
- if [[ ${TRAVIS_PHP_VERSION:0:1} -gt 7 ]]; then pecl install xmlrpc-beta; fi
- echo 'max_input_vars=5000' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
- phpenv config-rm xdebug.ini
- >
if [ "$TASK" = 'PHPUNIT' ];
if [ "$TASK" = 'PHPUNIT' -o "$TASK" = 'UPGRADE' ];
then
# Copy generic configuration in place.
cp config-dist.php config.php ;
@@ -191,9 +180,10 @@ before_script:
sed -i \
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
config.php ;
# Redis session tests
# Redis session tests, but not for PHP 7.2 and up. See MDL-60978 for more info.
redissession="define('TEST_SESSION_REDIS_HOST', '127.0.0.1');"
sed -i \
-e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
-e "/require_once/i \\${redissession}" \
config.php ;
# Initialise PHPUnit for Moodle.
@@ -223,7 +213,7 @@ before_script:
# We need the official upstream for comparison
git remote add upstream https://github.com/moodle/moodle.git;
git fetch upstream MOODLE_400_STABLE;
git fetch upstream MOODLE_310_STABLE;
export GIT_PREVIOUS_COMMIT="`git merge-base FETCH_HEAD $TRAVIS_COMMIT`";
export GIT_COMMIT="$TRAVIS_COMMIT";
export UPSTREAM_FETCH_HEAD=`git rev-parse FETCH_HEAD`
@@ -234,6 +224,32 @@ before_script:
export phpcmd=`which php`;
fi
########################################################################
# Upgrade test
########################################################################
- >
if [ "$TASK" = 'UPGRADE' ];
then
# We need the official upstream.
git remote add upstream https://github.com/moodle/moodle.git;
# Checkout 30 STABLE branch (the first version compatible with PHP 7.x)
git fetch upstream MOODLE_30_STABLE;
git checkout MOODLE_30_STABLE;
# Perform the upgrade
php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
# Return to the previous commit
git checkout -;
# Perform the upgrade
php admin/cli/upgrade.php --non-interactive --allow-unstable ;
# The local_ci repository can be used to check upgrade savepoints.
git clone https://github.com/moodlehq/moodle-local_ci.git local/ci ;
fi
script:
- >
if [ "$TASK" = 'PHPUNIT' ];
@@ -259,6 +275,23 @@ script:
git diff --cached --exit-code ;
fi
########################################################################
# Upgrade test
########################################################################
- >
if [ "$TASK" = 'UPGRADE' ];
then
cp local/ci/check_upgrade_savepoints/check_upgrade_savepoints.php ./check_upgrade_savepoints.php
result=`php check_upgrade_savepoints.php`;
# Check if there are problems
count=`echo "$result" | grep -P "ERROR|WARN" | wc -l` ;
if (($count > 0));
then
echo "$result"
exit 1 ;
fi
fi
after_script:
- >
if [ "$TASK" = 'PHPUNIT' ];
+762 -168
View File
@@ -16,129 +16,147 @@
/* eslint-env node */
/**
* Grunt configuration for Moodle.
*
* @copyright 2014 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/* eslint-env node */
/**
* Setup the Grunt Moodle environment.
* Calculate the cwd, taking into consideration the `root` option (for Windows).
*
* @param {Grunt} grunt
* @returns {Object}
* @param {Object} grunt
* @returns {String} The current directory as best we can determine
*/
const setupMoodleEnvironment = grunt => {
const getCwd = grunt => {
const fs = require('fs');
const path = require('path');
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
const getAmdConfiguration = () => {
// If the cwd is the amd directory in the current component then it will be empty.
// If the cwd is a child of the component's AMD directory, the relative directory will not start with ..
let inAMD = !path.relative(`${componentDirectory}/amd`, cwd).startsWith('..');
let cwd = fs.realpathSync(process.env.PWD || process.cwd());
// Globbing pattern for matching all AMD JS source files.
let amdSrc = [];
if (inComponent) {
amdSrc.push(
componentDirectory + "/amd/src/*.js",
componentDirectory + "/amd/src/**/*.js"
);
// Windows users can't run grunt in a subdirectory, so allow them to set
// the root by passing --root=path/to/dir.
if (grunt.option('root')) {
const root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) {
cwd = fs.realpathSync(path.join(__dirname, root));
grunt.log.ok('Setting root to ' + cwd);
} else {
amdSrc = ComponentList.getAmdSrcGlobList();
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
return cwd;
};
/**
* Register any stylelint tasks.
*
* @param {Object} grunt
* @param {Array} files
* @param {String} fullRunDir
*/
const registerStyleLintTasks = (grunt, files, fullRunDir) => {
const getCssConfigForFiles = files => {
return {
inAMD,
amdSrc,
stylelint: {
css: {
// Use a fully-qualified path.
src: files,
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
}
}
}
},
},
};
};
const getYuiConfiguration = () => {
let yuiSrc = [];
if (inComponent) {
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
const getScssConfigForFiles = files => {
return {
stylelint: {
scss: {
options: {syntax: 'scss'},
src: files,
},
},
};
};
let hasCss = true;
let hasScss = true;
if (files) {
// Specific files were passed. Just set them up.
grunt.config.merge(getCssConfigForFiles(files));
grunt.config.merge(getScssConfigForFiles(files));
} else {
// The stylelint system does not handle the case where there was no file to lint.
// Check whether there are any files to lint in the current directory.
const glob = require('glob');
const scssSrc = [];
glob.sync(`${fullRunDir}/**/*.scss`).forEach(path => scssSrc.push(path));
if (scssSrc.length) {
grunt.config.merge(getScssConfigForFiles(scssSrc));
} else {
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
hasScss = false;
}
return {
yuiSrc,
};
};
const cssSrc = [];
glob.sync(`${fullRunDir}/**/*.css`).forEach(path => cssSrc.push(path));
const getStyleConfiguration = () => {
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
// Build the cssSrc and scssSrc.
// Valid paths are:
// [component]/styles.css; and either
// [theme/[themename]]/scss/**/*.scss; or
// [theme/[themename]]/style/*.css.
//
// If a theme has scss, then it is assumed that the style directory contains generated content.
let cssSrc = [];
let scssSrc = [];
const checkComponentDirectory = componentDirectory => {
const isTheme = componentDirectory.startsWith('theme/');
if (isTheme) {
const scssDirectory = `${componentDirectory}/scss`;
if (fs.existsSync(scssDirectory)) {
// This theme has an SCSS directory.
// Include all scss files within it recursively, but do not check for css files.
scssSrc.push(`${scssDirectory}/*.scss`);
scssSrc.push(`${scssDirectory}/**/*.scss`);
} else {
// This theme has no SCSS directory.
// Only hte CSS files in the top-level directory are checked.
cssSrc.push(`${componentDirectory}/style/*.css`);
}
} else {
// This is not a theme.
// All other plugin types are restricted to a single styles.css in their top level.
cssSrc.push(`${componentDirectory}/styles.css`);
}
};
if (inComponent) {
checkComponentDirectory(componentDirectory);
if (cssSrc.length) {
grunt.config.merge(getCssConfigForFiles(cssSrc));
} else {
ComponentList.getComponentPaths(`${gruntFilePath}/`).forEach(componentPath => {
checkComponentDirectory(componentPath);
});
hasCss = false;
}
}
return {
cssSrc,
scssSrc,
};
};
const scssTasks = ['sass'];
if (hasScss) {
scssTasks.unshift('stylelint:scss');
}
grunt.registerTask('scss', scssTasks);
/**
* Calculate the cwd, taking into consideration the `root` option (for Windows).
*
* @param {Object} grunt
* @returns {String} The current directory as best we can determine
*/
const getCwd = grunt => {
let cwd = fs.realpathSync(process.env.PWD || process.cwd());
const cssTasks = [];
if (hasCss) {
cssTasks.push('stylelint:css');
}
grunt.registerTask('rawcss', cssTasks);
// Windows users can't run grunt in a subdirectory, so allow them to set
// the root by passing --root=path/to/dir.
if (grunt.option('root')) {
const root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) {
cwd = fs.realpathSync(path.join(__dirname, root));
grunt.log.ok('Setting root to ' + cwd);
} else {
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
grunt.registerTask('css', ['scss', 'rawcss']);
};
return cwd;
};
/**
* Grunt configuration.
*
* @param {Object} grunt
*/
module.exports = function(grunt) {
const path = require('path');
const tasks = {};
const async = require('async');
const DOMParser = require('xmldom').DOMParser;
const xpath = require('xpath');
const semver = require('semver');
const watchman = require('fb-watchman');
const watchmanClient = new watchman.Client();
const fs = require('fs');
const ComponentList = require(path.resolve('GruntfileComponents.js'));
const sass = require('node-sass');
// Verify the node version is new enough.
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
var actual = semver.valid(process.version);
if (!semver.satisfies(actual, expected)) {
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
}
// Detect directories:
// * gruntFilePath The real path on disk to this Gruntfile.js
@@ -153,19 +171,8 @@ const setupMoodleEnvironment = grunt => {
const relativeCwd = path.relative(gruntFilePath, cwd);
const componentDirectory = ComponentList.getOwningComponentDirectory(relativeCwd);
const inComponent = !!componentDirectory;
const inTheme = !!componentDirectory && componentDirectory.startsWith('theme/');
const runDir = inComponent ? componentDirectory : relativeCwd;
const fullRunDir = fs.realpathSync(gruntFilePath + path.sep + runDir);
const {inAMD, amdSrc} = getAmdConfiguration();
const {yuiSrc} = getYuiConfiguration();
const {cssSrc, scssSrc} = getStyleConfiguration();
let files = null;
if (grunt.option('files')) {
// Accept a comma separated list of files to process.
files = grunt.option('files').split(',');
}
grunt.log.debug('============================================================================');
grunt.log.debug(`= Node version: ${process.versions.node}`);
grunt.log.debug(`= grunt version: ${grunt.package.version}`);
@@ -185,80 +192,667 @@ const setupMoodleEnvironment = grunt => {
grunt.log.ok(`Running tasks for component directory ${componentDirectory}`);
}
return {
amdSrc,
componentDirectory,
cwd,
cssSrc,
files,
fullRunDir,
gruntFilePath,
inAMD,
inComponent,
inTheme,
relativeCwd,
runDir,
scssSrc,
yuiSrc,
};
};
/**
* Verify tha tthe current NodeJS version matches the required version in package.json.
*
* @param {Grunt} grunt
*/
const verifyNodeVersion = grunt => {
const semver = require('semver');
// Verify the node version is new enough.
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
var actual = semver.valid(process.version);
if (!semver.satisfies(actual, expected)) {
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
let files = null;
if (grunt.option('files')) {
// Accept a comma separated list of files to process.
files = grunt.option('files').split(',');
}
};
/**
* Grunt configuration.
*
* @param {Grunt} grunt
*/
module.exports = function(grunt) {
// Verify that the Node version meets our requirements.
verifyNodeVersion(grunt);
// If the cwd is the amd directory in the current component then it will be empty.
// If the cwd is a child of the component's AMD directory, the relative directory will not start with ..
const inAMD = !path.relative(`${componentDirectory}/amd`, cwd).startsWith('..');
// Setup the Moodle environemnt within the Grunt object.
grunt.moodleEnv = setupMoodleEnvironment(grunt);
// Globbing pattern for matching all AMD JS source files.
let amdSrc = [];
if (inComponent) {
amdSrc.push(componentDirectory + "/amd/src/*.js");
amdSrc.push(componentDirectory + "/amd/src/**/*.js");
} else {
amdSrc = ComponentList.getAmdSrcGlobList();
}
let yuiSrc = [];
if (inComponent) {
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
} else {
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
}
/**
* Add the named task.
* Function to generate the destination for the uglify task
* (e.g. build/file.min.js). This function will be passed to
* the rename property of files array when building dynamically:
* http://gruntjs.com/configuring-tasks#building-the-files-object-dynamically
*
* @param {string} name
* @param {Grunt} grunt
* @param {String} destPath the current destination
* @param {String} srcPath the matched src path
* @return {String} The rewritten destination path.
*/
const addTask = (name, grunt) => {
const path = require('path');
const taskPath = path.resolve(`./.grunt/tasks/${name}.js`);
grunt.log.debug(`Including tasks for ${name} from ${taskPath}`);
require(path.resolve(`./.grunt/tasks/${name}.js`))(grunt);
var babelRename = function(destPath, srcPath) {
destPath = srcPath.replace('src', 'build');
destPath = destPath.replace('.js', '.min.js');
return destPath;
};
// Startup tasks.
grunt.moodleEnv.startupTasks = [];
/**
* Find thirdpartylibs.xml and generate an array of paths contained within
* them (used to generate ignore files and so on).
*
* @return {array} The list of thirdparty paths.
*/
var getThirdPartyPathsFromXML = function() {
const thirdpartyfiles = ComponentList.getThirdPartyLibsList(gruntFilePath + '/');
const libs = ['node_modules/', 'vendor/'];
// Add Moodle task configuration.
addTask('gherkinlint', grunt);
addTask('ignorefiles', grunt);
thirdpartyfiles.forEach(function(file) {
const dirname = path.dirname(file);
addTask('javascript', grunt);
addTask('style', grunt);
addTask('componentlibrary', grunt);
const doc = new DOMParser().parseFromString(grunt.file.read(file));
const nodes = xpath.select("/libraries/library/location/text()", doc);
addTask('watch', grunt);
addTask('startup', grunt);
nodes.forEach(function(node) {
let lib = path.posix.join(dirname, node.toString());
if (grunt.file.isDir(lib)) {
// Ensure trailing slash on dirs.
lib = lib.replace(/\/?$/, '/');
}
// Look for duplicate paths before adding to array.
if (libs.indexOf(lib) === -1) {
libs.push(lib);
}
});
});
return libs;
};
/**
* Get the list of feature files to pass to the gherkin linter.
*
* @returns {Array}
*/
const getGherkinLintTargets = () => {
if (files) {
// Specific files were requested. Only check these.
return files;
}
if (inComponent) {
return [`${runDir}/tests/behat/*.feature`];
}
return ['**/tests/behat/*.feature'];
};
// Project configuration.
grunt.initConfig({
eslint: {
// Even though warnings dont stop the build we don't display warnings by default because
// at this moment we've got too many core warnings.
// To display warnings call: grunt eslint --show-lint-warnings
// To fail on warnings call: grunt eslint --max-lint-warnings=0
// Also --max-lint-warnings=-1 can be used to display warnings but not fail.
options: {
quiet: (!grunt.option('show-lint-warnings')) && (typeof grunt.option('max-lint-warnings') === 'undefined'),
maxWarnings: ((typeof grunt.option('max-lint-warnings') !== 'undefined') ? grunt.option('max-lint-warnings') : -1)
},
amd: {src: files ? files : amdSrc},
// Check YUI module source files.
yui: {src: files ? files : yuiSrc},
},
babel: {
options: {
sourceMaps: true,
comments: false,
plugins: [
'transform-es2015-modules-amd-lazy',
'system-import-transformer',
// This plugin modifies the Babel transpiling for "export default"
// so that if it's used then only the exported value is returned
// by the generated AMD module.
//
// It also adds the Moodle plugin name to the AMD module definition
// so that it can be imported as expected in other modules.
path.resolve('babel-plugin-add-module-to-define.js'),
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-syntax-import-meta',
['@babel/plugin-proposal-class-properties', {'loose': false}],
'@babel/plugin-proposal-json-strings'
],
presets: [
['minify', {
// This minification plugin needs to be disabled because it breaks the
// source map generation and causes invalid source maps to be output.
simplify: false,
builtIns: false
}],
['@babel/preset-env', {
targets: {
browsers: [
">0.25%",
"last 2 versions",
"not ie <= 10",
"not op_mini all",
"not Opera > 0",
"not dead"
]
},
modules: false,
useBuiltIns: false
}]
]
},
dist: {
files: [{
expand: true,
src: files ? files : amdSrc,
rename: babelRename
}]
}
},
sass: {
dist: {
files: {
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss",
"theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss"
}
},
options: {
implementation: sass,
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
}
},
watch: {
options: {
nospawn: true // We need not to spawn so config can be changed dynamically.
},
amd: {
files: inComponent
? ['amd/src/*.js', 'amd/src/**/*.js']
: ['**/amd/src/**/*.js'],
tasks: ['amd']
},
boost: {
files: [inComponent ? 'scss/**/*.scss' : 'theme/boost/scss/**/*.scss'],
tasks: ['scss']
},
rawcss: {
files: [
'**/*.css',
],
excludes: [
'**/moodle.css',
'**/editor.css',
],
tasks: ['rawcss']
},
yui: {
files: inComponent
? ['yui/src/*.json', 'yui/src/**/*.js']
: ['**/yui/src/**/*.js'],
tasks: ['yui']
},
gherkinlint: {
files: [inComponent ? 'tests/behat/*.feature' : '**/tests/behat/*.feature'],
tasks: ['gherkinlint']
}
},
shifter: {
options: {
recursive: true,
// Shifter takes a relative path.
paths: files ? files : [runDir]
}
},
gherkinlint: {
options: {
files: getGherkinLintTargets(),
}
},
});
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
tasks.ignorefiles = function() {
// An array of paths to third party directories.
const thirdPartyPaths = getThirdPartyPathsFromXML();
// Generate .eslintignore.
const eslintIgnores = [
'# Generated by "grunt ignorefiles"',
'*/**/yui/src/*/meta/',
'*/**/build/',
].concat(thirdPartyPaths);
grunt.file.write('.eslintignore', eslintIgnores.join('\n'));
// Generate .stylelintignore.
const stylelintIgnores = [
'# Generated by "grunt ignorefiles"',
'**/yui/build/*',
'theme/boost/style/moodle.css',
'theme/classic/style/moodle.css',
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
};
/**
* Shifter task. Is configured with a path to a specific file or a directory,
* in the case of a specific file it will work out the right module to be built.
*
* Note that this task runs the invidiaul shifter jobs async (becase it spawns
* so be careful to to call done().
*/
tasks.shifter = function() {
var done = this.async(),
options = grunt.config('shifter.options');
// Run the shifter processes one at a time to avoid confusing output.
async.eachSeries(options.paths, function(src, filedone) {
var args = [];
args.push(path.normalize(__dirname + '/node_modules/shifter/bin/shifter'));
// Always ignore the node_modules directory.
args.push('--excludes', 'node_modules');
// Determine the most appropriate options to run with based upon the current location.
if (grunt.file.isMatch('**/yui/**/*.js', src)) {
// When passed a JS file, build our containing module (this happen with
// watch).
grunt.log.debug('Shifter passed a specific JS file');
src = path.dirname(path.dirname(src));
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src', src)) {
// When in a src directory --walk all modules.
grunt.log.debug('In a src directory');
args.push('--walk');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*', src)) {
// When in module, only build our module.
grunt.log.debug('In a module directory');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*/js', src)) {
// When in module src, only build our module.
grunt.log.debug('In a source directory');
src = path.dirname(src);
options.recursive = false;
}
if (grunt.option('watch')) {
grunt.fail.fatal('The --watch option has been removed, please use `grunt watch` instead');
}
// Add the stderr option if appropriate
if (grunt.option('verbose')) {
args.push('--lint-stderr');
}
if (grunt.option('no-color')) {
args.push('--color=false');
}
var execShifter = function() {
grunt.log.ok("Running shifter on " + src);
grunt.util.spawn({
cmd: "node",
args: args,
opts: {cwd: src, stdio: 'inherit', env: process.env}
}, function(error, result, code) {
if (code) {
grunt.fail.fatal('Shifter failed with code: ' + code);
} else {
grunt.log.ok('Shifter build complete.');
filedone();
}
});
};
// Actually run shifter.
if (!options.recursive) {
execShifter();
} else {
// Check that there are yui modules otherwise shifter ends with exit code 1.
if (grunt.file.expand({cwd: src}, '**/yui/src/**/*.js').length > 0) {
args.push('--recursive');
execShifter();
} else {
grunt.log.ok('No YUI modules to build.');
filedone();
}
}
}, done);
};
tasks.gherkinlint = function() {
const done = this.async();
const options = grunt.config('gherkinlint.options');
// Grab the gherkin-lint linter and required scaffolding.
const linter = require('gherkin-lint/dist/linter.js');
const featureFinder = require('gherkin-lint/dist/feature-finder.js');
const configParser = require('gherkin-lint/dist/config-parser.js');
const formatter = require('gherkin-lint/dist/formatters/stylish.js');
// Run the linter.
return linter.lint(
featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
configParser.getConfiguration(configParser.defaultConfigFileName)
)
.then(results => {
// Print the results out uncondtionally.
formatter.printResults(results);
return results;
})
.then(results => {
// Report on the results.
// The done function takes a bool whereby a falsey statement causes the task to fail.
return results.every(result => result.errors.length === 0);
})
.then(done); // eslint-disable-line promise/no-callback-in-promise
};
tasks.startup = function() {
// Are we in a YUI directory?
if (path.basename(path.resolve(cwd, '../../')) == 'yui') {
grunt.task.run('yui');
// Are we in an AMD directory?
} else if (inAMD) {
grunt.task.run('amd');
} else {
// Run them all!.
grunt.task.run('css');
grunt.task.run('js');
grunt.task.run('gherkinlint');
}
};
/**
* This is a wrapper task to handle the grunt watch command. It attempts to use
* Watchman to monitor for file changes, if it's installed, because it's much faster.
*
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
* watcher for backwards compatibility.
*/
tasks.watch = function() {
var watchTaskDone = this.async();
var watchInitialised = false;
var watchTaskQueue = {};
var processingQueue = false;
// Grab the tasks and files that have been queued up and execute them.
var processWatchTaskQueue = function() {
if (!Object.keys(watchTaskQueue).length || processingQueue) {
// If there is nothing in the queue or we're already processing then wait.
return;
}
processingQueue = true;
// Grab all tasks currently in the queue.
var queueToProcess = watchTaskQueue;
// Reset the queue.
watchTaskQueue = {};
async.forEachSeries(
Object.keys(queueToProcess),
function(task, next) {
var files = queueToProcess[task];
var filesOption = '--files=' + files.join(',');
grunt.log.ok('Running task ' + task + ' for files ' + filesOption);
// Spawn the task in a child process so that it doesn't kill this one
// if it failed.
grunt.util.spawn(
{
// Spawn with the grunt bin.
grunt: true,
// Run from current working dir and inherit stdio from process.
opts: {
cwd: fullRunDir,
stdio: 'inherit'
},
args: [task, filesOption]
},
function(err, res, code) {
if (code !== 0) {
// The grunt task failed.
grunt.log.error(err);
}
// Move on to the next task.
next();
}
);
},
function() {
// No longer processing.
processingQueue = false;
// Once all of the tasks are done then recurse just in case more tasks
// were queued while we were processing.
processWatchTaskQueue();
}
);
};
const originalWatchConfig = grunt.config.get(['watch']);
const watchConfig = Object.keys(originalWatchConfig).reduce(function(carry, key) {
if (key == 'options') {
return carry;
}
const value = originalWatchConfig[key];
const taskNames = value.tasks;
const files = value.files;
let excludes = [];
if (value.excludes) {
excludes = value.excludes;
}
taskNames.forEach(function(taskName) {
carry[taskName] = {
files,
excludes,
};
});
return carry;
}, {});
watchmanClient.on('error', function(error) {
// We have to add an error handler here and parse the error string because the
// example way from the docs to check if Watchman is installed doesn't actually work!!
// See: https://github.com/facebook/watchman/issues/509
if (error.message.match('Watchman was not found')) {
// If watchman isn't installed then we should fallback to the other watch task.
grunt.log.ok('It is recommended that you install Watchman for better performance using the "watch" command.');
// Fallback to the old grunt-contrib-watch task.
grunt.renameTask('watch-grunt', 'watch');
grunt.task.run(['watch']);
// This task is finished.
watchTaskDone(0);
} else {
grunt.log.error(error);
// Fatal error.
watchTaskDone(1);
}
});
watchmanClient.on('subscription', function(resp) {
if (resp.subscription !== 'grunt-watch') {
return;
}
resp.files.forEach(function(file) {
grunt.log.ok('File changed: ' + file.name);
var fullPath = fullRunDir + '/' + file.name;
Object.keys(watchConfig).forEach(function(task) {
const fileGlobs = watchConfig[task].files;
var match = fileGlobs.some(function(fileGlob) {
return grunt.file.isMatch(`**/${fileGlob}`, fullPath);
});
if (match) {
// If we are watching a subdirectory then the file.name will be relative
// to that directory. However the grunt tasks expect the file paths to be
// relative to the Gruntfile.js location so let's normalise them before
// adding them to the queue.
var relativePath = fullPath.replace(gruntFilePath + '/', '');
if (task in watchTaskQueue) {
if (!watchTaskQueue[task].includes(relativePath)) {
watchTaskQueue[task] = watchTaskQueue[task].concat(relativePath);
}
} else {
watchTaskQueue[task] = [relativePath];
}
}
});
});
processWatchTaskQueue();
});
process.on('SIGINT', function() {
// Let the user know that they may need to manually stop the Watchman daemon if they
// no longer want it running.
if (watchInitialised) {
grunt.log.ok('The Watchman daemon may still be running and may need to be stopped manually.');
}
process.exit();
});
// Initiate the watch on the current directory.
watchmanClient.command(['watch-project', fullRunDir], function(watchError, watchResponse) {
if (watchError) {
grunt.log.error('Error initiating watch:', watchError);
watchTaskDone(1);
return;
}
if ('warning' in watchResponse) {
grunt.log.error('warning: ', watchResponse.warning);
}
var watch = watchResponse.watch;
var relativePath = watchResponse.relative_path;
watchInitialised = true;
watchmanClient.command(['clock', watch], function(clockError, clockResponse) {
if (clockError) {
grunt.log.error('Failed to query clock:', clockError);
watchTaskDone(1);
return;
}
// Generate the expression query used by watchman.
// Documentation is limited, but see https://facebook.github.io/watchman/docs/expr/allof.html for examples.
// We generate an expression to match any value in the files list of all of our tasks, but excluding
// all value in the excludes list of that task.
//
// [anyof, [
// [allof, [
// [anyof, [
// ['match', validPath, 'wholename'],
// ['match', validPath, 'wholename'],
// ],
// [not,
// [anyof, [
// ['match', invalidPath, 'wholename'],
// ['match', invalidPath, 'wholename'],
// ],
// ],
// ],
var matchWholeName = fileGlob => ['match', fileGlob, 'wholename'];
var matches = Object.keys(watchConfig).map(function(task) {
const matchAll = [];
matchAll.push(['anyof'].concat(watchConfig[task].files.map(matchWholeName)));
if (watchConfig[task].excludes.length) {
matchAll.push(['not', ['anyof'].concat(watchConfig[task].excludes.map(matchWholeName))]);
}
return ['allof'].concat(matchAll);
});
matches = ['anyof'].concat(matches);
var sub = {
expression: matches,
// Which fields we're interested in.
fields: ["name", "size", "type"],
// Add our time constraint.
since: clockResponse.clock
};
if (relativePath) {
/* eslint-disable camelcase */
sub.relative_root = relativePath;
}
watchmanClient.command(['subscribe', watch, 'grunt-watch', sub], function(subscribeError) {
if (subscribeError) {
// Probably an error in the subscription criteria.
grunt.log.error('failed to subscribe: ', subscribeError);
watchTaskDone(1);
return;
}
grunt.log.ok('Listening for changes to files in ' + fullRunDir);
});
});
});
};
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
var files = Object.keys(changedFiles);
grunt.config('eslint.amd.src', files);
grunt.config('eslint.yui.src', files);
grunt.config('shifter.options.paths', files);
grunt.config('gherkinlint.options.files', files);
grunt.config('babel.dist.files', [{expand: true, src: files, rename: babelRename}]);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
// Register NPM tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-stylelint');
grunt.loadNpmTasks('grunt-babel');
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
grunt.renameTask('watch', 'watch-grunt');
// Register JS tasks.
grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter);
grunt.registerTask('gherkinlint', 'Run gherkinlint against the current directory', tasks.gherkinlint);
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles);
grunt.registerTask('watch', 'Run tasks on file changes', tasks.watch);
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
grunt.registerTask('amd', ['eslint:amd', 'babel']);
grunt.registerTask('js', ['amd', 'yui']);
// Register CSS tasks.
registerStyleLintTasks(grunt, files, fullRunDir);
// Register the startup task.
grunt.registerTask('startup', 'Run the correct tasks for the current directory', tasks.startup);
// Register the default task.
grunt.registerTask('default', ['startup']);
+188
View File
@@ -0,0 +1,188 @@
// 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/>.
/**
* Helper functions for working with Moodle component names, directories, and sources.
*
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
/* eslint-env node */
/** @var {Object} A list of subsystems in Moodle */
const componentData = {};
/**
* Load details of all moodle modules.
*
* @returns {object}
*/
const fetchComponentData = () => {
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const gruntFilePath = process.cwd();
if (!Object.entries(componentData).length) {
componentData.subsystems = {};
componentData.pathList = [];
// Fetch the component definiitions from the distributed JSON file.
const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`));
// Build the list of moodle subsystems.
componentData.subsystems.lib = 'core';
componentData.pathList.push(process.cwd() + path.sep + 'lib');
for (const [component, thisPath] of Object.entries(components.subsystems)) {
if (thisPath) {
// Prefix "core_" to the front of the subsystems.
componentData.subsystems[thisPath] = `core_${component}`;
componentData.pathList.push(process.cwd() + path.sep + thisPath);
}
}
// The list of components incldues the list of subsystems.
componentData.components = componentData.subsystems;
// Go through each of the plugintypes.
Object.entries(components.plugintypes).forEach(([pluginType, pluginTypePath]) => {
// We don't allow any code in this place..?
glob.sync(`${pluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${pluginType}_${componentName}`;
componentData.components[`${pluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
// Look for any subplugins.
const subPluginConfigurationFile = `${componentPath}/db/subplugins.json`;
if (fs.existsSync(subPluginConfigurationFile)) {
const subpluginList = JSON.parse(fs.readFileSync(fs.realpathSync(subPluginConfigurationFile)));
Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => {
glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${subpluginType}_${componentName}`;
componentData.components[`${subpluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
});
});
}
});
});
}
return componentData;
};
/**
* Get the list of paths to build AMD sources.
*
* @returns {Array}
*/
const getAmdSrcGlobList = () => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
globList.push(`${componentPath}/amd/src/*.js`);
globList.push(`${componentPath}/amd/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to build YUI sources.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getYuiSrcGlobList = relativeTo => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
const relativeComponentPath = componentPath.replace(relativeTo, '');
globList.push(`${relativeComponentPath}/yui/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to thirdpartylibs.xml.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getThirdPartyLibsList = relativeTo => {
const fs = require('fs');
const path = require('path');
return fetchComponentData().pathList
.map(componentPath => path.relative(relativeTo, componentPath) + '/thirdpartylibs.xml')
.map(componentPath => componentPath.replace(/\\/g, '/'))
.filter(path => fs.existsSync(path))
.sort();
};
/**
* Find the name of the component matching the specified path.
*
* @param {String} path
* @returns {String|null} Name of matching component.
*/
const getComponentFromPath = path => {
const componentList = fetchComponentData().components;
if (componentList.hasOwnProperty(path)) {
return componentList[path];
}
return null;
};
/**
* Check whether the supplied path, relative to the Gruntfile.js, is in a known component.
*
* @param {String} checkPath The path to check. This can be with either Windows, or Linux directory separators.
* @returns {String|null}
*/
const getOwningComponentDirectory = checkPath => {
const path = require('path');
// Fetch all components into a reverse sorted array.
// This ensures that components which are within the directory of another component match first.
const pathList = Object.keys(fetchComponentData().components).sort().reverse();
for (const componentPath of pathList) {
// If the componentPath is the directory being checked, it will be empty.
// If the componentPath is a parent of the directory being checked, the relative directory will not start with ..
if (!path.relative(componentPath, checkPath).startsWith('..')) {
return componentPath;
}
}
return null;
};
module.exports = {
getAmdSrcGlobList,
getComponentFromPath,
getOwningComponentDirectory,
getYuiSrcGlobList,
getThirdPartyLibsList,
};
+35 -53
View File
@@ -1,66 +1,48 @@
MOODLE TRADEMARKS POLICY
========================
The Moodle Trademark
--------------------
The word "Moodle" is trademarked in many countries around the world. The word
was originally an acronym: Modular Object-Oriented Dynamic Learning
Environment. The trademark is owned by Martin Dougiamas, Founder and Director
of Moodle.
The brand and word "Moodle" has trade mark protection in many countries around
the world. Various Moodle™ trade marks are owned by either Moodle Pty Ltd or
one of its associated entities. The law obligates trade mark owners to police
their trade marks and prevent the use of confusingly similar names by
third parties.
The law obligates trademark owners to police their marks and prevent the use of
confusingly similar names by third parties. Through this policy wed like to
make it clear how Moodle-related projects, organisations, and people can use
the Moodle trademark. Wed also like to be clear about how use of the word is
restricted when used to promote commercial Moodle services. We do this to
protect the very business model that allows us to continue developing Moodle
for you.
We have created a more concise and thorough set of Trademark Guidelines
(https://moodle.com/wp-content/uploads/2023/02/Moodle-Trademark-Guidelines-2023-4.pdf)
to help you understand how to comply with Moodle's trade mark requirements.
The Trademark Guidelines will also assist our Moodle Certified Partners and the
community to understand some of the principles that inform Moodle's stance
whenever potential infringement has been detected by us or our community.
Allowed uses
------------
We need to be clear about use of the word "Moodle" and how we restrict its use
when promoting commercial Moodle™ branded services. The proper use of
trade marks reliably assures consumers about the quality of the associated
products or services and where they have been derived from. Because the
Moodle LMS is made available under the open source GNU General Public License'
that permits you to modify the copyrighted software, the distribution of such
modified software in combination with Moodle trade marks can potentially
mislead others in the community. To be clear, the GNU GPL does not include an
implied right or licence to use Moodle's trade marks.
The following uses dont require any permission at all:
We do all this to protect the very business model that allows us to continue
developing various Moodle software solutions for you.
Allowed uses of "Moodle"
------------------------
The following uses don't require any permission at all:
* Referring to the software or the Moodle project as the "Moodle™ software"
or the "Moodle™ project"
* Describing your own implementation of the Moodle™ software platform
(including within corporate settings).
* Referring to the software or the Moodle project.
* Describing your own Moodle implementation (including within corporate
settings).
* Describing a Moodle-based community hub.
* Describing certain software you've made that integrates with Moodle
branded software (e.g. a Moodle integration feature on another system).
* Describing some software youve made that integrates with Moodle
(eg a Moodle integration feature on another system).
Restricted uses of "Moodle"
---------------------------
Restricted uses
---------------
The following uses are generally prohibited without explicit and direct
permission being granted to you by Moodle Pty Ltd. We do this to protect the
Moodle project from software and sites which could confuse people. If in
doubt, reach out for clarification at <trademarks@moodle.com>
Moodle project from software and sites which could confuse people. Please
contact us to ask for permission in writing.
* You can't use the word "Moodle" or any Moodle logos for commercial purposes
without prior written permission from Moodle HQ.
* You can't use "Moodle" in the name of your software (including Mobile apps).
* You can't use "Moodle" in your company name.
* You can't use "Moodle" in your domain name.
* You can't use "Moodle" in advertising-related keywords (such as Adsense).
* You can't use "Moodle" to describe services around Moodle
(such as hosting, training, support, consulting, course creation services,
theme development, customisation, installation, integration, analytics
and certification) that cause consumers to be confused that you are
associated with Moodle HQ if you are not.
This applies even if you do not charge for the services.
Note that usually only Moodle Partners have this permission.
* You cant use "Moodle" in the name of your software (including Mobile apps)
* You cant use "Moodle" in your company name
* You cant use "Moodle" in your domain name
* You cant use "Moodle" in advertising-related keywords (such as Adsense)
* You cant use "Moodle" to describe services around Moodle (such as hosting,
training, support, consulting, course creation services, theme development,
customisation, installation, integration and certification). This applies
even if you do not charge for the services. Note that usually only Moodle
Partners have this permission.
For information about the Moodle Partner Certification Mark as well as for how
to contact us, please see <https://moodle.com/trademarks/>.
+8 -14
View File
@@ -54,19 +54,18 @@ if (!confirm_sesskey()) {
redirect($returnurl);
}
$needsupdate = false;
switch ($action) {
case 'disable':
// Remove from enabled list.
$class = \core_plugin_manager::resolve_plugininfo_class('antivirus');
$class::enable_plugin($antivirus, false);
$key = array_search($antivirus, $activeantiviruses);
unset($activeantiviruses[$key]);
break;
case 'enable':
// Add to enabled list.
if (!in_array($antivirus, $activeantiviruses)) {
$class = \core_plugin_manager::resolve_plugininfo_class('antivirus');
$class::enable_plugin($antivirus, true);
$activeantiviruses[] = $antivirus;
$activeantiviruses = array_unique($activeantiviruses);
}
break;
@@ -79,7 +78,6 @@ switch ($action) {
$fsave = $activeantiviruses[$key];
$activeantiviruses[$key] = $activeantiviruses[$key + 1];
$activeantiviruses[$key + 1] = $fsave;
$needsupdate = true;
}
}
break;
@@ -93,7 +91,6 @@ switch ($action) {
$fsave = $activeantiviruses[$key];
$activeantiviruses[$key] = $activeantiviruses[$key - 1];
$activeantiviruses[$key - 1] = $fsave;
$needsupdate = true;
}
}
break;
@@ -101,13 +98,10 @@ switch ($action) {
default:
break;
}
$new = implode(',', $activeantiviruses);
add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core');
set_config('antiviruses', $new);
if ($needsupdate) {
$new = implode(',', $activeantiviruses);
add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core');
set_config('antiviruses', $new);
core_plugin_manager::reset_caches();
}
core_plugin_manager::reset_caches();
redirect ($returnurl);
+24 -12
View File
@@ -40,15 +40,29 @@ if (!confirm_sesskey()) {
switch ($action) {
case 'disable':
// Remove from enabled list.
$class = \core_plugin_manager::resolve_plugininfo_class('auth');
$class::enable_plugin($auth, false);
// remove from enabled list
$key = array_search($auth, $authsenabled);
if ($key !== false) {
unset($authsenabled[$key]);
set_config('auth', implode(',', $authsenabled));
}
if ($auth == $CFG->registerauth) {
set_config('registerauth', '');
}
\core\session\manager::gc(); // Remove stale sessions.
core_plugin_manager::reset_caches();
break;
case 'enable':
// Add to enabled list.
$class = \core_plugin_manager::resolve_plugininfo_class('auth');
$class::enable_plugin($auth, true);
// add to enabled list
if (!in_array($auth, $authsenabled)) {
$authsenabled[] = $auth;
$authsenabled = array_unique($authsenabled);
set_config('auth', implode(',', $authsenabled));
}
\core\session\manager::gc(); // Remove stale sessions.
core_plugin_manager::reset_caches();
break;
case 'down':
@@ -62,9 +76,7 @@ switch ($action) {
$fsave = $authsenabled[$key];
$authsenabled[$key] = $authsenabled[$key + 1];
$authsenabled[$key + 1] = $fsave;
$value = implode(',', $authsenabled);
add_to_config_log('auth', $CFG->auth, $value, 'core');
set_config('auth', $value);
set_config('auth', implode(',', $authsenabled));
}
break;
@@ -79,9 +91,7 @@ switch ($action) {
$fsave = $authsenabled[$key];
$authsenabled[$key] = $authsenabled[$key - 1];
$authsenabled[$key - 1] = $fsave;
$value = implode(',', $authsenabled);
add_to_config_log('auth', $CFG->auth, $value, 'core');
set_config('auth', $value);
set_config('auth', implode(',', $authsenabled));
}
break;
@@ -90,3 +100,5 @@ switch ($action) {
}
redirect($returnurl);
+2
View File
@@ -171,6 +171,8 @@ function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts,
// limit for the setting name is 100.
continue;
}
} elseif ($fieldname == 'url') {
$fieldname = get_string('webpage');
} else {
$fieldname = get_string($fieldname);
}
+15 -16
View File
@@ -30,28 +30,26 @@
$strprotect = get_string('blockprotect', 'admin');
$strunprotect = get_string('blockunprotect', 'admin');
/// If data submitted, then process and store.
// If data submitted, then process and store.
if (!empty($hide) && confirm_sesskey()) {
if (!$block = $DB->get_record('block', ['id' => $hide])) {
throw new \moodle_exception('blockdoesnotexist', 'error');
if (!$block = $DB->get_record('block', array('id'=>$hide))) {
print_error('blockdoesnotexist', 'error');
}
$class = \core_plugin_manager::resolve_plugininfo_class('block');
$class::enable_plugin($block->name, false);
// Settings not required - only pages.
admin_get_root(true, false);
$DB->set_field('block', 'visible', '0', array('id'=>$block->id)); // Hide block
add_to_config_log('block_visibility', $block->visible, '0', $block->name);
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
if (!empty($show) && confirm_sesskey() ) {
if (!$block = $DB->get_record('block', ['id' => $show])) {
throw new \moodle_exception('blockdoesnotexist', 'error');
if (!$block = $DB->get_record('block', array('id'=>$show))) {
print_error('blockdoesnotexist', 'error');
}
$class = \core_plugin_manager::resolve_plugininfo_class('block');
$class::enable_plugin($block->name, true);
// Settings not required - only pages.
admin_get_root(true, false);
$DB->set_field('block', 'visible', '1', array('id'=>$block->id)); // Show block
add_to_config_log('block_visibility', $block->visible, '1', $block->name);
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
if (!empty($protect) && confirm_sesskey()) {
@@ -69,7 +67,6 @@
echo $OUTPUT->header();
echo $OUTPUT->heading($strmanageblocks);
echo $OUTPUT->notification(get_string('noteunneededblocks', 'admin'), 'info');
/// Main display starts here
/// Get and sort the existing blocks
@@ -237,3 +234,5 @@
}
echo $OUTPUT->footer();
+8 -11
View File
@@ -48,12 +48,6 @@ if (!($settingspage->check_access())) {
print_error('accessdenied', 'admin');
}
$hassiteconfig = has_capability('moodle/site:config', $PAGE->context);
if ($hassiteconfig) {
$PAGE->add_header_action($OUTPUT->render_from_template('core_admin/header_search_input', [
'action' => new moodle_url('/admin/search.php'),
]));
}
$statusmsg = '';
$errormsg = '';
@@ -81,7 +75,7 @@ if ($PAGE->user_allowed_editing() && $adminediting != -1) {
$USER->editing = $adminediting;
}
$buttons = null;
if ($PAGE->user_allowed_editing() && !$PAGE->theme->haseditswitch) {
if ($PAGE->user_allowed_editing()) {
$url = clone($PAGE->url);
if ($PAGE->user_is_editing()) {
$caption = get_string('blockseditoff');
@@ -146,7 +140,13 @@ if ($errormsg !== '') {
echo $OUTPUT->notification($statusmsg, 'notifysuccess');
}
echo $OUTPUT->heading(get_string('admincategory', 'admin', $settingspage->visiblename), 2);
$path = array_reverse($settingspage->visiblepath);
if (is_array($path)) {
$visiblename = join(' / ', $path);
} else {
$visiblename = $path;
}
echo $OUTPUT->heading(get_string('admincategory', 'admin', $visiblename), 2);
echo html_writer::start_tag('form', array('action' => '', 'method' => 'post', 'id' => 'adminsettings'));
echo html_writer::start_tag('div');
@@ -158,7 +158,4 @@ echo $outputhtml;
echo html_writer::end_tag('fieldset');
echo html_writer::end_tag('form');
// Add the form change checker.
$PAGE->requires->js_call_amd('core_form/changechecker', 'watchFormById', ['adminsettings']);
echo $OUTPUT->footer();
@@ -48,17 +48,6 @@ class testoutgoingmailconf_form extends \moodleform {
$mform->setType('recipient', PARAM_EMAIL);
$mform->addRule('recipient', get_string('required'), 'required');
// From user.
$options = ['maxlength' => '100', 'size' => '25'];
$mform->addElement('text', 'from', get_string('testoutgoingmailconf_fromemail', 'admin'), $options);
$mform->setType('from', PARAM_TEXT);
$mform->addHelpButton('from', 'testoutgoingmailconf_fromemail', 'admin');
// Additional subject text.
$options = ['size' => '25'];
$mform->addElement('text', 'additionalsubject', get_string('testoutgoingmailconf_subjectadditional', 'admin'), $options);
$mform->setType('additionalsubject', PARAM_TEXT);
$buttonarray = array();
$buttonarray[] = $mform->createElement('submit', 'send', get_string('testoutgoingmailconf_sendtest', 'admin'));
$buttonarray[] = $mform->createElement('cancel');
@@ -67,26 +56,4 @@ class testoutgoingmailconf_form extends \moodleform {
$mform->closeHeaderBefore('buttonar');
}
/**
* Validate Form field, should be a valid email format or a username that matches with a Moodle user.
*
* @param array $data
* @param array $files
* @return array
* @throws \dml_exception|\coding_exception
*/
public function validation($data, $files): array {
$errors = parent::validation($data, $files);
if (isset($data['from']) && $data['from']) {
$userfrom = \core_user::get_user_by_username($data['from']);
if (!$userfrom && !validate_email($data['from'])) {
$errors['from'] = get_string('testoutgoingmailconf_fromemail_invalid', 'admin');
}
}
return $errors;
}
}
-304
View File
@@ -1,304 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\local\entities;
use core_reportbuilder\local\filters\date;
use core_reportbuilder\local\filters\duration;
use core_reportbuilder\local\filters\select;
use core_reportbuilder\local\filters\text;
use core_reportbuilder\local\helpers\format;
use lang_string;
use core_reportbuilder\local\entities\base;
use core_reportbuilder\local\report\column;
use core_reportbuilder\local\report\filter;
use stdClass;
/**
* Task log entity class implementation
*
* @package core_admin
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_log extends base {
/** @var int Result success */
protected const SUCCESS = 0;
/** @var int Result failed */
protected const FAILED = 1;
/**
* Database tables that this entity uses and their default aliases
*
* @return array
*/
protected function get_default_table_aliases(): array {
return ['task_log' => 'tl'];
}
/**
* The default title for this entity in the list of columns/conditions/filters in the report builder
*
* @return lang_string
*/
protected function get_default_entity_title(): lang_string {
return new lang_string('entitytasklog', 'admin');
}
/**
* The default machine-readable name for this entity that will be used in the internal names of the columns/filters
*
* @return string
*/
protected function get_default_entity_name(): string {
return 'task_log';
}
/**
* Initialise the entity
*
* @return base
*/
public function initialise(): base {
$columns = $this->get_all_columns();
foreach ($columns as $column) {
$this->add_column($column);
}
$filters = $this->get_all_filters();
foreach ($filters as $filter) {
$this->add_filter($filter);
}
return $this;
}
/**
* Returns list of all available columns
*
* @return column[]
*/
protected function get_all_columns(): array {
$tablealias = $this->get_table_alias('task_log');
// Name column.
$columns[] = (new column(
'name',
new lang_string('name'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_field("$tablealias.classname")
->set_is_sortable(true)
->add_callback(static function(string $value): string {
$output = '';
if (class_exists($value)) {
$task = new $value;
if ($task instanceof \core\task\scheduled_task) {
$output = $task->get_name();
}
}
$output .= \html_writer::tag('div', "\\{$value}", [
'class' => 'task-class',
]);
return $output;
});
// Type column.
$columns[] = (new column(
'type',
new lang_string('tasktype', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_field("{$tablealias}.type")
->set_is_sortable(true)
->add_callback(static function(int $value): string {
if (\core\task\database_logger::TYPE_SCHEDULED === $value) {
return get_string('task_type:scheduled', 'admin');
}
return get_string('task_type:adhoc', 'admin');
});
// Start time column.
$columns[] = (new column(
'starttime',
new lang_string('task_starttime', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TIMESTAMP)
->add_field("{$tablealias}.timestart")
->set_is_sortable(true)
->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
// Duration column.
$columns[] = (new column(
'duration',
new lang_string('task_duration', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_FLOAT)
->add_field("{$tablealias}.timeend - {$tablealias}.timestart", 'duration')
->set_is_sortable(true)
->add_callback(static function(float $value): string {
$duration = round($value, 2);
if (empty($duration)) {
// The format_time function returns 'now' when the difference is exactly 0.
// Note: format_time performs concatenation in exactly this fashion so we should do this for consistency.
return '0 ' . get_string('secs', 'moodle');
}
return format_time($duration);
});
// Hostname column.
$columns[] = (new column(
'hostname',
new lang_string('hostname', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_field("$tablealias.hostname")
->set_is_sortable(true);
// PID column.
$columns[] = (new column(
'pid',
new lang_string('pid', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_field("{$tablealias}.pid")
->set_is_sortable(true);
// Database column.
$columns[] = (new column(
'database',
new lang_string('task_dbstats', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_fields("{$tablealias}.dbreads, {$tablealias}.dbwrites")
->set_is_sortable(true)
->add_callback(static function(int $value, stdClass $row): string {
$output = '';
$output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
$output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
return $output;
});
// Result column.
$columns[] = (new column(
'result',
new lang_string('task_result', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_field("$tablealias.result")
->set_is_sortable(true)
->add_callback(static function(int $value): string {
if ($value) {
return get_string('task_result:failed', 'admin');
}
return get_string('success');
});
return $columns;
}
/**
* Return list of all available filters
*
* @return filter[]
*/
protected function get_all_filters(): array {
$filters = [];
$tablealias = $this->get_table_alias('task_log');
// Name filter (Filter by classname).
$filters[] = (new filter(
text::class,
'name',
new lang_string('classname', 'tool_task'),
$this->get_entity_name(),
"{$tablealias}.classname"
))
->add_joins($this->get_joins());
// Output filter (Filter by task output).
$filters[] = (new filter(
text::class,
'output',
new lang_string('task_logoutput', 'admin'),
$this->get_entity_name(),
"{$tablealias}.output"
))
->add_joins($this->get_joins());
// Result filter.
$filters[] = (new filter(
select::class,
'result',
new lang_string('task_result', 'admin'),
$this->get_entity_name(),
"{$tablealias}.result"
))
->add_joins($this->get_joins())
->set_options([
self::SUCCESS => get_string('success'),
self::FAILED => get_string('task_result:failed', 'admin'),
]);
// Start time filter.
$filters[] = (new filter(
date::class,
'timestart',
new lang_string('task_starttime', 'admin'),
$this->get_entity_name(),
"{$tablealias}.timestart"
))
->add_joins($this->get_joins())
->set_limited_operators([
date::DATE_ANY,
date::DATE_RANGE,
date::DATE_PREVIOUS,
date::DATE_CURRENT,
]);
// Duration filter.
$filters[] = (new filter(
duration::class,
'duration',
new lang_string('task_duration', 'admin'),
$this->get_entity_name(),
"${tablealias}.timeend - {$tablealias}.timestart"
))
->add_joins($this->get_joins());
return $filters;
}
}
+2 -4
View File
@@ -98,7 +98,7 @@ class filesize extends \admin_setting {
if (empty($bytes)) {
return get_string('none');
}
return display_size($bytes, 0);
return display_size($bytes);
}
/**
@@ -126,7 +126,6 @@ class filesize extends \admin_setting {
if (is_null($bytes)) {
return null;
}
$bytes = intval($bytes);
return self::parse_bytes($bytes);
}
@@ -146,10 +145,9 @@ class filesize extends \admin_setting {
return get_string('errorsetting', 'admin');
}
// Calculate size in bytes, ensuring we don't overflow PHP_INT_MAX.
$bytes = $data['v'] * $data['u'];
$result = (is_int($bytes) && $this->config_write($this->name, $bytes));
$result = $this->config_write($this->name, $bytes);
return ($result ? '' : get_string('errorsetting', 'admin'));
}
@@ -1,37 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A settings page which can be viewed with a link directly.
*
* @package core_admin
* @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
use moodle_url;
interface linkable_settings_page {
/**
* Get the URL to view this settings page.
*
* @return moodle_url
*/
public function get_settings_page_url(): moodle_url;
}
@@ -1,121 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Admin setting to show current scheduled task's status.
*
* @package core
* @copyright 2021 Universitat Rovira i Virgili
* @author Jordi Pujol-Ahulló <jpahullo@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/moodlelib.php');
use admin_setting_description;
use core\task\manager;
use core\task\scheduled_task;
use html_writer;
use lang_string;
use moodle_url;
use stdClass;
/**
* This admin setting tells whether a given scheduled task is enabled, providing a link to its configuration page.
*
* The goal of this setting is to help contextualizing the configuration settings with related scheduled task status,
* providing the big picture of that part of the system.
*
* @package core
* @copyright 2021 Universitat Rovira i Virgili
* @author Jordi Pujol-Ahulló <jpahullo@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class setting_scheduled_task_status extends admin_setting_description {
/**
* @var string fully qualified class name of a scheduled task.
*/
private $classname;
/**
* @var string additional text to append to the description.
*/
private $extradescription;
/**
* setting_scheduled_task_status constructor.
* @param string $name unique setting name.
* @param string $scheduledtaskclassname full classpath class name of the scheduled task.
* @param string $extradescription extra detail to append to the scheduled task status to add context in the setting
* page.
*/
public function __construct(string $name, string $scheduledtaskclassname, string $extradescription = '') {
$visiblename = new lang_string('task_status', 'admin');
$this->classname = $scheduledtaskclassname;
$this->extradescription = $extradescription;
parent::__construct($name, $visiblename, '');
}
/**
* Calculates lazily the content of the description.
* @param mixed $data nothing expected in this case.
* @param string $query nothing expected in this case.
* @return string the HTML content to print for this setting.
*/
public function output_html($data, $query = ''): string {
if (empty($this->description)) {
$this->description = $this->get_task_description();
}
return parent::output_html($data, $query);
}
/**
* Returns the HTML to print as the description.
* @return string description to be printed.
*/
private function get_task_description(): string {
$task = manager::get_scheduled_task($this->classname);
if ($task->is_enabled()) {
$taskenabled = get_string('enabled', 'admin');
} else {
$taskenabled = get_string('disabled', 'admin');
}
$taskenabled = strtolower($taskenabled);
$gotourl = new moodle_url(
'/admin/tool/task/scheduledtasks.php',
[],
scheduled_task::get_html_id($this->classname)
);
if (!empty($this->extradescription)) {
$this->extradescription = '<br />' . $this->extradescription;
}
$taskdetail = new stdClass();
$taskdetail->class = $this->classname;
$taskdetail->name = $task->get_name();
$taskdetail->status = $taskenabled;
$taskdetail->gotourl = $gotourl->out(false);
$taskdetail->extradescription = $this->extradescription;
return html_writer::tag('p', get_string('task_status_desc', 'admin', $taskdetail));
}
}
@@ -1,158 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\local\systemreports;
use context_system;
use core_admin\local\entities\task_log;
use core_reportbuilder\local\entities\user;
use core_reportbuilder\local\report\action;
use lang_string;
use moodle_url;
use pix_icon;
use core_reportbuilder\system_report;
/**
* Task logs system report class implementation
*
* @package core_admin
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_logs extends system_report {
/**
* Initialise report, we need to set the main table, load our entities and set columns/filters
*/
protected function initialise(): void {
// Our main entity, it contains all of the column definitions that we need.
$entitymain = new task_log();
$entitymainalias = $entitymain->get_table_alias('task_log');
$this->set_main_table('task_log', $entitymainalias);
$this->add_entity($entitymain);
// Any columns required by actions should be defined here to ensure they're always available.
$this->add_base_fields("{$entitymainalias}.id");
// We can join the "user" entity to our "main" entity and use the fullname column from the user entity.
$entityuser = new user();
$entituseralias = $entityuser->get_table_alias('user');
$this->add_entity($entityuser->add_join(
"LEFT JOIN {user} {$entituseralias} ON {$entituseralias}.id = {$entitymainalias}.userid"
));
// Now we can call our helper methods to add the content we want to include in the report.
$this->add_columns();
$this->add_filters();
$this->add_actions();
// Set if report can be downloaded.
$this->set_downloadable(true, get_string('tasklogs', 'admin'));
}
/**
* Validates access to view this report
*
* @return bool
*/
protected function can_view(): bool {
return has_capability('moodle/site:config', context_system::instance());
}
/**
* Get the visible name of the report
*
* @return string
*/
public static function get_name(): string {
return get_string('entitytasklog', 'admin');
}
/**
* Adds the columns we want to display in the report
*
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
* unique identifier
*/
public function add_columns(): void {
$columns = [
'task_log:name',
'task_log:type',
'user:fullname',
'task_log:starttime',
'task_log:duration',
'task_log:hostname',
'task_log:pid',
'task_log:database',
'task_log:result',
];
$this->add_columns_from_entities($columns);
// It's possible to override the display name of a column, if you don't want to use the value provided by the entity.
if ($column = $this->get_column('user:fullname')) {
$column->set_title(new lang_string('user', 'admin'));
}
// It's possible to set a default initial sort direction for one column.
$this->set_initial_sort_column('task_log:starttime', SORT_DESC);
}
/**
* Adds the filters we want to display in the report
*
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
* unique identifier
*/
protected function add_filters(): void {
$filters = [
'task_log:name',
'task_log:output',
'task_log:result',
'task_log:timestart',
'task_log:duration',
];
$this->add_filters_from_entities($filters);
}
/**
* Add the system report actions. An extra column will be appended to each row, containing all actions added here
*
* Note the use of ":id" placeholder which will be substituted according to actual values in the row
*/
protected function add_actions(): void {
// Action to view individual task log on a popup window.
$this->add_action((new action(
new moodle_url('/admin/tasklogs.php', ['logid' => ':id']),
new pix_icon('e/search', ''),
[],
true,
new lang_string('view'),
)));
// Action to download individual task log.
$this->add_action((new action(
new moodle_url('/admin/tasklogs.php', ['logid' => ':id', 'download' => true]),
new pix_icon('t/download', ''),
[],
false,
new lang_string('download'),
)));
}
}
+292
View File
@@ -0,0 +1,292 @@
<?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/>.
/**
* Task log table.
*
* @package core_admin
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/tablelib.php');
/**
* Table to display list of task logs.
*
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_log_table extends \table_sql {
/**
* Constructor for the task_log table.
*
* @param string $filter
* @param int $resultfilter
*/
public function __construct(string $filter = '', int $resultfilter = null) {
global $DB;
if (-1 === $resultfilter) {
$resultfilter = null;
}
parent::__construct('tasklogs');
$columnheaders = [
'classname' => get_string('name'),
'type' => get_string('tasktype', 'admin'),
'userid' => get_string('user', 'admin'),
'timestart' => get_string('task_starttime', 'admin'),
'duration' => get_string('task_duration', 'admin'),
'hostname' => get_string('hostname', 'tool_task'),
'pid' => get_string('pid', 'tool_task'),
'db' => get_string('task_dbstats', 'admin'),
'result' => get_string('task_result', 'admin'),
'actions' => '',
];
$this->define_columns(array_keys($columnheaders));
$this->define_headers(array_values($columnheaders));
// The name column is a header.
$this->define_header_column('classname');
// This table is not collapsible.
$this->collapsible(false);
// The actions class should not wrap. Use the BS text utility class.
$this->column_class('actions', 'text-nowrap');
// Allow pagination.
$this->pageable(true);
// Allow sorting. Default to sort by timestarted DESC.
$this->sortable(true, 'timestart', SORT_DESC);
// Add filtering.
$where = [];
$params = [];
if (!empty($filter)) {
$orwhere = [];
$filter = str_replace('\\', '\\\\', $filter);
// Check the class name.
$orwhere[] = $DB->sql_like('classname', ':classfilter', false, false);
$params['classfilter'] = '%' . $DB->sql_like_escape($filter) . '%';
$orwhere[] = $DB->sql_like('output', ':outputfilter', false, false);
$params['outputfilter'] = '%' . $DB->sql_like_escape($filter) . '%';
$where[] = "(" . implode(' OR ', $orwhere) . ")";
}
if (null !== $resultfilter) {
$where[] = 'tl.result = :result';
$params['result'] = $resultfilter;
}
$where = implode(' AND ', $where);
$this->set_sql('', '', $where, $params);
}
/**
* Query the db. Store results in the table object for use by build_table.
*
* @param int $pagesize size of page for paginated displayed table.
* @param bool $useinitialsbar do you want to use the initials bar. Bar
* will only be used if there is a fullname column defined for the table.
*/
public function query_db($pagesize, $useinitialsbar = true) {
global $DB;
// Fetch the attempts.
$sort = $this->get_sql_sort();
if ($sort) {
$sort = "ORDER BY $sort";
}
$extrafields = get_extra_user_fields(\context_system::instance());
$userfields = \user_picture::fields('u', $extrafields, 'userid2', 'user');
$where = '';
if (!empty($this->sql->where)) {
$where = "WHERE {$this->sql->where}";
}
$sql = "SELECT
tl.id, tl.type, tl.component, tl.classname, tl.userid, tl.timestart, tl.timeend,
tl.hostname, tl.pid,
tl.dbreads, tl.dbwrites, tl.result,
tl.dbreads + tl.dbwrites AS db,
tl.timeend - tl.timestart AS duration,
{$userfields}
FROM {task_log} tl
LEFT JOIN {user} u ON u.id = tl.userid
{$where}
{$sort}";
$this->pagesize($pagesize, $DB->count_records_sql("SELECT COUNT('x') FROM {task_log} tl {$where}", $this->sql->params));
if (!$this->is_downloading()) {
$this->rawdata = $DB->get_records_sql($sql, $this->sql->params, $this->get_page_start(), $this->get_page_size());
} else {
$this->rawdata = $DB->get_records_sql($sql, $this->sql->params);
}
}
/**
* Format the name cell.
*
* @param \stdClass $row
* @return string
*/
public function col_classname($row) : string {
$output = '';
if (class_exists($row->classname)) {
$task = new $row->classname;
if ($task instanceof \core\task\scheduled_task) {
$output = $task->get_name();
}
}
$output .= \html_writer::tag('div', "\\{$row->classname}", [
'class' => 'task-class',
]);
return $output;
}
/**
* Format the type cell.
*
* @param \stdClass $row
* @return string
*/
public function col_type($row) : string {
if (\core\task\database_logger::TYPE_SCHEDULED == $row->type) {
return get_string('task_type:scheduled', 'admin');
} else {
return get_string('task_type:adhoc', 'admin');
}
}
/**
* Format the timestart cell.
*
* @param \stdClass $row
* @return string
*/
public function col_result($row) : string {
if ($row->result) {
return get_string('task_result:failed', 'admin');
} else {
return get_string('success');
}
}
/**
* Format the timestart cell.
*
* @param \stdClass $row
* @return string
*/
public function col_timestart($row) : string {
return userdate($row->timestart, get_string('strftimedatetimeshort', 'langconfig'));
}
/**
* Format the duration cell.
*
* @param \stdClass $row
* @return string
*/
public function col_duration($row) : string {
$duration = round($row->timeend - $row->timestart, 2);
if (empty($duration)) {
// The format_time function returns 'now' when the difference is exactly 0.
// Note: format_time performs concatenation in exactly this fashion so we should do this for consistency.
return '0 ' . get_string('secs', 'moodle');
}
return format_time($duration);
}
/**
* Format the DB details cell.
*
* @param \stdClass $row
* @return string
*/
public function col_db($row) : string {
$output = '';
$output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
$output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
return $output;
}
/**
* Format the actions cell.
*
* @param \stdClass $row
* @return string
*/
public function col_actions($row) : string {
global $OUTPUT;
$actions = [];
$url = new \moodle_url('/admin/tasklogs.php', ['logid' => $row->id]);
// Quick view.
$actions[] = $OUTPUT->action_icon(
$url,
new \pix_icon('e/search', get_string('view')),
new \popup_action('click', $url)
);
// Download.
$actions[] = $OUTPUT->action_icon(
new \moodle_url($url, ['download' => true]),
new \pix_icon('t/download', get_string('download'))
);
return implode('&nbsp;', $actions);
}
/**
* Format the user cell.
*
* @param \stdClass $row
* @return string
*/
public function col_userid($row) : string {
if (empty($row->userid)) {
return '';
}
$user = (object) [];
username_load_fields_from_object($user, $row, 'user');
return fullname($user);
}
}
+1 -8
View File
@@ -120,14 +120,7 @@ if ($options['unset'] || $options['set'] !== null) {
}
// Check that the variable is not hard-set in the main config.php already.
$component = $options['component'];
if (!empty($component)) {
$componentsettings = $CFG->forced_plugin_settings[$component] ?? [];
$settinginconfig = array_key_exists($options['name'], $componentsettings);
} else {
$settinginconfig = array_key_exists($options['name'], $CFG->config_php_settings);
}
if ($settinginconfig) {
if (array_key_exists($options['name'], $CFG->config_php_settings)) {
cli_error('The configuration variable is hard-set in the config.php, unable to change.', 4);
}
-65
View File
@@ -1,65 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI script to reset dashboards.
*
* @package core
* @subpackage cli
* @copyright 2021 Brendan Heywood (brendan@catalyst-au.net)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require_once($CFG->libdir.'/clilib.php');
require_once($CFG->dirroot.'/my/lib.php');
list($options, $unrecognized) = cli_get_params([
'help' => false,
'execute' => false,
], [
'h' => 'help',
'e' => 'execute',
]);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2);
}
if (!$options['execute']) {
$help = <<<EOF
Resets Moodle dashboards for all users
Options:
-h, --help Print out this help
-e, --execute Actually run the reset
Example:
\$ sudo -u www-data /usr/bin/php admin/cli/dashboard_reset.php -e
EOF;
echo $help;
exit(0);
}
$progressbar = new progress_bar();
$progressbar->create();
my_reset_page_for_all_users(MY_PAGE_PRIVATE, 'my-index', $progressbar);
-138
View File
@@ -1,138 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Fix orphaned calendar events that were broken by MDL-67494.
*
* This script will look for all the calendar events which userids
* where broken by a wrong upgrade step, affecting to Moodle 3.9.5
* and up.
*
* It performs checks to both:
* a) Detect if the site was affected (ran the wrong upgrade step).
* b) Look for orphaned calendar events, categorising them as:
* - standard: site / category / course / group / user events
* - subscription: events created via subscriptions.
* - action: normal action events, created to show common important dates.
* - override: user and group override events, particular, that some activities support.
* - custom: other events, not being any of the above, common or particular.
* By specifying it (--fix) try to recover as many broken events (missing userid) as
* possible. Standard, subscription, action, override events in core are fully supported but
* override or custom events should be fixed by each plugin as far as there isn't any standard
* API (plugin-wise) to launch a rebuild of the calendar events.
*
* @package core
* @copyright 2021 onwards Simey Lameze <simey@moodle.com>
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require_once(__DIR__ . '/../../config.php');
require_once($CFG->libdir . "/clilib.php");
require_once($CFG->libdir . '/db/upgradelib.php');
// Supported options.
$long = ['fix' => false, 'help' => false];
$short = ['f' => 'fix', 'h' => 'help'];
// CLI options.
[$options, $unrecognized] = cli_get_params($long, $short);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
$help = <<<EOT
Fix orphaned calendar events.
This script detects calendar events that have had their
userid lost. By default it will perform various checks
and report them, showing the site status in an easy way.
Also, optionally (--fix), it wil try to recover as many
lost userids as possible from different sources. Note that
this script aims to process well-know events in core,
leaving custom events in 3rd part plugins mostly unmodified
because there isn't any consistent way to regenerate them.
For more details: https://tracker.moodle.org/browse/MDL-71156
Options:
-h, --help Print out this help.
-f, --fix Fix the orphaned calendar events in the DB.
If not specified only check and report problems to STDERR.
Usage:
- Only report: \$ sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_calendar_events.php
- Report and fix: \$ sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_calendar_events.php -f
EOT;
cli_writeln($help);
die;
}
// Check various usual pre-requisites.
if (empty($CFG->version)) {
cli_error('Database is not yet installed.');
}
$admin = get_admin();
if (!$admin) {
cli_error('Error: No admin account was found.');
}
if (moodle_needs_upgrading()) {
cli_error('Moodle upgrade pending, script execution suspended.');
}
// Do everything as admin by default.
\core\session\manager::set_user($admin);
// Report current site status.
cli_heading('Checking the site status');
$needsfix = upgrade_calendar_site_status();
// Report current calendar events status.
cli_heading('Checking the calendar events status');
$info = upgrade_calendar_events_status();
$hasbadevents = $info['total']->bad > 0 || $info['total']->bad != $info['other']->bad;
$needsfix = $needsfix || $hasbadevents;
// If, selected, fix as many calendar events as possible.
if ($options['fix']) {
// If the report has told us that the fix was not needed... ask for confirmation!
if (!$needsfix) {
cli_writeln("This site DOES NOT NEED to run the calendar events fix.");
$input = cli_input('Are you completely sure that you want to run the fix? (y/N)', 'N', ['y', 'Y', 'n', 'N']);
if (strtolower($input) != 'y') {
exit(0);
}
cli_writeln("");
}
cli_heading('Fixing as many as possible calendar events');
upgrade_calendar_events_fix_remaining($info);
// Report current (after fix) calendar events status.
cli_heading('Checking the calendar events status (after fix)');
upgrade_calendar_events_status();
} else if ($needsfix) {
// Fix option was not provided but problem events have been found. Notify the user and provide info how to fix these events.
cli_writeln("This site NEEDS to run the calendar events fix!");
cli_writeln("To fix the calendar events, re-run this script with the --fix option.");
}
-79
View File
@@ -1,79 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Generates a secure key for the current server (presuming it does not already exist).
*
* @package core_admin
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use \core\encryption;
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/clilib.php');
// Get cli options.
[$options, $unrecognized] = cli_get_params(
['help' => false, 'method' => null],
['h' => 'help']);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
// TODO: MDL-71421 - Remove the openssl alternative once sodium becomes a requirement in Moodle 4.2.
if ($options['help']) {
echo "Generate secure key
This script manually creates a secure key within the secret data root folder (configured in
config.php as \$CFG->secretdataroot). You must run it using an account with access to write
to that folder.
In normal use Moodle automatically creates the key; this script is intended when setting up
a new Moodle system, for cases where the secure folder is not on shared storage and the key
may be manually installed on multiple servers.
Options:
-h, --help Print out this help
--method <method> Generate key for specified encryption method instead of default.
* sodium
* openssl-aes-256-ctr
Example:
php admin/cli/generate_key.php
";
exit;
}
$method = $options['method'];
if (encryption::key_exists($method)) {
echo 'Key already exists: ' . encryption::get_key_file($method) . "\n";
exit;
}
// Creates key with default permissions (no chmod).
echo "Generating key...\n";
encryption::create_key($method, false);
echo "\nKey created: " . encryption::get_key_file($method) . "\n\n";
echo "If the key folder is not shared storage, then key files should be copied to all servers.\n";
-24
View File
@@ -74,8 +74,6 @@ Options:
--adminpass=PASSWORD Password for the moodle admin account,
required in non-interactive mode.
--adminemail=STRING Email address for the moodle admin account.
--sitepreset=STRING Admin site preset to be applied during the installation process.
--supportemail=STRING Email address for support and help.
--upgradekey=STRING The upgrade key to be set in the config.php, leave empty to not set it.
--non-interactive No interactive questions, installation fails if any
problem encountered.
@@ -256,8 +254,6 @@ list($options, $unrecognized) = cli_get_params(
'adminuser' => 'admin',
'adminpass' => '',
'adminemail' => '',
'sitepreset' => '',
'supportemail' => '',
'upgradekey' => '',
'non-interactive' => false,
'agree-license' => false,
@@ -280,12 +276,6 @@ if (array_key_exists($lang, $languages)) {
$CFG->lang = $lang;
}
// Set up site admin preset.
$sitepreset = clean_param($options['sitepreset'], PARAM_RAW);
if (!empty($sitepreset)) {
$CFG->setsitepresetduringinstall = $sitepreset;
}
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
@@ -741,20 +731,6 @@ if (!$skipdatabase) {
$a = (object)['option' => 'adminemail', 'value' => $options['adminemail']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
// Ask for the support email address.
if ($interactive) {
cli_separator();
cli_heading(get_string('clisupportemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['supportemail']);
$options['supportemail'] = cli_input($prompt, $options['supportemail']);
}
// Validate that the support email address provided is valid.
if (!empty($options['supportemail']) && !validate_email($options['supportemail'])) {
$a = (object)['option' => 'supportemail', 'value' => $options['supportemail']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for the upgrade key.
-7
View File
@@ -56,7 +56,6 @@ Options:
--agree-license Indicates agreement with software license.
--fullname=STRING Name of the site
--shortname=STRING Name of the site
--summary=STRING The summary to be displayed on the front page
-h, --help Print out this help
Example:
@@ -97,7 +96,6 @@ list($options, $unrecognized) = cli_get_params(
'adminemail' => '',
'fullname' => '',
'shortname' => '',
'summary' => '',
'agree-license' => false,
'help' => false
),
@@ -106,11 +104,6 @@ list($options, $unrecognized) = cli_get_params(
)
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
// We show help text even if tables are installed.
if ($options['help']) {
echo $help;
+8 -8
View File
@@ -119,7 +119,7 @@ if (!empty($options['collation'])) {
if ($dbcollation->value !== $collation || $dbcharset->value !== $charset) {
// Try to convert the DB.
echo "Converting database to '$collation' for $CFG->wwwroot:\n";
$sql = "ALTER DATABASE `$CFG->dbname` DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
$sql = "ALTER DATABASE $CFG->dbname DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
try {
$DB->change_database_structure($sql);
} catch (exception $e) {
@@ -146,7 +146,7 @@ if (!empty($options['collation'])) {
} else {
try {
$DB->change_database_structure("ALTER TABLE `$table->name` CONVERT TO CHARACTER SET $charset COLLATE $collation");
$DB->change_database_structure("ALTER TABLE $table->name CONVERT TO CHARACTER SET $charset COLLATE $collation");
echo "CONVERTED\n";
$converted++;
} catch (ddl_exception $e) {
@@ -163,7 +163,7 @@ if (!empty($options['collation'])) {
}
}
$sql = "SHOW FULL COLUMNS FROM `$table->name` WHERE collation IS NOT NULL";
$sql = "SHOW FULL COLUMNS FROM $table->name WHERE collation IS NOT NULL";
$rs2 = $DB->get_recordset_sql($sql);
foreach ($rs2 as $column) {
$column = (object)array_change_key_case((array)$column, CASE_LOWER);
@@ -181,7 +181,7 @@ if (!empty($options['collation'])) {
$notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
$default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
// primary, unique and inc are not supported for texts
$sql = "ALTER TABLE `$table->name`
$sql = "ALTER TABLE $table->name
MODIFY COLUMN $column->field $column->type
CHARACTER SET $charset
COLLATE $collation $notnull $default";
@@ -192,11 +192,11 @@ if (!empty($options['collation'])) {
$default = !is_null($column->default) ? "DEFAULT '$column->default'" : '';
if ($rowformat != '') {
$sql = "ALTER TABLE `$table->name` $rowformat";
$sql = "ALTER TABLE $table->name $rowformat";
$DB->change_database_structure($sql);
}
$sql = "ALTER TABLE `$table->name`
$sql = "ALTER TABLE $table->name
MODIFY COLUMN $column->field $column->type
CHARACTER SET $charset
COLLATE $collation $notnull $default";
@@ -315,8 +315,8 @@ function mysql_set_row_format($tablename, $charset, $collation, $engine) {
if ($rs->row_format == 'Compact' || $rs->row_format == 'Redundant') {
$rowformat = $DB->get_row_format_sql($engine, $collation);
// Try to convert to compressed format and then try updating the collation again.
$DB->change_database_structure("ALTER TABLE `$tablename` $rowformat");
$DB->change_database_structure("ALTER TABLE `$tablename` CONVERT TO CHARACTER SET $charset COLLATE $collation");
$DB->change_database_structure("ALTER TABLE $tablename $rowformat");
$DB->change_database_structure("ALTER TABLE $tablename CONVERT TO CHARACTER SET $charset COLLATE $collation");
} else {
// Row format may not be the problem. Can not diagnose problem. Send fail reply.
return false;
+2 -2
View File
@@ -158,7 +158,7 @@ if (!empty($options['info'])) {
}
foreach ($fixtables as $table) {
$DB->change_database_structure("ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed");
$DB->change_database_structure("ALTER TABLE {$prefix}$table ROW_FORMAT=Compressed");
echo str_pad($prefix . $table, 32, ' ', STR_PAD_RIGHT) . " ... Compressed\n";
}
@@ -189,7 +189,7 @@ if (!empty($options['info'])) {
echo "SET GLOBAL innodb_file_per_table=1;\n";
echo "SET GLOBAL innodb_file_format=Barracuda;\n";
foreach ($fixtables as $table) {
echo "ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed;\n";
echo "ALTER TABLE {$prefix}$table ROW_FORMAT=Compressed;\n";
}
echo "\n";
exit(0);
+180
View File
@@ -0,0 +1,180 @@
<?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/>.
/**
* MySQL engine conversion tool.
*
* @package core
* @subpackage cli
* @copyright 2009 Petr Skoda (http://skodak.org)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require_once($CFG->libdir.'/clilib.php'); // cli only functions
if ($DB->get_dbfamily() !== 'mysql') {
cli_error('This function is designed for MySQL databases only!');
}
// now get cli options
list($options, $unrecognized) = cli_get_params(array('help'=>false, 'list'=>false, 'engine'=>false, 'available'=>false),
array('h'=>'help', 'l'=>'list', 'a'=>'available'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
$help =
"MySQL engine conversions script.
It is recommended to stop the web server before the conversion.
Do not use MyISAM if possible, because it is not ACID compliant
and does not support transactions.
Options:
--engine=ENGINE Convert MySQL tables to different engine
-l, --list Show table information
-a, --available Show list of available engines
-h, --help Print out this help
Example:
\$sudo -u www-data /usr/bin/php admin/cli/mysql_engine.php --engine=InnoDB
";
if (!empty($options['engine'])) {
$engines = mysql_get_engines();
$engine = clean_param($options['engine'], PARAM_ALPHA);
if (!isset($engines[strtoupper($engine)])) {
cli_error("Error: engine '$engine' is not available on this server!");
}
echo "Converting tables to '$engine' for $CFG->wwwroot:\n";
$prefix = $DB->get_prefix();
$prefix = str_replace('_', '\\_', $prefix);
$sql = "SHOW TABLE STATUS WHERE Name LIKE BINARY '$prefix%'";
$rs = $DB->get_recordset_sql($sql);
$converted = 0;
$skipped = 0;
$errors = 0;
foreach ($rs as $table) {
if (strtoupper($table->engine) === strtoupper($engine)) {
$newengine = mysql_get_table_engine($table->name);
echo str_pad($table->name, 40). " - NO CONVERSION NEEDED ($newengine)\n";
$skipped++;
continue;
}
echo str_pad($table->name, 40). " - ";
try {
$DB->change_database_structure("ALTER TABLE {$table->name} ENGINE = $engine");
$newengine = mysql_get_table_engine($table->name);
if (strtoupper($newengine) !== strtoupper($engine)) {
echo "ERROR ($newengine)\n";
$errors++;
continue;
}
echo "DONE ($newengine)\n";
$converted++;
} catch (moodle_exception $e) {
echo $e->getMessage()."\n";
$errors++;
continue;
}
}
$rs->close();
echo "Converted: $converted, skipped: $skipped, errors: $errors\n";
exit(0); // success
} else if (!empty($options['list'])) {
echo "List of tables for $CFG->wwwroot:\n";
$prefix = $DB->get_prefix();
$prefix = str_replace('_', '\\_', $prefix);
$sql = "SHOW TABLE STATUS WHERE Name LIKE BINARY '$prefix%'";
$rs = $DB->get_recordset_sql($sql);
$counts = array();
foreach ($rs as $table) {
if (isset($counts[$table->engine])) {
$counts[$table->engine]++;
} else {
$counts[$table->engine] = 1;
}
echo str_pad($table->engine, 10);
echo $table->name . "\n";
}
$rs->close();
echo "\n";
echo "Table engines summary for $CFG->wwwroot:\n";
foreach ($counts as $engine => $count) {
echo "$engine: $count\n";
}
exit(0); // success
} else if (!empty($options['available'])) {
echo "List of available MySQL engines for $CFG->wwwroot:\n";
$engines = mysql_get_engines();
foreach ($engines as $engine) {
echo " $engine\n";
}
die;
} else {
echo $help;
die;
}
// ========== Some functions ==============
function mysql_get_engines() {
global $DB;
$sql = "SHOW Engines";
$rs = $DB->get_recordset_sql($sql);
$engines = array();
foreach ($rs as $engine) {
if (strtoupper($engine->support) !== 'YES' and strtoupper($engine->support) !== 'DEFAULT') {
continue;
}
$engines[strtoupper($engine->engine)] = $engine->engine;
if (strtoupper($engine->support) === 'DEFAULT') {
$engines[strtoupper($engine->engine)] .= ' (default)';
}
}
$rs->close();
return $engines;
}
function mysql_get_table_engine($tablename) {
global $DB;
$engine = null;
$sql = "SHOW TABLE STATUS WHERE Name = '$tablename'"; // no special chars expected here
$rs = $DB->get_recordset_sql($sql);
if ($rs->valid()) {
$record = $rs->current();
$engine = $record->engine;
}
$rs->close();
return $engine;
}
+2 -2
View File
@@ -69,11 +69,11 @@ if ($options['help'] or (!$options['list'] and !$options['execute'])) {
die;
}
if ($options['showdebugging'] || !empty($CFG->showcrondebugging)) {
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql'] || !empty($CFG->showcronsql)) {
if ($options['showsql']) {
$DB->set_debug(true);
}
if ($options['list']) {
-12
View File
@@ -39,8 +39,6 @@ Options:
--purge-missing Uninstall all missing from disk plugins.
--plugins=<plugin name> A comma separated list of plugins to be uninstalled. E.g. mod_assign,mod_forum
--run Execute uninstall. If this option is not set, then the script will be run in a dry mode.
--showsql Show sql queries before they are executed.
--showdebugging Show developer level debugging information.
Examples:
@@ -74,8 +72,6 @@ list($options, $unrecognised) = cli_get_params([
'purge-missing' => false,
'plugins' => false,
'run' => false,
'showsql' => false,
'showdebugging' => false,
], [
'h' => 'help'
]);
@@ -90,14 +86,6 @@ if ($options['help']) {
exit(0);
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql']) {
$DB->set_debug(true);
}
$pluginman = core_plugin_manager::instance();
$plugininfo = $pluginman->get_plugins();
-9
View File
@@ -135,15 +135,6 @@ if (!$envstatus) {
exit(1);
}
// Make sure there are no files left over from previous versions.
if (upgrade_stale_php_files_present()) {
cli_problem(get_string('upgradestalefiles', 'admin'));
// Stale file info contains HTML elements which aren't suitable for CLI.
$upgradestalefilesinfo = get_string('upgradestalefilesinfo', 'admin', get_docs_url('Upgrading'));
cli_error(strip_tags($upgradestalefilesinfo));
}
// Test plugin dependencies.
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
+3 -6
View File
@@ -48,14 +48,12 @@ if (!isset($plugins[$name])) {
switch ($action) {
case 'disable':
if ($plugins[$name]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('contenttype');
$class::enable_plugin($name, false);
set_config('disabled', 1, 'contentbank_'. $name);
}
break;
case 'enable':
if (!$plugins[$name]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('contenttype');
$class::enable_plugin($name, true);
unset_config('disabled', 'contentbank_'. $name);
}
break;
case 'up':
@@ -65,7 +63,6 @@ switch ($action) {
$seq[$currentindex] = $seq[$currentindex - 1];
$seq[$currentindex - 1] = $name;
set_config('contentbank_plugins_sortorder', implode(',', $seq));
core_plugin_manager::reset_caches();
}
break;
case 'down':
@@ -75,10 +72,10 @@ switch ($action) {
$seq[$currentindex] = $seq[$currentindex + 1];
$seq[$currentindex + 1] = $name;
set_config('contentbank_plugins_sortorder', implode(',', $seq));
core_plugin_manager::reset_caches();
}
break;
}
core_plugin_manager::reset_caches();
$cache = cache::make('core', 'contentbank_enabled_extensions');
$cache->purge();
$cache = cache::make('core', 'contentbank_context_extensions');
-78
View File
@@ -1,78 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Reset course indentation
*
* @copyright 2023 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../../config.php');
require_admin();
$format = required_param('format', PARAM_PLUGIN);
$confirm = optional_param('confirm', false, PARAM_BOOL);
$backurl = new moodle_url('/admin/settings.php', ['section' => 'formatsetting'.$format]);
$PAGE->set_url('/admin/course/resetindentation.php', ['format' => $format]);
$PAGE->set_context(context_system::instance());
if ($confirm) {
require_sesskey();
$courses = $DB->get_records('course', ['format' => $format], 'id', 'id');
if (!empty($courses)) {
$courseids = array_keys($courses);
list($courseinsql, $courseparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, 'course');
$DB->set_field_select('course_modules', 'indent', '0', "course $courseinsql AND indent <> 0", $courseparams);
rebuild_course_cache(0, true);
}
redirect(
$backurl,
get_string('resetindentationsuccess', 'admin'),
null,
\core\output\notification::NOTIFY_SUCCESS
);
}
$strtitle = get_string('resetindentation', 'admin');
$PAGE->set_title($strtitle);
$PAGE->set_heading($strtitle);
navigation_node::override_active_url(new moodle_url(
'/admin/course/resetindentation.php',
['action' => 'confirm', 'format' => $format]
));
echo $OUTPUT->header();
$displayoptions = ['confirmtitle' => get_string('resetindentation_title', 'admin')];
$confirmbutton = new single_button(
new moodle_url('/admin/course/resetindentation.php', ['confirm' => 1, 'format' => $format, 'sesskey' => sesskey()]),
get_string('resetindentation', 'admin'),
'post'
);
$cancelbutton = new single_button($backurl, get_string('cancel'));
echo $OUTPUT->confirm(
get_string('resetindentation_help', 'admin', ['format' => get_string('pluginname', 'format_'.$format)]),
$confirmbutton,
$cancelbutton,
$displayoptions
);
echo $OUTPUT->footer();
+7 -4
View File
@@ -47,14 +47,17 @@ if (!isset($formatplugins[$formatname])) {
switch ($action) {
case 'disable':
if ($formatplugins[$formatname]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('format');
$class::enable_plugin($formatname, false);
if (get_config('moodlecourse', 'format') === $formatname) {
print_error('cannotdisableformat', 'error', $return);
}
set_config('disabled', 1, 'format_'. $formatname);
core_plugin_manager::reset_caches();
}
break;
case 'enable':
if (!$formatplugins[$formatname]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('format');
$class::enable_plugin($formatname, true);
unset_config('disabled', 'format_'. $formatname);
core_plugin_manager::reset_caches();
}
break;
case 'up':
+4 -4
View File
@@ -47,14 +47,14 @@ if (!isset($customfieldplugins[$customfieldname])) {
switch ($action) {
case 'disable':
if ($customfieldplugins[$customfieldname]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('customfield');
$class::enable_plugin($customfieldname, false);
set_config('disabled', 1, 'customfield_'. $customfieldname);
core_plugin_manager::reset_caches();
}
break;
case 'enable':
if (!$customfieldplugins[$customfieldname]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('customfield');
$class::enable_plugin($customfieldname, true);
unset_config('disabled', 'customfield_'. $customfieldname);
core_plugin_manager::reset_caches();
}
break;
}
+5 -4
View File
@@ -48,14 +48,14 @@ if (!isset($plugins[$name])) {
switch ($action) {
case 'disable':
if ($plugins[$name]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('dataformat');
$class::enable_plugin($name, false);
set_config('disabled', 1, 'dataformat_'. $name);
core_plugin_manager::reset_caches();
}
break;
case 'enable':
if (!$plugins[$name]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('dataformat');
$class::enable_plugin($name, true);
unset_config('disabled', 'dataformat_'. $name);
core_plugin_manager::reset_caches();
}
break;
case 'up':
@@ -78,3 +78,4 @@ switch ($action) {
break;
}
redirect($return);
+17 -10
View File
@@ -39,19 +39,22 @@ if (!confirm_sesskey()) {
redirect($returnurl);
}
$return = true;
switch ($action) {
case 'disable':
// Remove from enabled list.
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
$class::enable_plugin($editor, false);
// remove from enabled list
$key = array_search($editor, $active_editors);
unset($active_editors[$key]);
add_to_config_log('editor_visibility', '1', '0', $editor);
break;
case 'enable':
// Add to enabled list.
// add to enabled list
if (!in_array($editor, $active_editors)) {
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
$class::enable_plugin($editor, true);
$active_editors[] = $editor;
$active_editors = array_unique($active_editors);
add_to_config_log('editor_visibility', '0', '1', $editor);
}
break;
@@ -65,8 +68,6 @@ switch ($action) {
$active_editors[$key] = $active_editors[$key + 1];
$active_editors[$key + 1] = $fsave;
add_to_config_log('editor_position', $key, $key + 1, $editor);
set_config('texteditors', implode(',', $active_editors));
core_plugin_manager::reset_caches();
}
}
break;
@@ -81,8 +82,6 @@ switch ($action) {
$active_editors[$key] = $active_editors[$key - 1];
$active_editors[$key - 1] = $fsave;
add_to_config_log('editor_position', $key, $key - 1, $editor);
set_config('texteditors', implode(',', $active_editors));
core_plugin_manager::reset_caches();
}
}
break;
@@ -91,6 +90,14 @@ switch ($action) {
break;
}
// at least one editor must be active
if (empty($active_editors)) {
$active_editors = array('textarea');
}
set_config('texteditors', implode(',', $active_editors));
core_plugin_manager::reset_caches();
if ($return) {
redirect ($returnurl);
}
+12 -5
View File
@@ -43,18 +43,25 @@ $all = enrol_get_plugins(false);
$return = new moodle_url('/admin/settings.php', array('section'=>'manageenrols'));
$syscontext = context_system::instance();
switch ($action) {
case 'disable':
$class = \core_plugin_manager::resolve_plugininfo_class('enrol');
$class::enable_plugin($enrol, false);
unset($enabled[$enrol]);
set_config('enrol_plugins_enabled', implode(',', array_keys($enabled)));
core_plugin_manager::reset_caches();
$syscontext->mark_dirty(); // resets all enrol caches
break;
case 'enable':
if (!isset($all[$enrol])) {
break;
}
$class = \core_plugin_manager::resolve_plugininfo_class('enrol');
$class::enable_plugin($enrol, true);
$enabled = array_keys($enabled);
$enabled[] = $enrol;
set_config('enrol_plugins_enabled', implode(',', $enabled));
core_plugin_manager::reset_caches();
$syscontext->mark_dirty(); // resets all enrol caches
break;
case 'up':
@@ -122,4 +129,4 @@ switch ($action) {
}
redirect($return);
redirect($return);
-959
View File
@@ -2815,7 +2815,6 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.1.0" level="required">
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
@@ -2997,7 +2996,6 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.2.0" level="required">
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
@@ -3163,11 +3161,6 @@
<ON_CHECK message="sixtyfourbitswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_igbinary322_version" level="optional">
<FEEDBACK>
<ON_CHECK message="igbinary322buggyversion" />
</FEEDBACK>
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="3.10" requires="3.5">
@@ -3184,7 +3177,6 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.2.0" level="required">
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
@@ -3350,957 +3342,6 @@
<ON_CHECK message="sixtyfourbitswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_igbinary322_version" level="optional">
<FEEDBACK>
<ON_CHECK message="igbinary322buggyversion" />
</FEEDBACK>
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="3.11" requires="3.6">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.2.29" />
<VENDOR name="mysql" version="5.7" />
<VENDOR name="postgres" version="9.6" />
<VENDOR name="mssql" version="14.0" />
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.3.0" level="required">
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlrpc" level="optional">
<FEEDBACK>
<ON_CHECK message="xmlrpcrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="required">
<FEEDBACK>
<ON_ERROR message="intlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="optional"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
<FEEDBACK>
<ON_CHECK message="sixtyfourbitswarning" />
</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_xmlrpc_usage" level="optional">
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="4.0" requires="3.6">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.2.29" />
<VENDOR name="mysql" version="5.7" />
<VENDOR name="postgres" version="10" />
<VENDOR name="mssql" version="14.0" />
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.3.0" level="required">
<RESTRICT function="restrict_php_version_81" message="unsupportedphpversion81" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlrpc" level="optional">
<FEEDBACK>
<ON_CHECK message="xmlrpcrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="required">
<FEEDBACK>
<ON_ERROR message="intlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="optional"/>
<PHP_EXTENSION name="exif" level="optional"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
<FEEDBACK>
<ON_CHECK message="sixtyfourbitswarning" />
</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_CHECKS>
</MOODLE>
<MOODLE version="4.1" requires="3.9">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.4" />
<VENDOR name="mysql" version="5.7" />
<VENDOR name="postgres" version="12" />
<VENDOR name="mssql" version="14.0" />
<VENDOR name="oracle" version="19" />
</DATABASE>
<PHP version="7.4.0" level="required">
<RESTRICT function="restrict_php_version_82" message="unsupportedphpversion82" />
</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="optional"/>
<PHP_EXTENSION name="exif" level="optional"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
<FEEDBACK>
<ON_CHECK message="sixtyfourbitswarning" />
</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_CHECKS>
</MOODLE>
<MOODLE version="4.2" requires="3.11.8">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.6.7" />
<VENDOR name="mysql" version="8.0" />
<VENDOR name="postgres" version="13" />
<VENDOR name="mssql" version="14.0" />
<VENDOR name="oracle" version="19" />
</DATABASE>
<PHP version="8.0.0" level="required">
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="required">
<FEEDBACK>
<ON_ERROR message="intlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="required"/>
<PHP_EXTENSION name="exif" level="optional"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="required">
<FEEDBACK>
<ON_ERROR message="sixtyfourbitsrequired" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
<FEEDBACK>
<ON_CHECK message="iscustomadminwarnings" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="4.3" requires="3.11.8">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.6.7" />
<VENDOR name="mysql" version="8.0" />
<VENDOR name="postgres" version="13" />
<VENDOR name="mssql" version="14.0" />
<VENDOR name="oracle" version="19" />
</DATABASE>
<PHP version="8.0.0" level="required">
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="required">
<FEEDBACK>
<ON_ERROR message="intlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="required"/>
<PHP_EXTENSION name="exif" level="optional"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="required">
<FEEDBACK>
<ON_ERROR message="sixtyfourbitsrequired" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_admin_dir_usage" level="optional">
<FEEDBACK>
<ON_CHECK message="iscustomadminwarnings" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_xmlrpc_usage" level="optional">
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mod_assignment" level="required">
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+33 -43
View File
@@ -31,15 +31,14 @@ $filterpath = optional_param('filterpath', '', PARAM_PLUGIN);
admin_externalpage_setup('managefilters');
// Clean up bogus filter states first.
/** @var core\plugininfo\filter[] $plugininfos */
$plugininfos = core_plugin_manager::instance()->get_plugins_of_type('filter');
$filters = [];
$filters = array();
$states = filter_get_global_states();
foreach ($states as $state) {
if (!isset($plugininfos[$state->filter]) and !get_config('filter_'.$state->filter, 'version')) {
// Purge messy leftovers after incorrectly uninstalled plugins and unfinished installations.
$DB->delete_records('filter_active', ['filter' => $state->filter]);
$DB->delete_records('filter_config', ['filter' => $state->filter]);
// Purge messy leftovers after incorrectly uninstalled plugins and unfinished installs.
$DB->delete_records('filter_active', array('filter' => $state->filter));
$DB->delete_records('filter_config', array('filter' => $state->filter));
error_log('Deleted bogus "filter_'.$state->filter.'" states and config data.');
} else {
$filters[$state->filter] = $state;
@@ -51,6 +50,7 @@ foreach ($plugininfos as $filter => $info) {
if (isset($filters[$filter])) {
continue;
}
/** @var \core\plugininfo\base $info */
if ($info->is_installed_and_upgraded()) {
filter_set_global_state($filter, TEXTFILTER_DISABLED);
$states = filter_get_global_states();
@@ -72,9 +72,10 @@ switch ($action) {
case 'setstate':
if (isset($filters[$filterpath]) and $newstate = optional_param('newstate', '', PARAM_INT)) {
/** @var \core\plugininfo\filter $class */
$class = core_plugin_manager::resolve_plugininfo_class('filter');
$class::enable_plugin($filterpath, $newstate);
filter_set_global_state($filterpath, $newstate);
if ($newstate == TEXTFILTER_DISABLED) {
filter_set_applies_to_strings($filterpath, false);
}
}
break;
@@ -82,16 +83,12 @@ switch ($action) {
if (isset($filters[$filterpath])) {
$applytostrings = optional_param('stringstoo', false, PARAM_BOOL);
filter_set_applies_to_strings($filterpath, $applytostrings);
reset_text_filters_cache();
core_plugin_manager::reset_caches();
}
break;
case 'down':
if (isset($filters[$filterpath])) {
filter_set_global_state($filterpath, $filters[$filterpath]->active, 1);
reset_text_filters_cache();
core_plugin_manager::reset_caches();
}
break;
@@ -99,14 +96,14 @@ switch ($action) {
if (isset($filters[$filterpath])) {
$oldpos = $filters[$filterpath]->sortorder;
filter_set_global_state($filterpath, $filters[$filterpath]->active, -1);
reset_text_filters_cache();
core_plugin_manager::reset_caches();
}
break;
}
// Return.
// Reset caches and return.
if ($action) {
reset_text_filters_cache();
core_plugin_manager::reset_caches();
redirect(new moodle_url('/admin/filters.php'));
}
@@ -118,12 +115,12 @@ $states = filter_get_global_states();
$stringfilters = filter_get_string_filters();
$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->head = array(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->id = 'filterssetting';
$table->data = [];
$table->data = array();
$lastactive = null;
foreach ($states as $state) {
@@ -160,16 +157,15 @@ die;
/**
* Return action URL.
*
* @param string $filterpath which filter to get the URL for.
* @param string $action which action to get the URL for.
* @return moodle_url|null the requested URL.
* @param string $filterpath
* @param string $action
* @return moodle_url
*/
function filters_action_url(string $filterpath, string $action): ?moodle_url {
function filters_action_url($filterpath, $action) {
if ($action === 'delete') {
return core_plugin_manager::instance()->get_uninstall_url('filter_'.$filterpath, 'manage');
}
return new moodle_url('/admin/filters.php',
['sesskey' => sesskey(), 'filterpath' => $filterpath, 'action' => $action]);
return new moodle_url('/admin/filters.php', array('sesskey'=>sesskey(), 'filterpath'=>$filterpath, 'action'=>$action));
}
/**
@@ -182,25 +178,24 @@ function filters_action_url(string $filterpath, string $action): ?moodle_url {
* @param bool $applytostrings
* @return array data
*/
function get_table_row(\core\plugininfo\filter $plugininfo, stdClass $state,
bool $isfirstrow, bool $islastactive, bool $applytostrings): array {
function get_table_row(\core\plugininfo\filter $plugininfo, $state, $isfirstrow, $islastactive, $applytostrings) {
global $OUTPUT;
$row = [];
$row = array();
$filter = $state->filter;
$active = $plugininfo->is_installed_and_upgraded();
static $activechoices;
static $applytochoices;
if (!isset($activechoices)) {
$activechoices = [
$activechoices = array(
TEXTFILTER_DISABLED => get_string('disabled', 'core_filters'),
TEXTFILTER_OFF => get_string('offbutavailable', 'core_filters'),
TEXTFILTER_ON => get_string('on', 'core_filters'),
];
$applytochoices = [
);
$applytochoices = array(
0 => get_string('content', 'core_filters'),
1 => get_string('contentandheadings', 'core_filters'),
];
);
}
// Filter name.
@@ -214,7 +209,7 @@ function get_table_row(\core\plugininfo\filter $plugininfo, stdClass $state,
// Disable/off/on.
$select = new single_select(filters_action_url($filter, 'setstate'), 'newstate', $activechoices, $state->active, null, 'active' . $filter);
$select->set_label(get_string('isactive', 'filters'), ['class' => 'accesshide']);
$select->set_label(get_string('isactive', 'filters'), array('class' => 'accesshide'));
$row[] = $OUTPUT->render($select);
// Re-order.
@@ -222,14 +217,12 @@ function get_table_row(\core\plugininfo\filter $plugininfo, stdClass $state,
$spacer = $OUTPUT->spacer();
if ($state->active != TEXTFILTER_DISABLED) {
if (!$isfirstrow) {
$updown .= $OUTPUT->action_icon(filters_action_url($filter, 'up'),
new pix_icon('t/up', get_string('up'), '', ['class' => 'iconsmall']));
$updown .= $OUTPUT->action_icon(filters_action_url($filter, 'up'), new pix_icon('t/up', get_string('up'), '', array('class' => 'iconsmall')));
} else {
$updown .= $spacer;
}
if (!$islastactive) {
$updown .= $OUTPUT->action_icon(filters_action_url($filter, 'down'),
new pix_icon('t/down', get_string('down'), '', ['class' => 'iconsmall']));
$updown .= $OUTPUT->action_icon(filters_action_url($filter, 'down'), new pix_icon('t/down', get_string('down'), '', array('class' => 'iconsmall')));
} else {
$updown .= $spacer;
}
@@ -237,23 +230,20 @@ function get_table_row(\core\plugininfo\filter $plugininfo, stdClass $state,
$row[] = $updown;
// Apply to strings.
$select = new single_select(filters_action_url($filter, 'setapplyto'),
'stringstoo', $applytochoices, $applytostrings, null, 'applyto' . $filter);
$select->set_label(get_string('applyto', 'filters'), ['class' => 'accesshide']);
$select = new single_select(filters_action_url($filter, 'setapplyto'), 'stringstoo', $applytochoices, $applytostrings, null, 'applyto' . $filter);
$select->set_label(get_string('applyto', 'filters'), array('class' => 'accesshide'));
$select->disabled = ($state->active == TEXTFILTER_DISABLED);
$row[] = $OUTPUT->render($select);
// Settings link, if required.
if ($active and filter_has_global_settings($filter)) {
$row[] = html_writer::link(new moodle_url('/admin/settings.php',
['section' => 'filtersetting'.$filter]), get_string('settings'));
$row[] = html_writer::link(new moodle_url('/admin/settings.php', array('section'=>'filtersetting'.$filter)), get_string('settings'));
} else {
$row[] = '';
}
// Uninstall.
$row[] = html_writer::link(filters_action_url($filter, 'delete'),
get_string('uninstallplugin', 'core_admin'));
$row[] = html_writer::link(filters_action_url($filter, 'delete'), get_string('uninstallplugin', 'core_admin'));
return $row;
}
+1 -24
View File
@@ -53,12 +53,6 @@ if (!extension_loaded('xml')) {
die();
}
// Make sure mbstring extension is available.
if (!extension_loaded('mbstring')) {
echo 'Moodle requires the mbstring PHP extension. Please install or enable the mbstring extension.';
die();
}
define('NO_OUTPUT_BUFFERING', true);
if (isset($_POST['upgradekey'])) {
@@ -725,12 +719,6 @@ if (during_initial_install()) {
set_config('rolesactive', 1); // after this, during_initial_install will return false.
set_config('adminsetuppending', 1);
set_config('registrationpending', 1); // Remind to register site after all other setup is finished.
// Apply default preset, if it is defined in $CFG and has a valid value.
if (!empty($CFG->setsitepresetduringinstall)) {
\core_adminpresets\helper::change_default_preset($CFG->setsitepresetduringinstall);
}
// we need this redirect to setup proper session
upgrade_finished("index.php?sessionstarted=1&amp;lang=$CFG->lang");
}
@@ -831,7 +819,6 @@ $insecuredataroot = is_dataroot_insecure(true);
$SESSION->admin_critical_warning = ($insecuredataroot==INSECURE_DATAROOT_ERROR);
$adminroot = admin_get_root();
$PAGE->set_primary_active_tab('siteadminnode');
// Check if there are any new admin settings which have still yet to be set
if (any_new_admin_settings($adminroot)) {
@@ -920,15 +907,6 @@ $showcampaigncontent = !isset($CFG->showcampaigncontent) || $CFG->showcampaignco
// Encourage admins to enable the user feedback feature if it is not enabled already.
$showfeedbackencouragement = empty($CFG->enableuserfeedback);
// Check if the service and support content setting is enabled or not.
$servicesandsupportcontent = !isset($CFG->showservicesandsupportcontent) || $CFG->showservicesandsupportcontent;
// Check whether the XML-RPC protocol is enabled or not.
require_once($CFG->libdir . '/environmentlib.php');
$result = new environment_results('custom_checks');
$result = check_xmlrpc_usage($result);
$xmlrpcwarning = !is_null($result) ? get_string($result->getFeedbackStr(), 'admin') : '';
admin_externalpage_setup('adminnotifications');
$output = $PAGE->get_renderer('core', 'admin');
@@ -937,5 +915,4 @@ echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisp
$maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
$registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir,
$mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent,
$showcampaigncontent, $showfeedbackencouragement, $servicesandsupportcontent,
$xmlrpcwarning);
$showcampaigncontent, $showfeedbackencouragement);
+2 -4
View File
@@ -49,13 +49,11 @@ if (!array_key_exists($media, $plugins)) {
switch ($action) {
case 'disable':
$class = \core_plugin_manager::resolve_plugininfo_class('media');
$class::enable_plugin($media, false);
$plugins[$media]->set_enabled(false);
break;
case 'enable':
$class = \core_plugin_manager::resolve_plugininfo_class('media');
$class::enable_plugin($media, true);
$plugins[$media]->set_enabled(true);
break;
case 'up':
+58 -46
View File
@@ -48,52 +48,69 @@ if (($form = data_submitted()) && confirm_sesskey()) {
foreach ($providers as $provider) {
$componentproviderbase = $provider->component.'_'.$provider->name;
$disableprovidersetting = $componentproviderbase.'_disable';
$providerdisabled = false;
if (!isset($form->$disableprovidersetting)) {
$providerdisabled = true;
$newpreferences[$disableprovidersetting] = 1;
} else {
$newpreferences[$disableprovidersetting] = 0;
}
$componentprovidersetting = $componentproviderbase.'_locked';
foreach ($processors as $processor) {
$value = 0;
if (isset($form->{$componentprovidersetting}[$processor->name])) {
$value = $form->{$componentprovidersetting}[$processor->name];
if ($value == 'on') {
$value = 1;
}
}
// Record the site preference.
$newpreferences[$processor->name.'_provider_'.$componentprovidersetting] = $value;
}
$componentprovidersetting = $componentproviderbase.'_enabled';
$newsettings = [];
if (isset($form->$componentprovidersetting)) {
// Store defined comma-separated processors as setting value.
// Using array_filter eliminates elements set to 0 above.
$newsettings = array_keys(array_filter($form->{$componentprovidersetting}));
}
// Let's join existing setting values for disabled processors.
$property = 'message_provider_'.$componentprovidersetting;
if (property_exists($preferences, $property)) {
$existingsetting = $preferences->$property;
foreach ($disabledprocessors as $disable) {
if (strpos($existingsetting, $disable->name) > -1) {
$newsettings[] = $disable->name;
}
}
}
$value = join(',', $newsettings);
if (empty($value)) {
foreach (array('permitted', 'loggedin', 'loggedoff') as $setting) {
$value = null;
}
$componentprovidersetting = $componentproviderbase.'_'.$setting;
if ($setting == 'permitted') {
// If we deal with permitted select element, we need to create individual
// setting for each possible processor. Note that this block will
// always be processed first after entring parental foreach iteration
// so we can change form values on this stage.
foreach ($processors as $processor) {
$value = '';
if (isset($form->{$componentprovidersetting}[$processor->name])) {
$value = $form->{$componentprovidersetting}[$processor->name];
}
// Ensure that loggedin loggedoff options are set correctly for this permission.
if (($value == 'disallowed') || $providerdisabled) {
// It might be better to unset them, but I can't figure out why that cause error.
$form->{$componentproviderbase.'_loggedin'}[$processor->name] = 0;
$form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 0;
} else if ($value == 'forced') {
$form->{$componentproviderbase.'_loggedin'}[$processor->name] = 1;
$form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 1;
}
// Record the site preference.
$newpreferences[$processor->name.'_provider_'.$componentprovidersetting] = $value;
}
} else {
$newsettings = array();
if (property_exists($form, $componentprovidersetting)) {
// We must be processing loggedin or loggedoff checkboxes.
// Store defained comma-separated processors as setting value.
// Using array_filter eliminates elements set to 0 above.
$newsettings = array_keys(array_filter($form->{$componentprovidersetting}));
}
// Record the site preference.
$newpreferences['message_provider_'.$componentprovidersetting] = $value;
// Let's join existing setting values for disabled processors.
$property = 'message_provider_'.$componentprovidersetting;
if (property_exists($preferences, $property)) {
$existingsetting = $preferences->$property;
foreach ($disabledprocessors as $disable) {
if (strpos($existingsetting, $disable->name) > -1) {
$newsettings[] = $disable->name;
}
}
}
$value = join(',', $newsettings);
if (empty($value)) {
$value = null;
}
}
if ($setting != 'permitted') {
// We have already recoded site preferences for 'permitted' type.
$newpreferences['message_provider_'.$componentprovidersetting] = $value;
}
}
}
// Update database.
@@ -102,17 +119,10 @@ if (($form = data_submitted()) && confirm_sesskey()) {
// Save processors enabled/disabled status.
foreach ($allprocessors as $processor) {
$enabled = isset($form->{$processor->name});
$class = \core_plugin_manager::resolve_plugininfo_class('message');
$class::enable_plugin($processor->name, $enabled);
\core_message\api::update_processor_status($processor, $enabled);
}
foreach ($newpreferences as $name => $value) {
$old = isset($preferences->$name) ? $preferences->$name : '';
if ($old != $value) {
add_to_config_log($name, $old, $value, 'core');
}
set_config($name, $value, 'message');
}
$transaction->allow_commit();
@@ -125,6 +135,8 @@ if (($form = data_submitted()) && confirm_sesskey()) {
// Page settings
$PAGE->set_context(context_system::instance());
$PAGE->requires->js_init_call('M.core_message.init_defaultoutputs');
$renderer = $PAGE->get_renderer('core', 'message');
// Display the page.
+2 -11
View File
@@ -6,7 +6,7 @@ require_once(__DIR__ . '/../../config.php');
require_once($CFG->libdir.'/adminlib.php');
include_once($CFG->dirroot.'/mnet/lib.php');
$sort = optional_param('sort', 'username', PARAM_ALPHAEXT);
$sort = optional_param('sort', 'username', PARAM_ALPHA);
$dir = optional_param('dir', 'ASC', PARAM_ALPHA);
$page = optional_param('page', 0, PARAM_INT);
$perpage = optional_param('perpage', 30, PARAM_INT);
@@ -117,7 +117,6 @@ if ($form = data_submitted() and confirm_sesskey()) {
}
echo $OUTPUT->header();
echo $OUTPUT->render(mnet_get_deprecation_notice());
// Explain
echo $OUTPUT->box(get_string('ssoacldescr','mnet'));
@@ -154,15 +153,7 @@ foreach ($columns as $column) {
$headings[$column] = "<a href=\"?sort=$column&amp;dir=$columndir&amp;\">".$string[$column]."</a>$columnicon";
}
$headings['delete'] = '';
$sortorder = get_safe_orderby([
'username' => 'username',
'mnet_host_id' => 'mnet_host_id',
'access' => 'accessctrl',
'default' => 'username',
], $sort, $dir, false);
$acl = $DB->get_records('mnet_sso_access_control', null, $sortorder);
$acl = $DB->get_records('mnet_sso_access_control', null, "$sort $dir", '*'); //, $page * $perpage, $perpage);
$aclcount = $DB->count_records('mnet_sso_access_control');
if (!$acl) {
+3 -19
View File
@@ -46,23 +46,11 @@
$formcontinue = new single_button(new moodle_url('index.php', array('confirm' => md5($mnet->public_key))), get_string('yes'));
$formcancel = new single_button(new moodle_url('index.php', array()), get_string('no'));
echo $OUTPUT->header();
echo $OUTPUT->confirm(get_string("deletekeycheck", "mnet"), $formcontinue, $formcancel);
echo $OUTPUT->footer();
exit;
} else {
// We're deleting
// If no/cancel then redirect back to the network setting page.
if (!isset($form->confirm)) {
redirect(
new moodle_url('/admin/mnet/index.php'),
get_string('keydeletedcancelled', 'mnet'),
null,
\core\output\notification::NOTIFY_SUCCESS
);
}
if (!isset($SESSION->mnet_confirm_delete_key)) {
// fail - you're being attacked?
@@ -75,12 +63,8 @@
if($time < time() - 60) {
// fail - you're out of time.
redirect(
new moodle_url('/admin/mnet/index.php'),
get_string('deleteoutoftime', 'mnet'),
null,
\core\output\notification::NOTIFY_WARNING
);
print_error ('deleteoutoftime', 'mnet', 'index.php');
exit;
}
if ($key != md5(sha1($mnet->keypair['keypair_PEM']))) {
@@ -91,12 +75,12 @@
$mnet->replace_keys();
redirect('index.php', get_string('keydeleted','mnet'));
exit;
}
}
$hosts = $DB->get_records_select('mnet_host', "id <> ? AND deleted = 0", array($CFG->mnet_localhost_id), 'wwwroot ASC');
echo $OUTPUT->header();
echo $OUTPUT->render(mnet_get_deprecation_notice());
?>
<form method="post" action="index.php">
<table align="center" width="635" class="generaltable" border="0" cellpadding="5" cellspacing="0">
+3 -2
View File
@@ -59,8 +59,9 @@ class mnet_simple_host_form extends moodleform {
$wwwroot = 'http://'.$wwwroot;
}
if ($host = $DB->get_record('mnet_host', array('wwwroot' => $wwwroot))) {
$str = get_string('hostexists', 'mnet', (new moodle_url('/admin/mnet/peers.php', ['hostid' => $host->id]))->out());
return array('wwwroot' => $str);
global $CFG;
return array('wwwroot' => get_string('hostexists', 'mnet',
new moodle_url('/admin/mnet/peers.php', array('hostid' => $host->id))));
}
return array();
}
-5
View File
@@ -51,8 +51,6 @@ if ($hostid && $DB->get_field('mnet_host', 'deleted', array('id' => $hostid)) !=
$PAGE->set_url('/admin/mnet/peers.php');
admin_externalpage_setup($adminsection);
$deprecatenotify = mnet_get_deprecation_notice();
if (!extension_loaded('openssl')) {
print_error('requiresopenssl', 'mnet');
}
@@ -92,7 +90,6 @@ if ($formdata = $simpleform->get_data()) {
$formdata->oldpublickey = $mnet_peer->public_key; // set this so we can confirm on form post without having to recreate the mnet_peer object
$reviewform->set_data($mnet_peer);
echo $OUTPUT->header();
echo $OUTPUT->render($deprecatenotify);
echo $OUTPUT->box_start();
$reviewform->display();
echo $OUTPUT->box_end();
@@ -180,7 +177,6 @@ if ($formdata = $reviewform->get_data()) {
}
} else if ($reviewform->is_submitted()) { // submitted, but errors
echo $OUTPUT->header();
echo $OUTPUT->render($deprecatenotify);
echo $OUTPUT->box_start();
$reviewform->display();
echo $OUTPUT->box_end();
@@ -191,7 +187,6 @@ if ($formdata = $reviewform->get_data()) {
// normal flow - just display all hosts with links
echo $OUTPUT->header();
echo $OUTPUT->render($deprecatenotify);
$hosts = mnet_get_hosts(true);
// print the table to display the register all hosts setting
-1
View File
@@ -44,5 +44,4 @@ if (isset($mnet_peer->id) && $mnet_peer->id > 0) {
} else {
$tabs[] = new tabobject('mnetdetails', '#', $strmnetedithost, $strmnetedithost, false);
}
echo $OUTPUT->render(mnet_get_deprecation_notice());
print_tabs(array($tabs), $currenttab);
-1
View File
@@ -1,6 +1,5 @@
<?php
echo $OUTPUT->header();
echo $OUTPUT->render(mnet_get_deprecation_notice());
?>
<div id="trustedhosts"><!-- See theme/standard/styles_layout.css #trustedhosts .generaltable for rules -->
<table cellspacing="0" cellpadding="5" class="generaltable generalbox" >
+35 -10
View File
@@ -30,20 +30,43 @@
/// If data submitted, then process and store.
if (!empty($hide) and confirm_sesskey()) {
$class = \core_plugin_manager::resolve_plugininfo_class('mod');
if ($class::enable_plugin($hide, false)) {
// Settings not required - only pages.
admin_get_root(true, false);
if (!$module = $DB->get_record("modules", array("name"=>$hide))) {
print_error('moduledoesnotexist', 'error');
}
$DB->set_field("modules", "visible", "0", array("id"=>$module->id)); // Hide main module
// Remember the visibility status in visibleold
// and hide...
$sql = "UPDATE {course_modules}
SET visibleold=visible, visible=0
WHERE module=?";
$DB->execute($sql, array($module->id));
// Increment course.cacherev for courses where we just made something invisible.
// This will force cache rebuilding on the next request.
increment_revision_number('course', 'cacherev',
"id IN (SELECT DISTINCT course
FROM {course_modules}
WHERE visibleold=1 AND module=?)",
array($module->id));
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
redirect(new moodle_url('/admin/modules.php'));
}
if (!empty($show) && confirm_sesskey()) {
$class = \core_plugin_manager::resolve_plugininfo_class('mod');
if ($class::enable_plugin($show, true)) {
// Settings not required - only pages.
admin_get_root(true, false);
if (!empty($show) and confirm_sesskey()) {
if (!$module = $DB->get_record("modules", array("name"=>$show))) {
print_error('moduledoesnotexist', 'error');
}
$DB->set_field("modules", "visible", "1", array("id"=>$module->id)); // Show main module
$DB->set_field('course_modules', 'visible', '1', array('visibleold'=>1, 'module'=>$module->id)); // Get the previous saved visible state for the course module.
// Increment course.cacherev for courses where we just made something visible.
// This will force cache rebuilding on the next request.
increment_revision_number('course', 'cacherev',
"id IN (SELECT DISTINCT course
FROM {course_modules}
WHERE visible=1 AND module=?)",
array($module->id));
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
redirect(new moodle_url('/admin/modules.php'));
}
@@ -77,7 +100,7 @@
$missing = true;
} else {
// took out hspace="\10\", because it does not validate. don't know what to replace with.
$icon = "<img src=\"" . $OUTPUT->image_url('monologo', $module->name) . "\" class=\"icon\" alt=\"\" />";
$icon = "<img src=\"" . $OUTPUT->image_url('icon', $module->name) . "\" class=\"icon\" alt=\"\" />";
$strmodulename = $icon.' '.get_string('modulename', $module->name);
$missing = false;
}
@@ -140,3 +163,5 @@
$table->print_html();
echo $OUTPUT->footer();
+12 -25
View File
@@ -30,41 +30,28 @@
require_once(__DIR__ . '/../config.php');
// The state parameter we've given (used in moodle as a redirect url).
// Per https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1, state is required, even during error responses.
$state = required_param('state', PARAM_LOCALURL);
$redirecturl = new moodle_url($state);
$params = $redirecturl->params();
$error = optional_param('error', '', PARAM_RAW);
if ($error) {
$message = optional_param('error_description', null, PARAM_RAW);
// Errors can occur for authenticated users, such as when a user denies authorization for some internal service call.
// In such cases, propagate the error to the component redirect URI.
if (isloggedin()) {
if (isset($params['sesskey']) && confirm_sesskey($params['sesskey'])) {
$redirecturl->param('error', $error);
if ($message) {
$redirecturl->param('error_description', $message);
}
redirect($redirecturl);
}
$message = optional_param('error_description', '', PARAM_RAW);
if ($message) {
print_error($message);
} else {
print_error($error);
}
// Not logged in or the sesskey verification failed, redirect to login + show errors.
$SESSION->loginerrormsg = $message ?? $error;
redirect(new moodle_url(get_login_url()));
die();
}
// The authorization code generated by the authorization server.
$code = required_param('code', PARAM_RAW);
// The state parameter we've given (used in moodle as a redirect url).
$state = required_param('state', PARAM_LOCALURL);
$redirecturl = new moodle_url($state);
$params = $redirecturl->params();
if (isset($params['sesskey']) and confirm_sesskey($params['sesskey'])) {
$redirecturl->param('oauth2code', $code);
redirect($redirecturl);
} else {
$SESSION->loginerrormsg = get_string('invalidsesskey', 'error');
redirect(new moodle_url(get_login_url()));
print_error('invalidsesskey');
}
-2
View File
@@ -52,8 +52,6 @@ $pageurl = new moodle_url('/admin/plugins.php', $pageparams);
$pluginman = core_plugin_manager::instance();
$PAGE->set_primary_active_tab('siteadminnode');
if ($uninstall) {
if (!$confirmed) {
+9 -3
View File
@@ -102,15 +102,20 @@ if (($action == 'edit') || ($action == 'new')) {
require_sesskey();
$instance = portfolio_instance($portfolio);
$plugin = $instance->get('plugin');
$current = $instance->get('visible');
if (empty($current) && $instance->instance_sanity_check()) {
print_error('cannotsetvisible', 'portfolio', $baseurl);
}
if ($action == 'show') {
$visible = 1;
} else {
$visible = 0;
}
$class = \core_plugin_manager::resolve_plugininfo_class('portfolio');
$class::enable_plugin($plugin, $visible);
$instance->set('visible', $visible);
$instance->save();
core_plugin_manager::reset_caches();
$return = true;
} else if ($action == 'delete') {
$instance = portfolio_instance($portfolio);
@@ -241,3 +246,4 @@ if ($return) {
}
echo $OUTPUT->footer();
-390
View File
@@ -1,390 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets;
/**
* Admin presets helper class.
*
* @package core_adminpresets
* @copyright 2021 Sara Arjona (sara@moodle.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class helper {
/**
* Create an empty preset.
*
* @param array $data Preset data. Supported values:
* - name. To define the preset name.
* - comments. To change the comments field.
* - author. To update the author field.
* - iscore. Whether the preset is a core preset or not. Valid values on \core_adminpresets\manager class.
* @return int The identifier of the preset created.
*/
public static function create_preset(array $data): int {
global $CFG, $USER, $DB;
$name = array_key_exists('name', $data) ? $data['name'] : '';
$comments = array_key_exists('comments', $data) ? $data['comments'] : '';
$author = array_key_exists('author', $data) ? $data['author'] : fullname($USER);
$iscore = array_key_exists('iscore', $data) ? $data['iscore'] : manager::NONCORE_PRESET;
// Validate iscore value.
$allowed = [manager::NONCORE_PRESET, manager::STARTER_PRESET, manager::FULL_PRESET];
if (!in_array($iscore, $allowed)) {
$iscore = manager::NONCORE_PRESET;
}
$preset = [
'userid' => $USER->id,
'name' => $name,
'comments' => $comments,
'site' => $CFG->wwwroot,
'author' => $author,
'moodleversion' => $CFG->version,
'moodlerelease' => $CFG->release,
'iscore' => $iscore,
'timecreated' => time(),
'timeimported' => 0,
];
$presetid = $DB->insert_record('adminpresets', $preset);
return $presetid;
}
/**
* Helper method to add a setting item to a preset.
*
* @param int $presetid Preset identifier where the item will belong.
* @param string $name Item name.
* @param string $value Item value.
* @param string|null $plugin Item plugin.
* @param string|null $advname If the item is an advanced setting, the name of the advanced setting should be specified here.
* @param string|null $advvalue If the item is an advanced setting, the value of the advanced setting should be specified here.
* @return int The item identificator.
*/
public static function add_item(int $presetid, string $name, string $value, ?string $plugin = 'none',
?string $advname = null, ?string $advvalue = null): int {
global $DB;
$presetitem = [
'adminpresetid' => $presetid,
'plugin' => $plugin,
'name' => $name,
'value' => $value,
];
$itemid = $DB->insert_record('adminpresets_it', $presetitem);
if (!empty($advname)) {
$presetadv = [
'itemid' => $itemid,
'name' => $advname,
'value' => $advvalue,
];
$DB->insert_record('adminpresets_it_a', $presetadv);
}
return $itemid;
}
/**
* Helper method to add a plugin to a preset.
*
* @param int $presetid Preset identifier where the item will belong.
* @param string $plugin Plugin type.
* @param string $name Plugin name.
* @param int $enabled Whether the plugin will be enabled or not.
* @return int The plugin identificator.
*/
public static function add_plugin(int $presetid, string $plugin, string $name, int $enabled): int {
global $DB;
$pluginentry = [
'adminpresetid' => $presetid,
'plugin' => $plugin,
'name' => $name,
'enabled' => $enabled,
];
$pluginid = $DB->insert_record('adminpresets_plug', $pluginentry);
return $pluginid;
}
/**
* Apply the given preset. If it's a filename, the preset will be imported and then applied.
*
* @param string $presetnameorfile The preset name to be applied or a valid preset file to be imported and applied.
* @return int|null The preset identifier that has been applied or null if the given value was not valid.
*/
public static function change_default_preset(string $presetnameorfile): ?int {
global $DB;
$presetid = null;
// Check if the given variable points to a valid preset file to be imported and applied.
if (is_readable($presetnameorfile)) {
$xmlcontent = file_get_contents($presetnameorfile);
$manager = new manager();
list($xmlnotused, $preset) = $manager->import_preset($xmlcontent);
if (!is_null($preset)) {
list($applied) = $manager->apply_preset($preset->id);
if (!empty($applied)) {
$presetid = $preset->id;
}
}
} else {
// Check if the given preset exists; if that's the case, it will be applied.
$stringmanager = get_string_manager();
if ($stringmanager->string_exists($presetnameorfile . 'preset', 'core_adminpresets')) {
$params = ['name' => get_string($presetnameorfile . 'preset', 'core_adminpresets')];
} else {
$params = ['name' => $presetnameorfile];
}
if ($preset = $DB->get_record('adminpresets', $params)) {
$manager = new manager();
list($applied) = $manager->apply_preset($preset->id);
if (!empty($applied)) {
$presetid = $preset->id;
}
}
}
return $presetid;
}
/**
* Helper method to create default site admin presets and initialize them.
*/
public static function create_default_presets(): void {
// Create the "Starter" site admin preset.
$data = [
'name' => get_string('starterpreset', 'core_adminpresets'),
'comments' => get_string('starterpresetdescription', 'core_adminpresets'),
'iscore' => manager::STARTER_PRESET,
];
$presetid = static::create_preset($data);
// Add settings to the "Starter" site admin preset.
static::add_item($presetid, 'usecomments', '0');
static::add_item($presetid, 'usetags', '0');
static::add_item($presetid, 'enablenotes', '0');
static::add_item($presetid, 'enableblogs', '0');
static::add_item($presetid, 'enablebadges', '0');
static::add_item($presetid, 'enableanalytics', '0');
static::add_item($presetid, 'enabled', '0', 'core_competency');
static::add_item($presetid, 'pushcourseratingstouserplans', '0', 'core_competency');
static::add_item($presetid, 'showdataretentionsummary', '0', 'tool_dataprivacy');
static::add_item($presetid, 'forum_maxattachments', '3');
static::add_item($presetid, 'guestloginbutton', '0');
// Set Activity chooser tabs to "Starred, All, Recommended".
static::add_item($presetid, 'activitychoosertabmode', '1');
// Modules: Hide chat, database, external tool (lti), IMS content package (imscp), lesson, SCORM, survey, wiki, workshop.
static::add_plugin($presetid, 'mod', 'chat', false);
static::add_plugin($presetid, 'mod', 'data', false);
static::add_plugin($presetid, 'mod', 'lti', false);
static::add_plugin($presetid, 'mod', 'imscp', false);
static::add_plugin($presetid, 'mod', 'lesson', false);
static::add_plugin($presetid, 'mod', 'scorm', false);
static::add_plugin($presetid, 'mod', 'survey', false);
static::add_plugin($presetid, 'mod', 'wiki', false);
static::add_plugin($presetid, 'mod', 'workshop', false);
// Availability restrictions: Hide Grouping, User profile.
static::add_plugin($presetid, 'availability', 'grouping', false);
static::add_plugin($presetid, 'availability', 'profile', false);
// Blocks: Hide Activities, Blog menu, Blog tags, Comments, Course completion status, Courses, Flickr,
// Global search, Latest badges, Learning plans, Logged in user, Login, Main menu, Mentees, Network servers, Online users,
// Private files, Recent blog entries, Recently accessed courses, Search forums, Section links, Social activities,
// Starred courses, Tags, YouTube.
// Hidden by default: Course/site summary, RSS feeds, Self completion, Feedback.
static::add_plugin($presetid, 'block', 'activity_modules', false);
static::add_plugin($presetid, 'block', 'blog_menu', false);
static::add_plugin($presetid, 'block', 'blog_tags', false);
static::add_plugin($presetid, 'block', 'comments', false);
static::add_plugin($presetid, 'block', 'completionstatus', false);
static::add_plugin($presetid, 'block', 'course_summary', false);
static::add_plugin($presetid, 'block', 'course_list', false);
static::add_plugin($presetid, 'block', 'tag_flickr', false);
static::add_plugin($presetid, 'block', 'globalsearch', false);
static::add_plugin($presetid, 'block', 'badges', false);
static::add_plugin($presetid, 'block', 'lp', false);
static::add_plugin($presetid, 'block', 'myprofile', false);
static::add_plugin($presetid, 'block', 'login', false);
static::add_plugin($presetid, 'block', 'site_main_menu', false);
static::add_plugin($presetid, 'block', 'mentees', false);
static::add_plugin($presetid, 'block', 'mnet_hosts', false);
static::add_plugin($presetid, 'block', 'private_files', false);
static::add_plugin($presetid, 'block', 'blog_recent', false);
static::add_plugin($presetid, 'block', 'rss_client', false);
static::add_plugin($presetid, 'block', 'search_forums', false);
static::add_plugin($presetid, 'block', 'section_links', false);
static::add_plugin($presetid, 'block', 'selfcompletion', false);
static::add_plugin($presetid, 'block', 'social_activities', false);
static::add_plugin($presetid, 'block', 'tags', false);
static::add_plugin($presetid, 'block', 'tag_youtube', false);
static::add_plugin($presetid, 'block', 'feedback', false);
static::add_plugin($presetid, 'block', 'online_users', false);
static::add_plugin($presetid, 'block', 'recentlyaccessedcourses', false);
static::add_plugin($presetid, 'block', 'starredcourses', false);
// Course formats: Disable Social format.
static::add_plugin($presetid, 'format', 'social', false);
// Data formats: Disable Javascript Object Notation (.json).
static::add_plugin($presetid, 'dataformat', 'json', false);
// Enrolments: Disable Cohort sync, Guest access.
static::add_plugin($presetid, 'enrol', 'cohort', false);
static::add_plugin($presetid, 'enrol', 'guest', false);
// Filter: Disable MathJax, Activity names auto-linking.
static::add_plugin($presetid, 'filter', 'mathjaxloader', TEXTFILTER_DISABLED);
static::add_plugin($presetid, 'filter', 'activitynames', TEXTFILTER_DISABLED);
// Question behaviours: Disable Adaptive mode (no penalties), Deferred feedback with CBM, Immediate feedback with CBM.
static::add_plugin($presetid, 'qbehaviour', 'adaptivenopenalty', false);
static::add_plugin($presetid, 'qbehaviour', 'deferredcbm', false);
static::add_plugin($presetid, 'qbehaviour', 'immediatecbm', false);
// Question types: Disable Calculated, Calculated multichoice, Calculated simple, Drag and drop markers,
// Drag and drop onto image, Embedded answers (Cloze), Numerical, Random short-answer matching.
static::add_plugin($presetid, 'qtype', 'calculated', false);
static::add_plugin($presetid, 'qtype', 'calculatedmulti', false);
static::add_plugin($presetid, 'qtype', 'calculatedsimple', false);
static::add_plugin($presetid, 'qtype', 'ddmarker', false);
static::add_plugin($presetid, 'qtype', 'ddimageortext', false);
static::add_plugin($presetid, 'qtype', 'multianswer', false);
static::add_plugin($presetid, 'qtype', 'numerical', false);
static::add_plugin($presetid, 'qtype', 'randomsamatch', false);
// Repositories: Disable Server files, URL downloader, Wikimedia.
static::add_plugin($presetid, 'repository', 'local', false);
static::add_plugin($presetid, 'repository', 'url', false);
static::add_plugin($presetid, 'repository', 'wikimedia', false);
// Text editors: Disable TinyMCE HTML editor.
static::add_plugin($presetid, 'editor', 'tinymce', false);
// Create the "Full" site admin preset.
$data = [
'name' => get_string('fullpreset', 'core_adminpresets'),
'comments' => get_string('fullpresetdescription', 'core_adminpresets'),
'iscore' => manager::FULL_PRESET,
];
$presetid = static::create_preset($data);
// Add settings to the "Full" site admin preset.
static::add_item($presetid, 'usecomments', '1');
static::add_item($presetid, 'usetags', '1');
static::add_item($presetid, 'enablenotes', '1');
static::add_item($presetid, 'enableblogs', '1');
static::add_item($presetid, 'enablebadges', '1');
static::add_item($presetid, 'enableanalytics', '1');
static::add_item($presetid, 'enabled', '1', 'core_competency');
static::add_item($presetid, 'pushcourseratingstouserplans', '1', 'core_competency');
static::add_item($presetid, 'showdataretentionsummary', '1', 'tool_dataprivacy');
static::add_item($presetid, 'forum_maxattachments', '9');
static::add_item($presetid, 'guestloginbutton', '1');
// Set Activity chooser tabs to the default value ("Starred, All, Activities, Resources, Recommended").
static::add_item($presetid, 'activitychoosertabmode', '0');
// Modules: Enable chat, database, external tool (lti), IMS content package (imscp), lesson, SCORM, survey, wiki, workshop.
static::add_plugin($presetid, 'mod', 'chat', true);
static::add_plugin($presetid, 'mod', 'data', true);
static::add_plugin($presetid, 'mod', 'lti', true);
static::add_plugin($presetid, 'mod', 'imscp', true);
static::add_plugin($presetid, 'mod', 'lesson', true);
static::add_plugin($presetid, 'mod', 'scorm', true);
static::add_plugin($presetid, 'mod', 'survey', true);
static::add_plugin($presetid, 'mod', 'wiki', true);
static::add_plugin($presetid, 'mod', 'workshop', true);
// Availability restrictions: Enable Grouping, User profile.
static::add_plugin($presetid, 'availability', 'grouping', true);
static::add_plugin($presetid, 'availability', 'profile', true);
// Blocks: Enable Activities, Blog menu, Blog tags, Comments, Course completion status, Courses, Flickr,
// Global search, Latest badges, Learning plans, Logged in user, Login, Main menu, Mentees, Network servers, Online users,
// Private files, Recent blog entries, Recently accessed courses, Search forums, Section links, Social activities,
// Starred courses, Tags, YouTube.
// Hidden by default: Course/site summary, RSS feeds, Self completion, Feedback.
static::add_plugin($presetid, 'block', 'activity_modules', true);
static::add_plugin($presetid, 'block', 'blog_menu', true);
static::add_plugin($presetid, 'block', 'blog_tags', true);
static::add_plugin($presetid, 'block', 'comments', true);
static::add_plugin($presetid, 'block', 'completionstatus', true);
static::add_plugin($presetid, 'block', 'course_list', true);
static::add_plugin($presetid, 'block', 'tag_flickr', true);
static::add_plugin($presetid, 'block', 'globalsearch', true);
static::add_plugin($presetid, 'block', 'badges', true);
static::add_plugin($presetid, 'block', 'lp', true);
static::add_plugin($presetid, 'block', 'myprofile', true);
static::add_plugin($presetid, 'block', 'login', true);
static::add_plugin($presetid, 'block', 'site_main_menu', true);
static::add_plugin($presetid, 'block', 'mentees', true);
static::add_plugin($presetid, 'block', 'mnet_hosts', true);
static::add_plugin($presetid, 'block', 'private_files', true);
static::add_plugin($presetid, 'block', 'blog_recent', true);
static::add_plugin($presetid, 'block', 'search_forums', true);
static::add_plugin($presetid, 'block', 'section_links', true);
static::add_plugin($presetid, 'block', 'social_activities', true);
static::add_plugin($presetid, 'block', 'tags', true);
static::add_plugin($presetid, 'block', 'online_users', true);
static::add_plugin($presetid, 'block', 'recentlyaccessedcourses', true);
static::add_plugin($presetid, 'block', 'starredcourses', true);
// Course formats: Enable Social format.
static::add_plugin($presetid, 'format', 'social', true);
// Data formats: Enable Javascript Object Notation (.json).
static::add_plugin($presetid, 'dataformat', 'json', true);
// Enrolments: Enable Cohort sync, Guest access.
static::add_plugin($presetid, 'enrol', 'cohort', true);
static::add_plugin($presetid, 'enrol', 'guest', true);
// Filter: Enable MathJax, Activity names auto-linking.
static::add_plugin($presetid, 'filter', 'mathjaxloader', TEXTFILTER_ON);
static::add_plugin($presetid, 'filter', 'activitynames', TEXTFILTER_ON);
// Question behaviours: Enable Adaptive mode (no penalties), Deferred feedback with CBM, Immediate feedback with CBM.
static::add_plugin($presetid, 'qbehaviour', 'adaptivenopenalty', true);
static::add_plugin($presetid, 'qbehaviour', 'deferredcbm', true);
static::add_plugin($presetid, 'qbehaviour', 'immediatecbm', true);
// Question types: Enable Calculated, Calculated multichoice, Calculated simple, Drag and drop markers,
// Drag and drop onto image, Embedded answers (Cloze), Numerical, Random short-answer matching.
static::add_plugin($presetid, 'qtype', 'calculated', true);
static::add_plugin($presetid, 'qtype', 'calculatedmulti', true);
static::add_plugin($presetid, 'qtype', 'calculatedsimple', true);
static::add_plugin($presetid, 'qtype', 'ddmarker', true);
static::add_plugin($presetid, 'qtype', 'ddimageortext', true);
static::add_plugin($presetid, 'qtype', 'multianswer', true);
static::add_plugin($presetid, 'qtype', 'numerical', true);
static::add_plugin($presetid, 'qtype', 'randomsamatch', true);
// Repositories: Enable Server files, URL downloader, Wikimedia.
static::add_plugin($presetid, 'repository', 'local', true);
static::add_plugin($presetid, 'repository', 'url', true);
static::add_plugin($presetid, 'repository', 'wikimedia', true);
// Text editors: Enable TinyMCE HTML editor.
static::add_plugin($presetid, 'editor', 'tinymce', true);
}
}
@@ -1,57 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Select setting for blog's bloglevel setting.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_bloglevel extends adminpresets_admin_setting_configselect {
/**
* Extended to change the block visibility.
*
* @param bool $name Setting name to store.
* @param mixed $value Setting value to store.
* @return int|false config_log inserted id or false whenever the value has not been saved.
*/
public function save_value($name = false, $value = null) {
global $DB;
if (!$id = parent::save_value($name, $value)) {
return false;
}
// Object values if no arguments.
if ($value === null) {
$value = $this->value;
}
// Pasted from admin_setting_bloglevel (can't use write_config).
if ($value == 0) {
$DB->set_field('block', 'visible', 0, ['name' => 'blog_menu']);
} else {
$DB->set_field('block', 'visible', 1, ['name' => 'blog_menu']);
}
return $id;
}
}
@@ -1,47 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
use admin_setting_configcheckbox;
/**
* Checkbox setting.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configcheckbox extends adminpresets_setting {
/**
* Sets the visible name for the setting selected value
*/
protected function set_visiblevalue() {
/** @var admin_setting_configcheckbox $settingdata */
$settingdata = $this->get_settingdata();
// We need to compare the "yes" value of the inner checkbox, which isn't necessarily boolean.
if ($this->value == $settingdata->yes) {
$str = get_string('yes');
} else {
$str = get_string('no');
}
$this->visiblevalue = $str;
}
}
@@ -1,48 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
use admin_setting;
/**
* Checkbox with an advanced checkbox that controls an additional $name.'_adv' config setting.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configcheckbox_with_advanced extends adminpresets_admin_setting_configcheckbox {
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
// To look for other values.
$this->attributes = ['adv' => $settingdata->name . '_adv'];
parent::__construct($settingdata, $dbsettingvalue);
}
/**
* Uses delegation
*/
protected function set_visiblevalue() {
parent::set_visiblevalue();
if (!is_null($this->attributesvalues) && array_key_exists($this->attributes['adv'], $this->attributesvalues)) {
$value = $this->attributesvalues[$this->attributes['adv']];
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($value, 'advanced');
}
}
}
@@ -1,47 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
use admin_setting;
/**
* Checkbox with an advanced checkbox that controls an additional $name.'_locked' config setting.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configcheckbox_with_lock extends adminpresets_admin_setting_configcheckbox {
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
// To look for other values.
$this->attributes = ['locked' => $settingdata->name . '_locked'];
parent::__construct($settingdata, $dbsettingvalue);
}
/**
* Uses delegation
*/
protected function set_visiblevalue() {
parent::set_visiblevalue();
if (!is_null($this->attributesvalues) && array_key_exists($this->attributes['locked'], $this->attributesvalues)) {
$value = $this->attributesvalues[$this->attributes['locked']];
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($value, 'locked');
}
}
}
@@ -1,41 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Used to validate a textarea used for ip addresses.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configiplist extends adminpresets_admin_setting_configtext {
protected function set_value($value) {
// Check ip format.
if ($this->settingdata->validate($value) !== true) {
$this->value = false;
$this->set_visiblevalue();
return false;
}
$this->value = $value;
$this->set_visiblevalue();
return true;
}
}
@@ -1,32 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Class to be extended by multicheckbox settings.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configmulticheckbox extends adminpresets_admin_setting_configmultiselect {
public function set_behaviors() {
$this->behaviors['loadchoices'] = &$this->settingdata;
}
}
@@ -1,76 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Extends the base class and lists the selected values separated by comma.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configmultiselect extends adminpresets_setting {
/**
* Ensure that the $value values are setting choices.
*
* @param mixed $value Setting value
* @return mixed Returns false if wrong param value
*/
protected function set_value($value) {
if ($value) {
$options = explode(',', $value);
foreach ($options as $option) {
foreach ($this->settingdata->choices as $key => $choice) {
if ($key == $option) {
$this->value = $option;
$this->set_visiblevalue();
return true;
}
}
}
$value = implode(',', $options);
}
$this->value = $value;
$this->set_visiblevalue();
return true;
}
protected function set_visiblevalue() {
$values = explode(',', $this->value);
$visiblevalues = [];
foreach ($values as $value) {
if (!empty($this->settingdata->choices[$value])) {
$visiblevalues[] = $this->settingdata->choices[$value];
}
}
if (empty($visiblevalues)) {
$this->visiblevalue = '';
return false;
}
$this->visiblevalue = implode(', ', $visiblevalues);
}
}
@@ -1,32 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Generalizes a configmultipleselect with load_choices().
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configmultiselect_with_loader extends adminpresets_admin_setting_configmultiselect {
public function set_behaviors() {
$this->behaviors['loadchoices'] = &$this->settingdata;
}
}
@@ -1,65 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Select one value from list.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configselect extends adminpresets_setting {
/**
* Sets the setting value cleaning it.
*
* @param mixed $value must be one of the setting choices.
* @return bool true if the value one of the setting choices
*/
protected function set_value($value) {
// When we intantiate the class we need the choices.
if (empty($this->settingdata->choices) && method_exists($this->settingdata, 'load_choices')) {
$this->settingdata->load_choices();
}
if (!is_null($this->settingdata->choices) and is_array($this->settingdata->choices)) {
foreach ($this->settingdata->choices as $key => $choice) {
if ($key == $value) {
$this->value = $value;
$this->set_visiblevalue();
return true;
}
}
}
$this->value = false;
$this->set_visiblevalue();
return false;
}
protected function set_visiblevalue() {
// Just to avoid heritage problems.
if (empty($this->settingdata->choices[$this->value])) {
$this->visiblevalue = '';
} else {
$this->visiblevalue = $this->settingdata->choices[$this->value];
}
}
}
@@ -1,59 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
use admin_setting;
/**
* Adds support for the "advanced" attribute.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configselect_with_advanced extends adminpresets_admin_setting_configselect {
/** @var string Name of the advanced setting. **/
protected $advancedkey;
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
// Getting the advanced defaultsetting attribute name.
if (is_array($settingdata->defaultsetting)) {
foreach ($settingdata->defaultsetting as $key => $defaultvalue) {
if ($key != 'value') {
$this->advancedkey = $key;
}
}
}
// To look for other values.
$this->attributes = [$this->advancedkey => $settingdata->name . '_adv'];
parent::__construct($settingdata, $dbsettingvalue);
}
/**
* Funcionality used by other _with_advanced settings
*/
protected function set_visiblevalue() {
parent::set_visiblevalue();
if (!is_null($this->attributesvalues)) {
$attribute = $this->attributes[$this->advancedkey];
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($this->attributesvalues[$attribute], 'advanced');
}
}
}
@@ -1,58 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Basic text setting, cleans the param using the admin_setting paramtext attribute.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configtext extends adminpresets_setting {
/**
* Validates the value using paramtype attribute
*
* @param mixed $value
* @return boolean Cleaned or not, but always true.
*/
protected function set_value($value) {
$this->value = $value;
if (empty($this->settingdata->paramtype)) {
// For configfile, configpasswordunmask....
$this->settingdata->paramtype = 'RAW';
}
$paramtype = 'PARAM_' . strtoupper($this->settingdata->paramtype);
// Regexp.
if (!defined($paramtype)) {
$this->value = preg_replace($this->settingdata->paramtype, '', $this->value);
// Standard moodle param type.
} else {
$this->value = clean_param($this->value, constant($paramtype));
}
$this->set_visiblevalue();
return true;
}
}
@@ -1,47 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
use admin_setting;
/**
* Adds the advanced attribute.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configtext_with_advanced extends adminpresets_admin_setting_configtext {
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
// To look for other values.
$this->attributes = ['fix' => $settingdata->name . '_adv'];
parent::__construct($settingdata, $dbsettingvalue);
}
/**
* Delegates
*/
protected function set_visiblevalue() {
parent::set_visiblevalue();
if (!is_null($this->attributesvalues) && array_key_exists($this->attributes['fix'], $this->attributesvalues)) {
$value = $this->attributesvalues[$this->attributes['fix']];
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($value, 'advanced');
}
}
}
@@ -1,67 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Time selector.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_configtime extends adminpresets_setting {
/**
* To check that the value is one of the options
*
* @param string $name
* @param mixed $value
*/
public function set_attribute_value($name, $value) {
for ($i = 0; $i < 60; $i = $i + 5) {
$minutes[$i] = $i;
}
if (!empty($minutes[$value])) {
$this->attributesvalues[$name] = $value;
} else {
$this->attributesvalues[$name] = $this->settingdata->defaultsetting['m'];
}
}
protected function set_value($value) {
$this->attributes = ['m' => $this->settingdata->name2];
for ($i = 0; $i < 24; $i++) {
$hours[$i] = $i;
}
if (empty($hours[$value])) {
$this->value = false;
}
$this->value = $value;
$this->set_visiblevalue();
}
protected function set_visiblevalue() {
if (!is_null($this->attributesvalues) && array_key_exists($this->settingdata->name2, $this->attributesvalues)) {
$this->visiblevalue = $this->value . ':' . $this->attributesvalues[$this->settingdata->name2];
}
}
}
@@ -1,43 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Reimplementation to allow human friendly view of the selected regexps.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_devicedetectregex extends adminpresets_admin_setting_configtext {
public function set_visiblevalue() {
$values = json_decode($this->get_value());
if (!$values) {
parent::set_visiblevalue();
return;
}
$this->visiblevalue = '';
foreach ($values as $key => $value) {
$this->visiblevalue .= $key . ' = ' . $value . ', ';
}
$this->visiblevalue = rtrim($this->visiblevalue, ', ');
}
}
@@ -1,61 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
use admin_setting;
/**
* A select with force and advanced options
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_gradecat_combo extends adminpresets_admin_setting_configselect {
/**
* One db value for two setting attributes
*
* @param admin_setting $settingdata
* @param mixed $dbsettingvalue
*/
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
// The set_attribute_value() method will mod the VARNAME_flag value.
$this->attributes = ['forced' => $settingdata->name . '_flag', 'adv' => $settingdata->name . '_flag'];
parent::__construct($settingdata, $dbsettingvalue);
}
/**
* Special treatment! the value be extracted from the $value argument
*/
protected function set_visiblevalue() {
parent::set_visiblevalue();
if (!is_null($this->attributesvalues) && array_key_exists($this->settingdata->name . '_flag', $this->attributesvalues)) {
$flagvalue = $this->attributesvalues[$this->settingdata->name . '_flag'];
if (isset($flagvalue)) {
$forcedvalue = (($flagvalue % 2) == 1);
$advancedvalue = ($flagvalue >= 2);
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($forcedvalue, 'forced');
$this->visiblevalue .= $this->delegation->extra_set_visiblevalue($advancedvalue, 'advanced');
}
}
}
}
@@ -1,67 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Reimplemented to store values in course table, not in config or config_plugins.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_sitesettext extends adminpresets_admin_setting_configtext {
/**
* Overwritten to store the value in the course table
*
* @param bool $name
* @param mixed $value
* @return int|false config_log inserted id or false whenever the new value is the same as old value.
*/
public function save_value($name = false, $value = null) {
global $DB;
// Object values if no arguments.
if ($value === null) {
$value = $this->value;
}
if (!$name) {
$name = $this->settingdata->name;
}
$sitecourse = $DB->get_record('course', ['id' => 1]);
$actualvalue = $sitecourse->{$name};
// If it's the same value skip.
if ($actualvalue == $value) {
return false;
}
// Plugin name or ''.
$plugin = $this->settingdata->plugin;
if ($plugin == 'none' || $plugin == '') {
$plugin = null;
}
// Updating mdl_course.
$sitecourse->{$name} = $value;
$DB->update_record('course', $sitecourse);
return $this->to_log($plugin, $name, $this->value, $actualvalue);
}
}
@@ -1,53 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Special control for selecting days to backup.
*
* It doesn't specify loadchoices behavior because is set_visiblevalue who needs it.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_special_backupdays extends adminpresets_setting {
protected function set_value($value) {
$this->value = clean_param($value, PARAM_SEQUENCE);
$this->set_visiblevalue();
}
protected function set_visiblevalue() {
$this->settingdata->load_choices();
$days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
$selecteddays = [];
$week = str_split($this->value);
foreach ($week as $key => $day) {
if ($day) {
$index = $days[$key];
$selecteddays[] = $this->settingdata->choices[$index];
}
}
$this->visiblevalue = implode(', ', $selecteddays);
}
}
@@ -1,44 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Special admin control for calendar weekend.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_special_calendar_weekend extends adminpresets_setting {
protected function set_visiblevalue() {
if (!$this->value) {
parent::set_visiblevalue();
return;
}
$days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
for ($i = 0; $i < 7; $i++) {
if ($this->value & (1 << $i)) {
$settings[] = get_string($days[$i], 'calendar');
}
}
$this->visiblevalue = implode(', ', $settings);
}
}
@@ -1,39 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
/**
* Extends configselect to reuse set_valuevisible.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_admin_setting_users_with_capability extends adminpresets_admin_setting_configmultiselect {
protected function set_behaviors() {
$this->behaviors['loadchoices'] = &$this->settingdata;
}
protected function set_value($value) {
// Dirty hack (the value stored in the DB is '').
$this->settingdata->choices[''] = $this->settingdata->choices['$@NONE@$'];
return parent::set_value($value);
}
}
@@ -1,268 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
use admin_setting;
use moodle_exception;
use stdClass;
/**
* Admin tool presets plugin to load some settings.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class adminpresets_setting {
/**
* @var admin_setting
*/
protected $settingdata;
/**
* @var delegation
*/
protected $delegation;
/**
* The setting DB value
*
* @var mixed
*/
protected $value;
/**
* Stores the visible value of the setting DB value
*
* @var string
*/
protected $visiblevalue;
/**
* For multiple value settings, used to look for the other values
*
* @var string
*/
protected $attributes = false;
/**
* To store the setting attributes
*
* @var array
*/
protected $attributesvalues;
/**
* Stores the setting data and the selected value
*
* @param admin_setting $settingdata admin_setting subclass
* @param mixed $dbsettingvalue Actual value
*/
public function __construct(admin_setting $settingdata, $dbsettingvalue) {
$this->settingdata = $settingdata;
$this->delegation = new delegation();
if ($this->settingdata->plugin == '') {
$this->settingdata->plugin = 'none';
}
// Applies specific children behaviors.
$this->set_behaviors();
$this->apply_behaviors();
// Cleaning value.
$this->set_value($dbsettingvalue);
}
/**
* Each class can overwrite this method to specify extra processes
*/
protected function set_behaviors() {
}
/**
* Applies the children class specific behaviors
*
* See delegation class for the available extra behaviors
*/
protected function apply_behaviors() {
if (!empty($this->behaviors)) {
foreach ($this->behaviors as $behavior => $arguments) {
// The arguments of the behavior depends on the caller.
$methodname = 'extra_' . $behavior;
$this->delegation->{$methodname}($arguments);
}
}
}
/**
* Gets the setting value.
*
* @return mixed The setting value
*/
public function get_value() {
return $this->value;
}
/**
* Sets the setting value cleaning it
*
* Child classes should overwrite method to clean more acurately
*
* @param mixed $value Setting value
* @return mixed Returns false if wrong param value
*/
protected function set_value($value) {
$this->value = $value;
$this->set_visiblevalue();
}
public function get_visiblevalue() {
return $this->visiblevalue;
}
/**
* Sets the visible name for the setting selected value
*
* In most cases the child classes will overwrite
*/
protected function set_visiblevalue() {
$this->visiblevalue = $this->value;
}
public function get_attributes() {
return $this->attributes;
}
public function get_attributes_values() {
return $this->attributesvalues;
}
public function get_settingdata() {
return $this->settingdata;
}
public function set_attribute_value($name, $value) {
$this->attributesvalues[$name] = $value;
}
/**
* Saves the setting attributes values
*
* @return array Array of inserted ids (in config_log)
*/
public function save_attributes_values() {
// Plugin name or null.
$plugin = $this->settingdata->plugin;
if ($plugin == 'none' || $plugin == '') {
$plugin = null;
}
if (!$this->attributesvalues) {
return false;
}
// To store inserted ids.
$ids = [];
foreach ($this->attributesvalues as $name => $value) {
// Getting actual setting.
$actualsetting = get_config($plugin, $name);
// If it's the actual setting get off.
if ($value == $actualsetting) {
return false;
}
if ($id = $this->save_value($name, $value)) {
$ids[] = $id;
}
}
return $ids;
}
/**
* Stores the setting into database, logs the change and returns the config_log inserted id
*
* @param bool $name Setting name to store.
* @param mixed $value Setting value to store.
* @return int|false config_log inserted id or false whenever the new value is the same as old value.
* @throws dml_exception
* @throws moodle_exception
*/
public function save_value($name = false, $value = null) {
// Object values if no arguments.
if ($value === null) {
$value = $this->value;
}
if (!$name) {
$name = $this->settingdata->name;
}
// Plugin name or null.
$plugin = $this->settingdata->plugin;
if ($plugin == 'none' || $plugin == '') {
$plugin = null;
}
// Getting the actual value.
$actualvalue = get_config($plugin, $name);
// If it's the same it's not necessary.
if ($actualvalue == $value) {
return false;
}
set_config($name, $value, $plugin);
return $this->to_log($plugin, $name, $value, $actualvalue);
}
/**
* Copy of config_write method of the admin_setting class
*
* @param string $plugin
* @param string $name
* @param mixed $value
* @param mixed $actualvalue
* @return integer The stored config_log id
*/
protected function to_log($plugin, $name, $value, $actualvalue) {
global $DB, $USER;
// Log the change (pasted from admin_setting class).
$log = new stdClass();
$log->userid = during_initial_install() ? 0 : $USER->id; // 0 as user id during install.
$log->timemodified = time();
$log->plugin = $plugin;
$log->name = $name;
$log->value = $value;
$log->oldvalue = $actualvalue;
// Getting the inserted config_log id.
if (!$id = $DB->insert_record('config_log', $log)) {
throw new moodle_exception('errorinserting', 'core_adminpresets');
}
return $id;
}
}
@@ -1,53 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_adminpresets\local\setting;
use admin_setting;
/**
* Cross-class methods
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class delegation {
/**
* Adds a piece of string to the $type setting
*
* @param boolean $value
* @param string $type Indicates the "extra" setting
* @return string
*/
public function extra_set_visiblevalue(bool $value, string $type): string {
// Adding the advanced value to the text string if present.
if ($value) {
$string = get_string('markedas' . $type, 'core_adminpresets');
} else {
$string = get_string('markedasnon' . $type, 'core_adminpresets');
}
// Adding the advanced state.
return ', ' . $string;
}
public function extra_loadchoices(admin_setting &$adminsetting) {
$adminsetting->load_choices();
}
}
File diff suppressed because it is too large Load Diff
-125
View File
@@ -1,125 +0,0 @@
<?php
// This file is part of The Course Module Navigation Block
//
// 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_adminpresets\privacy;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\userlist;
/**
* Admin presets this file handle privacy provider.
*
* @package core_adminpresets
* @copyright 2021 Pimenko <support@pimenko.com><pimenko.com>
* @author Jordan Kesraoui | Sylvain Revenu | Pimenko based on David Monllaó <david.monllao@urv.cat> code
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\subsystem\provider,
\core_privacy\local\request\core_userlist_provider {
/**
* Returns information about the user data stored in this component.
*
* @param collection $collection A list of information about this component
* @return collection The collection object filled out with information about this component.
*/
public static function get_metadata(collection $collection) : collection {
// These tables are really data about site configuration and not user data.
// The adminpresets includes information about which user performed a configuration change using the admin_presets
// tool.
// This is not considered to be user data.
$collection->add_database_table('adminpresets', [
'userid' => 'privacy:metadata:adminpresets:userid',
'name' => 'privacy:metadata:adminpresets:name',
'comments' => 'privacy:metadata:adminpresets:comments',
'site' => 'privacy:metadata:adminpresets:site',
'moodlerelease' => 'privacy:metadata:adminpresets:moodlerelease',
'timecreated' => 'privacy:metadata:adminpresets:timecreated',
], 'privacy:metadata:adminpresets');
// The adminpresets_app includes information about which user performed configuration change using the admin_presets
// tool.
// This is not considered to be user data.
$collection->add_database_table('adminpresets_app', [
'adminpresetid' => 'privacy:metadata:adminpresets_app:adminpresetid',
'userid' => 'privacy:metadata:adminpresets_app:userid',
'time' => 'privacy:metadata:adminpresets_app:time',
], 'privacy:metadata:adminpresets_app');
return $collection;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
return new contextlist();
}
/**
* Get the list of users who have data within a context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
// Don't add any user.
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
// None of the core tables should be exported.
}
/**
* Delete all data for all users in the specified context.
*
* @param context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
// None of the the data from these tables should be deleted.
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
// None of the the data from these tables should be deleted.
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
// None of the the data from these tables should be deleted.
}
}
-24
View File
@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<PRESET>
<NAME>Imported preset</NAME>
<COMMENTS>&lt;p dir="ltr" style="text-align:left;"&gt;Porfolios enabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced&lt;/p&gt;</COMMENTS>
<PRESET_DATE>1631615985</PRESET_DATE>
<SITE_URL>http://demo.moodle</SITE_URL>
<AUTHOR>Ada Lovelace</AUTHOR>
<MOODLE_VERSION>2021091100</MOODLE_VERSION>
<MOODLE_RELEASE>4.0dev (Build: 20210911)</MOODLE_RELEASE>
<ADMIN_SETTINGS>
<MOD_LESSON>
<SETTINGS>
<MAXANSWERS maxanswers_adv="">2</MAXANSWERS>
<MEDIAWIDTH>900</MEDIAWIDTH>
</SETTINGS>
</MOD_LESSON>
<NONE>
<SETTINGS>
<ALLOWEMOJIPICKER>1</ALLOWEMOJIPICKER>
<ENABLEPORTFOLIOS>1</ENABLEPORTFOLIOS>
</SETTINGS>
</NONE>
</ADMIN_SETTINGS>
</PRESET>
@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<PRESET>
<NAME>Imported preset</NAME>
<COMMENTS>&lt;p dir="ltr" style="text-align:left;"&gt;Porfolios enabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced. Plugins: disabled block_html, mod_database and mod_chat plugins and enabled atto_html, block_activity_modules and mod_lesson.&lt;/p&gt;</COMMENTS>
<PRESET_DATE>1631615985</PRESET_DATE>
<SITE_URL>http://demo.moodle</SITE_URL>
<AUTHOR>Ada Lovelace</AUTHOR>
<MOODLE_VERSION>2021091100</MOODLE_VERSION>
<MOODLE_RELEASE>4.0dev (Build: 20210911)</MOODLE_RELEASE>
<ADMIN_SETTINGS>
<MOD_LESSON>
<SETTINGS>
<MAXANSWERS maxanswers_adv="">2</MAXANSWERS>
<MEDIAWIDTH>900</MEDIAWIDTH>
</SETTINGS>
</MOD_LESSON>
<NONE>
<SETTINGS>
<ALLOWEMOJIPICKER>1</ALLOWEMOJIPICKER>
<ENABLEPORTFOLIOS>1</ENABLEPORTFOLIOS>
</SETTINGS>
</NONE>
</ADMIN_SETTINGS>
<PLUGINS>
<ATTO>
<HTML>1</HTML>
</ATTO>
<BLOCK>
<HTML>0</HTML>
<ACTIVITY_MODULES>1</ACTIVITY_MODULES>
</BLOCK>
<MOD>
<CHAT>0</CHAT>
<DATA>0</DATA>
<LESSON>1</LESSON>
</MOD>
</PLUGINS>
</PRESET>
@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<PRESET>
<NAME>Imported preset</NAME>
<COMMENTS>&lt;p dir="ltr" style="text-align:left;"&gt;Porfolios enabled, Emojipicker enabled, Lesson media width set to 900 and maxanswers set to 2 and disabled advanced&lt;/p&gt;</COMMENTS>
<PRESET_DATE>1631615985</PRESET_DATE>
<SITE_URL>http://demo.moodle</SITE_URL>
<AUTHOR>Ada Lovelace</AUTHOR>
<MOODLE_VERSION>2021091100</MOODLE_VERSION>
<MOODLE_RELEASE>4.0dev (Build: 20210911)</MOODLE_RELEASE>
<ADMIN_SETTINGS>
<MOD_LESSON>
<SETTINGS>
<MAXANSWERS maxanswers_adv="">2</MAXANSWERS>
<MEDIAWIDTH>900</MEDIAWIDTH>
</SETTINGS>
</MOD_LESSON>
<NONE>
<SETTINGS>
<UNEXISTINGSETTING>0</UNEXISTINGSETTING>
<ALLOWEMOJIPICKER>1</ALLOWEMOJIPICKER>
<ENABLEPORTFOLIOS>1</ENABLEPORTFOLIOS>
</SETTINGS>
</NONE>
</ADMIN_SETTINGS>
</PRESET>

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