Compare commits

..

1439 Commits

Author SHA1 Message Date
Jun Pataleta b21d86f807 Moodle release 3.8.5 2020-09-11 10:41:55 +08:00
Sara Arjona 472d293a16 weekly release 3.8.4+ 2020-09-10 08:52:05 +02:00
Sara Arjona 168fa1dda1 Merge branch 'MDL-69466-3.8' of https://github.com/JBThong/moodle into MOODLE_38_STABLE 2020-09-09 11:39:42 +02:00
Thong Bui a8e70bad23 MDL-69466 Autocomplete widget: Improve keyboard accessibility 2020-09-09 13:52:53 +07:00
Eloy Lafuente (stronk7) 7ed55774f1 Merge branch 'MDL-69116-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-09-08 23:16:52 +02:00
Sara Arjona 784156217a Merge branch 'MDL-69525-38-1' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-09-08 14:22:16 +02:00
Michael Hawkins 0425db5a80 MDL-69340 tag: Correct the filter input HTML in the tag manager 2020-09-08 08:48:24 +02:00
Mihail Geshoski 6e1451fb39 MDL-69048 book: Sanitize previous chapter value in add new chapter page 2020-09-08 08:48:24 +02:00
Andrew Nicols 8c274e82f4 MDL-68974 calendar: Use page context for block check 2020-09-08 08:48:24 +02:00
Andrew Nicols 4a488b9a5c MDL-68974 blocks: Check permission before generating content 2020-09-08 08:48:24 +02:00
Mihail Geshoski 11e49d6676 MDL-65115 repository: Prevent unzipping if it will exceed allowed quota 2020-09-08 08:48:24 +02:00
Mihail Geshoski 6f4e2cb799 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:48:24 +02:00
Andrew Nicols 7790b6727a MDL-68974 admin: Unit tests for context parent/child test 2020-09-08 08:48:24 +02:00
Andrew Nicols 20f7e23af4 MDL-68974 admin: Unit tests for loginas 2020-09-08 08:48:24 +02:00
Andrew Nicols 52b6d73c03 MDL-68974 admin: Prevent login as outside of the desired context 2020-09-08 08:48:24 +02:00
Sara Arjona 78eacf034a Merge branch 'MDL-68344-3.8' of https://github.com/JBThong/moodle into MOODLE_38_STABLE 2020-09-08 08:45:28 +02:00
Jun Pataleta 67e3dbab7f Merge branch 'MDL-69492-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-09-08 12:56:09 +08:00
Eloy Lafuente (stronk7) ed3482f9cc Merge branch 'MDL-69262-38-2' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-09-07 23:43:17 +02:00
Sara Arjona 3852238df4 Merge branch 'MDL-67468-MOODLE_38_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_38_STABLE 2020-09-07 13:20:17 +02:00
Paul Holden 1c51eaa50c MDL-69492 auth_cas: normalise member distinguished name config. 2020-09-04 08:39:11 +01:00
Paul Holden c329d99d8a MDL-69492 auth_ldap: normalise member distinguished name config. 2020-09-04 08:39:11 +01:00
Nathan Nguyen f48f213e40 MDL-67468 filter_activitynames: use MUC 2020-09-04 15:41:36 +10:00
Thong Bui c2686daae4 MDL-68344 filepicker: File Picker focus lost on upload 2020-09-04 09:50:30 +07:00
Sara Arjona 28a155e712 weekly release 3.8.4+ 2020-09-03 17:09:22 +02:00
Sara Arjona f90459df6f NOBUG: Fixed SVG browser compatibility 2020-09-03 17:09:20 +02:00
Andrew Nicols bf0778595f Merge branch 'MDL-69391-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-09-03 11:49:48 +08:00
Andrew Nicols 3a257a2808 Merge branch 'MDL-69360-38' of git://github.com/NoelDeMartin/moodle into MOODLE_38_STABLE 2020-09-03 10:52:27 +08:00
Andrew Nicols 45f5453b2a Merge branch 'MDL-69246_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-09-03 10:40:33 +08:00
Andrew Nicols b74d8568eb Merge branch 'MDL-55340-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-09-03 10:14:46 +08:00
Andrew Nicols 9f770c1be6 Merge branch 'MDL-69069-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-09-03 09:37:37 +08:00
Eloy Lafuente (stronk7) 049bb1d7a7 Merge branch 'MDL-69608-38' of https://github.com/marinaglancy/moodle into MOODLE_38_STABLE 2020-09-03 00:03:51 +02:00
Sara Arjona 687047148f Merge branch 'MDL-68680-MOODLE_38_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_38_STABLE 2020-09-02 17:16:21 +02:00
Marina Glancy ab48f37f68 MDL-69608 core_form: frozen forms do not have form tag 2020-09-02 11:27:29 +02:00
Noel De Martin 6180264ae8 MDL-69360 behat: Fix js ready checks for non-moodle sites 2020-09-02 10:21:09 +02:00
Eloy Lafuente (stronk7) b7905dd4e0 Merge branch 'wip_MDL-69491_m38' of git://github.com/gjb2048/moodle into MOODLE_38_STABLE 2020-09-02 00:27:50 +02:00
Sara Arjona 8d470c5802 Merge branch 'MDL-64525-m38' of https://github.com/NeillM/moodle into MOODLE_38_STABLE 2020-09-01 14:20:44 +02:00
Mihail Geshoski 1d183e38b1 MDL-69525 core: Publish a single event when toggling slave checkboxes 2020-09-01 15:07:49 +08:00
Sara Arjona 80efaa9828 Merge branch 'MDL-51709-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-09-01 09:04:37 +02:00
Sara Arjona 25c47ba407 Merge branch 'MDL-69394-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-09-01 06:45:38 +02:00
Tim Hunt 33f880fba7 MDL-69507 duration form field: should return an int number of seconds 2020-09-01 11:38:36 +08:00
Andrew Nicols 9e9a1db47a Merge branch 'MDL-69387-38-2' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-09-01 11:00:04 +08:00
Andrew Nicols a711c69d8f Merge branch 'MDL-69505-38' of https://github.com/snake/moodle into MOODLE_38_STABLE 2020-09-01 07:30:40 +08:00
Andrew Nicols 2a98eedef0 Merge branch 'MDL-56595-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-09-01 07:30:40 +08:00
Luca Bösch dadccb9237 MDL-51709 gradebook: Name display in single view. 2020-08-31 18:26:01 +02:00
Shamim Rezaie 2ce0766cfc 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-09-01 00:09:38 +10:00
Shamim Rezaie d456737d72 MDL-69116 qtype_mutichoice: Use label for the "clear my choice" link 2020-08-31 23:59:22 +10:00
Bas Brands cef948595b MDL-69069 theme_boost: color contrast for custom alerts 2020-08-31 08:47:25 +02:00
Jake Dallimore 24bf9c39d9 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 08:11:59 +08:00
Gareth Barnard adca4fe505 MDL-69491 themes: No 'fontsize' setting in Boost causes unit conflict. 2020-08-28 14:08:27 +01:00
Marina Glancy a44ce9a024 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:24 +02:00
Andrew Nicols fde001145b Merge branch 'MDL-69112-38' of git://github.com/merrill-oakland/moodle into MOODLE_38_STABLE 2020-08-28 13:27:39 +08:00
Nathan Nguyen 85ffac56e8 MDL-68680 core_grades: check grade item before trigger delete event 2020-08-28 11:40:14 +10:00
Paul Holden 11b4e810fb MDL-56595 tool_usertours: set page params when configuring tours/steps. 2020-08-27 23:07:59 +01:00
Tim Hunt ab1545b20e 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:40:45 +01:00
Sara Arjona c3673a9be1 weekly release 3.8.4+ 2020-08-27 17:36:26 +02:00
Sara Arjona 9283ba7380 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-08-27 17:36:24 +02:00
Jun Pataleta bb41dd7921 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:23:24 +08:00
Jun Pataleta 8305c3ce9a 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:17:45 +08:00
Andrew Nicols 1592b68f0b Merge branch 'MDL-69458-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-08-27 12:43:48 +08:00
Andrew Nicols faf7b144a1 Merge branch 'MDL-69501-38-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-08-27 11:31:35 +08:00
eWallah 08c359f366 MDL-67413 competencies: do nothing upon activity completion 2020-08-27 11:09:09 +08:00
Andrew Nicols b03196fe78 Merge branch 'MOODLE_38_MDL-69358' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2020-08-27 10:58:17 +08:00
Justin Hunt ec92de9187 MDL-66810 mod_lti: Reinstate deprecated default permissions on iframe
microphone, webcam, camera, midi, encrypted-media, geolocation
2020-08-27 10:27:02 +08:00
AMOS bot c3fcedf205 Automatically generated installer lang files 2020-08-27 00:07:14 +00:00
Adrian Greeve d2dec45ec8 Merge branch 'MDL-69419-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-08-27 08:06:30 +08:00
Sara Arjona 84564c42c8 Merge branch 'MDL-69389-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-08-26 18:03:13 +02:00
Sara Arjona 1084eba9a8 Merge branch 'MDL-69114-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-08-26 16:29:01 +02:00
Jun Pataleta 6895074a62 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:07:41 +08:00
Jun Pataleta d79cd16ae7 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:07:41 +08:00
Jun Pataleta 9579c751ab 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:28 +08:00
Jun Pataleta 1cb1763216 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:28 +08:00
Jun Pataleta 2fb006bfb1 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:01:17 +08:00
Andrew Nicols fbc937f4b4 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:49 +08:00
AMOS bot e30b6117f7 Automatically generated installer lang files 2020-08-26 00:07:33 +00:00
Jun Pataleta d0d16bd8fb 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-08-25 14:48:40 +08:00
Jun Pataleta dc378c70e3 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-08-25 14:47:51 +08:00
Neill Magill 15aa7e0b20 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:01:26 +01:00
Neill Magill 5192605a11 MDL-64525 comments: Tests for deleting frozen comments 2020-08-24 08:01:26 +01:00
Mihail Geshoski c6d2515534 MDL-69458 report_insights: Respect perpage value in pagination bar 2020-08-24 09:30:57 +08:00
Eloy Lafuente (stronk7) 4f3271c536 Merge branch 'MDL-69493-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-22 17:09:54 +02:00
AMOS bot b4025d8655 Automatically generated installer lang files 2020-08-22 00:07:58 +00:00
Eloy Lafuente (stronk7) a4ab0db4bd weekly release 3.8.4+ 2020-08-21 20:43:15 +02:00
Helen Foster 972f50ff90 MDL-69501 lang: Import fixed English strings (en_fix)
Significant string change: error:nobadges,core_badges - Additional info
explaining that site badges can only have other site badges as criteria
2020-08-21 13:58:56 +02:00
Jun Pataleta 5aeec826f8 Merge branch 'MDL-66818-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-08-21 11:32:57 +08:00
Andrew Nicols 94d2dcb8e1 MDL-66818 mod_forum: Use cap manager to check exportability 2020-08-21 08:17:27 +08:00
Andrew Nicols c8273f7d7f MDL-42434 chat: Disable stylelint important check 2020-08-21 07:38:06 +08:00
Sara Arjona affb1ae2ff 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:00 +01:00
Sara Arjona fea72a6eb3 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:00 +01:00
Andrew Nicols 64d0d94aeb Merge branch 'MDL-69375_38' of https://github.com/Cvmcosta/moodle into MOODLE_38_STABLE 2020-08-20 11:51:24 +08:00
Adrian Greeve 9b4d87bcc2 Merge branch 'MDL-68964-38' of git://github.com/ferranrecio/moodle into MOODLE_38_STABLE 2020-08-20 11:43:33 +08:00
Adrian Greeve 18740e4938 Merge branch 'MDL-42434-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-08-20 11:25:35 +08:00
Adrian Greeve 261be42ab5 Merge branch 'MDL-68683-38-fix' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-08-20 10:25:59 +08:00
Andrew Nicols 181bef2ed6 Merge branch 'MDL-69449-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-20 09:26:59 +08:00
Andrew Nicols 94bd3452e4 Merge branch 'MDL-68889-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-08-20 09:20:01 +08:00
Simey Lameze fb9670a9b2 MDL-68683 competencies: fix query to delete stale files 2020-08-20 09:17:42 +08:00
Andrew Nicols 00cbbbc930 Merge branch 'MDL-67415_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-08-20 08:31:12 +08:00
Andrew Nicols bb31c5eb3e Merge branch 'MDL-66818-38' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-08-20 08:17:17 +08:00
Simey Lameze 9d5a987a97 MDL-66818 mod_forum: remove unnecessary behat steps 2020-08-20 08:05:13 +08:00
gthomas2 a1b7b8b98f MDL-66818 mod_forum: hide portfolio export button based on caps 2020-08-20 08:05:13 +08:00
Andrew Nicols 1e157fb528 Merge branch 'MDL-66900-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-20 07:55:34 +08:00
Andrew Nicols b5c1e5379e Merge branch 'MDL-69271_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-08-20 07:36:44 +08:00
Andrew Nicols c78a136be4 Merge branch 'MDL-61215-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-08-20 07:17:37 +08:00
Andrew Nicols 978fff44ab Merge branch 'MDL-69401-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-08-20 07:03:54 +08:00
Victor Deniz Falcon 3b212136de Merge branch 'MDL-69297-38' of git://github.com/peterRd/moodle into MOODLE_38_STABLE 2020-08-19 23:48:56 +01:00
Eloy Lafuente (stronk7) 9ffab782f7 MDL-63375 workshop: apply specific IE10/11 fix
Credit goes to Matt Davidson (Syxton)
2020-08-19 17:54:18 +02:00
Peter Dias 30ccbb075c 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 15:48:33 +08:00
Adrian Greeve 793823bca8 Merge branch 'MDL-66665-38-POC2' of git://github.com/peterRd/moodle into MOODLE_38_STABLE 2020-08-19 14:29:58 +08:00
Peter Dias dd8b086494 MDL-66665 assign: Check whether a modified user could actually grade 2020-08-19 13:41:02 +08:00
Adrian Greeve 30b2b58c27 Merge branch 'MDL-68683-38' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-08-19 12:58:27 +08:00
Adrian Greeve 8c5a8a25b5 Merge branch 'MDL-69475_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-08-19 10:46:01 +08:00
Andrew Nicols f6c9f72a76 Merge branch 'MDL-26401-38' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-08-19 08:52:43 +08:00
Eloy Lafuente (stronk7) 7e1223958c Merge branch 'MDL-65847-auth_db_error_handling-38' of git://github.com/leonstr/moodle into MOODLE_38_STABLE 2020-08-19 00:35:48 +02:00
Eloy Lafuente (stronk7) 43362649e5 Merge branch 'MDL-63375-38' of https://github.com/syxton/moodle into MOODLE_38_STABLE 2020-08-19 00:13:24 +02:00
Eloy Lafuente (stronk7) bddf4eecf6 Merge branch 'MDL-68444-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-08-18 19:15:23 +02:00
Eloy Lafuente (stronk7) e881a516d0 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 16:25:55 +02:00
Eloy Lafuente (stronk7) 62c1a7b816 Merge branch 'MDL-69273-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-08-18 10:59:50 +02:00
Simey Lameze 0bca22b30f MDL-68683 competencies: step to delete orphaned evidence files 2020-08-18 16:07:08 +08:00
Simey Lameze 45d06fe9b6 MDL-68683 core: fix DML exception on upgrade step 2020-08-18 16:04:34 +08:00
Andrew Nicols 43930d5e8a MDL-69273 travis: Use exttests for https too 2020-08-18 07:50:48 +08:00
Andrew Nicols b226665e80 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 07:40:14 +08:00
Paul Holden edd91d16fa MDL-69493 cohort: remove escaping of return URL params. 2020-08-17 21:30:15 +01:00
Mihail Geshoski 5c3bdc9259 MDL-69401 book: Limit character length in chapter title 2020-08-17 09:04:36 +08:00
carlos 8dc60e1926 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-14 17:12:54 -03:00
Sara Arjona b91869f889 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-14 17:13:13 +02:00
Sara Arjona 25128d16aa 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-14 17:06:51 +02:00
Sara Arjona 62cdf371df 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-14 17:06:50 +02:00
Sara Arjona e6bf955210 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-14 17:06:50 +02:00
Eloy Lafuente (stronk7) 4ec7c29b30 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-14 13:40:13 +02:00
Andrew Nicols cf6cdd99d4 weekly release 3.8.4+ 2020-08-14 14:42:31 +08:00
Andrew Nicols 1ed9fa8f4a NOBUG: Fixed SVG browser compatibility 2020-08-14 14:42:29 +08:00
Andrew Nicols f520dbe674 Merge branch 'MDL-68666-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-08-13 15:21:52 +08:00
Bas Brands b61392fa53 MDL-68666 core_pix: add missing fallback icons 2020-08-13 08:51:18 +02:00
Andrew Nicols c4fc929e3f Merge branch 'MDL-69253_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-08-13 11:53:06 +08:00
Andrew Nicols ae320424ef Merge branch 'MDL-60492-tagcloud_html-38' of https://github.com/leonstr/moodle into MOODLE_38_STABLE 2020-08-13 11:45:28 +08:00
Adrian Greeve 2d14596f5a Merge branch 'MDL-68423-38' of git://github.com/ferranrecio/moodle into MOODLE_38_STABLE 2020-08-13 11:06:30 +08:00
Andrew Nicols 11e171ffe5 Merge branch 'MDL-69421-38' of git://github.com/noeldemartin/moodle into MOODLE_38_STABLE 2020-08-13 09:36:14 +08:00
Andrew Nicols 3d5679803d Merge branch 'MDL-60260-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-13 07:55:52 +08:00
Eloy Lafuente (stronk7) bdea78ba61 MDL-67415 environment: change requirements
- mysql requirement up to 5.7
- postgres requirement up to 9.6
2020-08-13 01:30:26 +02:00
Eloy Lafuente (stronk7) c6fb7763bb 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-13 01:30:26 +02:00
Eloy Lafuente (stronk7) 1d412ff1df Merge branch 'MDL-68860-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-13 01:08:43 +02:00
Eloy Lafuente (stronk7) 2e93f26f2f Merge branch 'MDL-68558-38-plugindepscheckdeadend' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-08-13 00:40:25 +02:00
Eloy Lafuente (stronk7) 81dfa11ba8 Merge branch 'MDL-67394-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-13 00:29:24 +02:00
Eloy Lafuente (stronk7) 6a6caa019f Merge branch 'MDL-67002_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-08-13 00:26:20 +02:00
Ferran Recio c1b3ba3e07 MDL-68964 mod_chat: fix theme param 2020-08-12 17:31:42 +02:00
Bas Brands 5d412e18e7 MDL-68889 block_recentlyaccessedcourses: small viewport issues
- on small devices the recentlyaccessedcourses does not show any courses
2020-08-12 13:06:20 +02:00
Paul Holden b73bb7b9c4 MDL-66900 course: don't clean category description when editing. 2020-08-12 11:48:35 +01:00
Simey Lameze d4d744d544 MDL-26401 group: change import to use csv_import_reader class 2020-08-12 16:36:05 +08:00
Simey Lameze 4cdcf3a407 MDL-26401 group: add delimiter and encoding fields to import 2020-08-12 16:36:05 +08:00
Paul Holden a0283e7bb3 MDL-69449 block_timeline: use dayslimit context data in template.
Ensures the correct value is used when initially rendering the
course timeline.
2020-08-12 09:19:47 +01:00
Andrew Nicols 0ae11f6123 Merge branch 'MDL-68618-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-12 13:41:21 +08:00
Andrew Nicols c1efa9acf4 Merge branch 'MDL-69353-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-12 11:22:59 +08:00
Andrew Nicols 5ed2aef513 Merge branch 'MDL-68334-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-08-12 11:14:35 +08:00
Andrew Nicols 1466bef278 Merge branch 'MDL-69296-m38' of https://github.com/NeillM/moodle into MOODLE_38_STABLE 2020-08-12 10:31:43 +08:00
Mikhail Golenkov 7132e1a398 MDL-69358 backup: Do not clean up records for incomplete adhoc tasks.
Co-authored-by: Heena Agheda <heenaagheda@catalyst-au.net>
2020-08-12 12:09:30 +10:00
Andrew Nicols 4328b93712 Merge branch 'MDL-68731_38' of https://github.com/jonof/moodle into MOODLE_38_STABLE 2020-08-12 09:12:37 +08:00
Andrew Nicols bdfc738c6f Merge branch 'MDL-69168_recently-accessed-items-block-uses-stock-lti-icon' of https://github.com/stopfstedt/moodle into MOODLE_38_STABLE 2020-08-11 13:00:54 +08:00
Adrian Greeve 07d4b70470 Merge branch 'MDL-69204-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-11 08:46:22 +08:00
Paul Holden de58d4b0a1 MDL-68618 mod_forum: stop reverting idnumber when updating instance. 2020-08-10 09:11:20 +01:00
Paul Holden 349ebe7f45 MDL-68860 mod_lti: Oracle support for retrieving shared secrets.
Thanks to Mark van Hoek!
2020-08-10 09:06:33 +01:00
Adrian Greeve fe39303913 Merge branch 'MDL-60493-grader_span_tag-38' of https://github.com/leonstr/moodle into MOODLE_38_STABLE 2020-08-10 09:23:13 +08:00
Luca Bösch 7abc2da93b MDL-68334 user: Display name in footer as elsewhere. 2020-08-08 10:30:04 +02:00
Stefan Topfstedt bf9d8d79d5 MDL-69168 block_recentlyaccesseditems: apply custom icon
Overwrite the default mod icon with the configured icon url if
applicable.
2020-08-07 09:13:06 -07:00
Matt Davidson 155332f4aa MDL-63375 workshop: fix rubric grid view 2020-08-07 08:49:27 -04:00
Eloy Lafuente (stronk7) 24c68767e5 weekly release 3.8.4+ 2020-08-06 20:51:27 +02:00
Noel De Martin 5b38dd9e1e MDL-69421 behat: Revert app behat navigation to call session visit 2020-08-06 12:15:07 +02:00
Jun Pataleta 72f730972a Merge branch 'MDL-60501-h4_close_tag-38' of https://github.com/leonstr/moodle into MOODLE_38_STABLE 2020-08-06 12:11:07 +08:00
Jun Pataleta f5c7fcd181 Merge branch 'MDL-69111-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-08-06 11:48:34 +08:00
Adrian Greeve 2d436520dc Merge branch 'MDL-40227-38-1' of git://github.com/peterRd/moodle into MOODLE_38_STABLE 2020-08-06 11:29:35 +08:00
Peter eb5d0d7d59 MDL-40227 mod_lesson: Use localised float formatting
* Leverage PARAM_LOCALISEDFLOAT
* Store all numbers with standard '.' dec formatting
* Show all numbers based on locale settings
* Behat test to cover different cases using numeric questions and modified locale setting
2020-08-06 10:44:48 +08:00
Adrian Greeve d158589158 Merge branch 'MOODLE_38_MDL-66626' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2020-08-06 09:08:26 +08:00
Eloy Lafuente (stronk7) 268e3b893a Merge branch 'MDL-66670-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-08-06 00:58:33 +02:00
Leon Stringer 54004f286e MDL-60492 core_tag: Fix title attribute
Attribute 'title' was specified inside a condition but closing `"` was
outside condition possibly resulting in <a href="..." class="..." ">.
Also moved </a> outside of condition to match <a>.
2020-08-05 12:56:02 +01:00
Adrian Greeve 12baca4b15 Merge branch 'MDL-68647-38-forumprivacysql' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-08-05 14:23:28 +08:00
Adrian Greeve 08e86bd7b1 Merge branch 'MDL-60932-38' of git://github.com/aanabit/moodle into MOODLE_38_STABLE 2020-08-05 10:09:44 +08:00
Eloy Lafuente (stronk7) 36e03f1596 Merge branch 'MDL-67831-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-08-05 00:48:31 +02:00
Tim Hunt b1341895b1 MDL-69253 mod_quiz: unit test for the last commit 2020-08-04 14:51:13 +01:00
Josh Ebarvia 6d3dca55f8 MDL-69253 mod_quiz: Fix timecreated is 0 when creating a quiz activity 2020-08-04 14:51:12 +01:00
Jun Pataleta d86741395e Merge branch 'MDL-60574_38' of https://github.com/t-schroeder/moodle into MOODLE_38_STABLE 2020-08-04 19:50:20 +08:00
Eloy Lafuente (stronk7) 0f6c21c836 Merge branch 'MDL-55299-38' of git://github.com/ferranrecio/moodle into MOODLE_38_STABLE 2020-08-04 12:34:15 +02:00
Tim Schroeder 8ae39ac69e MDL-60574 atto_undo: fixed redo erasing content
When you'd hit ctrl-y with nothing on the redo stack the entire
content of Atto would get deleted with no way of getting it back.
2020-08-04 09:25:23 +02:00
Leon Stringer 957baa0871 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-03 11:42:50 +01:00
Eloy Lafuente (stronk7) 678bcecc0d Merge branch 'MDL-62980-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-08-03 12:38:37 +02:00
Bas Brands 06f6b499eb MDL-69114 theme_boost: improve the color contrast for .*-info classes 2020-08-03 11:41:40 +02:00
Eric Merrill 88aa4e2071 MDL-69112 assign: Improve parsing of uploaded feedback names 2020-07-31 19:08:43 -04:00
Amaia Anabitarte 49403f979a MDL-60932 core_user: Fix docs link for participants page
Co-authored by: David Mudrák <david@moodle.com>
2020-07-31 10:30:43 +02:00
Neill Magill 28047fa3b1 MDL-69296 resource: Pressing cancel should always exit settings form
Before this change if a user used navigated to a resource activity
from another activity and then edited the settings it was likely
that using the cancel button would result in file downloading,
rather than being returned to their last page.

After this change the user will be back on the page they came from.
2020-07-31 07:58:16 +01:00
Paul Holden 98292864e8 MDL-67394 dml: improve thrown exception when Oracle can't parse query. 2020-07-30 16:23:02 +01:00
Victor Deniz Falcon 71f3a7fca9 weekly release 3.8.4+ 2020-07-30 12:54:08 +01:00
Victor Deniz Falcon 8a416d4e63 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-07-30 12:54:02 +01:00
Paul Holden 94f4f39ab7 MDL-62980 tool_dataprivacy: show persistent errors inside form. 2020-07-30 08:23:26 +01:00
Eloy Lafuente (stronk7) ad30b41f91 Merge branch 'MDL-63252-38' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-07-30 00:48:15 +02:00
Victor Deniz Falcon 7803827502 Merge branch 'MDL-66707-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-07-29 23:18:09 +01:00
Victor Deniz Falcon a6986b3e36 Merge branch 'MDL-68968-38' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-07-29 22:03:16 +01:00
Paul Holden 73b7597a8c MDL-60260 course: validate external fields on create/update course.
Ensure course fullname/shortname fields are not empty.
2020-07-29 19:57:30 +01:00
Victor Deniz Falcon 9b54ddd465 Merge branch 'MDL-68706-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-07-29 19:04:18 +01:00
Victor Deniz Falcon 39dc97aef9 Merge branch 'MDL-69199-38' of git://github.com/aanabit/moodle into MOODLE_38_STABLE 2020-07-29 11:56:08 +01:00
Jonathon Fowler 8351210984 MDL-68731 forum: fix digests not correctly updating post read statuses 2020-07-29 15:41:21 +10:00
Jun Pataleta bfce37757f Merge branch 'MDL-69252-close_tag-38' of https://github.com/leonstr/moodle into MOODLE_38_STABLE 2020-07-29 11:17:32 +08:00
Eloy Lafuente (stronk7) b4d8be2042 Merge branch 'MDL-69319-38' of https://github.com/snake/moodle into MOODLE_38_STABLE 2020-07-29 00:20:53 +02:00
Leon Stringer 7d3b148e94 MDL-60493 mod_assign: Unused JS variables
Removed unused JavaScript variables fixing CI warning "ESLint error
[no-unused-vars]".
2020-07-28 12:05:49 +01:00
Leon Stringer 595e05d2a7 MDL-60493 mod_assign: Remove rogue </span>
In the grading interface (/mod/assign/view.php?id=2&action=grader)
there was a rogue </span> with no opening <span>.  Also changed
<span><form> to <div><form> in included template fixing CiBoT HTML
Validation error.
2020-07-28 12:05:12 +01:00
Jun Pataleta 4a776d2f67 Merge branch 'MDL-65453-38' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-07-28 11:41:46 +08:00
Simey Lameze 975c1d4438 MDL-65453 core: fix behaviour of --skip-database option on install 2020-07-28 11:27:39 +08:00
Paul Holden 019e7dd26c MDL-69204 tool_dataprivacy: summary link only on current user profile. 2020-07-27 17:24:48 +01:00
Jun Pataleta 1b479562cd Merge branch 'MDL-66755-38' of https://github.com/SergioComeron/moodle into MOODLE_38_STABLE 2020-07-27 17:07:38 +08:00
AMOS bot d2b35aea26 Automatically generated installer lang files 2020-07-27 00:07:37 +00:00
AMOS bot 3678ad0949 Automatically generated installer lang files 2020-07-27 00:07:37 +00:00
Mikhail Golenkov 8c4893ffdc MDL-66626 assignfeedback_editpdf: Check page count for attempt.
Co-Authored-By: John Yao <johnyao@catalyst-au.net>
2020-07-27 09:51:54 +10:00
Mikhail Golenkov bab00d9b8c MDL-66626 assignfeedback_editpdf: Count files outside of foreach loop.
Co-Authored-By: John Yao <johnyao@catalyst-au.net>
2020-07-27 09:51:54 +10:00
AMOS bot 88723a6a1d Automatically generated installer lang files 2020-07-25 00:08:02 +00:00
Paul Holden 035c042f1e MDL-68706 customfield_textarea: allow field content to be cleared. 2020-07-24 13:44:58 +01:00
Paul Holden 6ed3f966b7 MDL-69353 admin: set page title when prompting for upgrade key. 2020-07-24 13:30:34 +01:00
Tim Hunt a7f70278c8 MDL-67002 quiz reports: fix sorting on Oracle in the responses report 2020-07-24 11:44:43 +01:00
Sergio Comerón ae1e1dfbd6 MDL-66755 forum: Subscription cancel when edit a message 2020-07-24 09:03:07 +02:00
Sam Marshall 5f417739f3 MDL-63252 tool_xmldb: convert default to float to avoid false positives 2020-07-24 07:54:02 +08:00
Simey Lameze 0d2f34b40d MDL-68968 core: fix wrong phpdoc on admin_externalpage 2020-07-24 07:46:33 +08:00
Amaia Anabitarte e0aa753fe1 MDL-69199 mod_quiz: Show timefinish in user Complete report 2020-07-23 18:54:25 +02:00
Victor Deniz Falcon f001dc447e weekly release 3.8.4+ 2020-07-23 16:10:30 +01:00
Victor Deniz Falcon cc80dec71e Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-07-23 16:10:25 +01:00
David Mudrák b89ebd255c MDL-68558 admin: Allow to go back to plugins check page on failed deps
Once the admin reaches the Plugin dependencies check with a failed
plugin dependency, the "Continue" button should take him/her to the
previous page where the dependency can be sorted out, or the plugin
installation cancelled. Also the "Cancel this installation" should work
on this page, too.

None of this was happening correctly because the page with failed
dependencies is loaded with "confirmplugincheck" set to 1 as a result
of confirming the previous step. We must explicitly override it back to
0 to navigate the user back to the previous step.
2020-07-23 17:05:03 +02:00
Bas Brands 0c773a6a16 MDL-67831 core_message: use space available for message index page
- the prevents the message reply box from being out of view when
a user has many conversations.
2020-07-23 11:34:52 +02:00
AMOS bot b45835b7b8 Automatically generated installer lang files 2020-07-23 00:07:56 +00:00
Victor Deniz Falcon 5aacc83bc4 Merge branch 'MDL-65819-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-07-22 19:01:36 +01:00
Ferran Recio ebb0e91226 MDL-55299 mod_feedback: fix quoted values donwload 2020-07-22 19:23:35 +02:00
Andrew Nicols 3ecf4dff52 MDL-69138 behat: Update session->visit() to use visit step 2020-07-22 16:48:37 +08:00
Andrew Nicols 3f2b9661d8 MDL-69138 behat: Add "I visit :localurl" step 2020-07-22 16:48:37 +08:00
Jun Pataleta 6b3d7a34dd Merge branch 'MDL-52052-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-07-22 13:46:59 +08:00
Jun Pataleta 2e38a7cc40 Merge branch 'MDL-68178-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-07-22 12:58:38 +08:00
Eloy Lafuente (stronk7) 95269fdb77 Merge branch 'MDL-69160-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-21 23:29:48 +02:00
Bas Brands 5a1745b254 MDL-69111 mod_forum: forum grading on small viewports
- changes to make the forum grading UI accessible in small
viewports to meet criterion 1.4.10 Reflow.
2020-07-21 17:42:55 +02:00
David Mudrák e271e28e78 MDL-68647 forum: Add index over posts privatereplyto field
This is to further improve the performance of searching of posts related
to the given user. Once both userid and privatereplyto are indexed, the
query planner can use the merged index to search for posts records.
2020-07-21 11:45:56 +02:00
David Mudrák 9cfcb4bf8a MDL-68647 forum: Improve the SQL performance in the privacy provider
The idea here is to replace the existing LEFT JOINs and
OR / IS NOT NULL conditions with INNER JOINs and ANDs. So we gather the
discussions data from all three areas in individual queries, make their
UNION. The GROUP BY was present before and maybe it is not even needed
any more (due to how UNION works) but it should not hurt to keep it.

This leads to significantly improved performance.
2020-07-21 11:45:56 +02:00
David Mudrák f25f8f0701 MDL-68647 forum: Add missing advanced grading library inclusion
The method get_grading_manager() is called in the file so make sure the
library is loaded. Without it, the forum's privacy provider unit test
ended with error.

Not directly related to the issue, but noticed while working on it.
2020-07-21 11:45:55 +02:00
Adrian Greeve 03670af6da Merge branch 'MDL-67657-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-21 14:49:14 +08:00
Ferran Recio 13f06f7a8e MDL-68423 message: avoid self-xss when send a message 2020-07-20 19:56:13 +02:00
Eloy Lafuente (stronk7) a080d4c0df Merge branch 'm38_MDL-67440' of https://github.com/danmarsden/moodle into MOODLE_38_STABLE 2020-07-20 17:08:31 +02:00
Leon Stringer ab7849c105 MDL-60501 themes: Fix closing <h4> in template
In site admin pages (/admin/search.php) <h4> elements were generated
with an incorrect second opening <h4> instead of a closing </h4>.
2020-07-20 15:20:42 +01:00
Bas Brands 756e148f31 MDL-66670 theme_boost: list bullet styling
Ensure lists with bullets are not cut off
2020-07-20 14:49:04 +02:00
Jake Dallimore 5a2ca41bba MDL-69319 mod_lti: style and docs changes in external tests 2020-07-20 15:04:10 +08:00
Jake Dallimore c9d1d8141f MDL-69319 mod_lti: replace try/catch with expectException in ext tests 2020-07-20 15:04:10 +08:00
Jake Dallimore 34616581c5 MDL-69319 mod_lti: remove unused vars from externallib_test 2020-07-20 15:04:10 +08:00
Jake Dallimore 33ec9e3a37 MDL-69319 mod_lti: move test data generation out of common setup 2020-07-20 15:04:10 +08:00
Jake Dallimore 147b984630 MDL-69319 mod_lti: call clean_returnvalue in external tests 2020-07-20 15:04:09 +08:00
Mihail Geshoski 4a2a779e12 MDL-68178 auth: CSRF protection for the resend confirmation email form
Credit to Chandra Kishor.
2020-07-20 12:31:06 +08:00
Adrian Greeve 6364b15e24 Merge branch 'MDL-69113_38' of https://github.com/jonof/moodle into MOODLE_38_STABLE 2020-07-20 10:37:49 +08:00
Mihail Geshoski b71744bb4d MDL-52052 gradeimport_csv: Do not skip rows with blank user fields 2020-07-20 08:55:51 +08:00
Eloy Lafuente (stronk7) 241eacaa7a Merge branch 'MDL-69278-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-18 11:56:15 +02:00
Paul Holden 37f3c318ea MDL-65819 message: send contact requests using recipient language. 2020-07-17 13:38:08 +01:00
Sara Arjona 4a6de87cae weekly release 3.8.4+ 2020-07-16 21:28:30 +02:00
Andrew Nicols a89aaec1af MDL-67657 behat: Open course with editing using URL
This is a huge performance improvement for behat.

The current set of steps loads the page
It then looks for the Classic/Clean version of the settings menu
If it fails to find it looks for the Boost Cog
Then it clicks the "Turn editing on" button

This can take a substantial period.

We do not actually need to run these steps as we are able to jump
straight to the URL. We already have access to the sesskey value
required to do this.

There is not loss in testing functionality because the actual testing of
the Turn editing functionality is tested in other places sufficiently.
2020-07-16 11:06:43 +08:00
Andrew Nicols 00df049b9a MDL-67657 behat: Convert existing uses of executeScript 2020-07-16 11:06:31 +08:00
Andrew Nicols a37313a6d1 MDL-67657 behat: Add wrapper for JS execution 2020-07-16 11:05:32 +08:00
Jun Pataleta b3c5e4f5d7 Merge branch 'MDL-69215-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-16 09:42:42 +08:00
Andrew Nicols 5eb38638bb MDL-69278 behat: Correct variable name 2020-07-16 08:30:13 +08:00
Andrew Nicols aeb85b66f2 MDL-69278 behat: Mark tests as failed when unable to start Session 2020-07-16 08:30:13 +08:00
Andrew Nicols 7ba288d1d0 MDL-69215 output: Correct use of icon_system::instance 2020-07-16 07:30:32 +08:00
Andrew Nicols d7e8f35e91 MDL-69215 output: Correct font awesome for themes 2020-07-16 07:30:32 +08:00
Eloy Lafuente (stronk7) db6f80a784 Merge branch 'MDL-69165-38' of https://github.com/HuongNV13/moodle into MOODLE_38_STABLE 2020-07-15 23:47:52 +02:00
Charles Fulton b20a875381 MDL-69074 admin: ensure consistent default for getremoteaddrconf 2020-07-15 19:06:06 +02:00
Sara Arjona f3d6fa182b Merge branch 'MDL-68605_38' of https://github.com/t-schroeder/moodle into MOODLE_38_STABLE 2020-07-15 18:52:57 +02:00
Sara Arjona 68a6b6db8d Merge branch 'MDL-68210-38' of https://github.com/snake/moodle into MOODLE_38_STABLE 2020-07-15 18:19:54 +02:00
Shamim Rezaie 9a66680ae1 MDL-66707 mod_forum: do not blindly mark discussion replies as read 2020-07-15 22:27:22 +10:00
Sara Arjona 8d90570067 Merge branch 'MDL-67671_38_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_38_STABLE 2020-07-15 14:11:55 +02:00
Sara Arjona a30f7f13ea Merge branch 'MDL-57678-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-07-15 12:56:54 +02:00
Jun Pataleta d780b1866e MDL-57678 core_course: Remove padding of nbsp's on category names
Padding nested course categories by space to make them render in a tree
structure does not really make a lot of sense as they are already being
rendered as full paths. It's simpler to show them without the
indentation.
2020-07-15 18:28:10 +08:00
Sara Arjona 273ef0b4e3 Merge branch 'MDL-69068-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-15 12:20:39 +02:00
Andrew Nicols 8402724494 MDL-69068 behat: Allow singular, pivotted data generators 2020-07-15 15:27:31 +08:00
Andrew Nicols 83b5aea43c MDL-69068 behat: New step to support singular generators 2020-07-15 15:25:27 +08:00
Sara Arjona 51f4f8c612 Merge branch 'MDL-68715-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-07-14 14:32:10 +02:00
Shamim Rezaie 5d9fb70f70 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-07-14 22:12:59 +10:00
Shamim Rezaie 0368c8e2a8 MDL-68444 calendar: Improve how screenreaders read day titles
Screenreaders now know if each day has any event or not
2020-07-14 22:12:59 +10:00
Paul Holden 9fea1cc6e4 MDL-68715 completion: fix form default value for course prerequisites.
Adds filtering on the completion criteria form to ensure we are only
selecting actual course instances of this type. Prior to this change
we would also get NULL values from unrelated criteria types.
2020-07-14 12:45:54 +01:00
Sara Arjona b09e569189 Merge branch 'MDL-69228-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-14 12:41:33 +02:00
Sara Arjona 9afc404947 Merge branch 'MDL-69115-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-07-13 14:24:26 +02:00
Andrew Nicols 70d6af63ba MDL-69160 workshop: Ensure steps are chained 2020-07-13 14:22:31 +08:00
Andrew Nicols 4338982098 MDL-69160 behat: Add form field setter step 2020-07-13 14:22:31 +08:00
Eloy Lafuente (stronk7) 8634f2b672 Moodle release 3.8.4 2020-07-12 12:12:53 +02:00
Leon Stringer 678ca3ded7 MDL-69252 templates: Invalid HTML
Invalid HTML generated when the page count exceeded the maximum number
of page links to display: <span>...</a>.  Also added example context.
2020-07-11 12:54:43 +01:00
AMOS bot 7ec2bf3776 Automatically generated installer lang files 2020-07-10 19:52:55 +00:00
Eloy Lafuente (stronk7) a6227d5675 weekly release 3.8.3+ 2020-07-10 20:22:15 +02:00
Eloy Lafuente (stronk7) e4d47ed2cc Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-07-10 20:22:09 +02:00
Jake Dallimore 4d069c9339 Merge branch 'MDL-69232-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-10 15:12:11 +08:00
Andrew Nicols 3e741db933 MDL-69232 behat: Simplify hooks
The behat hooks were needlessly complicated which made them much harder
to read, and understand, leading to bugs during development.

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

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

Since the session is restarted more frequently, and now between every
test, it no longer makes sense to do this. The test should only be
_stopped_ if the first attempt to obtain the Session fails. Once a
Session has been retrieved at least once it no longer makes sense to
assume that the failure was a configuration failure, but a connection
failure. Therefore subsequent tests should be attempted.
2020-07-10 08:40:29 +08:00
Mark Johnson 2b36e5be2e MDL-67671 backup: Fix modname display on backup form 2020-07-09 10:13:08 +01:00
Jake Dallimore f2de1293e1 Merge branch 'MDL-69135-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-09 10:38:51 +08:00
Michael Hawkins ea79b6597a MDL-68426 theme: Set a limit on paths length in yui_combo
The maximum paths length is now consistent with the YUI loader.
This fix also removes any duplicate paths, so each file is only ever
fetched once.
2020-07-09 10:24:01 +08:00
Andrew Nicols 3b97a56c6a MDL-69232 behat: Add debugging information to Selenium fails 2020-07-09 09:45:35 +08:00
Andrew Nicols 07414b90e3 MDL-69232 behat: Move suite tests to BeforeSuite hook 2020-07-09 09:45:34 +08:00
Eloy Lafuente (stronk7) d49c18bba5 Merge branch 'MDL-69134-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-08 20:53:32 +02:00
Huong Nguyen 82ddfd7ea6 MDL-69165 Questions: Incorrect id used in init_submit_button function 2020-07-08 11:48:56 +07:00
Andrew Nicols ecc61a125b Merge branch 'MDL-68784-38' of https://github.com/Peterburnett/moodle into MOODLE_38_STABLE 2020-07-08 12:37:56 +08:00
Andrew Nicols d8538f29c4 Merge branch 'm38_MDL-66322_Travis_Run_Using_Docker_ExtTests' of https://github.com/scara/moodle into MOODLE_38_STABLE 2020-07-08 12:22:20 +08:00
Peter Burnett 881b487433 MDL-68784: Updated variable for graph report 2020-07-08 14:07:35 +10:00
Andrew Nicols da91dd3ea0 MDL-69228 tool_mobile: Hide dependant settings 2020-07-08 11:50:18 +08:00
Andrew Nicols e0c0a0c05c Merge branch 'MDL-60494-stray_img_end-38' of https://github.com/leonstr/moodle into MOODLE_38_STABLE 2020-07-08 09:25:11 +08:00
Andrew Nicols 246a03f7dd MDL-69134 competencies: Behat fails randomly opening dialogues 2020-07-08 09:21:54 +08:00
Jake Dallimore 121373ec8f MDL-68210 mod_lesson: fix random failure in override behat test 2020-07-08 09:10:20 +08:00
Jake Dallimore 8fb613ee9f MDL-68210 overrides: allow copy and delete of inactive overrides
This brings lesson and assign in line with the expected behaviour
already implemented in quiz. When an override is inactive, all controls
are shown.
2020-07-08 09:10:20 +08:00
Andrew Nicols 44fd35e8ee Merge branch 'MDL-69109-38-2' of git://github.com/marinaglancy/moodle into MOODLE_38_STABLE 2020-07-08 08:41:07 +08:00
Matt Clarkson 63b646acb1 MDL-67440 analytics: optimse delete's in clean up task. 2020-07-08 11:19:09 +12:00
Matteo Scaramuccia a28a24e2f2 MDL-66322 travis: Configure a local copy of 'exttests' 2020-07-07 21:55:47 +02:00
Eloy Lafuente (stronk7) 3639dc845e Merge branch 'MDL-69086-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-07 19:17:29 +02:00
Eloy Lafuente (stronk7) d63c297351 Merge branch 'm38_MDL-68588_Hide_Backuptempdir_From_Message_And_Debuginfo' of https://github.com/scara/moodle into MOODLE_38_STABLE 2020-07-07 19:10:51 +02:00
Eloy Lafuente (stronk7) 54faefbefb Merge branch 'MDL-68784-38' of https://github.com/Peterburnett/moodle into MOODLE_38_STABLE 2020-07-07 18:52:36 +02:00
Tim Schroeder 8c3e24b46c MDL-68605 mod_assign: return grp submissns from ws
Co-authored-by: Septatrix <24257556+Septatrix@users.noreply.github.com>
2020-07-07 12:56:28 +02:00
Víctor Déniz Falcón 735de9020e MDL-69093 enrol_manual: added check for allowed roles a user can assign 2020-07-07 08:33:18 +02:00
Andrew Nicols 71e5f30504 Merge branch 'MDL-69106-38' of git.in.moodle.com:cameron/moodle into MOODLE_38_STABLE 2020-07-07 14:16:48 +08:00
Eloy Lafuente (stronk7) 5b9c5ccf83 Merge branch 'MDL-60827-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-07-07 00:17:35 +02:00
Andrew Nicols 46b6ca69d1 Merge branch 'MDL-69158-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-07-06 12:12:47 +08:00
Jake Dallimore dbd41fa613 Merge branch 'MDL-69136-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-06 10:44:50 +08:00
Michael Hawkins 381f45d005 MDL-69129 report: Limit config changes report sort direction values 2020-07-06 10:11:39 +08:00
Mihail Geshoski 0397309abf MDL-60827 oauth2: Consider requireconfirmation setting on login 2020-07-06 10:05:50 +08:00
Michael Hawkins dca95c6fe4 MDL-69128 admin: Convert HTML entities when populating tasklogs filter 2020-07-06 10:05:05 +08:00
AMOS bot 112fc4d513 Automatically generated installer lang files 2020-07-06 00:08:36 +00:00
Leon Stringer 3b81550b8e MDL-60494 mod_lti: Invalid </img>, example context
<img> was followed by an invalid </img>.  Also added example context for
template so it passes CI checks.
2020-07-05 15:58:35 +01:00
Matteo Scaramuccia 0cf43f11f0 MDL-68588 Backup: Hide ->backuptempdir in exception info 2020-07-03 21:19:12 +02:00
Eloy Lafuente (stronk7) 035f5d9423 weekly release 3.8.3+ 2020-07-03 18:41:29 +02:00
Eloy Lafuente (stronk7) 1bae8bd482 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-07-03 18:41:24 +02:00
Jake Dallimore 3bd1b121ed Merge branch 'MDL-69130-38-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-07-02 12:08:53 +08:00
Jake Dallimore db58c4cdf2 Merge branch 'MDL-69149-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-02 11:57:34 +08:00
Jake Dallimore b730bb5702 Merge branch 'MDL-69122-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-07-02 11:49:35 +08:00
AMOS bot d45a6dd3c3 Automatically generated installer lang files 2020-07-02 00:08:16 +00:00
Eloy Lafuente (stronk7) 0097d8d481 Merge branch 'MDL-69072-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-07-01 23:24:10 +02:00
Jake Dallimore ef6538a8c7 Merge branch 'MDL-68584-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-07-01 16:43:14 +08:00
Jun Pataleta 7a54747c9a MDL-69115 course: More course management accessibility fixes
* Added aria-label for category single select element when on Courses
view mode.
* Fix correct labelling of custom control checkboxes. Instead of adding
aria-label in the label element, add an sr-only span within the label.
* Remove inappropriate 'group' role for the list of courses.
The list of courses is not being rendered as a tree structure
so adding a 'group' role to the list of courses is not really
necessary.
* Add aria-label for the search courses field.
* Add legend for the search courses fieldset.
* Use the primary colour for the category selection highlight instead
of the info colour.
* Changed the labels for the up/down icons using moveup/movedown
lang strings.
2020-07-01 14:45:37 +08:00
Paul Holden fe65ebcf1c MDL-69150 message_airnotifier: correct apps portal link. 2020-07-01 08:39:59 +08:00
Paul Holden bc2d3e8bb9 MDL-69151 message_airnotifier: start output before accesskey request.
This allows debugging generated by the request to be shown on the
page.
2020-07-01 08:30:10 +08:00
Andrew Nicols d6ce289176 Merge branch 'MDL-67172-38' of git://github.com/cescobedo/moodle into MOODLE_38_STABLE 2020-07-01 07:47:53 +08:00
Marina Glancy d690ed3dd3 MDL-69109 theme: try to load icons from the current theme 2020-06-30 10:13:45 +02:00
Marina Glancy 704153c454 MDL-69109 core: use different cache keys for FA icon maps 2020-06-30 10:13:45 +02:00
Cameron Ball 37ee0fd966 MDL-69106 assignfeedback_editpdf: Keep files in conversion queue
In some circumstances, a submission waiting to be converted needs to persist
in the conversion queue so that it can be polled on subsequent cron runs.
2020-06-30 13:59:28 +08:00
Peter Burnett 58bf57d9d3 MDL-68784 scorm: Removed limit on allowed scorm users in report 2020-06-30 15:21:15 +10:00
Luca Bösch 71d4cc2f4e MDL-69158 block_blog_menu: format search form. 2020-06-29 11:13:46 +02:00
Andrew Nicols 913b96cb21 MDL-69136 behat: Improve reliability of navigation steps 2020-06-29 11:36:36 +08:00
Andrew Nicols 7c2fef6484 MDL-69136 behat: Support find on a NodeElement 2020-06-29 11:36:30 +08:00
Andrew Nicols 687c727cf9 MDL-69072 behat: Remove restart_browser_after feature
This is no longer required as the Mink session is restarted after every
test regardless.
2020-06-29 11:05:53 +08:00
Andrew Nicols ee6d899130 MDL-69072 mod_scorm: Stop mink reset after tests
This is now done for all scenarios. It is no longer necessary to do so
specifically for mod_scorm.
2020-06-26 21:17:22 +08:00
Andrew Nicols c18b08912f MDL-69072 behat: Relaunch browser session between scenarios 2020-06-26 21:17:22 +08:00
Andrew Nicols a46018529b MDL-69149 core_grade: Correct xpath attribute selector 2020-06-26 19:59:56 +08:00
Andrew Nicols 5ae95f265a MDL-69135 core_calendar: PendingJS for event filtering 2020-06-26 07:58:36 +08:00
Luca Bösch 456530205e MDL-68584 core_question: flexbox compatible separator for question types
* the br tag does not work well in a flexbox context, a 100% with div
works in both classic and boost.
2020-06-25 21:57:43 +02:00
cescobedo 6bfddeea21 MDL-67172 core_h5p: Prevent synchronous access to save the same h5p
Backport MDL-67095.
When deploying a new H5P resource we need to ensure that
we don't start deploying the same H5P in another thread
(e.g. for another session/user).
2020-06-25 18:42:40 +02:00
Eloy Lafuente (stronk7) 4557b7fed2 weekly release 3.8.3+ 2020-06-25 18:06:27 +02:00
Eloy Lafuente (stronk7) d93d8f65a8 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-06-25 18:06:22 +02:00
Helen Foster 406d9bb40f MDL-69130 lang: Import fixed English strings (en_fix) 2020-06-25 14:30:09 +02:00
Jonathon Fowler cd8c136c70 MDL-69113 assign: save grader app workflow/marker filters correctly 2020-06-25 14:39:54 +10:00
Bas Brands a66d07b15c MDL-69122 report_competency: fix clearfix
- a misplaced clearfix caused part of the recontrols to be
inaccessible
2020-06-24 09:15:39 +02:00
Jake Dallimore 44b19c47bf Merge branch 'MDL-68992-38_france_digital_age' of https://github.com/martignoni/moodle into MOODLE_38_STABLE 2020-06-24 09:40:52 +08:00
Eloy Lafuente (stronk7) 81b393a717 Merge branch 'MDL-66568-38-2' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-06-23 17:57:33 +02:00
Nicolas Martignoni 6fb0f6f941 MDL-68992 Privacy: Update default minimal digital age of consent
Updating default minimal digital age of consent according to current legislation,
that was updated for several countries since 2018.
2020-06-23 12:23:36 +02:00
Jake Dallimore 4d26e345d0 Merge branch 'MDL-69021-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-06-23 11:31:48 +08:00
Adrian Greeve 1c8b779f27 Merge branch 'MDL-68841-3.8.3' of https://github.com/DinhHien0307/moodle into MOODLE_38_STABLE 2020-06-23 09:50:54 +08:00
Bas Brands a4099f2932 MDL-69021 theme_boost: improve link styles in alerts
- provide default styles for links in alerts if the .alert-link
css class is omitted.
2020-06-22 16:51:03 +02:00
Adrian Greeve 2557a7f8ff Merge branch 'MDL-69077_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-06-22 10:42:49 +08:00
AMOS bot 9518c81ab8 Automatically generated installer lang files 2020-06-21 00:07:28 +00:00
Sara Arjona befe7cce8d Merge branch 'MDL-69008-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-06-19 16:49:29 +02:00
Andrew Nicols 2dc698fb17 MDL-69086 theme_boost: Improve pendingJs checks for bootstrap
Where an element, like an `alert`, is closed it is removed from the DOM
before the event fires (this is a correct behaviour).

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

This change moves the end event listener to only be added after a start
event has been fired, and to attach directly to the HTMLElement where it
will be fired. This means that the Event handler will still be called,
even though it has been removed from the DOM, because it does not need
to bubble up to the body.
2020-06-19 08:17:45 +08:00
Sara Arjona 898415efec weekly release 3.8.3+ 2020-06-18 14:13:55 +02:00
Sara Arjona 5b5233321e Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-06-18 14:13:53 +02:00
Victor Deniz Falcon 4d4ad0fe60 Merge branch 'MDL-66899-log-quiz-regrade_38' of https://github.com/rboyatt/moodle into MOODLE_38_STABLE 2020-06-18 04:55:12 +01:00
Tim Hunt 8fcb1b459d MDL-69077 questions: question tag capabilties are relevant 2020-06-17 13:07:45 +01:00
Jun Pataleta 8816107de4 Merge branch 'MDL-68890-3.8.3' of https://github.com/DinhHien0307/moodle into MOODLE_38_STABLE 2020-06-17 19:54:19 +08:00
Jun Pataleta 42cf09b5b4 MDL-69008 core: Fix accessibility issues in paged content templates
* Added menuitem role for the "Show x per page" menu.
* Added appropriate aria-labels for the links in the paging bar.
2020-06-17 15:59:57 +08:00
Jake Dallimore 408c793ed7 Merge branch 'MDL-68215-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-06-17 14:59:02 +08:00
Jun Pataleta 6324b63372 Merge branch 'MDL-68971_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-06-17 11:35:01 +08:00
Jun Pataleta 3c91dc0784 Merge branch 'MDL-67294-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-06-17 10:34:06 +08:00
Andrew Nicols 4d3658f7d8 MDL-66568 behat: Reset theme CSS between scenarios 2020-06-17 07:51:47 +08:00
Andrew Nicols bcbc91091c MDL-66568 behat: Support building of themes for behat 2020-06-17 07:51:47 +08:00
Andrew Nicols d57acc9d80 MDL-66568 core_output: Return built theme CSS 2020-06-17 07:51:47 +08:00
Mihail Geshoski bc125390bb MDL-67294 assignsubmission_file: Make sure record exists before updating 2020-06-17 00:55:57 +08:00
Víctor Déniz Falcón f097a1a20f Merge branch 'MDL-69049-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-06-16 17:52:32 +01:00
Jun Pataleta adc032b170 Merge branch 'MDL-68436_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-06-16 14:39:02 +08:00
Jun Pataleta 6c8f7e1ce2 MDL-69049 tool_dataprivacy: Add possibly missing comment format columns
The earlier CONTRIB plugin versions of the tool (<33.2.0, <34.2.0) were
missing the following columns in the data requests table:
* commentsformat
* dpocommentformat
And the upgrade scripts for the merged tool failed in
Moodle 3.3.8+/3.3.0+ failed to add these columns.
So a site which uses the CONTRIB plugin and eventually upgrading to 3.9
will encounter an error during upgrade because of the missing
dpocommentformat column.
2020-06-15 23:42:10 +08:00
Luca Bösch 8cb7cb1fdc MDL-68215 block_activity_result: Format elements more nicely. 2020-06-15 15:25:28 +02:00
hiendinh 5f6ce419c4 MDL-68890 progressbar: prevent display exist file's progress bar 2020-06-15 10:53:12 +07:00
AMOS bot 74235813b3 Automatically generated installer lang files 2020-06-14 00:07:26 +00:00
Sara Arjona 409baab766 weekly release 3.8.3+ 2020-06-11 18:03:58 +02:00
Andrew Nicols ee884c9728 Merge branch 'MDL-69006-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-06-11 13:05:39 +08:00
Andrew Nicols c6a9898ed0 Merge branch 'MDL-69002-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-06-11 11:21:16 +08:00
Adrian Greeve 80c3dcb8bf MDL-66601 atto_image: Remove bad build files. 2020-06-11 10:48:36 +08:00
Adrian Greeve 3c142d923f Merge branch 'MDL-66601-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-06-11 09:55:51 +08:00
Eloy Lafuente (stronk7) 53e4c04237 Merge branch 'MDL-68954-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-06-11 00:10:28 +02:00
Bas Brands 8cf375b627 MDL-69006 repository_flickr: flickr authentication fails
- Flickr does not like useragents including the word "Bot"
2020-06-10 15:56:27 +02:00
Tim Hunt 5e7c083dba MDL-68436 atto_recordrtc: only works once per page 2020-06-10 13:48:12 +01:00
Sara Arjona 7d896212f2 MDL-69002 core_badges: move backpack validation to a separate page
Instead of running the site backpack validation every time badges/backpacks.php
page is loaded, an action button has been added to the backpacks with OB set
to 2.0 to let admins running manually this verification when needed.
2020-06-10 13:01:29 +02:00
Sara Arjona 3a6950ccd7 MDL-69002 core_badges: add methods to support backpack validation
A more generic method has been added to the API to validate the
backpack connection (for now, there was only one method for
validating current backpack).
Besides, a renderer has been added to display this information
depending on the backpackid.
2020-06-10 12:45:14 +02:00
Sara Arjona 24562c031c MDL-69002 core_badges: remove site backpack verification from settings
This site backpack verification is not required so, instead of
running it always here, it will be moved to a separate page to let
admins decide when to check it.
2020-06-10 12:42:03 +02:00
Mihail Geshoski deca8028d9 MDL-66601 atto_image: Set the max-height of the image selection dialogue 2020-06-10 12:21:21 +08:00
Jun Pataleta 3063e8415a Merge branch 'MDL-68864-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-06-10 11:26:21 +08:00
Jun Pataleta ccbe61ee98 MDL-68864 qtype_multichoice: Rebuild clearchoice source map 2020-06-10 11:21:00 +08:00
Bas Brands ef874ad928 MDL-68864 qtype_multichoice: shift focus to first option on keyboard tab
- This prevents losing focus when using keyboard navigation
2020-06-10 11:15:17 +08:00
Bas Brands 9a33db6bea MDL-68864 qtype_multichoice: clearchoice
- Reverted changes from MDL-67901
2020-06-10 11:15:17 +08:00
Jake Dallimore b51501b403 Merge branch 'MDL-68972-38-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-06-10 09:16:08 +08:00
Jake Dallimore 4f142bccce Merge branch 'MDL-68995-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-06-10 08:53:55 +08:00
Helen Foster dac9cc3139 MDL-68972 lang: Import fixed English strings (en_fix) 2020-06-09 21:08:54 +02:00
Paul Holden 281c882327 MDL-68995 atto_image: remove initial dialogue image src attribute.
It caused a spurious request to be sent to the server on display.
2020-06-09 15:47:55 +01:00
Sara Arjona bbc79e490a weekly release 3.8.3+ 2020-06-09 12:14:38 +02:00
Tim Hunt 666365e46b MDL-68971 webservice: errors should give enough info to find the problem 2020-06-09 11:09:45 +01:00
Russell Boyatt 28509546d3 MDL-66899 quiz: Log a regrading event when quiz attempt is regraded. 2020-06-09 10:08:24 +01:00
Russell Boyatt a860a76a68 MDL-66899 quiz: Adding test for regrading quiz event. 2020-06-09 10:08:03 +01:00
Mihail Geshoski 8d650d9a01 MDL-68954 repository_flickr_public: Return only photo media 2020-06-09 12:37:35 +08:00
Mihail Geshoski bbaab1109e MDL-68954 repository_flickr_public: Handle when photo cannot be found 2020-06-09 12:37:34 +08:00
Jake Dallimore c8a07a5b68 Merge branch 'MDL-68929-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-06-08 11:11:00 +08:00
Andrew Nicols abb076ebbd Merge branch 'MDL-68899-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-06-08 10:29:27 +08:00
Mihail Geshoski 56d6a5d731 MDL-68899 theme_classic: Fix dashboard course cards rendering
Co-authored-by: Bas Brands <bas@moodle.com>
2020-06-08 09:16:00 +08:00
Mihail Geshoski 59417f0b1d MDL-68929 core_filepicker: Fix radio button alignment 2020-06-07 11:40:47 +08:00
Eloy Lafuente (stronk7) 4180fe0f42 weekly release 3.8.3+ 2020-06-06 18:12:56 +02:00
Eloy Lafuente (stronk7) 8a53b489bb Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-06-06 18:12:52 +02:00
AMOS bot fecb0dcceb Automatically generated installer lang files 2020-06-06 00:07:27 +00:00
Sara Arjona 2b0ae390d7 MDL-68704 h5plib_v124: upgrade JQuery version to 1.12.4 2020-06-05 19:47:49 +01:00
Eloy Lafuente (stronk7) 1f274f5032 Merge branch 'MDL-68888-38-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-06-05 19:23:07 +02:00
Sara Arjona 6f0115e399 weekly release 3.8.3+ 2020-06-05 13:24:16 +02:00
Helen Foster 4369ef0304 MDL-68888 lang: Import fixed English strings (en_fix) 2020-06-05 09:35:38 +02:00
Adrian Greeve fe3d7cdbaa Merge branch 'MDL-67773' of https://github.com/radzisze/moodle into MOODLE_38_STABLE 2020-06-05 11:48:52 +08:00
Anthony Radziszewski c852856ba7 MDL-67773 course: Make sure tags are enabled before logging the setting. 2020-06-04 11:43:01 -06:00
Adrian Greeve 019420fd11 Merge branch 'MDL-68203-decode-url-quiz-restore-MOODLE_38_STABLE' of https://github.com/ilya-catalyst/moodle into MOODLE_38_STABLE 2020-06-04 08:31:50 +08:00
Sara Arjona c2263f903d Merge branch 'MDL-68772-38' of https://github.com/Clyxz/moodle into MOODLE_38_STABLE 2020-06-03 13:18:00 +02:00
Jake Dallimore 719333e0ec Merge branch 'MDL-68875_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-06-03 12:29:08 +08:00
Andrew Nicols 3a98b992e9 Merge branch 'MDL-68312-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-06-03 08:09:41 +08:00
Martin Hanusch 27a12aba40 MDL-68772 mod_quiz: Navigation overlay fix 2020-06-02 16:53:33 +02:00
Eloy Lafuente (stronk7) b529ffad65 MDL-68875 privacy: Keep moodle_content_writer->get_path() the same
In MDL-62853 a new clean_param(PARAM_PATH) was added to the
moodle_content_writer->get_path() method. And this caused some
Windows tests to start failing.

The problem is that clean_param(PARAM_PATH) does normalise directory
separators to be always forward backslashes and that's normally ok
but the get_path() method has some DIRECTORY_SEPARATOR dependent code
that stopped working under windows.

After analysing various solutions, and trying to keep the behavior
EXACTLY like it was before MDL-62853, but with the cleaning included
we have applied 2 changes:

b) Move the clean_param() to later within the array_map() function,
that way the code there, that uses DIRECTORY_SEPARATOR will continue
working the same.

b) As far as there are more DIRECTORY_SEPARATOR dependent code later
in the function, also perform a str_replace() to convert back to the
OS directory separator.

Those 2 points together (a and b) make the behavior to be 100% the
original one, with separators being kept and the paths being cleaned.

This solution corresponds 100% with the proposed fixes named 3) and
4) in the issue.

Final note... all that DIRECTORY_SEPARATOR maybe needs a review because
it really shouldn't be used unless strictly needed. But that falls out
from this issue which goal was to keep things safely working like they
were before the regression (but with the cleaning applied).
2020-06-02 15:53:45 +02:00
Sara Arjona b5b8b1a486 weekly release 3.8.3+ 2020-06-02 13:03:13 +02:00
Sara Arjona 2f360b90c5 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-06-02 13:03:11 +02:00
Adrian Greeve efa47a2ba5 Merge branch 'MDL-68828-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-06-02 09:32:33 +08:00
Andrew Nicols 4b47df0236 Merge branch 'MDL-67518_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-06-02 09:20:19 +08:00
Adrian Greeve d9fe693347 Merge branch 'MDL-68723-38' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-06-02 08:58:37 +08:00
Eloy Lafuente (stronk7) 74206f3d78 Merge branch 'MDL-63284-38' of https://github.com/Clyxz/moodle into MOODLE_38_STABLE 2020-06-02 00:25:17 +02:00
Eloy Lafuente (stronk7) 0fce71647f Merge branch 'MDL-68866-38' of https://github.com/mchurchward/moodle into MOODLE_38_STABLE 2020-06-02 00:14:42 +02:00
Eloy Lafuente (stronk7) 3d50844c9f Merge branch 'MDL-68844-38' of https://github.com/roland04/moodle into MOODLE_38_STABLE 2020-06-02 00:09:48 +02:00
Mike Churchward 661c7a1988 MDL-68866 accesslib: Fixing parameter documentation. 2020-06-01 13:42:16 -04:00
Víctor Déniz Falcón f8f58c441b Merge branch 'MDL-68353-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-06-01 16:52:24 +01:00
Shamim Rezaie cdb0af69e1 MDL-68353 theme_classic: Update filepicker xpath selector 2020-06-01 03:45:32 +10:00
AMOS bot 85da65606b Automatically generated installer lang files 2020-05-30 00:07:22 +00:00
Martin Hanusch 6e64255df2 MDL-63284 question: Moving questions with tags disabled bug fix 2020-05-29 16:39:32 +02:00
Eloy Lafuente (stronk7) ec602d2f26 MDL-67518 phpunit: avoid DB sorting randomness in test
While reading from mdl_config, sometimes this test was failing
because an order was being presumed. Now we convert the records
array to an associative one to perform tests against it.
2020-05-29 16:26:07 +02:00
Jun Pataleta 6079a72373 Merge branch 'MDL-68353-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-05-29 22:25:54 +08:00
Sara Arjona 111fc893da weekly release 3.8.3+ 2020-05-29 12:52:30 +02:00
Sara Arjona 5d7f88d98b Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-05-29 12:52:27 +02:00
Mikel Martín 3eb69a0a9e MDL-68844 formslib: Fix inline layout for static elements 2020-05-29 11:11:40 +02:00
Shamim Rezaie 465c6e7c45 MDL-68353 test: Update existing tests to work with file elements 2020-05-29 14:51:58 +10:00
Shamim Rezaie 46323748fa MDL-68353 test: Update filemanager/filepicker xpath selector 2020-05-29 14:51:58 +10:00
Shamim Rezaie 32d28f8fac MDL-68353 test: get_field_locator to support custom field labels 2020-05-29 14:51:58 +10:00
Shamim Rezaie 2591f4ce79 MDL-68353 form: filepicker label fix 2020-05-29 14:51:54 +10:00
Shamim Rezaie c3764823cd MDL-68353 admin: Not use label tag in admin setting elements when needed 2020-05-29 14:35:46 +10:00
Shamim Rezaie 49e32e25ff MDL-68353 message: enclose privacy settings within a fieldset 2020-05-29 14:35:46 +10:00
Shamim Rezaie 46962930f7 MDL-68353 core: replace invalid labels with div 2020-05-29 14:35:46 +10:00
Shamim Rezaie 4c97f30360 MDL-68353 form: filemanager label fix 2020-05-29 14:35:43 +10:00
Jun Pataleta 35282e4d1a Merge branch 'MDL-64175-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-05-29 12:01:58 +08:00
Shamim Rezaie 78f4960bce MDL-68353 form: Only include the size attribute if there is a size set 2020-05-29 13:52:39 +10:00
Shamim Rezaie 6fa2f55cd0 MDL-68353 form: Removed the size attribute
The size attribute does not work with the checkbox input type.
2020-05-29 13:52:39 +10:00
Shamim Rezaie d3756efc83 MDL-68353 core: do not output empty labels 2020-05-29 13:52:38 +10:00
Shamim Rezaie 261804e95c MDL-68353 core: Set aria-label for close buttons on YUI dialogues 2020-05-29 13:52:36 +10:00
Mihail Geshoski 53c46ffb2e MDL-68723 filepicker: Display parent content in filemanger tree view 2020-05-29 11:46:32 +08:00
AMOS bot 7ba5f4896e Automatically generated installer lang files 2020-05-29 00:07:50 +00:00
Sara Arjona 3a76c07806 MDL-64175 atto_media: update advanced settings
Some OS, such as Ubuntu, are slightly changing the audio attributes,
from <audio attribute1="true"> to <audio attribute1>.
This patch is for reviewing this piece of code and covering both cases.
2020-05-28 17:27:16 +02:00
Eloy Lafuente (stronk7) 1794636ee6 Merge branch 'MDL-68753-38-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-05-28 13:02:29 +02:00
Sara Arjona 24906971d7 Merge branch 'MDL-68244-38' of https://github.com/Chocolate-lightning/moodle into MOODLE_38_STABLE 2020-05-28 12:42:50 +02:00
Sara Arjona 1ac59631d8 Merge branch 'MDL-68565-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-05-28 12:00:32 +02:00
hiendinh 4a77582d16 MDL-68841 Modal dialogs: Wrong behavior of popup 2020-05-28 16:33:11 +07:00
Eloy Lafuente (stronk7) 2140fe5549 Merge branch 'MDL-68789-38' of git://github.com/crazyserver/moodle into MOODLE_38_STABLE 2020-05-28 10:47:06 +02:00
Pau Ferrer Ocaña fc13b8c1a0 MDL-68789 behat: Rename the app from Moodle Mobile to Moodle app 2020-05-28 08:40:54 +02:00
Jake Dallimore f4163d2748 Merge branch 'MDL-67903-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-05-28 13:59:13 +08:00
Adrian Greeve a90af06899 Merge branch 'MDL-68847-38' of https://github.com/snake/moodle into MOODLE_38_STABLE 2020-05-28 12:01:42 +08:00
Jake Dallimore 81e276c743 Merge branch 'mdl-68425-m38' of https://github.com/deraadt/moodle into MOODLE_38_STABLE 2020-05-28 11:24:07 +08:00
Jake Dallimore 45da2ac9d3 MDL-68847 mod_url: fix bug when using dnd to handle urls
This generates a notice, which wasn't seen because the feature works
asynchronously.
2020-05-28 09:32:34 +08:00
Andrew Nicols 8c83815ab1 Merge branch 'MDL-68846_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-05-28 07:35:59 +08:00
Paul Holden e34877300c MDL-68565 tool_usertours: account for optional config in WS response. 2020-05-27 22:10:56 +01:00
Eloy Lafuente (stronk7) e917a595b2 MDL-68846 behat: Avoid asserting AM/PM strings. They are not cross-os
The exists/contains steps of behat are case-sensitive, in the other
side, depending of the OS and locales, time functions are not 100%
consistent. See https://bugs.php.net/bug.php?id=76378 for example.

So only solutions are:

1) Create a specific new step performing the checks case insensitively.
2) Avoid making AM / PM part of the checks.

Here we have opted by the 2nd approach, it's not critical part to check.
2020-05-27 18:05:07 +02:00
Thomas.Ludwig 852cda447f MDL-67903 core_grades: remove outdated CSS for grade import form 2020-05-27 16:02:11 +02:00
Sara Arjona 9e2cb2075c Merge branch 'MDL-68343-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-05-27 15:09:52 +02:00
Sara Arjona 13b26170b9 Merge branch 'MDL-68667-38' of git://github.com/aanabit/moodle into MOODLE_38_STABLE 2020-05-27 12:27:00 +02:00
Jake Dallimore 6f792b5ed8 Merge branch 'MDL-52138-38-take4' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-05-27 14:25:52 +08:00
Andrew Nicols 1612572a62 Merge branch 'MDL-68765-M38' of https://github.com/ised-isde-canada/moodle into MOODLE_38_STABLE 2020-05-27 12:50:13 +08:00
Andrew Nicols 5c5b0ee137 Merge branch 'm38_MDL-68054' of https://github.com/danmarsden/moodle into MOODLE_38_STABLE 2020-05-27 12:14:12 +08:00
Jun Pataleta 582e43bebe Merge branch 'MDL-68750-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-05-27 11:04:04 +08:00
Andrew Nicols 2ea2d6a72f MDL-68750 tool_dataprivacy: Correct behat test modal checks 2020-05-27 10:40:30 +08:00
Ilya Tregubov 37d7820816 MDL-68203 restore: Decode quiz links when restore into existing course
or duplicating.
2020-05-27 10:39:49 +10:00
Eloy Lafuente (stronk7) fc2c76e78e Merge branch 'MDL-68789-38' of git://github.com/crazyserver/moodle into MOODLE_38_STABLE 2020-05-26 23:42:56 +02:00
Luca Bösch 4c5684135a MDL-52138 core_grades: gradebook striped styling 2020-05-26 23:32:22 +02:00
Eloy Lafuente (stronk7) 35dd608161 weekly release 3.8.3+ 2020-05-26 22:52:25 +02:00
Sara Arjona 9faa136ca0 Merge branch 'MDL-68388_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-05-26 20:03:45 +02:00
Helen Foster 667d004a17 MDL-68753 lang: Import fixed English strings (en_fix) 2020-05-26 19:15:48 +02:00
Eloy Lafuente (stronk7) 640838c117 MDL-68388 core_grades: Tweak unit test assertion to make Oracle happy
Also modify some comments and get rid of some void return types.
2020-05-26 19:02:12 +02:00
Bas Brands f4a77e8381 MDL-68828 theme_classic: fix for mobile
- setting a max width so the page does not overflow its container on
mobile
- fixing dashboard cards to be 100% wide on mobile
2020-05-26 14:13:44 +02:00
Andrew Nicols 833d8bceb8 MDL-68750 analytics: Correct behat test modal checks 2020-05-26 12:56:25 +08:00
Andrew Nicols bc010acae0 MDL-68750 core_tag: Add missing confirmation dialogue title 2020-05-26 12:56:25 +08:00
Andrew Nicols 0deabbfbfd MDL-68750 behat: Correct dialogue selector 2020-05-26 12:56:25 +08:00
Andrew Nicols 404288d3bc Merge branch 'MDL-68099-38' of git://github.com/marinaglancy/moodle into MOODLE_38_STABLE 2020-05-26 11:38:32 +08:00
deraadt b16b681a79 MDL-68425 user: Add capability check for messaging 2020-05-26 13:01:06 +10:00
Andrew Nicols 14cfb3dcbf MDL-68388 grade: Tidy comments and whitespace 2020-05-26 10:19:09 +08:00
Andrew Nicols 074bdceb1f Merge branch 'M3.8-MDL-68388' of https://github.com/marcusboon/moodle into MOODLE_38_STABLE 2020-05-26 10:16:35 +08:00
Andrew Nicols c7545dc852 Merge branch 'MDL-64427-m38' of https://github.com/NeillM/moodle into MOODLE_38_STABLE 2020-05-26 10:05:58 +08:00
Andrew Nicols cd1a39717a Merge branch 'MDL-68270-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-05-26 08:03:06 +08:00
Victor Deniz Falcon c933e28af6 Merge branch 'MDL-68252_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-05-26 00:56:32 +01:00
Marcus Boon 0b62a26225 MDL-68388 core_grades: Use MUC for grade letters
In the get_grade_letters there is a static variable that is used
to cache grade letters, we should use MUC for this so that it is
reset properly between unit tests.
2020-05-26 09:27:05 +10:00
Bas Brands 8a977030fc MDL-68270 core_output: prevent blurring of navbar logo 2020-05-25 15:49:19 +02:00
Pau Ferrer Ocaña 0ff1309b3a MDL-68789 behat: Change app page menu text selector 2020-05-25 14:55:52 +02:00
Andrew Nicols 26badfdd1a Merge branch 'MDL-68103-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-05-25 19:55:33 +08:00
Bas Brands 1dafe5fbe5 MDL-68103 theme_classic: show content full width when printing 2020-05-25 13:49:39 +02:00
Nick Phillips f8621e3d58 MDL-68103 theme_classic: hidden-print => d-print-none for BS4. 2020-05-25 13:49:39 +02:00
Amaia Anabitarte e48b197957 MDL-68667 filepicker: Use shortitle parameter 2020-05-25 13:36:56 +02:00
Mathew May 7045cd8e67 MDL-68244 auth_email: Update unit test, remove hard assertion 2020-05-25 16:39:05 +08:00
Adrian Greeve 48583d2740 Merge branch 'MDL-68629_38' of https://github.com/t-schroeder/moodle into MOODLE_38_STABLE 2020-05-25 16:16:44 +08:00
Jake Dallimore 4ad9de59ea Merge branch 'MDL-62853-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-05-25 16:12:17 +08:00
Andrew Nicols b22accf82b Merge branch 'MDL-68658_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-05-25 15:26:36 +08:00
Adrian Greeve 99f948b4df Merge branch 'MDL-63812_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-05-25 14:42:08 +08:00
Ruslan Kabalin e94499f9b3 MDL-68592 formslib: Fix inline layout for nested groups 2020-05-22 17:55:50 +02:00
Eloy Lafuente (stronk7) 4e60865e2c MDL-68658 phpunit: Ensure that the configured proxy is applied always
Previously, if the RSS feed (extests) was being served locally,
CFG->proxybypass was applied and causing the test to fail (proxy
ignored).

In that exact test we need the configured proxy to be applied
always, because the test is exaclty about detecting the problem
when a wrong proxy is used.
2020-05-22 17:07:10 +02:00
Pau Ferrer Ocaña 43268a6a1c MDL-68789 behat: Adapt login step to new app version 2020-05-22 16:45:23 +02:00
Victor Deniz Falcon 38cc6d1071 weekly release 3.8.3+ 2020-05-22 14:21:47 +01:00
Victor Deniz Falcon 92ba52e21d Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-05-22 14:21:42 +01:00
Andrew Nicols 13215b2415 Merge branch '68137-moodle38-prevent-removing-all-dots-in-filename' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_38_STABLE 2020-05-22 11:55:20 +08:00
Andrew Nicols 0b464b93d8 Merge branch 'MDL-57240_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-05-22 11:48:35 +08:00
Andrew Nicols e3b6ebadcc Merge branch 'MDL-68783-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-05-22 11:24:16 +08:00
Andrew Nicols 6944da3315 Merge branch 'MDL-67700-38' of git://github.com/ferranrecio/moodle into MOODLE_38_STABLE 2020-05-22 10:51:47 +08:00
David Mudrák e67a6060e0 MDL-68738 wiki: Prevent URLs inside links from turning into another link
There was a problem with wiki pages in the HTML markup syntax. If they
contain a link and the link text has a URL in it, that URL was converted
into another link. But it was not correctly nested and it caused
additional troubles with filters (particularly the multimedia filter if
the URL was a video such as on youtube).

The solution here is similar to what we do in filters. We protect the
whole explicit link so that its content is not further parsed. That
prevents the inner URL to be converted into another link and the
explicit link has the full control.
2020-05-21 21:12:42 +02:00
Sara Arjona 0aadca7a48 Merge branch 'm38_MDL-67497' of https://github.com/danmarsden/moodle into MOODLE_38_STABLE 2020-05-21 19:01:45 +02:00
Ferran Recio 0efd87b0f2 MDL-67700 message: prevent async loading conversation message mix 2020-05-21 18:04:31 +02:00
Sara Arjona d42ad4800d Merge branch 'MDL-66471-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-05-21 17:33:33 +02:00
Sara Arjona 19ebf2dc92 Merge branch 'MDL-67126_38' of https://github.com/ffhs/moodle into MOODLE_38_STABLE 2020-05-21 13:35:18 +02:00
Adrian Greeve a644c50920 Merge branch 'MDL-68733_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-05-21 08:36:23 +08:00
AMOS bot de19504712 Automatically generated installer lang files 2020-05-21 00:07:22 +00:00
Eloy Lafuente (stronk7) ff5773d511 Merge branch 'MDL-52578-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-05-21 00:57:22 +02:00
Michael Milette 314e9a4064 MDL-68765 auth: Login form has DIV tag with 2 CLASS attributes. 2020-05-20 14:07:37 -04:00
Neill Magill 2f5490410e MDL-64427 course: Mark activities during course contents deletion
When we want to delete all of the activities in a course we should
mark them as having a deletion in progress, as this makes them
unavailable to users immediately.

This should make it much less likely that a request to get a context
that does not exist should be made when a user accesses a page.
2020-05-20 08:30:05 +01:00
Neill Magill 34f176586b MDL-64427 course: Do not allow dirty cm_info during course delete
When deleting a course (especially one containing a large amount of
data) the course mod info cache could contain entries for deleted
activities for a signifcant amount of time making it possible that
users could see errors in Moodle.
2020-05-20 08:30:04 +01:00
Neill Magill 7a168c3beb MDL-64427 category: Stop error when another user deleting courses
If you try to visit a category where another user is deleting a
course the coursecat cache may not be fresh. This is because there
is a breif time where the course record will have been deleted,
while it is deleting other course information, before the event that
triggers the coursecat cache to be purged is fired.
2020-05-20 08:30:04 +01:00
Neill Magill 0be9bb13c7 MDL-64427 category: Test getting category courses during deletion
Adding a unit test for the situation where a course is partially
deleted when a list of courses in a category is retrived.
2020-05-20 08:30:04 +01:00
Jun Pataleta 55dde65d11 MDL-68783 core_grades: Fix outcome page's add/remove button styles
* Applied proper styles of btn-secondary.
* Added some vertical spacing between the buttons by enclosing them in
divs with 'm-y-1' class instead of just a br tag.
2020-05-20 13:13:27 +08:00
Jun Pataleta 45978220ab MDL-52578 core_course: Peer review fixes
* Fetch parent category only when necessary.
* Fix outdated variable names in original patch.
* Fix variable scope for $outcomeexists.
2020-05-20 10:31:31 +08:00
Steve Bader e8e5f49883 MDL-52578 core_course: Activity weight set to 0 on creation 2020-05-20 10:31:31 +08:00
Dan Marsden efeef8d82d MDL-68054 lib: viewhiddenactivities should be set as captype:read 2020-05-20 14:03:02 +12:00
AMOS bot 9821d4d9a7 Automatically generated installer lang files 2020-05-20 00:07:31 +00:00
Paul Holden f138423971 MDL-66471 user: fix user_selector debug about extra identity fields. 2020-05-19 19:12:23 +01:00
Sara Arjona e6d212fc07 weekly release 3.8.3+ 2020-05-19 17:54:31 +02:00
Sara Arjona 1adda884fd Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-05-19 17:54:28 +02:00
Tim Hunt 4fae2c3001 MDL-68733 quiz editing: behat test for altering random question tags 2020-05-19 11:10:04 +01:00
Bence Molnar 3427a6ec76 MDL-68733 quiz editing: be more careful deleting random question tags 2020-05-19 11:10:04 +01:00
Tim Hunt ea5c0c6b61 MDL-68733 question behat: question tag generator and use in quiz test 2020-05-19 11:10:03 +01:00
Ferran Recio fcbc4ccee6 MDL-67700 message: correcting conversation timer reset 2020-05-19 09:58:17 +02:00
Jun Pataleta dd293c28e1 Merge branch 'MDL-68528-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-05-19 11:45:55 +08:00
Andrew Nicols 79c6d0a453 MDL-68528 js: Normalise core component for template strings 2020-05-19 11:37:55 +08:00
Andrew Nicols 1ac5b70c5a MDL-68528 js: Normalise empty component to "core" for string 2020-05-19 11:34:59 +08:00
AMOS bot 9b38e44dfb Automatically generated installer lang files 2020-05-19 00:07:24 +00:00
Sara Arjona 57382b0e5e Merge branch 'MDL-68760_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-05-18 20:33:19 +02:00
Sara Arjona 2d2e93c6c6 Merge branch 'MDL-68728-38-2' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-05-18 20:23:47 +02:00
Tim Hunt e23b038479 MDL-68760 timezones: add string for new timezone America/Nuuk 2020-05-18 17:32:13 +01:00
Tim Hunt a2defe29c4 MDL-68760 string tests: make test_timezone_lang_strings message helpful 2020-05-18 17:32:12 +01:00
Marina Glancy aecc9e7170 MDL-68099 gradereport_grader: prevent exception without groups 2020-05-18 15:19:05 +02:00
Andrew Nicols a30ff32351 Merge branch 'MDL-68503_38_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_38_STABLE 2020-05-18 20:31:28 +08:00
Sara Arjona 1b34fbb716 Merge branch 'MDL-68253-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-05-18 13:56:43 +02:00
Adrian Perez 69e2477f90 MDL-67126 assign: set completion state for all group members 2020-05-18 12:25:57 +02:00
Andrew Nicols bca7a73d14 MDL-68728 calendar: Pending promises for event summary 2020-05-18 13:32:42 +08:00
AMOS bot c27c7abb6b Automatically generated installer lang files 2020-05-18 00:07:46 +00:00
AMOS bot 82d46e5037 Automatically generated installer lang files 2020-05-17 00:07:17 +00:00
Luca Bösch 4853c245c5 MDL-68253 mod_book: Remove prev arrow on the firstmost page. 2020-05-15 12:17:52 +02:00
Eloy Lafuente (stronk7) 4d56bb43b3 weekly release 3.8.3+ 2020-05-15 11:07:01 +02:00
Andrew Nicols 0cbb91e4c0 Merge branch 'MDL-66917-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-05-15 10:55:05 +08:00
Eloy Lafuente (stronk7) 2ef16003f1 Merge branch 'MDL-68677-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-05-15 02:00:39 +02:00
Andrew Nicols 80787a98b3 MDL-68677 core: Correct usage of templaterev for caching templates
The M.cfg.templaterev variable should only be used to present persistent
caching, not caching of content within the same page load.

Preventing caching of same-page content makes it difficult to develop
for real user experiences as content is slow to load and does not give a
realistic and consistent loading experience.

This change affects the loading of partials specifically which notably
includes the loading spinner. Without this patch the loading icon is
often not seen at all because it does not load in a timely fashion and
the content being loaded is loaded first.
2020-05-15 07:55:59 +08:00
Eloy Lafuente (stronk7) 698f0cff54 Merge branch 'MDL-68084-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-05-15 01:30:52 +02:00
Sara Arjona 0e73dacaaf Merge branch 'MDL-68200-38-take2' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-05-14 13:12:50 +02:00
Jake Dallimore 2ba93cc439 Merge branch 'MDL-68631_38' of https://github.com/jonof/moodle into MOODLE_38_STABLE 2020-05-13 09:25:22 +08:00
Paul Holden cd0af947a7 MDL-68084 blocks: check capability before getting content.
Some blocks (e.g. Calendar) load additional JS modules when returning
content. We need to make sure they aren't asked to generate content
unless the user can actually view the block, or the expected content
required by the JS will not exist in the DOM and can cause exceptions.
2020-05-12 19:21:35 +01:00
Sara Arjona 9b2253898a weekly release 3.8.3+ 2020-05-12 14:16:49 +02:00
Shamim Rezaie a81508489d MDL-68200 core: Fix phpdoc for the external return functions 2020-05-12 15:07:23 +10:00
Shamim Rezaie 3ec67cf4bb MDL-68200 core: Fix datetime format
date.toISOString() prints out the seconds as well.
Current code supports most valid values for the datetime attribute
2020-05-12 15:07:23 +10:00
Shamim Rezaie 365bfab967 MDL-68200 mod_forum: fix invalid format of the time tag on modern view 2020-05-12 15:07:23 +10:00
Shamim Rezaie a8b4b9f407 MDL-68200 mod_forum: Fix the invalid date format in the time tags 2020-05-12 15:07:23 +10:00
Jun Pataleta c59656006b MDL-68200 mod_forum: Use core/time_element for the discussion list page 2020-05-12 15:05:04 +10:00
Jun Pataleta 84d550cacb MDL-68200 core: Add new time_element template 2020-05-12 15:05:04 +10:00
Jun Pataleta b238304072 MDL-68200 core: Support fixday/hour for core/user_date's get() method 2020-05-12 15:05:04 +10:00
Jun Pataleta 10127ac33d MDL-68200 core: Support fixday/hour for core_external::get_user_dates() 2020-05-12 15:05:04 +10:00
Shamim Rezaie 6a7350d44b MDL-68200 core: Add calendartype param to user_date.loadDatesFromServer 2020-05-12 15:05:03 +10:00
Shamim Rezaie ed19fe85e4 MDL-68200 core: Add type param to core_get_user_dates external function 2020-05-12 15:05:03 +10:00
Shamim Rezaie bd76f0bb66 MDL-68200 mod_forum: remove address tags
Reasons:
- The element “h4” must not appear as a descendant of the “address” element
- This element should not contain more information than the contact
information, like a publication date (which belongs in a <time> element)
 element)
2020-05-12 15:02:05 +10:00
Shamim Rezaie c78ebc9586 MDL-68200 mod_forum: single discussion to follow nestet_v2 display rules 2020-05-12 15:02:05 +10:00
Shamim Rezaie d2886d283a MDL-68200 theme_boost: workaround for IE for flexbox not filling height
read more:
https://philipwalton.com/articles/normalizing-cross-browser-flexbox-bugs/
2020-05-12 15:02:05 +10:00
Eloy Lafuente (stronk7) 3ab743dcd9 Merge branch 'MDL-68579-38' of git://github.com/cescobedo/moodle into MOODLE_38_STABLE 2020-05-11 23:14:10 +02:00
Brendan Heywood 6f0506fa9d MDL-68276 admin: Skip risky tables and columns in db_replace 2020-05-11 23:11:46 +02:00
Jun Pataleta 2faa47c934 Merge branch 'MDL-66109-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-05-12 00:03:10 +08:00
Mihail Geshoski 6c86327b33 MDL-68576 filepicker: Cover in behat file edition in filemanager
The added behat tests would also confirm whether the behaviour of
a click action on a file using different views in the filemanager
is consistent.
2020-05-11 16:35:09 +02:00
Mihail Geshoski 6619bdf99d MDL-68576 filepicker: Cover in behat file selection from filepicker
The added behat tests would cover the issue in MDL-68576. They test
whether the behaviour of a click action on a file using different
views in the filepicker is consistent.
2020-05-11 16:34:59 +02:00
cescobedo 74860627f2 MDL-68579 core_h5p: Add a check to avoid execute task using BEHAT 2020-05-11 10:15:01 +02:00
Andrew Nicols 738da05555 MDL-66109 js: Built file changes from new Node version 2020-05-11 10:53:49 +08:00
Andrew Nicols 9c07f29d8e MDL-66109 js: Fix circular dependency in Shifter dependency
Shifter is using an ancient and no-longer supported of Istanbul. That
version contains a circular dependency whereby it fetches the version
from the index that included the file in the first place.  This throws a
warning on newer versions of Node.

The fix here is simple and intended to be the bare minimum to remove
these warnings anad resolve the issue.

We have forked the istanbul project and created a v0.1.37_moodle branch
at the root version of the Istanbul version that Shifter uses (v0.1.37
tag). The circular dependency is then addressed and a new tag created.

I have then forked Shifter, pointing its package.json at the tar.gz
download of that new tag and pushed a new branch and tag for that fix.

Following this our own package.json is updated to point to the tar.gz
version of the new Shifter tag.
2020-05-11 10:53:48 +08:00
Andrew Nicols ed68a025ef MDL-66109 js: Upgrade to latest stable version of NodeJS
Version 14.0.0 has just been released as stable, and will make its way
to an LTS release which will be supported until 30th April 2023.

At time of writing it is the "Current stable" release and will remain in
this phase until 20th October 2020, at whciih point it will transition
to LTS status.
2020-05-11 10:53:48 +08:00
Eloy Lafuente (stronk7) 5afef2670e Moodle release 3.8.3 2020-05-09 20:05:41 +02:00
Eloy Lafuente (stronk7) fda378562d weekly release 3.8.2+ 2020-05-08 13:30:01 +02:00
Eloy Lafuente (stronk7) 5edc307f7a Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-05-08 13:29:59 +02:00
Jake Dallimore 8f17c2f11c Merge branch 'MDL-51694-38' of https://github.com/MartinGauk/moodle into MOODLE_38_STABLE 2020-05-08 11:22:55 +08:00
Eloy Lafuente (stronk7) b8b889c7c9 Merge branch 'MDL-68443-xmldb-path-validation-MOODLE_38_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_38_STABLE 2020-05-07 19:16:54 +02:00
Paul Holden 2b188d2299 MDL-68415 core: test attachments in email_to_user from allowed paths. 2020-05-07 18:40:56 +02:00
fujiwara 926277865c MDL-68415 email: Fix attachment in email_to_user() 2020-05-07 18:40:49 +02:00
Tim Schroeder 1f59f848d7 MDL-68629 mod_choice: multilang coursename support 2020-05-07 15:47:53 +02:00
Jake Dallimore b6dfd9d89e Merge branch 'MDL-62403-38' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-05-07 14:19:09 +08:00
Simey Lameze 837651249b MDL-62403 portfolio: add upgrade notes for google docs 2020-05-07 13:06:35 +08:00
Ryan Wyllie c4015ffff4 MDL-62403 portfolio: create directories for google drive export
I've modified the Google Drive portfolio export so that it creates a
root directory in Drive for all of the files in the export. This allows
each export to be contained from each other to help with clashing file
names.

Additionally, the paths for the exported files will now be created in
Drive so that exported files are in the correct directory structure.
This is important for forum posts exports which assume a certain
directory structure in the export.
2020-05-07 12:43:14 +08:00
Jun Pataleta 91d3e7a632 MDL-68355 gradingform_guide: Improve lang strings 2020-05-07 11:50:48 +08:00
Jonathon Fowler b9fc865245 MDL-68631 cron: ensure the cron user is reset between scheduled tasks 2020-05-07 13:26:51 +10:00
Andrew Nicols 0bda145eaa Merge branch 'MDL-68556-38-pluginscheckcss' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-05-07 09:14:01 +08:00
Paul Holden fadae3cfe9 MDL-68410 mod_scorm: safer status operator comparison. 2020-05-07 09:03:09 +08:00
Ferran Recio 8aa0b41e9b MDL-68430 filter_mathjaxloader: update default CDN to 2.7.8 2020-05-06 11:14:22 +02:00
Jun Pataleta e247ec921a Merge branch 'MDL-68402_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-05-06 17:04:35 +08:00
Tim Hunt 1673baf5dd MDL-68402 accesslib: fix coding style of loops 2020-05-06 09:59:55 +01:00
Tim Hunt 7172233782 MDL-68402 accesslib: Modernise coding style in the functions changed 2020-05-06 09:59:54 +01:00
Tim Hunt 4508f85b7b MDL-68402 accesslib: fix get_with_capability_join logic
In fact, rather than fix the old logic, I noticed that the correct
logic was already implemented in get_users_by_capability. So, I
refactored to extract the working version into a function, which it
turns out can have exactly the same API as get_with_capability_join,
which was convenient.
2020-05-06 09:59:54 +01:00
Jake Dallimore bd0a6a98b8 Merge branch 'MDL-68293-38' of git://github.com/jleyva/moodle into MOODLE_38_STABLE 2020-05-06 12:53:38 +08:00
Jun Pataleta 9ae897f9c9 Merge branch 'MDL-68301-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-05-06 10:32:49 +08:00
Andrew Nicols 02e93de9e1 Merge branch 'MDL-63609-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-05-06 08:51:48 +08:00
Jake Dallimore 1b8bed6664 Merge branch 'MDL-68355-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-05-06 08:36:26 +08:00
AMOS bot 41c21d354e Automatically generated installer lang files 2020-05-06 00:13:12 +00:00
Eloy Lafuente (stronk7) b3c89dafd3 weekly release 3.8.2+ 2020-05-05 19:05:42 +02:00
Eloy Lafuente (stronk7) 9504266620 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-05-05 19:05:39 +02:00
Bas Brands f1dbea7200 MDL-68266 core_message: disable custom switches for behat testing 2020-05-05 14:20:10 +02:00
Andrew Nicols 18aa8915f0 Merge branch 'MDL-67881-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-05-05 11:18:20 +08:00
Jun Pataleta 6f869765b8 Merge branch 'MDL-68266-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-05-05 09:20:46 +08:00
Bas Brands ab320de86d MDL-68266 theme_boost: behat enable custom switches 2020-05-05 09:12:14 +08:00
AMOS bot 871291264b Automatically generated installer lang files 2020-05-05 00:11:34 +00:00
Eloy Lafuente (stronk7) cfab3a6e6c Merge branch 'MDL-52904-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-05-04 22:32:16 +02:00
Martin Gauk b1345143ea MDL-51694 core_grades: use transactions when deleting 2020-05-04 12:48:10 +00:00
Sara Arjona 11e2fc4b0a Merge branch 'MDL-68315-MOODLE_38_STABLE' of https://github.com/kabalin/moodle into MOODLE_38_STABLE 2020-05-04 10:37:30 +02:00
Andrew Nicols 3cc76c335a Merge branch 'MDL-68266-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-05-04 15:33:33 +08:00
Bas Brands 5190632f6b MDL-68266 core_course: accessibility improvements for course managent
colour contrast improvements
use custom checkboxes
use accessible colour for text-muted
2020-05-04 09:12:15 +02:00
David Saylor 8a29ee1722 MDL-52904 completion: reference context in cron query
Co-authored-by: Barbara Lawrence <blawrence@harlow-college.ac.uk>
2020-05-04 09:58:06 +08:00
Jun Pataleta 2ddc2e8430 MDL-52904 completion: Unit tests for daily completion task 2020-05-04 09:58:06 +08:00
Andrew Nicols f6f68bd59f Merge branch 'MDL-66263_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-05-03 20:23:26 +08:00
Andrew Nicols f2e7e84f0e Merge branch 'MDL-68509-38' of https://github.com/Dagefoerde/moodle into MOODLE_38_STABLE 2020-05-03 19:54:49 +08:00
Eloy Lafuente (stronk7) 577e336927 MDL-66263 travis: Simple bump to php74
Also update a couple of places (mysql, node)
that were not runnig really on highest. Now they are.
2020-05-02 17:19:23 +02:00
Eloy Lafuente (stronk7) 69ae995d5c weekly release 3.8.2+ 2020-05-02 16:36:42 +02:00
Eloy Lafuente (stronk7) 2fba5aee43 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-05-02 16:36:38 +02:00
Andrew Nicols 2564088c4c Merge branch 'MDL-68492-m38' of https://github.com/sammarshallou/moodle into MOODLE_38_STABLE 2020-05-01 12:07:23 +08:00
Andrew Nicols 91d3dc31a6 Merge branch 'MOODLE_38_MDL-67540' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2020-05-01 11:21:16 +08:00
Andrew Nicols f0e452240e Merge branch 'MDL-57680_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-05-01 11:06:58 +08:00
Eloy Lafuente (stronk7) 01ee979b0e Merge branch 'MDL-68427-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-04-30 23:35:23 +02:00
Jun Pataleta d9245d6f87 Merge branch 'MDL-68404-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-04-30 13:32:57 +08:00
Jun Pataleta c9d9fb3ff7 Merge branch 'MDL-68309-38' of https://github.com/snake/moodle into MOODLE_38_STABLE 2020-04-30 09:57:37 +08:00
AMOS bot 3c67ae2c14 Automatically generated installer lang files 2020-04-30 00:11:57 +00:00
Eloy Lafuente (stronk7) 6fc1bf6646 Merge branch 'MDL-68434-38-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-04-29 22:52:51 +02:00
David Mudrák ece9b780d5 MDL-68434 lang: Use the updated terminology in the tests 2020-04-29 17:47:36 +02:00
David Mudrák 0bfb8c4d83 MDL-68556 admin: Fix some minor styling issues on the plugins check page
The patch fixes missing space around elements and some other minor
visual issues detected. This was a good opportunity to get rid of custom
CSS rules and use the native bootstrap classes and utilities.
2020-04-29 14:33:33 +02:00
Dan Marsden d95f185556 MDL-67497 lib: backuptargetimport should be set as captype:read 2020-04-29 08:14:45 +12:00
Helen Foster 53611ca744 MDL-68434 lang: Import fixed English strings (en_fix)
Significant string changes:

* pluginnamesummary,qtype_ddimageortext and
  pluginnamesummary,qtype_ddmarker - Note about the question type not
  being accessible to visually impaired users
2020-04-28 15:35:48 +02:00
Andrew Nicols a56ecac082 Merge branch 'MDL66035_38_STABLE' of https://github.com/jwalits/moodle into MOODLE_38_STABLE 2020-04-28 20:04:43 +08:00
Luca Bösch 8f15f3e753 MDL-68404 gradingform_rubric: Style "Add level" button. 2020-04-28 14:04:07 +02:00
Andrew Nicols 23cd7eb539 Merge branch 'MDL-68445_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-28 18:31:11 +08:00
Julien Boulen af9bf5f609 MDL-68137 core_files: replace consecutive dots in filename by single dot 2020-04-28 11:29:52 +02:00
Eloy Lafuente (stronk7) d946fcd870 weekly release 3.8.2+ 2020-04-28 11:15:30 +02:00
Eloy Lafuente (stronk7) 7a53f91feb Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-04-28 11:15:27 +02:00
Andrew Nicols 74b553af3e Merge branch 'MDL-68525-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-04-28 10:22:24 +02:00
Andrew Nicols 1cbf0b9513 Merge branch 'MDL-66259_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-28 10:22:21 +02:00
Andrew Nicols d75dd9318a Merge branch 'MDL-67316_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-28 10:22:18 +02:00
Andrew Nicols 6d9c9e24a4 Merge branch 'MDL-68047_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-28 10:22:15 +02:00
Eloy Lafuente (stronk7) 7d599aeea4 MDL-68525 behat: chrome/switches caps not allowed in Chrome > 81
Now we need to use extra_capabilities/chromeOptions/args instead

The former was deprecated long ago, it seems that Chrome 81 has
stopped accepting it. The later seems to be working at very least
since Chrome 76 (haven't gone further back).
2020-04-28 12:32:11 +08:00
Eloy Lafuente (stronk7) 65e1204528 Merge branch 'MDL-68393-38-availableupdateui' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-04-27 17:40:00 +02:00
Eloy Lafuente (stronk7) 055bd177fd Merge branch 'MDL-65967-38' of https://github.com/danielneis/moodle into MOODLE_38_STABLE 2020-04-27 17:31:29 +02:00
AMOS bot 0d4a715c46 Automatically generated installer lang files 2020-04-27 00:11:31 +00:00
Jwalit Shah 51c65d7bc5 MDL-66035 message: Restore missing message preferences files 2020-04-27 09:49:20 +10:00
Tim Hunt af64d73515 MDL-57680 form autocomplete: extend Behat tests 2020-04-26 15:11:52 +01:00
Tim Hunt 27e80b99b7 MDL-57680 form autocomplete: fix triggering change event 2020-04-26 14:21:19 +01:00
Tim Hunt 79542e4f11 MDL-57680 form autocomplete: let singleselects be cleared.
This was already working after ajax had refreshed the choices, it was just
broken on first page load.
2020-04-26 14:21:18 +01:00
Mikhail Golenkov a58cfea205 MDL-67540 quiz: Start transaction before selecting existing slots.
Co-authored-by: Conn <conn@cmrwarwicker.com>
2020-04-26 10:55:17 +10:00
Thiagolivramento 114d51f98b MDL-65967 tool_recyclebin: add recycle bin link to category edit menu 2020-04-24 17:08:33 -03:00
Eloy Lafuente (stronk7) 5ff9020fe3 MDL-68445 behat: Bump to 3.6.x
composer.lock generated with PHP 7.1, following:

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

Also, ensure Symfony/Process > 4.0 compatibility
(needed for parallel runs)
2020-04-24 15:57:12 +02:00
Eloy Lafuente (stronk7) 92deb62243 MDL-67316 ldap: Pass correct hex chars to hexdec()
Before php74 they were silently discarded, now they
show a deprecation message.
2020-04-24 15:56:46 +02:00
Eloy Lafuente (stronk7) f769b8f4d0 MDL-67316 typo3: Pass correct hex chars to hexdec()
Typo3 was relaying on the feature of base converter
functions silently removing invalid chars so, for example:

'U+00A0' => '00A0' => 160

Since php74, the existence of those invalid chars do produce
a deprecation warning, no matter the outcome continues being the same.

So, here, we are just converting that invalud 'U+' by '0x'
2020-04-24 15:56:46 +02:00
Tim Hunt bc113f89cc MDL-66259 qtypes: Add missing comment on get_random_guess_score
A bit off-topic for this issue number, but I noticed it while
working on this, and though it was not worth creating a
separate MDL for.
2020-04-24 15:56:31 +02:00
Tim Hunt f18b531639 MDL-66259 qtype_numerical: remove no-longer relevant todo I noticed 2020-04-24 15:56:31 +02:00
Eloy Lafuente (stronk7) a18a00bd2d MDL-66259 qtypes: get_question_options() always call parent::
To get the question->options initialised, children must
call parent::get_question_options() always. Also, it is
just general good practice. Subclasses are meant to be
adaptations of the base class, not something completely
different.

Note, there are some changes in the data structure
produced (see changes in the tests) but these changes
are not wrong.
2020-04-24 15:56:31 +02:00
Tim Hunt d37c61365a MDL-66259 quiz responses: fix unrealistic test setup 2020-04-24 15:56:31 +02:00
Eloy Lafuente (stronk7) 15ffdf736a MDL-66259 qtype: add tests to all remaining involved qtypes
That way we get the load_question_data() method covered
and all the main data, options, hints checked.
2020-04-24 15:56:31 +02:00
Tim Hunt 42eae914f1 MDL-66259 qtype_truefalse: unit test of loading questions from the DB
This is about to be changes, so we need a test first to catch regressions.
2020-04-24 15:56:31 +02:00
sam marshall 6effee8992 MDL-68492 Behat: Use faster direct link steps in lib/tests/behat 2020-04-24 12:08:14 +01:00
sam marshall eeef704d40 MDL-68492 Behat: Direct URL links for courses, activities 2020-04-24 12:08:14 +01:00
Tim Hunt f42b67ab2c MDL-68252 question tags: fix tag editing for missingtype questions 2020-04-24 11:26:39 +01:00
Tim Hunt 088d4309fe MDL-68252 question bank: for 'missingtype' questions, hide actions 2020-04-24 11:26:38 +01:00
Shamim Rezaie 4281fe1070 MDL-68509 core_ddl: Keep databasemeta cache after dropping temptables
Backport of MDL-58584 (934c2ee + 94e2509)
2020-04-24 11:05:59 +02:00
Jun Pataleta a6f315c1e7 weekly release 3.8.2+ 2020-04-24 09:41:12 +08:00
Jun Pataleta 094b66ea85 NOBUG: Fixed file access permissions 2020-04-24 09:41:11 +08:00
Jun Pataleta 8af31de77b Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-04-24 09:41:10 +08:00
Mark Johnson a84620c2d5 MDL-68503 user profile: Make sortorders relative to existing records 2020-04-23 15:55:53 +01:00
Eloy Lafuente (stronk7) 6da6114778 Merge branch 'MDL-67886_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-23 16:06:26 +02:00
Tim Hunt 59afcdd850 MDL-63812 qtype_gapselect: fix questions with non-consecutive gap nos 2020-04-23 14:41:38 +01:00
Tim Hunt 69b0bbde10 MDL-63812 qtype_gapselect: test data generator to standard qtype pattern 2020-04-23 14:41:37 +01:00
Eloy Lafuente (stronk7) 656a05bef8 MDL-67886 phpunit: Make tests cross-db
The suggested SQL in some of the assertions was not cross-db
but db-dependent. Now we just keep that part out from the
assertions, because it's not important to verify the
errors that are being asserted.
2020-04-23 12:30:17 +02:00
Andrew Nicols 76223a290d MDL-68427 core: Correct previous/next page in paging bar 2020-04-23 12:49:06 +08:00
Jun Pataleta 801c9c2717 Merge branch 'MDL-68351_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-23 11:17:27 +08:00
AMOS bot fc2497fbc5 Automatically generated installer lang files 2020-04-23 00:14:37 +00:00
Eloy Lafuente (stronk7) 6c73d86264 Merge branch 'MDL-67886_38' of git://github.com/mdjnelson/moodle into MOODLE_38_STABLE 2020-04-23 01:37:10 +02:00
Mark Nelson 3aa10ddd4f MDL-67886 core: check_database_schema() checks for missing indexes 2020-04-22 23:19:16 +02:00
Tim Hunt 660fa2871a MDL-57240 quiz: don't show useless links on overdue attempt summary page 2020-04-22 21:38:52 +01:00
Jun Pataleta 81c011d388 Merge branch 'MDL-68392_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-22 11:09:35 +08:00
Shamim Rezaie 24d7375f0f MDL-68312 grade: Fix empty links
If a link contains no text, the function or purpose of the link will not
be presented to the user. This can introduce confusion for keyboard and
screen reader users.
2020-04-22 04:33:05 +10:00
Shamim Rezaie 71caffb7e0 MDL-68312 output: Fix empty links
If a link contains no text, the function or purpose of the link will not
be presented to the user. This can introduce confusion for keyboard and
screen reader users.
2020-04-22 04:33:04 +10:00
Shamim Rezaie 04e9010c92 MDL-68312 gradereport_grader: Remove adjacent links to the same URL 2020-04-22 04:33:04 +10:00
Shamim Rezaie 9912c37afd MDL-68312 gradereport_grader: replace invalid label by aria-describedby
The for attribute of the label element should not refer to a non-hidden
form control.
2020-04-22 04:33:04 +10:00
Shamim Rezaie d37757abf1 MDL-68312 gradereport_grader: Use caption instead of summary in table
The summary attribute on the table element is obsolete.
2020-04-22 04:33:04 +10:00
Shamim Rezaie f9b144d6bf MDL-68343 gradereport_singleview: Remove adjacent links to the same URL 2020-04-22 04:31:06 +10:00
Shamim Rezaie 85bf5b2e2c MDL-68343 gradereport_singleview: Use caption instead of summary
The summary attribute on the table element is obsolete.
2020-04-22 04:31:06 +10:00
Shamim Rezaie cc36c39b46 MDL-68343 gradereport_singleview: fix empty links 2020-04-22 04:31:06 +10:00
Shamim Rezaie 5d2be187a2 MDL-68343 gradereport_singleview: Only output label tag if label exists
This also fixes the issue of having multiple form labels for a single
element.
2020-04-22 04:31:06 +10:00
Shamim Rezaie 10bc73d5b6 MDL-68343 output: fix html table structure
A <th> that contains no text may result in cells with missing or
incorrect header information. WAVE advises that we should make a cell
a <td> rather than a <th> if the cell must remain empty (such as the
top-left cell in a data table).

Also note that the scope attribute is only valid for <th>
2020-04-22 04:31:06 +10:00
Paul Holden bde34b41f8 MDL-63609 media_videojs: support Youtube URL start time. 2020-04-21 14:45:53 +01:00
Paul Holden 80827f076c MDL-62853 privacy: sanitize subcontext paths. 2020-04-21 14:38:14 +01:00
Paul Holden 059f402a51 MDL-66917 admin: validate uploaded plugin version.
Prevent overwriting current plugins with older versions of themselves.
2020-04-21 14:36:18 +01:00
Jun Pataleta 9116fd6e97 Merge branch 'MDL-68356-38' of git://github.com/cescobedo/moodle into MOODLE_38_STABLE 2020-04-21 09:25:10 +08:00
Jun Pataleta 06fe619327 Merge branch 'MDL-68339_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-20 21:52:49 +08:00
Bas Brands fe2fc1c79b MDL-67881 core_message: fix tab order for message drawer 2020-04-20 12:03:06 +02:00
AMOS bot 78939c0069 Automatically generated installer lang files 2020-04-19 00:13:19 +00:00
Brendan Heywood db94d504f7 MDL-68443 xmldb: Improve path validation on view_xml action 2020-04-18 20:50:41 +10:00
Andrew Nicols cba151a391 Merge branch 'MDL-67317_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-17 18:36:15 +08:00
cescobedo 00de69b59f MDL-68356 core_h5p: Fix h5p mimetype
Add a correct mime type for h5p files and update existing
mime type for stored h5p files.
2020-04-17 09:07:17 +02:00
AMOS bot 072050567a Automatically generated installer lang files 2020-04-17 00:16:18 +00:00
Eloy Lafuente (stronk7) 76b745e76a MDL-67317 behat: Bump to 3.38.4 moodle-behat-extension
It comes with behat/mink 1.8.x that provides php74 compatibility.

lock file generated with php71 (min version supported by the branch)
2020-04-16 20:28:56 +02:00
Eloy Lafuente (stronk7) cd93d0b9cf MDL-67317 behat: Ensure that on every scenario we have a session.
Before Mink 1.8.0, any call to getSession() used to auto-start
the session if it was not avaliable there. That always has been
an unsupported detail.

With https://github.com/minkphp/Mink/pull/705 new sessions aren't
auto-created anymore.

And we were relying on that.

So this is, simply about to explicitly create the new session
in our before_scenario stuff, to guarantee that it's always there.
2020-04-16 20:28:56 +02:00
Shamim Rezaie 11278ad7a3 MDL-68351 libraries: Update the upgrade instructions
Backport of MDL-67374
2020-04-16 20:28:41 +02:00
Shamim Rezaie d9c1feece4 MDL-68351 libraries: Upgrade SimplePie to version 1.5.3
Backport of MDL-67374
2020-04-16 20:28:41 +02:00
Eloy Lafuente (stronk7) 35bf8e5c25 MDL-68339 message: move array_key_exists() to property_exists()
Towards PHP 7.4 compliance:

array_key_exists(): Using array_key_exists() on objects is
deprecated. Use isset() or property_exists() instead
2020-04-16 20:28:30 +02:00
Eloy Lafuente (stronk7) 666cc20c30 weekly release 3.8.2+ 2020-04-16 19:34:28 +02:00
Eloy Lafuente (stronk7) e0fd39791c Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-04-16 19:34:23 +02:00
Juan Leyva dcc4bfa042 MDL-68293 mobile: Update language strings to mention new app plans
We need to update different language strings to let our site admins know about the new app restrictions
(for both features and user devices able to receive notifications)
2020-04-16 12:53:36 +02:00
Adrian Greeve d0323fb7c6 Merge branch 'MDL-68196-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-04-16 10:56:37 +08:00
Shamim Rezaie 0a9b84efff MDL-68196 core: not expand autocomplete elements too soon on IE 2020-04-16 12:19:00 +10:00
Eloy Lafuente (stronk7) f8c8576f63 Merge branch 'MDL-66849-M38' of https://github.com/ised-isde-canada/moodle into MOODLE_38_STABLE 2020-04-16 01:02:53 +02:00
Eloy Lafuente (stronk7) 14a4038810 Merge branch 'MDL-68323-38' of git://github.com/marinaglancy/moodle into MOODLE_38_STABLE 2020-04-16 00:53:58 +02:00
Eloy Lafuente (stronk7) d6347d8c3c Merge branch 'MDL-68279-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-04-16 00:33:19 +02:00
Eloy Lafuente (stronk7) 29dccc952c Merge branch 'MDL-68189-m38' of https://github.com/NeillM/moodle into MOODLE_38_STABLE 2020-04-16 00:13:42 +02:00
Eloy Lafuente (stronk7) 100c569431 Merge branch 'MDL-68280-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-04-16 00:10:48 +02:00
Sara Arjona b1c442ccc4 Merge branch 'MDL-67751-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-04-15 17:57:13 +02:00
Jun Pataleta e45c2fd424 Merge branch 'MDL-66200-MOODLE_38_STABLE_gradebook_csv_import' of https://github.com/jwalits/moodle into MOODLE_38_STABLE 2020-04-15 23:17:50 +08:00
Paul Holden 7ada02755d MDL-67751 course: include inline folders in list of resources. 2020-04-15 13:59:41 +01:00
Eloy Lafuente (stronk7) f7c1752fb3 Merge branch 'MDL-67499-38' of git://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-04-15 12:49:42 +02:00
Bas Brands 210794be38 MDL-68301 theme_boost: move course format css
this reduces duplication of css in format_topic
and format_weeks
2020-04-15 09:53:06 +02:00
Adrian Greeve 6278b8af59 Merge branch 'MDL-67663-38-3' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-04-15 13:23:12 +08:00
Michael Milette 9ff584a1e9 MDL-66849 output: Remove custom menu title when not specified 2020-04-14 22:24:13 -04:00
Jun Pataleta 194a801160 Merge branch 'MDL-68405-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-04-14 16:09:24 +08:00
Andrew Nicols 5af33db074 MDL-68405 js: Ensure correct exit code for gherkinlint 2020-04-14 15:09:48 +08:00
AMOS bot 052c43eec9 Automatically generated installer lang files 2020-04-11 00:11:54 +00:00
AMOS bot f43c324b0b Automatically generated installer lang files 2020-04-11 00:11:54 +00:00
David Mudrák 64bff8a106 MDL-68393 admin: Fix some minor styling issues on the notifications page
The patch makes the available update information elements more
distinguishable, the Download button more prominent, and the Check for
available update button better aligned. It reduces the space between
multiple available Moodle updates, too.
2020-04-10 14:41:13 +02:00
Eloy Lafuente (stronk7) 6090492eec Merge branch 'MDL-67919-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-04-10 11:55:30 +02:00
Eloy Lafuente (stronk7) 3d94784459 Merge branch 'MDL-67910-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-04-10 11:36:42 +02:00
Luca Bösch 4e445b9709 MDL-68392 travis: Fix validation warnings and infos
Can verify that this file passes the validation @
https://config.travis-ci.com/explore
2020-04-10 00:14:08 +02:00
Jun Pataleta 706f17d90f MDL-68355 gradingform_guide: Fix accessibility issues
* Add sr-only label for criterion information.
* Add sr-only label for frequently used comments picker button.
* Removed unused string grade_help.
* Fixed tags for hidden help texts, changing them from <small> to <span>
* Added aria-label for the score and additional comments fields so that
  the user would know which criterion they are currently working on.
* Added score_help and remark_help lang strings for more description
  for the score and additional comments fields.
* Remove text-muted class for additional comments' field label to avoid
  colour contrast issues.
2020-04-09 21:46:08 +08:00
Jun Pataleta de7c77913c MDL-67663 mod_forum: Show/hide elements from screen reader on search
* When the search input gets shown, users can still navigate on the
close button and the grading status container which can cause confusion
among users. So hide and show them accordingly as well.
* Hide/show user picker and body container when the search results
container is shown/hidden.
2020-04-09 21:44:28 +08:00
Jun Pataleta 485917574e MDL-67663 core: Do not use aria-hidden="false" on drawer
From https://www.w3.org/TR/wai-aria-1.1/#aria-hidden:
* "aria-hidden="false" is known to work inconsistently in browsers"
2020-04-09 21:44:28 +08:00
Jun Pataleta c20f4f5efd MDL-67663 mod_forum: Add missing lang strings 2020-04-09 21:44:28 +08:00
Jun Pataleta 8896d073e2 MDL-67663 mod_forum: Designate forum grading landmark regions
Adding the following landmark regions for easier keyboard navigation:
* Forum grading navigation
* User's forum posts
* Forum grading panel
2020-04-09 21:44:28 +08:00
Jun Pataleta c08eb88ae9 MDL-67663 mod_forum: Use proper lang string for aria-label
Use a proper language string for the aria-label of the hide grader
panel button instead of a hard-coded one.
2020-04-09 21:44:28 +08:00
Jun Pataleta dceb61ac68 MDL-67663 mod_forum: Fix focus order of the grading form
* Focus should flow from the form header down to the forum posts, and
then to the grading panel itself.
2020-04-09 21:44:28 +08:00
Jun Pataleta 79d668fc8f MDL-67663 mod_forum: Make user switching more accessible
* Add a more descriptive label for the next and previous buttons so that
the users would know that clicking on the next or previous buttons will
save the changes they made before proceeding to the next user.
* Add an sr-only div with aria-live to the user picker to let the grader
know the current user that is being graded.
* Hide the user picture from screen readers
2020-04-09 21:44:27 +08:00
Jwalit Shah 305060c055 MDL-66200 gradebook: check selected feedback option when importing data 2020-04-09 11:00:49 +10:00
Sara Arjona 49f07dc861 weekly release 3.8.2+ 2020-04-08 16:24:48 +02:00
Sara Arjona d6e96f06cc Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-04-08 16:24:45 +02:00
Andrew Nicols 7d726708ff Merge branch 'MDL-68148-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-04-08 11:24:14 +08:00
Shamim Rezaie c332400ba6 MDL-68148 user: remove the noscript tag
The submit button remains deactive if js is disabled. So having a
noscript tag to output a submit button here does not make sense.
2020-04-08 11:44:28 +10:00
Shamim Rezaie 94a55738ad MDL-68148 user: fixed stray end tag (input) 2020-04-08 11:44:28 +10:00
Shamim Rezaie b77c5e78dc MDL-68148 core_user: avoid multiple enrol buttons with the same id 2020-04-08 11:44:28 +10:00
Shamim Rezaie 5dfebd739f MDL-68148 core_user: set the fullname column as the header column
ref: https://www.w3.org/WAI/tutorials/tables/
2020-04-08 11:44:28 +10:00
Shamim Rezaie cabbb145dd MDL-68148 output: type attribute is unnecessary for javascript resources 2020-04-08 11:44:28 +10:00
Shamim Rezaie 351262b192 MDL-68148 core: remove cellspacing
The cellspacing attribute of <table> is not supported in HTML5.
So the removed line did not have any effect since ages ago.
2020-04-08 11:44:28 +10:00
AMOS bot 74ff19965a Automatically generated installer lang files 2020-04-08 00:11:13 +00:00
AMOS bot c1159327b4 Automatically generated installer lang files 2020-04-08 00:11:12 +00:00
Sara Arjona b5c776a789 Merge branch 'MDL-40081-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-04-07 15:10:14 +02:00
Sara Arjona 0a92167603 Merge branch 'MOODLE_38_MDL-68223' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2020-04-07 13:43:03 +02:00
Sara Arjona 7cb0548c1b Merge branch 'MOODLE_38_MDL-65700' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2020-04-07 13:34:22 +02:00
Mikhail Golenkov 214542af79 MDL-65700 javascript: Add url-polyfill. 2020-04-07 20:56:46 +10:00
Andrew Nicols 6a0f166fef Merge branch 'MDL-68285-38' of git://github.com/cescobedo/moodle into MOODLE_38_STABLE 2020-04-07 13:43:06 +08:00
Sara Arjona c904d2249f Merge branch 'MDL-65539-m38' of https://github.com/NeillM/moodle into MOODLE_38_STABLE 2020-04-06 16:42:10 +02:00
Paul Holden 63cf950324 MDL-40081 completion: clean up criteria records for deleted courses. 2020-04-06 12:21:57 +01:00
Paul Holden 5a63310250 MDL-67499 restore: account for deleted user truncated email/username. 2020-04-06 12:09:54 +01:00
Eloy Lafuente (stronk7) 98014f03cd MDL-67499 restore: add 100% cov. to restore_dbops::precheck_user()
Supports multiple mails to be tested.

So we can perform changes to it and also some related stuff,
like delete_user() with confidence.
2020-04-06 11:48:36 +01:00
Paul Holden 80a8c362ea MDL-67499 user: truncate long username/email during user deletion. 2020-04-06 11:48:36 +01:00
Paul Holden 42396a33e9 MDL-68280 user: fix PHP notice for unknown user invalid login token. 2020-04-06 11:46:17 +01:00
Paul Holden 46a290b1b9 MDL-68279 admin: filter site fullname when sending test email. 2020-04-06 11:41:26 +01:00
Sara Arjona edb85411b8 Merge branch 'MDL-68239-38' of https://github.com/NinaHerrmann/moodle into MOODLE_38_STABLE 2020-04-06 10:18:40 +02:00
Jake Dallimore b90f72b304 MDL-68309 overrides: clarify inactive overrides help string 2020-04-06 07:38:21 +08:00
Eloy Lafuente (stronk7) 11b3c817a5 MDL-68047 tcpdf: Prevent images out from cache to be removed
This corresponds to https://github.com/tecnickcom/TCPDF/pull/174
(and was fixed bycommit 510070b) and was a regression causing
image files to be removed unconditionally. Only if the images
are from cache, they can be removed.

It's fixed upstream in version 6.3.4 and up.
2020-04-06 00:31:02 +02:00
Sara Arjona bcd723cf97 MDL-67919 dataprivacy: Fix behat error when contacting DPO 2020-04-03 19:49:43 +02:00
Ruslan Kabalin 13413304ef MDL-68315 formslib: Fix completion attribute in course form element.
This fixes 'onlywithcompletion' attribute in course form element.
2020-04-03 16:15:22 +01:00
n_herr03 39bf9c63e6 MDL-68239 mod_data: make required icon in multimenu visible 2020-04-03 12:21:04 +02:00
Neill Magill 8d6234bedc MDL-65539 dragdrop: Ignore drag proxy in keyboard menu
Before this change the node that is displayed during a the last mouse
drag and drop would be listed in a keyboard drag and drop if it was
the container node of one of the types of node being moved in this action.

If a node is inside a node with the .yui3-dd-proxy class then it is
one of the proxy elements used to display the dragged content during
mouse drag and drop so we will start ignoring it.
2020-04-03 08:37:47 +01:00
Neill Magill a7ac45bc7d MDL-65539 dragdrop: Allow sections and blocks to move to the top
Before this change sections and blocks could not be moved to be the
top item when using keyboard drag and drop.

They can now be moved to the top in one action.

The way they move using keyboard drag and drop has changed when they
are below the item they are dropped on, not instead of appearing
below it they will be placed above it.
2020-04-03 08:37:47 +01:00
Neill Magill 1170bb3465 MDL-65539 dragdrop: Allow direction detection when using keyboard
Before this change keyboard drag and drop could not detect the
direction of movement, this meant that an item would only be placed
below an item or at the top of a container item.

This change means that extending modules can declare
detectkeyboarddirection to true. This will mean that when an item is
moved it's position will be determined by the direction of travel as
it would be when dragging using the mouse.

If detectkeyboarddirection is true then:

* If you move an item upwards it will be placed before the item
  selected in the drop menu
* If you move a item downwards it will be placed after the item
  selected in the drop menu
* The item above the one being dragged will now be displayed on
  the drop menu

If detectkeyboarddirection is false there will be no change in
behaviour.
2020-04-03 08:37:46 +01:00
Neill Magill a8c0956b22 MDL-65539 course: Keyboad drag and drop should not break page
Before this change keyboard drag and drop of sections would alter
the structure of the page.

This occured because in this case the dragnode was the original node
2020-04-03 08:37:46 +01:00
Neill Magill 231d5161d6 MDL-65539 formats: Section labels not updated during move
Before this change when moving a section via drag and drop the
aria-label for the section was not being updated neither was the
title on the drag handle.

The result was the the drop menu on keyboard drag and drop displayed
the wrong information after a section was moved.
2020-04-03 08:37:46 +01:00
Neill Magill 96988de3ff MDL-68189 course: Section name change should display in DD menu
Before this patch if a section was renamed inline the old name was
still displayed in the keyboard drag and drop menu until the page
was refreshed.

This change ensures that the two places that section names were not
updated in get changed after an inline update to the name.
2020-04-03 08:37:26 +01:00
Sara Arjona 255b396328 weekly release 3.8.2+ 2020-04-02 16:51:17 +02:00
Sara Arjona 525688f879 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-04-02 16:51:14 +02:00
Marina Glancy 8effb03227 MDL-68323 core: add --max-lint-warnings option to grunt 2020-04-02 13:44:46 +02:00
Luca Bösch 0b4ac78d6d MDL-67672 user: Display name in user menu as elsewhere. 2020-04-02 00:17:41 +02:00
Eloy Lafuente (stronk7) 9c42bab6bc Merge branch 'MDL-68265-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-04-01 23:29:21 +02:00
Eloy Lafuente (stronk7) 4ea9f5d7db Merge branch 'MDL-68193_38' of git://github.com/mdjnelson/moodle into MOODLE_38_STABLE 2020-04-01 23:22:35 +02:00
Mark Nelson 390a7cc8d2 MDL-68193 core: added new database_text_field_content_replaced event 2020-04-01 23:20:54 +02:00
Eloy Lafuente (stronk7) b3c6d95eee Merge branch 'MDL-68191_38' of git://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-04-01 20:18:34 +02:00
Eloy Lafuente (stronk7) c0c6ffd9d5 Merge branch 'MDL-67995-38' of git://github.com/cescobedo/moodle into MOODLE_38_STABLE 2020-04-01 19:11:50 +02:00
Jake Dallimore 8cee84e682 Merge branch 'MDL-67672-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-04-01 16:43:28 +08:00
Sara Arjona 97d21f097d Merge branch 'MDL-68281_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-04-01 09:25:25 +02:00
Sara Arjona aefb25dae5 Merge branch 'MDL-68277_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-04-01 09:14:47 +02:00
Luca Bösch b16cd34860 MDL-67672 user: Display name in user menu as elsewhere. 2020-04-01 09:03:39 +02:00
Sara Arjona 795a11a328 Merge branch 'MDL-58964-38' of git://github.com/abias/moodle into MOODLE_38_STABLE 2020-03-31 19:13:44 +02:00
Eloy Lafuente (stronk7) f9ecf3d3af Merge branch 'MDL-64494-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-03-31 18:59:24 +02:00
Bas Brands 463ad12363 MDL-64494 theme_boost: accessible theme colours 2020-03-31 18:54:19 +02:00
Sara Arjona 3b1be8fb8f Merge branch 'MDL-66245-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-03-31 15:09:15 +02:00
Sara Arjona 3466e64d62 MDL-67910 behat: PendingJS improvements for deleteevent modal 2020-03-31 08:40:43 +02:00
Jake Dallimore b38841280d Merge branch 'MDL-68144-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-03-31 13:59:39 +08:00
Eloy Lafuente (stronk7) 81c8aee9f2 Merge branch 'MDL-68269-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-03-30 22:54:17 +02:00
Eloy Lafuente (stronk7) 1e1eed0aa4 Merge branch 'MDL-68049-38' of https://github.com/spvickers/moodle into MOODLE_38_STABLE 2020-03-30 16:23:27 +02:00
cescobedo d2791a63ec MDL-68285 core_h5p: Fix unused variables and undeclared globals 2020-03-30 11:37:59 +02:00
Andrew Nicols ecc9d9c48c Merge branch 'MDL-52319-38-environmentxml' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-03-30 16:54:37 +08:00
Shamim Rezaie 3999cbaa6a MDL-68269 form: fieldset in group elements should be full width 2020-03-30 18:32:39 +11:00
cescobedo 6e3dfc7927 MDL-67995 format_singleactivity: Fix dropwdown type of activity 2020-03-30 08:27:02 +02:00
Mikhail Golenkov 4a363544eb MDL-68223 assign: Fix selection of comment text. 2020-03-30 14:57:36 +11:00
Andrew Nicols 478c14d75d MDL-68265 core_question: Switch question import to request dir 2020-03-30 08:14:46 +08:00
Andrew Nicols 02ed9c4196 MDL-68265 mod_lesson: Switch question import to request dir 2020-03-30 08:14:46 +08:00
AMOS bot 7d4ade8bb1 Automatically generated installer lang files 2020-03-29 00:11:46 +00:00
Eloy Lafuente (stronk7) 3eeadb6ae2 MDL-68281 unit test: Include required class
Also, add missing line break, that I did not see 1 week ago.
2020-03-28 16:27:29 +01:00
AMOS bot 548e3f2aef Automatically generated installer lang files 2020-03-28 00:11:38 +00:00
Tim Hunt 7e6d6f97aa MDL-68277 qtype_essay: answer area in reviews should be right size
The answer box size is set by teachers and provides a useful
visual cue how long a response was expected. Therefore, it is
useful to keep the space at least that size in quiz reviews, etc.
2020-03-27 14:12:37 +00:00
Luca Bösch 75532d2266 MDL-68144 mod_folder: make top margins less dominant for folder content 2020-03-27 07:12:54 +01:00
Jake Dallimore 49914a57d4 weekly release 3.8.2+ 2020-03-27 09:18:37 +08:00
Jake Dallimore c23192f642 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-03-27 09:18:36 +08:00
Eloy Lafuente (stronk7) fa33530059 Merge branch 'MDL-64429-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-03-26 18:38:18 +01:00
Paul Holden 02e24d7098 MDL-64429 tool_usertours: upgrade step to fix existing tours sortorder. 2020-03-26 16:48:56 +00:00
Eloy Lafuente (stronk7) 3d247d80bb Merge branch 'MDL-68183-38-mysqlpwdresetsql' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-03-26 01:18:20 +01:00
Eloy Lafuente (stronk7) 9f9134e1ae Merge branch 'MDL-63865-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-03-26 00:32:05 +01:00
Eloy Lafuente (stronk7) 39f07a058f Merge branch 'MDL-68116-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-03-26 00:28:11 +01:00
Eloy Lafuente (stronk7) 8d0fb6a548 Merge branch 'MDL-67442_38' of https://github.com/jonof/moodle into MOODLE_38_STABLE 2020-03-26 00:04:18 +01:00
Jun Pataleta 658624d7d0 Merge branch 'MDL-68149_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-03-26 00:09:38 +08:00
Jun Pataleta 4390cc47d9 Merge branch 'MDL-68153_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-03-25 22:34:27 +08:00
Jun Pataleta d89837abf6 Merge branch 'MDL-67024-38' of git://github.com/farhan6318/moodle into MOODLE_38_STABLE 2020-03-25 08:34:23 +08:00
Eloy Lafuente (stronk7) b669b3cb86 Merge branch 'MDL-67731-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-03-25 00:06:12 +01:00
Eloy Lafuente (stronk7) 570faa0c48 Merge branch 'MDL-67930-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-03-24 22:48:14 +01:00
Eloy Lafuente (stronk7) ed8046b929 Merge branch 'MDL-68068-38' of git://github.com/cescobedo/moodle into MOODLE_38_STABLE 2020-03-24 22:39:32 +01:00
Jake Dallimore c155794221 Merge branch 'MDL-68135-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-03-24 12:10:55 +08:00
AMOS bot c1707b2b50 Automatically generated installer lang files 2020-03-24 00:11:05 +00:00
Alexander Bias eaf3679e08 MDL-58964 navigation: Reindex array when element is removed 2020-03-23 21:36:13 +01:00
David Mudrák b6caef105b MDL-52319 upgrade: Better report the environment checks in CLI scripts
Before we did not display the source of the environment check failure
(whether it was a core check or a plugin) and there was a missing space
before the "Error" status.
2020-03-23 11:27:01 +01:00
Tim Hunt 8eab502760 MDL-52319 install: Fix some coding style issues 2020-03-23 11:27:01 +01:00
Tim Hunt 213d9daf8d MDL-52319 upgrade: Also run environment checks if plugins need upgrades
Also perform the environment checks if a plugin triggers the upgrade.
Core upgrade and CLI upgrade was doing this already.
2020-03-23 11:27:01 +01:00
AMOS bot f09e31b9c2 Automatically generated installer lang files 2020-03-23 00:12:12 +00:00
Paul Holden 241edb45ec MDL-64429 tool_usertours: ensure tour sortorder can't move out of range. 2020-03-22 20:04:00 +00:00
Paul Holden e8c219a187 MDL-63865 tool_dataprivacy: unit test for plugin privacy provider. 2020-03-22 19:59:49 +00:00
Paul Holden 41831d5651 MDL-67731 backup: fix async restores in progress table listing. 2020-03-22 19:57:25 +00:00
Paul Holden 9fbbb1e46d MDL-67930 mod_forum: consistent default group image when hidden. 2020-03-22 19:55:00 +00:00
AMOS bot 4e64d26901 Automatically generated installer lang files 2020-03-22 00:10:44 +00:00
Sara Arjona d9c9c01f26 MDL-68116 atto_h5p: simplify fields to add H5P content
The embed section has been removed in order to simplify this screen.
It was added to make easier include content coming from h5p.org but,
as soon users won't be able to use it, it makes no sense.
Users will still be able to use the "HTML" button to paste the
embed code.
2020-03-20 10:08:00 +01:00
Sara Arjona da8426112f MDL-68116 filter_h5p: remove h5p.org from allowed sources
h5p.org has to be removed as default value for the allowedsources in
the "Display H5P" filter because H5P is going to close it down completely
so that only the author can see the test content.
2020-03-20 10:08:00 +01:00
cescobedo dc0cbc24f3 MDL-68068 core_h5p: Replace $_SESSION by $SESSION
The third-party library H5P has some references to  instead of Moodle's.
That implies that the information is not saved to backends and other issues,
so only the Moodle one should be used by core (core should be free from  and always use .).
2020-03-20 07:53:30 +01:00
Farhan Karmali 98ae29ae24 MDL-67024 Lib: Check if user->mnethostid is set before using it 2020-03-20 11:59:45 +05:30
Adrian Greeve 46fe2c5533 weekly release 3.8.2+ 2020-03-20 13:35:49 +08:00
Alexander Bias cf0270260b MDL-58964 navigation: Add class attributes to Boost flat navigation 2020-03-19 20:48:38 +01:00
Stephen Vickers c84b8e77f1 MDL-68049 mod_lti: Fix link-level memberships service
Fix cause of 404 error
Ensure personal name and email fields are included
Add ext_user_username field when being passed in LTI messages
2020-03-19 11:22:37 +00:00
Adrian Greeve 95d3c122bf Merge branch 'MDL-68081-MOODLE_38_STABLE' of https://github.com/kritisingh1/moodle into MOODLE_38_STABLE 2020-03-19 11:27:53 +08:00
Adrian Greeve 4fdcc6a534 Merge branch 'MDL-68014-38' of git://github.com/peterRd/moodle into MOODLE_38_STABLE 2020-03-19 11:04:54 +08:00
Jun Pataleta e1f9aa101b Merge branch 'MDL-68108-38' of git://github.com/crazyserver/moodle into MOODLE_38_STABLE 2020-03-18 22:59:42 +08:00
Pau Ferrer Ocaña cc3985ed02 MDL-68108 formslib: Add element password inline template 2020-03-18 08:45:57 +01:00
Adrian Greeve 9d0c43f072 Merge branch 'MDL-67901-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-03-18 09:59:58 +08:00
Tim Hunt c16c0271bb MDL-68191 CSS minification: apply upstream performance/accuracy fix
There was a bug with the code to strip comments.
https://github.com/matthiasmullie/minify/issues/317

Applying the fix as a Moodle-specific change for now, because the
effect is significant.
2020-03-17 23:28:15 +00:00
David Mudrák bee8448520 MDL-68183 auth: Fix the performance of get_complete_user_data search
When searching for the user by a case-insensitive field (email address
is the only one supported now), the performance may be very poor as the
DB cannot use the index due to the LOWER() operation and the full
sequential scan of all the user records is performed. On some DBs such
as MySQL, this can be significantly improved by pre-filtering the users
with accent-insensitive search.

So we first perform accent-insensitive search for potential candidates
in a subselect, which can use the index. Only then we perform the
additional accent-sensitive search on this limited set or records.
2020-03-17 14:51:15 +01:00
David Mudrák d23fba1deb MDL-68183 auth: Fix the performance of signup_validate_data search query
When searching for other users with the same email address, we perform
the case-insensitive and accent-sensitive search. That may be expensive
as some DBs such as MySQL cannot use the index in that case. Instead,
sequential scan of all the user records is performed and the comparison
uses the LOWER function to filter the matching records. This leads to
significant performance heavy queries which in turn represent a surface
for DoS attacks.

For that reason, we first perform accent-insensitive search for
potential candidates in a subselect, which can use the index. Only then
we perform the additional accent-sensitive search on this limited set or
records.
2020-03-17 14:10:47 +01:00
David Mudrák 1e19d154ba MDL-68183 auth: Fix the performance of forgotten password user search
When searching for the user matching the given email address, we perform
the case-insensitive and accent-sensitive search. That may be expensive
as some DBs such as MySQL cannot use the index in that case. Instead,
sequential scan of all the user records is performed and the comparison
uses the LOWER function to filter the matching records. This leads to
significant performance heavy queries which in turn represent a surface
for DoS attacks.

For that reason, we first perform accent-insensitive search for
potential candidates, which can use the index. Only then we perform the
additional accent-sensitive search on this limited set or records.
2020-03-17 14:08:54 +01:00
Jun Pataleta d9eea68192 Merge branch 'MDL-68069-38' of git://github.com/cescobedo/moodle into MOODLE_38_STABLE 2020-03-17 16:14:49 +08:00
Adrian Greeve e2e6b49aab Merge branch 'MDL-67970-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-03-17 15:25:10 +08:00
Shamim Rezaie 41a5c8c54d MDL-67970 output: use fieldset in core/chooser instead of label 2020-03-17 18:20:06 +11:00
Shamim Rezaie b29634d89f MDL-67970 core: remove unnecessary roles
- The navigation role is unnecessary for element nav
- The textbox role is unnecessary for element textarea
2020-03-17 18:20:02 +11:00
Shamim Rezaie 3611f682e9 MDL-67970 output: replace new-sections attribute with data-new-sections
new-sections is not a valid attribute name for the a element.
Replaced that with data-new-sections
2020-03-17 18:20:02 +11:00
Shamim Rezaie 84c87b62f2 MDL-67970 output: fixed duplicate id attribute
action_menu::export_for_template generates the id attributes and send it
to core/action_menu_trigger template as part of the attributes variable.
2020-03-17 18:20:02 +11:00
Shamim Rezaie 9ecde13781 MDL-67970 search: fixed stray end tag (input) 2020-03-17 18:20:02 +11:00
Adrian Greeve 90227d2d76 Merge branch 'MDL-67981_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-03-17 11:32:30 +08:00
Jonathon Fowler 06c3a4cc55 MDL-67442 assign: expand/contract text works in all browsers now 2020-03-16 08:58:44 +10:00
kritisingh1 eed0cbe176 MDL-68081 Groups: Fixes string error in member removal function 2020-03-14 23:24:30 +05:30
Victor Deniz Falcon c78e908404 weekly release 3.8.2+ 2020-03-12 14:22:23 +00:00
Victor Deniz Falcon 7862e1fa12 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-03-12 14:22:17 +00:00
Eloy Lafuente (stronk7) 2f2f184cdb Merge branch 'MDL-66607-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-03-12 10:09:46 +01:00
Eloy Lafuente (stronk7) c96bfdd6a0 Merge branch 'MDL-68125-regression-MOODLE_38_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_38_STABLE 2020-03-12 01:19:41 +01:00
Brendan Heywood af97e88071 MDL-68125 core: Fixed $CFG->reverseproxyignore install regression 2020-03-12 09:53:54 +11:00
Eloy Lafuente (stronk7) 355f829ad9 Merge branch 'MDL-68061-38' of git://github.com/mickhawkins/moodle into MOODLE_38_STABLE 2020-03-11 22:56:23 +01:00
Tim Hunt 8a90179246 MDL-68153 qbank: question of unknown type should not cause fatal error
Regression casued by MDL-67153
2020-03-11 20:41:27 +00:00
Tim Hunt faf7ab39f2 MDL-68149 qtype_match: correctly distinguish 0 and 0.0 answers
Also added a test for backup & restore (which was working).
2020-03-11 13:44:26 +00:00
Tim Hunt 57cc9b6499 MDL-68149 qtype_match: Updatey tests to follow make_question() pattern 2020-03-11 13:44:26 +00:00
Andrew Nicols 736f6a6602 MDL-66607 message: Add pendingJS checks 2020-03-11 20:41:25 +08:00
Andrew Nicols 1c24b2f567 MDL-66607 message: Resolve race conditions in message deletion process
This commit makes several changes:
1) Explicitly stop polling for messages when a conversation is deleted;
2) Check for deleted conversations when displaying new messages;
3) Do not add a new empty conversation; and
4) Introduce pendingJS checks to ensure that Behat waits for messags to finish rendering.
2020-03-11 20:41:25 +08:00
Andrew Nicols c9a466cee7 Merge branch 'MDL-68146_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-03-11 11:52:03 +08:00
Eloy Lafuente (stronk7) 6b46f1a53a MDL-68146 forms: remove duped help and advanced icons in checkboxes
They are exceptionally shown later, after the checkbox text already.

This is a fix for the regression introduced by MDL-63424.
2020-03-10 23:04:08 +01:00
Eloy Lafuente (stronk7) 55b717ee66 Merge branch 'MDL-65724-38-3' of git://github.com/peterRd/moodle into MOODLE_38_STABLE 2020-03-10 13:51:25 +01:00
Eloy Lafuente (stronk7) 4d1ccc6700 Merge branch 'MDL-67189-38' of git://github.com/dpalou/moodle into MOODLE_38_STABLE 2020-03-10 11:30:32 +01:00
Shamim Rezaie 4293339fc9 MDL-68135 output: remove the presentation role from user pic
"presentation" is not a valid role for the img element.
Moreover, it doesn't make sense to have both role="presentation" and
aria-hidden="true" for an element at the same time.
For more info please see:
https://timwright.org/blog/2016/11/19/difference-rolepresentation-aria-hiddentrue/
2020-03-10 19:06:01 +11:00
Dani Palou fef31ac7c1 MDL-67189 external: Add test to catch PHP exceptions 2020-03-10 08:32:14 +01:00
Dani Palou 3f128fff10 MDL-67189 external: Catch Throwable in call_external_function 2020-03-10 08:32:14 +01:00
Eloy Lafuente (stronk7) 1aa7347965 Merge branch 'MDL-67827-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-03-09 20:36:17 +01:00
Sara Arjona 8fba462e74 Merge branch 'MDL-66671-m38-master' of https://github.com/dthies/moodle into MOODLE_38_STABLE 2020-03-09 18:49:11 +01:00
Sara Arjona 19b644ed08 Merge branch 'MDL-67968-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-03-09 18:17:06 +01:00
Sara Arjona 1bbace8bd0 Merge branch 'MDL-67902-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-03-09 15:06:49 +01:00
Andrew Nicols be9325c7cf MDL-67827 behat: Pending JS improvements for dialogues 2020-03-09 08:31:21 +08:00
Andrew Nicols 836e523edd MDL-67827 behat: Add missing exception use 2020-03-09 08:31:21 +08:00
AMOS bot 85162ad8e1 Automatically generated installer lang files 2020-03-09 00:11:53 +00:00
Tim Hunt 11212ea69b MDL-67981 questions: avoid errors deleting contextless questions 2020-03-06 18:02:36 +00:00
Shamim Rezaie 399369fb19 MDL-67968 calendar: use aria-label instead of the abbr tag 2020-03-07 04:12:28 +11:00
Shamim Rezaie 11a8af9012 MDL-67968 calendar: explain weekday abbreviations 2020-03-07 04:08:10 +11:00
Shamim Rezaie bb24115b88 MDL-67968 form: not to put empty label when no label is available 2020-03-07 04:08:10 +11:00
Shamim Rezaie d7bca2339a MDL-67968 question: do not display sr-only legends
.accesshide was removed because:
 1. It was only kept in case it's still used somewhere, in a custom form
 field for instance.
 2. It was broken since 3.5 where we integrated
 https://github.com/bmbrands/moodle/compare/ab65b87f3d...MDL-62419-master
 So it's been ages that the reason mentioned on point 1 was not being
 satisfied
2020-03-07 04:08:10 +11:00
Shamim Rezaie eebe003104 MDL-67968 form: grouped element label fix 2020-03-07 04:08:10 +11:00
Sara Arjona 9ce2442ea9 Moodle release 3.8.2 2020-03-06 12:34:11 +01:00
cescobedo 9f4968676a MDL-68069 core_h5p: delete cache assets when removing libraries
The cache assets linked to a library have to be removed also when a
library is deleted, in order to rebuild them again next time they are
required.
2020-03-06 09:51:31 +01:00
Peter fc51caf533 MDL-65724 core: Force restore to use the settings from the plan
When importing use the import settings.
2020-03-06 14:13:45 +08:00
AMOS bot 9044d294a2 Automatically generated installer lang files 2020-03-06 00:10:50 +00:00
Peter Dias 628c056258 MDL-68014 lti: Remove alt text for image 2020-03-06 07:57:06 +08:00
Sara Arjona cd9828dadf weekly release 3.8.1+ 2020-03-05 17:31:32 +01:00
Sara Arjona 28f2858004 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-03-05 17:31:28 +01:00
Michael Hawkins 941507e78a MDL-67861 core: Fix getremoteaddr unit test to match new proxy setup 2020-03-05 14:39:34 +08:00
Brendan Heywood 1954482cc5 MDL-67861 core: Added $CFG->reverseproxyignore IP subnet list
If your server is behind multiple reverse proxies that append to the
X-Forwarded-For header then you will need to specify a comma separated
list of ip addresses or subnets of the reverse proxies to be ignored
in order to find the users correct IP address.
2020-03-05 01:27:57 +01:00
Brendan Heywood 7d8096eb18 MDL-67861 libraries: Refactor is_ip_in_subnet_list in ip_utils 2020-03-05 01:27:57 +01:00
Brendan Heywood 1cf6629ba2 MDL-67861 admin: Default $CFG->getremoteaddrconf to only use REMOTE_ADDR 2020-03-05 01:27:57 +01:00
Brendan Heywood d403416579 MDL-67861 core: Use last ip in X-Forwarded-For list 2020-03-05 01:27:57 +01:00
Andrew Nicols 9d23ee9003 MDL-65106 theme_classic: Remove unused variable 2020-03-05 08:15:54 +08:00
Andrew Nicols c706dd09a3 Merge branch 'MDL-65106-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-03-05 08:15:48 +08:00
Eloy Lafuente (stronk7) 563931d924 Merge branch 'MDL-62768-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-03-04 18:37:17 +01:00
Sara Arjona a552c30018 Merge branch 'MDL-67696-MOODLE_38_STABLE_count_warning' of https://github.com/JayChurchward/moodle into MOODLE_38_STABLE 2020-03-04 17:55:48 +01:00
Bas Brands 5288ca8a73 MDL-67901 type_multichoice: clear my choice accessibility
Improve the accessibility for the clear my choice option. The
extra radio input controlling the reset feature was removed and
resetting the choice is now controlled by JavaScript.
This fixes the missing label reported in Accessibility audit and W3C
validation of the reset link

By this change this issue also fixes MDL-67280
2020-03-04 16:45:03 +01:00
Sara Arjona 2f7e2ff457 Merge branch 'MDL-67767-38' of git://github.com/dpalou/moodle into MOODLE_38_STABLE 2020-03-04 15:04:58 +01:00
Dani Palou 714a816050 MDL-67767 tool_mobile: Allow using more characters in forcedurlscheme 2020-03-04 14:22:54 +01:00
Sara Arjona e490f86d57 Merge branch 'MDL-67863-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-03-04 14:05:29 +01:00
Sara Arjona eccde3bc19 Merge branch 'MDL-67969-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-03-04 12:58:17 +01:00
Marina Glancy 4c16eba0b5 MDL-56287 gradereport_history: Separate groups queries improved 2020-03-04 11:47:19 +01:00
Jun Pataleta ec7ce8f204 MDL-56287 gradereport_history: Show users from groups that can be viewed 2020-03-04 11:47:19 +01:00
Eloy Lafuente (stronk7) 47f96d5e9f Merge branch 'MDL-67641-38' of git://github.com/dpalou/moodle into MOODLE_38_STABLE 2020-03-04 10:47:55 +01:00
Sara Arjona be47691d79 Merge branch 'MDL-68008-38' of git://github.com/ferranrecio/moodle into MOODLE_38_STABLE 2020-03-04 08:41:30 +01:00
Dani Palou 235f139992 MDL-67641 auth: Fix shortname type in get_signup_settings WS 2020-03-04 08:12:04 +01:00
AMOS bot e10cf2368a Automatically generated installer lang files 2020-03-04 00:11:12 +00:00
Eloy Lafuente (stronk7) 7bda43ee60 Merge branch 'MDL-67728-38' of git://github.com/crazyserver/moodle into MOODLE_38_STABLE 2020-03-03 19:50:17 +01:00
Eloy Lafuente (stronk7) 28298a6fe9 Merge branch 'MDL-68038-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-03-03 19:45:15 +01:00
Eloy Lafuente (stronk7) ddaee0c87d Merge branch 'MDL-67971-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-03-03 19:02:30 +01:00
Sara Arjona 9515f40ced Merge branch 'MDL-67993-38' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-03-03 18:06:37 +01:00
Ferran Recio 7949aaceae MDL-68008 tool_capability: shows multiple contexts when overrides exists 2020-03-03 17:51:27 +01:00
Sara Arjona 305807d27b Merge branch 'MDL-68048-38-behatnotfound' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-03-03 17:01:44 +01:00
Sara Arjona 845c943d7f Merge branch 'MDL-68060-38-huburlcompare' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-03-03 13:10:13 +01:00
Sara Arjona 007ab3cf17 Merge branch 'MDL-67891-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-03-03 12:48:24 +01:00
Bas Brands 8540968781 MDL-65106 theme_classic: set custom navigationitem icon 2020-03-03 11:53:41 +01:00
Sara Arjona 8bf66cf2d3 Merge branch 'MDL-63316-38' of https://github.com/azito122/moodle into MOODLE_38_STABLE 2020-03-03 11:10:46 +01:00
Sara Arjona e0ba5fb608 Merge branch 'MDL-67945-38' of git://github.com/ferranrecio/moodle into MOODLE_38_STABLE 2020-03-03 10:10:45 +01:00
Sara Arjona 3687eb52a0 Merge branch 'MDL-67749-38' of git://github.com/dpalou/moodle into MOODLE_38_STABLE 2020-03-03 09:30:21 +01:00
Adrian Hutchinson 80f4ad43b8 MDL-67988 mod_lti: remove padding from JWS base64url encoding 2020-03-02 14:01:05 +01:00
Paul Holden 9da23023af MDL-67891 tool_cohortroles: move upgrade step inside plugin.
The step added in MDL-67458 was added to core, which broke the upgrade
process if this plugin had been uninstalled prior.
2020-03-02 08:50:35 +00:00
Sara Arjona caf37336d2 MDL-67971 core_badges: review issuer URL 2020-03-02 08:02:31 +01:00
Sara Arjona b3eb933a40 MDL-68038 core_h5p: rename can_update_library test 2020-03-02 08:00:54 +01:00
Andrew Zito b7fe18eb8b MDL-63316 participants: lastname sort for participants table 2020-02-28 14:34:01 -05:00
Daniel Thies 4a2e0b810f MDL-66671 enrol_lti: Skip grade sync when cm deleted 2020-02-28 09:30:34 -06:00
Eloy Lafuente (stronk7) b4a13e9a65 weekly release 3.8.1+ 2020-02-28 12:22:42 +01:00
Bas Brands 324d931ed0 MDL-67863 theme_boost: change keyboard tab order
Move navdrawer up in the dom for a more logical tab order
Hide navdrawer links for tab / screenreader when navdrawer is closed
2020-02-27 17:11:45 +01:00
Michael Hawkins 535be631f8 MDL-68061 gradereport_history: Restrict per page config value to int 2020-02-27 15:41:23 +08:00
Eloy Lafuente (stronk7) c2a1fb945e Merge branch 'MDL-67865-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-02-26 23:37:00 +01:00
Eloy Lafuente (stronk7) 9adfd8ccd5 Merge branch 'MDL-64686-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-02-26 23:27:29 +01:00
Eloy Lafuente (stronk7) 779f58b227 Merge branch 'MDL-67758-38' of git://github.com/dpalou/moodle into MOODLE_38_STABLE 2020-02-26 17:35:55 +01:00
Eloy Lafuente (stronk7) a4a667ab06 Merge branch 'MDL-67132-MOODLE_38' of https://github.com/cengage/moodle into MOODLE_38_STABLE
(amended to move the upgrade.txt info to correct 3.8.2)
2020-02-26 17:18:15 +01:00
Eloy Lafuente (stronk7) fc7e263912 Merge branch 'MDL-67979-38-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-02-26 17:13:37 +01:00
Anthony Forth c47d17b93b MDL-67945 enrol: missing $DB in edit_instance_form 2020-02-26 16:34:38 +01:00
David Mudrák 5aea4d98cb MDL-68060 registration: Improve the sites directory location check
This allows to define the custom HUB_MOODLEORGHUBURL with HTTP Basic
Auth credentials so that the registration features can be tested against
our staging site.
2020-02-26 10:56:05 +01:00
Jun Pataleta b6970abb18 Merge branch 'MDL-67921-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-02-26 16:51:12 +08:00
Jun Pataleta d2b37ff747 Merge branch 'MOODLE_38_MDL-67980' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2020-02-26 14:30:40 +08:00
David Balch 75d4b0f949 MDL-67993 roles: Fix pix_icon() calls. 2020-02-26 12:15:31 +08:00
Claude Vervoort d2c96c5be9 MDL-67132 mod_lti: document new param 2020-02-25 21:24:36 -05:00
Eloy Lafuente (stronk7) 80509c0cdd Merge branch 'MDL-67644-38' of git://github.com/dpalou/moodle into MOODLE_38_STABLE 2020-02-26 00:10:13 +01:00
Eloy Lafuente (stronk7) 2de3eefda5 Merge branch 'MDL-67806-38' of git://github.com/dpalou/moodle into MOODLE_38_STABLE 2020-02-25 23:57:55 +01:00
Eloy Lafuente (stronk7) 5d83769d27 Merge branch 'MDL-67237-38' of git://github.com/dpalou/moodle into MOODLE_38_STABLE 2020-02-25 23:53:28 +01:00
Eloy Lafuente (stronk7) 341a509763 Merge branch 'MDL-67920-38' of git://github.com/aanabit/moodle into MOODLE_38_STABLE 2020-02-25 23:33:39 +01:00
Paul Holden 0111c671e4 MDL-62768 tool_policy: add page title & breadcrumb navigation. 2020-02-25 22:05:56 +00:00
Paul Holden a8df356e33 MDL-62768 tool_dataprivacy: add page breadcrumbs to navigation. 2020-02-25 21:37:56 +00:00
Helen Foster 69935b2021 MDL-67979 lang: Import fixed English strings (en_fix)
* configcustommenuitems,core_admin - corrected example
* custommenuitems_desc,tool_mobile - fallback behaviour of custom menu
  items in the app
2020-02-25 12:23:36 +01:00
Eloy Lafuente (stronk7) b424d7956e Merge branch 'MDL-67862-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-02-25 12:09:48 +01:00
Eloy Lafuente (stronk7) 34a98290d2 Merge branch 'MDL-67364-38' of git://github.com/mickhawkins/moodle into MOODLE_38_STABLE 2020-02-25 12:05:48 +01:00
David Mudrák 706e99c6d4 MDL-68048 behat: Fix the ElementNotFoundException message wording
The exception class itself adds the "not found" to the error message.
2020-02-25 11:55:57 +01:00
Shamim Rezaie 169917563c MDL-67902 calendar: keyboard users should be able to toggle day popover 2020-02-25 03:40:45 +11:00
Shamim Rezaie 7df5814667 MDL-67902 calendar: informative aria label for event days in mini cals 2020-02-25 03:40:45 +11:00
Shamim Rezaie fa88a2c32a MDL-67902 calendar: informative aria label for event days in calendar 2020-02-25 03:40:44 +11:00
Shamim Rezaie 66fbe3c48b MDL-67902 calendar: Fix label of the course filter in calendar 2020-02-25 03:40:44 +11:00
Mikhail Golenkov 3d20910e88 MDL-67980 tasks: Sort ad-hoc tasks by nextruntime. 2020-02-24 09:32:37 +11:00
Pau Ferrer Ocaña 7d623c4a45 MDL-67728 behat: Increase app start timeout 2020-02-21 12:46:04 +01:00
Pau Ferrer Ocaña 1c447dcc44 MDL-67728 behat: Improve behat app selectors 2020-02-21 12:46:04 +01:00
Sara Arjona ae778f4193 MDL-67921 core_h5p: re-implement framework->getOption
The implementation done for getOption was not correct because it
was only taking into account the displayoptions for download and
embed.
Besides, setOption implementation has been added.
2020-02-21 09:29:29 +01:00
Amaia Anabitarte c1fbab8a81 MDL-67920 core_h5p: Move upload button into form and fix title
Minor bugs in Site administration > H5P > Manage H5P content types admin page'
2020-02-21 09:00:16 +01:00
Luca Bösch 26143b5d62 MDL-64686 theme: align course search form for small screens sizes. 2020-02-21 06:36:40 +01:00
Jun Pataleta 7b37466710 weekly release 3.8.1+ 2020-02-21 11:04:05 +08:00
Jun Pataleta 09f6b75f70 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-02-21 11:03:25 +08:00
Eloy Lafuente (stronk7) cd0e753519 Merge branch 'MDL-67727-38' of git://github.com/crazyserver/moodle into MOODLE_38_STABLE 2020-02-20 16:12:48 +01:00
Eloy Lafuente (stronk7) 4d951d4bac Merge branch 'MDL-67899-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-02-20 00:41:29 +01:00
Luke Tucker 421537407d MDL-50455: tool_capability: Use static cache when loading context data 2020-02-20 00:29:32 +01:00
Eloy Lafuente (stronk7) 61f6f15177 Merge branch 'MDL-67942-38' of https://github.com/HuongNV13/moodle into MOODLE_38_STABLE 2020-02-19 19:18:44 +01:00
Eloy Lafuente (stronk7) 11a4df56f8 Merge branch 'MDL-67947_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-02-19 17:48:26 +01:00
Tim Hunt 7bde84a705 MDL-67947 questions: questions_in_use should ask all components
Previously it was only checking mods.
2020-02-19 11:58:12 +00:00
Dani Palou 4d4b22da05 MDL-67749 ws: Set private token when reset or manual create token 2020-02-19 12:04:57 +01:00
Shamim Rezaie 85a43994ca MDL-67969 lib: Fix duplicate blockinstanceid for fake blocks 2020-02-19 21:25:47 +11:00
Huong Nguyen fcf3d8b748 MDL-67942 Quiz: Quiz attempt report delete_selected_attempts issue 2020-02-19 15:35:55 +07:00
Eloy Lafuente (stronk7) 663cdc54fe Merge branch 'MDL-67471_38' of https://github.com/t-schroeder/moodle into MOODLE_38_STABLE 2020-02-18 23:54:44 +01:00
Eloy Lafuente (stronk7) 4eeb89d0a7 Merge branch 'MDL-61390-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-02-18 19:06:51 +01:00
Eloy Lafuente (stronk7) b6aae0fc5b Merge branch 'MDL-67953-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-02-18 17:18:58 +01:00
Shamim Rezaie 68a3863961 MDL-67865 output: Fix id of the dropdown trigger 2020-02-18 16:19:17 +11:00
Eloy Lafuente (stronk7) 7e17a2a4fc Merge branch 'MDL-61389-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-02-17 23:30:08 +01:00
Eloy Lafuente (stronk7) bb6281a5c9 Merge branch 'MDL-67817-m38-master' of https://github.com/dthies/moodle into MOODLE_38_STABLE 2020-02-17 22:09:05 +01:00
Tim Schroeder 4745203bc0 MDL-67471 message: fixed mark_notification_read with messaging disabled 2020-02-17 09:16:13 +01:00
Jun Pataleta f1dd21a3c7 MDL-61390 mod_forum: Create template for forum search results 2020-02-17 15:58:04 +08:00
Jun Pataleta 4d90df63d2 MDL-61389 mod_forum: Descriptive aria-label for "Discuss this topic" 2020-02-17 15:52:06 +08:00
AMOS bot 37397ed119 Automatically generated installer lang files 2020-02-16 00:11:11 +00:00
Daniel Thies b9792633c9 MDL-67817 core_date: Add test for timezone localization strings 2020-02-14 11:56:33 -06:00
Daniel Thies f5677dadeb MDL-67817 core_lang: Update timezone strings 2020-02-14 11:56:33 -06:00
Sara Arjona 199ff6cc6b weekly release 3.8.1+ 2020-02-14 12:12:12 +01:00
Sara Arjona 462002f1ec Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-02-14 12:12:10 +01:00
Jun Pataleta 7fdcd5cb4d Merge branch 'MDL-67965-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-02-14 13:25:10 +08:00
Andrew Nicols ca63a87509 MDL-67965 behat: Get theme-specific context classes correctly 2020-02-14 10:15:49 +08:00
Claude Vervoort 1fde9dea67 MDL-67132 mod_lti: call grade api to trigger course total computation 2020-02-13 18:45:05 -05:00
Michael Hawkins 2359ec14f7 MDL-67364 output: Add unit testing for editor_scss_to_css 2020-02-13 22:53:19 +08:00
Michael Hawkins 999bb6578b MDL-67364 output: Allow child themes to use parent editor_scss config
This still allows child themes to override editor_scss, but will fall
back to what the parent is using if they do not specify it. This
negates the need for every child them to have the config duplicated
in order to utilise it.
2020-02-13 22:53:19 +08:00
Pau Ferrer Ocaña 71f62ad8ce MDL-67727 behat: Reset ionic app properly 2020-02-13 08:37:28 +01:00
Andrew Nicols 8ccb773f9b MDL-67953 grunt: Work around spawn length limits 2020-02-13 13:34:03 +08:00
Eloy Lafuente (stronk7) 84a6421857 Merge branch 'MDL-67876_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-02-12 15:51:17 +01:00
Dani Palou c3fc5fca65 MDL-67644 tool_mobile: Add OAuth 2 providers in disabled features 2020-02-12 14:13:17 +01:00
Tim Hunt bb9176eee4 MDL-67876 forms: not all field types need validation JS 2020-02-12 10:02:27 +00:00
Tim Hunt 5048dbbf06 MDL-67876 forms: scroll to any invalid element if form cannot submit 2020-02-12 10:01:24 +00:00
Shamim Rezaie a2d619941f MDL-67899 message: Add aria-label to the emoji picker button 2020-02-12 15:40:45 +11:00
Eloy Lafuente (stronk7) 5df69d28ad Merge branch 'MDL-67532-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-02-11 23:08:07 +01:00
Eloy Lafuente (stronk7) 95ecaf2d1e Merge branch 'MDL-67675-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-02-11 22:56:17 +01:00
Eloy Lafuente (stronk7) 13caf292eb Merge branch 'MDL-67690-38' of git://github.com/merrill-oakland/moodle into MOODLE_38_STABLE 2020-02-11 22:45:27 +01:00
Sara Arjona 1fae040842 Merge branch 'MDL-59303-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-02-11 13:52:29 +01:00
Sara Arjona 659795e8e8 Merge branch 'MDL-66847-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-02-11 12:28:46 +01:00
Sara Arjona 5e3aad0090 Merge branch 'MDL-66834-MOODLE_38_STABLE' of https://github.com/kepeter/moodle into MOODLE_38_STABLE 2020-02-11 11:54:22 +01:00
Sara Arjona 934e913a97 Merge branch 'mdl67142-moodle38' of https://github.com/AngadSethi/moodle into MOODLE_38_STABLE 2020-02-11 10:18:59 +01:00
Sara Arjona a10e70cf56 Merge branch 'MDL-67894-38' of https://github.com/grabs/moodle into MOODLE_38_STABLE 2020-02-11 08:20:38 +01:00
Dani Palou c618f24c70 MDL-67758 airnotifier: Send wwwroot to airnotifier 2020-02-10 11:55:51 +01:00
Jun Pataleta fb13d3a118 MDL-66245 privacy: Encode each part of the data URL instead of the whole 2020-02-10 16:56:10 +08:00
Jun Pataleta 90a3ce934e MDL-67862 message: Render dialogue header only when necessary 2020-02-10 13:12:35 +08:00
Angad Sethi 9dd517653c MDL-67142 quiz: fixed error when deleting saved questions long-name-quiz
An error was showing up while deleting questions
(in the question_save_from_deletion method) which had been saved
and which belonged to a quiz with a super long name, not exceeding 255
characters, as the 'name' field in 'question_categories' table had a
max size of 255 characters. The shorten_text function was used to
shorten the string to 255 characters and a unit test was added with
the name test_question_save_from_deletion_quiz_with_long_name to test
the patch.
2020-02-08 19:46:59 +05:30
AMOS bot 68b1fa37d5 Automatically generated installer lang files 2020-02-08 00:11:54 +00:00
Andreas Grabs df55da0a4b MDL-67894 mod_feedback: database error on show responses 2020-02-07 18:47:37 +01:00
Paul Holden f179253ab7 MDL-59303 auth_shibboleth: consistent readme URL. 2020-02-07 14:26:06 +00:00
Luca Bösch 82fa8144a5 MDL-66847 webservice: Correct breadcrumb + title for ws documentation. 2020-02-07 14:40:10 +01:00
Paul Holden 103c623b83 MDL-67532 badges: better default for new badge language. 2020-02-07 09:47:03 +00:00
Sara Arjona 9691980198 weekly release 3.8.1+ 2020-02-07 09:44:56 +01:00
Sara Arjona 3ae5f9ce0c Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-02-07 09:44:54 +01:00
Brendan Heywood 8973440f1f MDL-67726 tool_phpunit: add missing input escaping 2020-02-06 19:43:32 +01:00
Dani Palou 71b91e606b MDL-67237 tool_mobile: Add H5P offline option in disabled features 2020-02-06 11:34:10 +01:00
Andrew Nicols b079a267b4 Merge branch 'MDL-67175-38' of git://github.com/ferranrecio/moodle into MOODLE_38_STABLE 2020-02-06 10:20:54 +08:00
Eloy Lafuente (stronk7) 5016b08fcc Merge branch 'MDL-67832_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE
(fixed a couple of typos in the merge commit)
2020-02-06 00:02:25 +01:00
Eloy Lafuente (stronk7) c58d4d4591 Merge branch 'MDL-67732-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-02-05 20:05:41 +01:00
Eloy Lafuente (stronk7) ff3b9e1afa Merge branch 'MDL-67830_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-02-05 19:08:05 +01:00
Andrew Nicols 0d3c0e4377 Merge branch 'MDL-49103-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2020-02-05 13:51:15 +08:00
Eloy Lafuente (stronk7) 7005e1c999 Merge branch 'MDL-67842_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-02-04 22:46:24 +01:00
Eloy Lafuente (stronk7) bed550541b Merge branch 'MDL-63424-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-02-04 19:28:44 +01:00
Eloy Lafuente (stronk7) ca9ff05eba Merge branch 'MDL-66875-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-02-04 19:02:33 +01:00
Sara Arjona 2ff1e5d1fa MDL-49103 badges: bake badges with iTXt chunk instead of tEXt
The final OB 1.0 specification changed the baking badges method
from tEXt to iTXt. Besides, the iTXt chunk should be a signed
assertion or the raw JSON (instead of the assertion URL).
This has been changed in order to make Moodle OB compliant.

Yuliya Bozhko, thanks for the patch! :-)
2020-02-04 18:50:01 +01:00
Ferran Recio 5bd9eaaef0 MDL-67175 mod_scorm: fixing js eslint errors 2020-02-04 12:37:31 +01:00
Sam Hemelryk ede71aea73 MDL-67175 mod_scorm: sync XHR requests use sendBeacon when available
Totara reference TL-22621 (original code by Sam Hemelryk)
https://github.com/moodle/moodle/commit/2add402f8183c50bc1238ef2da5ea9cd06cb1dd9
2020-02-04 12:37:31 +01:00
Brendan Cox ab1939e5e6 MDL-67175 session: set SameSite=None for Chrome 78 and above
Totara reference TL-22311 (original code by Brendan Cox and Sam Hemelryk)
https://github.com/moodle/moodle/commit/a3f4de2b7efe66de6617a67ce7c87f2862e76ac6
2020-02-04 12:37:15 +01:00
Andrew Nicols 045d69a61d Merge branch 'MDL-60126-38-3' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-02-04 14:40:20 +08:00
Peter c6e2821be1 MDL-60126 competency: Unit tests 2020-02-04 08:51:50 +08:00
Simey Lameze 75c21efdea MDL-60126 core: upgrade step to clean user comp 2020-02-04 08:51:45 +08:00
Simey Lameze c852a0d308 MDL-60126 competency: delete content upon user delete 2020-02-04 08:40:25 +08:00
AMOS bot f722f3ef15 Automatically generated installer lang files 2020-02-04 00:11:15 +00:00
Sara Arjona e47f0220a6 Merge branch 'MDL-67721-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-02-03 14:52:30 +01:00
Sara Arjona 94e2bc3cac Merge branch 'MDL-67511-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-02-03 14:10:30 +01:00
Peter Eliyahu Kornfeld 90ae31ecb1 MDL-66834 Questions: add transaction, move trigger 2020-02-03 12:28:19 +02:00
Andrew Nicols feb32ff597 MDL-67511 core: Adjust spacing at top of toast-wrapper 2020-02-03 07:38:06 +08:00
Tim Hunt e5c2879063 MDL-67832 quiz: fix lots of PHPdoc in attemptlib.php 2020-01-31 19:09:28 +00:00
Paul Holden c3496f8599 MDL-67732 group: observe viewfullnames capability.
Backport from MDL-67245.
2020-01-31 16:48:08 +00:00
JayChurchward 7476acd514 MDL-67696 mod_forum: Changed invalid count() to loop counter. 2020-01-30 15:01:24 -05:00
Tim Hunt 8ad3593d0c MDL-67842 questions: Cannot remove the idnumber from a question 2020-01-30 17:29:23 +00:00
Eloy Lafuente (stronk7) 7f697f7a44 weekly release 3.8.1+ 2020-01-30 16:11:27 +01:00
Eloy Lafuente (stronk7) efcc2a7ac5 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-01-30 16:11:24 +01:00
Jun Pataleta d2ba630385 Merge branch 'MDL-67353-38' of https://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-30 12:41:22 +08:00
Eloy Lafuente (stronk7) b2dfaa5d3a MDL-67353 course: move form tearDown() to reset_all_data()
We are already cleaning all sort of caches, statics, singletons
there and it's better to ensure they are always reset to avoid
myterious failures @ distance.
2020-01-30 12:41:04 +08:00
Eloy Lafuente (stronk7) ccb5136b94 MDL-67353 filters: fix filterlib tests
- move resetAfterTest() to test units.
- remove setUp(), moving code to remove_all_filters_from_config().
- remove class properties, moving to return values of own setup_xxx() methods.
2020-01-30 12:41:04 +08:00
Eloy Lafuente (stronk7) 89a4d27f34 MDL-67353 favourites: Random DB id matching solved
Depending on the tests executed it was possible to arrive
to favourites tests with 2 "concepts" (say userid and contextid,
or userid and itemid) having the same ID.

Then, the array_diff() operations used by some mock stuff in the
tests wrongly was returning matches by value, ultimately causing
the test to fail.

Now, the matching is performed using array_diff_assoc() that takes
keys into considation when performing the match.
2020-01-30 12:41:04 +08:00
Andrew Nicols b2e08b7caa MDL-67353 course: Fix more broken unit tests 2020-01-30 12:41:04 +08:00
Andrew Nicols a946a9aac6 MDL-67353 course: Fix broken unit test 2020-01-30 12:41:04 +08:00
Michelle Melton ad5a2c9b07 MDL-64169 course: fix padding when display on one section per page
(amended to keep the $o.= consistent with surrounding code)
2020-01-29 22:35:49 +01:00
Tim Hunt 54908ae907 MDL-67830 quiz: notice in grade details redirect script 2020-01-29 18:35:28 +00:00
Jun Pataleta 36d2a83aa6 Merge branch 'MDL-67626_38' of git://github.com/adpe/moodle into MOODLE_38_STABLE 2020-01-29 21:37:08 +08:00
Adrian Greeve e02fbba097 Merge branch 'MDL-67768-38-componentdirs' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-01-29 10:02:58 +08:00
Eloy Lafuente (stronk7) d18b6693ad Merge branch 'MDL-67472-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-01-28 22:57:37 +01:00
Eloy Lafuente (stronk7) 9b1e5ee508 Merge branch 'MDL-52189_38' of https://github.com/jonof/moodle into MOODLE_38_STABLE 2020-01-28 22:45:14 +01:00
Eloy Lafuente (stronk7) c11ad45a99 Merge branch 'MDL-67447-38-autocomplete' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-01-28 22:24:31 +01:00
Eloy Lafuente (stronk7) c1ad1072da Merge branch 'MDL-67722-38' of git://github.com/mickhawkins/moodle into MOODLE_38_STABLE 2020-01-28 20:13:37 +01:00
David Mudrák 572c8c74cc MDL-67447 form: Fix the duplicate autocomplete selection node
When the autocomplete selection is updated, the content of the selection
wrapper is replaced with the new list of selected items. We must replace
only the content of the selection wrapper and not to nest it into
itself.
2020-01-28 19:52:29 +01:00
Shamim Rezaie 4a87ffb336 MDL-67675 atto_h5p: No need to manually clear the H5P placeholder 2020-01-28 22:30:37 +11:00
Eloy Lafuente (stronk7) 0419687a7f Merge branch 'MDL-57755_38' of https://github.com/t-schroeder/moodle into MOODLE_38_STABLE 2020-01-28 10:34:56 +01:00
David Mudrák d8cc1761f1 MDL-67768 core: Add some common dirs to core_component::$ignoreddirs
The core_component::$ignoreddirs lists all directories that are reserved
and cannot be used as valid plugin names. This is particularly important
for some plugin types such as 'webservice' that share the same root
location as the core subsystem of the same name.
2020-01-28 10:33:37 +01:00
Adrian Greeve 1ff0018969 Merge branch 'MDL-67740-38-behatstepsfilter' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-01-28 15:07:56 +08:00
Adrian Greeve 557a351daf Merge branch 'MOODLE_38_MDL-67746' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2020-01-28 13:13:45 +08:00
AMOS bot 916130a390 Automatically generated installer lang files 2020-01-28 00:11:42 +00:00
Adrian Greeve c3c3d12462 Merge branch 'MDL-67691_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-01-28 07:53:31 +08:00
Shamim Rezaie c385803441 MDL-67721 mod_forum: See 'view grade' button on single discussion forums 2020-01-28 05:03:12 +11:00
Eloy Lafuente (stronk7) 912ba0f5d0 Merge branch 'MDL-64531-38-questiondeletejson' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-01-27 17:08:07 +01:00
Eloy Lafuente (stronk7) b25bd34adf Merge branch 'MDL-67577-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-01-27 16:19:49 +01:00
Eloy Lafuente (stronk7) 7163df9a93 Merge branch 'm38_MDL-67414_Add_PostgreSQL_12x_Support' of https://github.com/scara/moodle into MOODLE_38_STABLE 2020-01-27 12:16:17 +01:00
Bas Brands 1719110c23 MDL-67577 core_message: navbar_output order
* moved the logic from core_message_popup_render_navbar_output to
message_popup_render_navbar_output in message/output/popup/lib.php

* using float: left instead of float: right in theme
2020-01-27 12:15:18 +01:00
Dani Palou bb0a08a7b4 MDL-67806 tool_mobile: Add Dark mode option in disabled features
We must allow site admins to remotely disable that feature in the app
2020-01-27 11:33:04 +01:00
Tim Schroeder c2f2919cf8 MDL-57755 message: fix notificaiton read status when messaging disabled 2020-01-27 09:18:28 +01:00
Matteo Scaramuccia ec2ea6c725 MDL-67414 adodb: Backport upstream fix for PostgreSQL 12.x
Upstream: https://github.com/ADOdb/ADOdb/commit/a4876f100602c2ce4760bb72d3050f73387adcca
          pgsql: stop using obsolete pg_attrdef.adsrc column
2020-01-26 09:40:22 +01:00
Matteo Scaramuccia 05a89b9b45 MDL-67414 database: Fixed PostgreSQL 12.x support 2020-01-26 09:40:21 +01:00
AMOS bot 5b90fa9f73 Automatically generated installer lang files 2020-01-25 00:11:41 +00:00
Luca Bösch a2841e3af6 MDL-66875 calendar: allow the use of day, mon and year again. 2020-01-25 01:01:54 +01:00
Luca Bösch de9c260296 MDL-63424 form: allow checkboxes to have req icon. 2020-01-24 17:38:20 +01:00
David Mudrák 2648ab76be MDL-67740 behat: Show info as collapsed at the acceptance testing page
The static information with the links to Behat documentation is quite
long an irrelevant for experienced developers returning to this page. No
need to waste the prominent screen place with it - better to offer it
only when needed via collapsible form section.
2020-01-24 10:44:37 +01:00
David Mudrák aa9f7001da MDL-67740 behat: Improve the layout of the acceptance testing page
- The CSS contains more specific selectors.
- Make use of the whole screen width for the list of found steps.
- Visually distinguish found steps from each other.
- Make it look less like a unicorn rainbow.
2020-01-24 10:44:37 +01:00
David Mudrák 5013ed92a2 MDL-67740 behat: Fix the name of the class in the inline documentation
The said class is provided by the moodlehq/behat-extension composer
package and was renamed as a part of upgrade to Behat 3.0.x (MDL-46891).
2020-01-24 10:44:37 +01:00
David Mudrák c538c5a1a3 MDL-67740 behat: Allow multiple words filter at acceptance testing page
Because of the too strict input param type, the form did not allow to
search for Behat steps containing the given phrase. The patch sets the
param type to match the one in the form definition, and makes sure that
the submitted value can be safely used as a CLI script argument.
2020-01-24 10:44:37 +01:00
Mikhail Golenkov 2cb5e23006 MDL-67746 Tasks: Cleanup task logs in chunks. 2020-01-24 14:03:48 +11:00
Adrian Greeve 85a035b1c5 weekly release 3.8.1+ 2020-01-24 10:17:40 +08:00
Adrian Greeve 1f3bc3164e Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-01-24 10:17:30 +08:00
Eric Merrill 7bfcb01b81 MDL-67690 block_myoverview: Clean usage of starred vs favourites
The block accidentally mixes usage of starred vs favourites, but core
requires favourites. This fixes the issue of user settings remembering
the correct value without a more major work.
2020-01-23 15:22:02 -05:00
Eloy Lafuente (stronk7) 2abbcb4761 Merge branch 'MDL-51225-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-23 11:14:12 +01:00
Jun Pataleta 9afa3fc326 MDL-51225 mod_forum: Revert @javascript tag removal
Put back the removed  @javascript tag to prevent random goutte
fails.
2020-01-23 15:30:36 +08:00
Jun Pataleta b4466151b0 Merge branch 'MDL-67118_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-01-23 12:55:28 +08:00
Jun Pataleta e4ae433b3b Merge branch 'MDL-67115_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-01-23 11:40:57 +08:00
Jun Pataleta 7c7932aaa5 Merge branch 'MDL-65952_m38' of https://github.com/fabiendallet/moodle into MOODLE_38_STABLE 2020-01-23 10:43:41 +08:00
Eloy Lafuente (stronk7) 5977f2fc3d Merge branch 'MDL-67296-38' of git://github.com/vmdef/moodle into MOODLE_38_STABLE 2020-01-22 23:46:18 +01:00
Víctor Déniz Falcón f7355ebc2c MDL-67296 core_h5p: tests modified to use exttests 2020-01-22 20:41:23 +00:00
Víctor Déniz Falcón b80d4a6b26 MDL-67296 core_h5p: minor changes
core.php-Avoid to use the factory for each content type
h5p_get_content_types_task-new method to simplify test execution
framework.php-returns error if you get a 404 response after requesting a file
2020-01-22 18:56:38 +00:00
Jun Pataleta c4e6d74577 Merge branch 'MDL-66897-38-1' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2020-01-22 23:17:05 +08:00
Mihail Geshoski ac32e20ada MDL-66897 mod_assign: Properly display error messages in quick grading 2020-01-22 14:02:59 +08:00
Adrian Greeve 37821e0918 Merge branch 'MDL-67424-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-01-22 13:57:53 +08:00
Adrian Greeve b1e2c36330 Merge branch 'MDL-67653_38' of https://github.com/timhunt/moodle into MOODLE_38_STABLE 2020-01-22 11:04:09 +08:00
Adrian Greeve 4ea5ab220a Merge branch 'MDL-67660-38-v2' of https://github.com/TobiGa/moodle into MOODLE_38_STABLE 2020-01-22 10:42:24 +08:00
Jun Pataleta f2955fae89 Merge branch 'MDL-67684-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-01-22 10:38:02 +08:00
Adrian Greeve 0206502461 Merge branch 'MDL-67680-38' of git://github.com/marinaglancy/moodle into MOODLE_38_STABLE 2020-01-22 10:30:05 +08:00
Colin Campbell b4779307a2 MDL-52189 file: skip deleting temp files that appear during cleanup 2020-01-22 12:09:50 +10:00
Adrian Greeve 4ff40b48e7 Merge branch 'MDL-67656-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-01-22 09:45:58 +08:00
Eloy Lafuente (stronk7) 830ef192ad Merge branch 'MDL-66858_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-01-22 01:57:28 +01:00
Michael Milette 8b466d2803 MDL-66858 master: Enable <header> tags in Atto editor.
(amended to add the src/editor/js/clean.js
file that was originally missing)
2020-01-22 00:06:14 +01:00
Eloy Lafuente (stronk7) bd290493b1 Merge branch 'MDL-51225-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-21 23:40:16 +01:00
Adrian Greeve 6e6b973f0a Merge branch 'MDL-66237-38' of git://github.com/mickhawkins/moodle into MOODLE_38_STABLE 2020-01-21 11:20:32 +08:00
Jun Pataleta 43b39b0ce9 Merge branch 'MDL-66108-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-01-21 09:50:56 +08:00
Eloy Lafuente (stronk7) 7523e0c352 Merge branch 'MDL-66024-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-01-20 22:48:27 +01:00
Eloy Lafuente (stronk7) 77234ad1ef Merge branch 'MDL-66220-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-20 22:34:17 +01:00
Eloy Lafuente (stronk7) 132809e8ff Merge branch 'MDL-66712-38-selfautounenrol' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2020-01-20 22:29:00 +01:00
Paul Holden e53dadd3a1 MDL-65884 filters: update exclusive separator characters for tags.
The previous characters mangled the output of filtered text, exhibited
in the activity names filter for activities named '-' (single hyphen).
2020-01-20 20:55:34 +01:00
David Mudrák 7b6f691f3d MDL-64531 course: Add Behat test for deleting a quiz with own questions
Teachers can delete Quiz activities that have a question in their own
context via AJAX request with the course recycle bin disabled. This used
to lead to "Unexpected token < in JSON" because of the extra HTML in the
output.
2020-01-20 18:20:27 +01:00
Tim Hunt 596cbeb955 MDL-64531 course: course_delete_module shouldn't output during AJAX
Committer's note: This change was originally part of a bigger patchset
submitted by the author. This is a stripped-down version that does not
use phpunit tests for the new behaviour.
2020-01-20 18:07:17 +01:00
Eloy Lafuente (stronk7) 4a617ad4c6 Merge branch 'MDL-67724-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-20 10:53:28 +01:00
Sara Arjona 9ef53aba3a Merge branch 'MDL-67312-38' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-01-20 08:03:52 +01:00
Adrian Greeve 288d4fc575 Merge branch 'MDL-66761-38' of git://github.com/mickhawkins/moodle into MOODLE_38_STABLE 2020-01-20 14:47:30 +08:00
Adrian Greeve 68fd5cfaf4 Merge branch 'MDL-67583-38' of https://github.com/KietChan/moodle into MOODLE_38_STABLE 2020-01-20 13:38:14 +08:00
Simey Lameze df6160f8a1 MDL-67312 core_user: clean subs events on user deletion 2020-01-20 08:50:55 +08:00
Simey Lameze 7434f3abf3 MDL-67312 calendar: upgrade step to delete orphaned events 2020-01-20 08:50:51 +08:00
Simey Lameze abaf1375c1 MDL-67312 core: change db upgrade step to use get_fieldset_sql 2020-01-20 08:47:34 +08:00
Eloy Lafuente (stronk7) 646e72349d MDL-67691 behat: inform about the_following_exist() removal
behat_data_generators::the_following_exist() has been removed, please use
behat_data_generators::the_following_entities_exist() instead.

See MDL-67691 for more info.
2020-01-20 00:11:57 +01:00
Eloy Lafuente (stronk7) 7781e1e2bf MDL-67115 google: php74 params order for implode()
Passing parameters to implode() in reverse order is deprecated, use
implode($glue, $parts) instead of implode($parts, $glue).

This commit corresponds to general search of wrong cases.
2020-01-19 18:49:24 +01:00
Eloy Lafuente (stronk7) 41f06cfc92 MDL-67115 htmlpurifier: php74 params order for implode()
Passing parameters to implode() in reverse order is deprecated, use
implode($glue, $parts) instead of implode($parts, $glue).

This commit corresponds to general search of wrong cases.
2020-01-19 18:49:24 +01:00
Eloy Lafuente (stronk7) 903428a532 MDL-67115 minify: php74 params order for implode()/join()
Passing parameters to implode() in reverse order is deprecated, use
implode($glue, $parts) instead of implode($parts, $glue).

This commit corresponds to phpunit detections, minify library.
2020-01-19 18:49:23 +01:00
Eloy Lafuente (stronk7) 20c78476a3 MDL-67115 core: php74 params order for implode()/join()
Passing parameters to implode() in reverse order is deprecated, use
implode($glue, $parts) instead of implode($parts, $glue).

This commit corresponds to phpunit and manual detections, core files.
2020-01-19 18:49:23 +01:00
Adrian Perez 63b7cd9927 MDL-67626 assign: fix view full/view summary control in IE 2020-01-18 14:16:07 +01:00
AMOS bot dc89ea0e88 Automatically generated installer lang files 2020-01-18 00:10:49 +00:00
fdallet 52136af780 MDL-65952 mod_scorm: Fix unwanted changes to require status 2020-01-17 17:29:36 +01:00
Paul Holden 7b0a8e09c0 MDL-66108 course: fix false positives when bulk moving categories. 2020-01-17 16:19:17 +00:00
Jun Pataleta 13a34d0aa7 MDL-67724 mod_glossary: Improve Behat test
Improve the "Glossary entries are not always editable" scenario by:
* No need to use the @javascript tag
* The maxediting time can be set to a lower value to
reduce the overall wait time.
2020-01-17 17:50:11 +08:00
Tobias Garske a6a79e25f4 MDL-67660 core_message: Messages search change input focus 2020-01-17 09:40:18 +01:00
Michael Hawkins 511dc1cd96 MDL-67722 mod_forum: Reduce wait time on time limit expires behat test 2020-01-17 15:46:45 +08:00
Jun Pataleta df7cacee50 MDL-51225 mod_forum: Use can_view_post to determine whether to show post
Use \mod_forum\local\managers\capability::can_view_post() to
consistently determine whether a forum post will be rendered in the
recent activity block.
This helps the recent activity block to provide a more consistent
behaviour with the forum's discussion view itself.
2020-01-17 14:45:50 +08:00
Jun Pataleta 994ec1690d MDL-51225 mod_forum: Create behat tests for forum recent activity 2020-01-17 14:45:50 +08:00
Jun Pataleta b92880fd4a MDL-51225 mod_forum: New behat step for creating question discussion 2020-01-17 14:45:50 +08:00
Michael Hawkins 27557f1a55 MDL-66761 forumreport_summary: Added groups filter behat testing 2020-01-17 10:35:37 +08:00
Michael Hawkins 58c1af595e MDL-66761 mod_forum: Behat support group ID in bulk discussion adding 2020-01-17 10:35:37 +08:00
AMOS bot 4c495c2aa3 Automatically generated installer lang files 2020-01-17 00:12:19 +00:00
Eloy Lafuente (stronk7) 86362a7fb2 MDL-67118 enrol_ldap: add pagesize/subcontexts provider
With that provider we'll be explicitly checking that any
pagesize and subcontexts search is returning results consistently
so the internal paging/servercontrols work as expected.
2020-01-16 19:16:21 +01:00
Eloy Lafuente (stronk7) f8b9cc01c3 MDL-67118 enrol_ldap: paged results functions deprecated php74 and up
Starting with php74 the following functions are deprecated:
- ldap_control_paged_result()
- ldap_control_paged_result_response()

Starting with php73, ldap servercontrols were included. One of those
servercontrols, LDAP_CONTROL_PAGEDRESULTS, is the one in charge of
controlling paged results.

So, we are going to add some conditional code here:

1) if php < 7.3, use old paged result functions.
2) if php >= 7.3, switch to LDAP_CONTROL_PAGEDRESULTS servercontrol.

With a TODO about removing 1) in Moodle 4.1, once php73 becomes required.
2020-01-16 19:16:21 +01:00
Eloy Lafuente (stronk7) 19e3cdbad9 MDL-67118 auth_ldap: add pagesize/subcontexts test provider
With that provider we'll be explicitly covering that any
pagesize and subcontexts search is returning results consistently
so the internal paging/servercontrols work as expected.
2020-01-16 19:16:21 +01:00
Eloy Lafuente (stronk7) bcf7349371 MDL-67118 auth_ldap: paged results functions deprecated php74 and up
Starting with php74 the following functions are deprecated:
- ldap_control_paged_result()
- ldap_control_paged_result_response()

Starting with php73, ldap servercontrols were included. One of those
servercontrols, LDAP_CONTROL_PAGEDRESULTS, is the one in charge of
controlling paged results.

So, we are going to add some conditional code here:

1) if php < 7.3, use old paged result functions.
2) if php >= 7.3, switch to LDAP_CONTROL_PAGEDRESULTS servercontrol.

With a TODO about removing 1) in Moodle 4.1, once php73 becomes required.
2020-01-16 19:16:21 +01:00
Sara Arjona 36984d4d1d weekly release 3.8.1+ 2020-01-16 17:19:21 +01:00
Sara Arjona bcb56b9071 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-01-16 17:19:19 +01:00
David Mudrák 82505a878b MDL-66712 enrol: Fix the reported days of inactivity on unenrolment
There were two problems here. Firstly, the $days was not correctly
calculated due to missing parentheses. Secondly, the sentence had
grammar issues.
2020-01-16 13:44:22 +01:00
Jun Pataleta 8e45839933 MDL-66220 mod_forum: Prevent from replying to a post the user can't see 2020-01-16 15:06:11 +08:00
Jun Pataleta e1eea0cf36 MDL-66220 mod_forum: Cache result of forum_user_can_see_post()
* Cache the result of this function to avoid doing multiple DB calls
for the same post when loading posts in a discussion.
2020-01-16 15:06:11 +08:00
Jun Pataleta cf32c9116b MDL-66220 mod_forum: Additional unit test for can_reply_to_post 2020-01-16 15:06:11 +08:00
Andrew Nicols cdf31c3d57 Merge branch 'wip-MDL-66918-38stable' of https://github.com/Beedell/moodle into MOODLE_38_STABLE 2020-01-16 11:43:18 +08:00
Eloy Lafuente (stronk7) 0c01f98410 Merge branch 'MDL-67625-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-01-16 00:26:57 +01:00
Sara Arjona e7721e50c6 Merge branch 'MDL-67379-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-01-15 22:12:41 +01:00
Eloy Lafuente (stronk7) 8f112b1064 Merge branch 'MDL-67622_38' of git://github.com/dmonllao/moodle into MOODLE_38_STABLE 2020-01-15 18:55:55 +01:00
Shamim Rezaie 65fcabe132 MDL-67424 mod_forum: error on complete report when no rating or grade 2020-01-16 03:17:52 +11:00
Shamim Rezaie 2c76c1893f MDL-67424 report_outline: behat user report with a no-grade forum 2020-01-16 03:17:52 +11:00
Shamim Rezaie e27ac65f3d MDL-67379 libraries: Upgrade scssphp to 1.0.6 2020-01-16 00:26:47 +11:00
Sara Arjona 3d8f92e4be Merge branch 'MDL-67617-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2020-01-15 12:43:10 +01:00
Sara Arjona 35fd550dc9 Merge branch 'MDL-67638-38' of https://github.com/nguyenphuctien/moodle into MOODLE_38_STABLE 2020-01-15 12:19:44 +01:00
Andrew Nicols 712b21c6e7 Merge branch 'MDL-67486-swap-cron-lock-MOODLE_38_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_38_STABLE 2020-01-15 13:53:56 +08:00
Mark Johnson b5410980aa MDL-67674 Cache: Lock rebuilding of the course category tree cache 2020-01-15 00:02:06 +01:00
Sara Arjona b2c6ab2d0a Merge branch 'MDL-65573-38-2' of git://github.com/peterRd/moodle into MOODLE_38_STABLE 2020-01-14 12:20:09 +01:00
Andrew Nicols 4fb25b5b6c Merge branch 'MDL-66721-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2020-01-14 14:09:42 +08:00
Andrew Nicols 3467ce09c8 MDL-67684 core: Add missing li tag 2020-01-14 08:47:08 +08:00
Andrew Nicols 83d4daee8d Merge branch 'MDL-35971-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-14 08:32:14 +08:00
AMOS bot e653281d4a Automatically generated installer lang files 2020-01-14 00:10:24 +00:00
Peter 03b372b804 MDL-65573 mod_forum: Set userid properly after split
* Set the discussion's userid properly when splitting a discussion.
* Update step to correct existing incorrect records.
2020-01-14 07:37:41 +08:00
Eloy Lafuente (stronk7) c1724722c8 Merge branch 'MDL-65649-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-01-13 18:56:52 +01:00
Eloy Lafuente (stronk7) d1b3b4af95 Merge branch 'MDL-65987-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-01-13 18:37:30 +01:00
Marina Glancy f9a80888bc MDL-67680 core: Catch PHP exceptions in the after_config callback 2020-01-13 17:01:27 +01:00
Sara Arjona 0ebf9b16ea Merge branch 'MDL-59817-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-01-13 14:26:49 +01:00
Kiet.Chan 01fd8ac565 MDL-67583 themes: Popover placement should react to scroll event 2020-01-13 17:29:46 +07:00
Bas Brands 80a5640ed2 MDL-67472 theme_boost: configurable sass variable for drawer bgcolour 2020-01-13 09:16:36 +01:00
Tien Nguyen Phuc decf6b62ae MDL-67638 Course: update course timemodified on bulk category move 2020-01-13 10:42:06 +07:00
Andrew Nicols 5b31655420 Merge branch 'MDL-67204-38' of https://github.com/mwehr/moodle into MOODLE_38_STABLE 2020-01-13 08:53:56 +08:00
Brendan Heywood 8e725dd819 MDL-67486 cron: Improve throughput by holding cron lock for less time 2020-01-12 00:45:02 +11:00
Tim Hunt d0c48cd693 MDL-67653 questions: prevent the flag flickering as the page loads 2020-01-10 14:28:16 +00:00
Andrew Nicols b2f13181ec MDL-59817 atto_accessibilitychecker: Handle transparency properly
Some browsers, notably Firefox, do not return the computed style for
background colour in a computed RGB format. Instead they return the RGBA
where the alpha channel is set to fully transparent.

To solve this we need to work up the hierarchy and compute the
background colour for each parent node until we reach full alpha (1).

We can use a standard calculation to approximate the value for the
resultant element background by multiplying the alpha of the current
transparent (or semi-transparent) node with the R, G, or B channel in
question, and that of the parent node's background colour.

There are cases where this will not be 100% accurate - notably where
there is some additional content in addition to the parent background,
but this gives us a reasoable approximation for the majority of cases.
Additionally the code has never considered the full set of node content
when calculating this information.
2020-01-10 15:26:51 +08:00
Andrew Nicols fcdc318982 MDL-67656 behat: Removed nested spin 2020-01-10 13:37:43 +08:00
Andrew Nicols c89d25a046 MDL-67656 behat: Fix usleep call in spin 2020-01-10 13:37:36 +08:00
Andrew Nicols 77be1e3fe3 Moodle release 3.8.1 2020-01-10 13:03:44 +08:00
Andrew Nicols de7b3e37b3 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-01-10 13:03:42 +08:00
AMOS bot ffd8dfcf27 Automatically generated installer lang files 2020-01-10 00:12:13 +00:00
Luca Bösch b116f84589 MDL-67625 quiz: only section titles should be large when editing. 2020-01-09 17:23:11 +01:00
Luca Bösch 36e70e664b MDL-67617 gradereport_singleview: Style the form element with bs classes 2020-01-09 17:22:18 +01:00
Mario Wehr 0debc8f826 MDL-67204 assign task: Use lastruntime from task_scheduled 2020-01-09 17:11:20 +01:00
John Beedell 81801a0685 MDL-66918 behat: Behat app step failing 2020-01-09 15:57:27 +00:00
Sara Arjona 8a82f51043 weekly release 3.8+ 2020-01-09 15:42:53 +01:00
Jun Pataleta 68cab31dba Merge branch 'MDL-67544-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-01-09 15:22:35 +08:00
Andrew Nicols 3f50c24fc3 MDL-67544f= mod_forum: Correct "for" attribute on private checkbox 2020-01-09 14:55:52 +08:00
Andrew Nicols 9973646ca7 MDL-67544 mod_forum: Ensure post actions menu id is unique 2020-01-09 14:09:21 +08:00
Andrew Nicols f14420c739 Merge branch 'MOODLE_38_MDL-67485' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2020-01-09 12:40:19 +08:00
Mikhail Golenkov 70868d8648 MDL-67485 task: Release the task runner lock before throwing exception. 2020-01-09 14:49:38 +11:00
Andrew Nicols 8f45c9b6a5 Merge branch 'MDL-67596-cron-ramp-up-MOODLE_38_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_38_STABLE 2020-01-09 09:32:49 +08:00
Brendan Heywood 1f5c6c6b7a MDL-67596 cron: Allow runners to ramp up instantly 2020-01-09 11:07:19 +11:00
Eloy Lafuente (stronk7) 26999dda23 Merge branch 'MDL-67544-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-01-08 16:35:32 +01:00
Eloy Lafuente (stronk7) 022206f2fe Merge branch 'MDL-67533-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-08 16:31:18 +01:00
Jake Dallimore f9e0f61467 MDL-67637 core_message: only preview lastmessage text if safe to do so
If any html/script tags are found in the text() value, don't display it.
2020-01-08 12:31:17 +01:00
Jun Pataleta c07bc83480 MDL-67533 mod_forum: Remove duplicate Re in experimental view subject 2020-01-08 16:29:43 +08:00
Jun Pataleta de2238985d MDL-35971 mod_forum: Add proper discussion list table description 2020-01-08 16:04:20 +08:00
Sara Arjona 7d7d3520a7 Merge branch 'MDL-67417-38' of https://github.com/KietChan/moodle into MOODLE_38_STABLE 2020-01-08 08:26:44 +01:00
Andrew Nicols f34f8131ba MDL-67544 mod_forum: Ensure that private reply checkbox has unique id 2020-01-08 15:26:03 +08:00
Sara Arjona 85ba5d1d88 Merge branch 'MDL-67510-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-08 08:11:01 +01:00
Andrew Nicols e0b8a3b17a Merge branch 'MDL-64764-38' of git://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-01-08 08:30:33 +08:00
Eloy Lafuente (stronk7) 5577e472e5 Merge branch 'MDL-67469-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-07 22:59:51 +01:00
Marina Glancy 571f508d4e MDL-64764 core_admin: allow to submit empty list of allowed roles.
Co-authored-by: Paul Holden <paulh@moodle.com>
2020-01-07 10:01:33 +00:00
Andrew Nicols 764ec8d7fb Merge branch 'MDL-65849-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-01-07 13:26:56 +08:00
Andrew Nicols eb04dc8792 Merge branch 'MDL-66938-38' of https://github.com/grabs/moodle into MOODLE_38_STABLE 2020-01-07 12:49:42 +08:00
Paul Holden 2f19ac90c6 MDL-66237 message_popup: Get redirecturl from notification contexturl 2020-01-07 11:18:24 +08:00
Andrew Nicols 6fefb88819 MDL-67114 mod_wiki: Whitespace fix 2020-01-07 11:05:02 +08:00
Andrew Nicols 1b2a8dad89 Merge branch 'MDL-67114_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-01-07 11:04:55 +08:00
Andrew Nicols ec63d3eab4 Merge branch 'MDL-66871-38-v2' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-01-07 08:54:44 +08:00
Bas Brands 63052bffb0 MDL-66721 core_chooser: height correction for chooser modal 2020-01-06 10:13:12 +01:00
Andrew Nicols 5f4250dc43 MDL-67544 form: Ensure that form errors have a unique id 2020-01-06 15:01:07 +08:00
Andrew Nicols b024306e5c MDL-67544 mod_forum: Add missing label for discussion move 2020-01-06 15:01:07 +08:00
Andrew Nicols 0d285e9334 MDL-67544 mod_forum: Add missing menuitem roles 2020-01-06 15:01:07 +08:00
Andrew Nicols bed212f61b MDL-67544 mod_forum: Correct aria-labelledby node 2020-01-06 15:01:07 +08:00
Andrew Nicols 14d58697a3 MDL-67544 mod_forum: Correct aria-controls to point to valid node 2020-01-06 15:01:07 +08:00
Andrew Nicols e98103354d MDL-67544 mod_forum: Add missing aria label for grade search 2020-01-06 15:01:07 +08:00
Andrew Nicols d8dfb98417 MDL-67544 core: Ensure unique IDs for YUI dialogues 2020-01-06 15:01:07 +08:00
Andrew Nicols 3684d9e03c MDL-67544 theme: Ensure that search box is in valid li 2020-01-06 15:01:06 +08:00
Andrew Nicols 629ef7772f MDL-67544 mod_forum: Add default role for favourite toggle 2020-01-06 15:01:06 +08:00
Andrew Nicols 9e57c09d7b MDL-67544 mod_forum: Add missing aria label for discussion actions 2020-01-06 15:01:06 +08:00
Andrew Nicols 949d3f1c02 MDL-67544 mod_forum: Correct aria-role => aria-live 2020-01-06 15:01:06 +08:00
Andrew Nicols 11524653b0 MDL-67544 mod_forum: Correct aria-role => role 2020-01-06 15:01:06 +08:00
David Monllaó 74299cd64b MDL-67622 mlbackend_python: Fix f1score calculation 2020-01-06 13:16:38 +08:00
Jun Pataleta f9b2f6634d MDL-67510 tool_dataprivacy: Fix the reply-to name of the privacy officer 2020-01-06 11:36:49 +08:00
Simey Lameze dafe4c5a78 MDL-66871 calendar: fix deprecated parameter in the phpDoc 2020-01-06 10:42:22 +08:00
Simey Lameze 550c4e1c42 MDL-66871 calendar: add unit test coverage for ics importing 2020-01-06 10:42:22 +08:00
Simey Lameze 0287928c4b MDL-66871 calendar: fix ics importing logic 2020-01-06 10:42:22 +08:00
Luca Bösch 50bcb24e09 MDL-65987 mod_forum: Add string 'Advanced' for the advanced editor.
AMOS BEGIN
    CPY [advanced,moodle],[showadvancededitor,moodle]
   AMOS END
2020-01-06 09:41:51 +08:00
Jake Dallimore 701d27e5d9 Merge branch 'MDL-67336-38' of https://github.com/roland04/moodle into MOODLE_38_STABLE 2020-01-06 09:36:53 +08:00
Andreas Grabs 13d5d3edb1 MDL-66938 mod_feedback: Export includes unwanted html in field names 2020-01-05 19:33:27 +01:00
Eloy Lafuente (stronk7) abc8f149ce MDL-67114 core: php74 fix. Fix use of scalar as array in core
There are various places where it's not guaranteed that the
variable being used is array, and instead, can be null, bool, int...

We need to check that because php74 warns about it.

Where possible we have used the coalesce operator as
replacement for isset() ternary operations.
2020-01-03 11:33:23 +01:00
Eloy Lafuente (stronk7) c3a6437220 MDL-67114 scssphp: php74 compatibility local fixes
Note they are already available upstream, versions 1.0.4 and up so,
in next upgrade they will be fixed.
2020-01-03 11:33:23 +01:00
Eloy Lafuente (stronk7) c910982c49 MDL-67114 mustache: php74 fix. Fix use of scalar as array
Trying to use values of type null, bool, int, float or resource as an
array (such as $null["key"]) will now generate a notice. This does not
affect array accesses performed by list().

RFC: https://wiki.php.net/rfc/notice-for-non-valid-array-container
2020-01-03 11:33:23 +01:00
Jake Dallimore 4d5849b0e4 weekly release 3.8+ 2020-01-03 11:25:08 +08:00
Jake Dallimore cc0b18ec0e Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-01-03 11:25:05 +08:00
AMOS bot 3c7ebda9a5 Automatically generated installer lang files 2020-01-03 00:12:10 +00:00
Adrian Greeve 19401adbdd Merge branch 'MDL-67599-38' of https://github.com/snake/moodle into MOODLE_38_STABLE 2020-01-02 15:16:18 +08:00
Jake Dallimore a7fb29a8ff MDL-67599 behat: fix behat tests assuming Jan 2020 is a future date 2020-01-02 13:52:24 +08:00
Jake Dallimore c53861fd66 Merge branch 'MDL-67598_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-01-02 10:19:30 +08:00
AMOS bot 88d4a01089 Automatically generated installer lang files 2020-01-02 00:10:23 +00:00
Eloy Lafuente (stronk7) b71e7b79e8 MDL-67598 unit tests: Pass day of month without leading zero
Note this fixes the unit tests. Still the calendar API itself
should be able to manage this cases, both casting (int) or
being stricter about what's allowed there (param hinting).

But that falls out from this issue and the code that introduced
the failures, so the pure unit-test fix has been applied.
2020-01-02 00:10:16 +01:00
Eloy Lafuente (stronk7) 6c7199a426 Merge branch 'MDL-67593-38' of https://github.com/snake/moodle into MOODLE_38_STABLE 2019-12-31 10:50:41 +01:00
Jake Dallimore 827f3cd471 MDL-67593 core_iplookup: update lang string describing download process
Let users know they need to register on maxmind before granted download
access.
2019-12-31 15:54:33 +08:00
Jake Dallimore 0260074ba1 MDL-67593 core_iplookup: use MaxMind test database in unit tests
Instead of downloading a live database (now not available publicly)
use a local test database.
2019-12-31 15:54:27 +08:00
Jun Pataleta edab811944 Merge branch 'MDL-63996-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2019-12-31 15:19:17 +08:00
Jun Pataleta 348ceb4631 Merge branch 'MDL-67487-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2019-12-31 11:55:55 +08:00
Jun Pataleta 5544dc1cc7 Merge branch 'MDL-67470-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2019-12-31 11:29:52 +08:00
Bas Brands c02d168cd7 MDL-67470 theme_boost: settings_menu_proxy correct background
the .region_main_settings_proxy was introduced in MDL-56582 using the
wrong bootstrap variable for the background color
2019-12-31 09:59:51 +08:00
Adrian Greeve 53fde6278a Merge branch 'MDL-67233-38' of git://github.com/peterRd/moodle into MOODLE_38_STABLE 2019-12-30 12:56:59 +08:00
Jun Pataleta 25221f73a6 Merge branch 'MDL-67491-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2019-12-30 12:41:40 +08:00
Didier 'OdyX' Raboud b901252f6d MDL-67491 core_message: Primary'fy the contact request counts 2019-12-30 11:47:36 +08:00
Eloy Lafuente (stronk7) be73a0ed4e Merge branch 'MDL-67523-38' of git://github.com/marinaglancy/moodle into MOODLE_38_STABLE 2019-12-29 23:32:07 +01:00
Eloy Lafuente (stronk7) e654258446 Merge branch 'MDL-67527-38-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2019-12-29 23:27:13 +01:00
Adrian Greeve 8c14984028 Merge branch 'MDL-63107-38' of git://github.com/bmbrands/moodle into MOODLE_38_STABLE 2019-12-27 16:34:10 +08:00
Adrian Greeve dd6bbf3962 Merge branch 'MDL-65809-38-onlyenv' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2019-12-24 14:54:57 +08:00
Adrian Greeve 01e84ac720 Merge branch 'MOODLE_38_STABLE-MDL-67524' of https://github.com/yao9394/moodle into MOODLE_38_STABLE 2019-12-23 10:30:23 +08:00
John Yao b423c5ad38 MDL-67524 book: fixing view hidden chapter issue
* Users who has permission should be able to view after turning editing off
2019-12-23 09:48:31 +11:00
AMOS bot f70cc95a13 Automatically generated installer lang files 2019-12-21 00:10:57 +00:00
Luca Bösch d9887f7350 MDL-67487 forms: align "Custom" checkbox for course section name. 2019-12-20 13:48:48 +01:00
Eloy Lafuente (stronk7) f2db42f921 weekly release 3.8+ 2019-12-20 11:02:10 +01:00
Eloy Lafuente (stronk7) b85896f7bc NOBUG: Fixed SVG browser compatibility 2019-12-20 11:02:08 +01:00
Eloy Lafuente (stronk7) 6350a758d7 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2019-12-20 11:02:07 +01:00
Eloy Lafuente (stronk7) a3ea0db227 Merge branch 'MDL-67151-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2019-12-19 23:01:23 +01:00
Shamim Rezaie cd62c520e2 MDL-67151 qtype_numerical: convert the tolerance to string before saving
Fix the sqlserver issue when saving a number into a text field
2019-12-20 01:20:12 +11:00
Marina Glancy 86d4aca10d MDL-67523 core_admin: do not require admin to view category
Revert changes from MDL-58439 (in this file only)
2019-12-19 10:15:10 +01:00
Jun Pataleta 40ba9d9cfa Merge branch 'MOODLE_38_STABLE_MDL-63795_core_setting_defaults' of https://github.com/mattporritt/moodle into MOODLE_38_STABLE 2019-12-19 11:17:41 +08:00
Matt Porritt 5c510b92e2 MDL-63795 Administration: CLI upgrade apply all settings
This patch fixes a regression caused by MDL-62777.  MDL-62777 added output to inform
administrators of new default settings.  However, the recursion in the code did not
handle new settings made available as the result of the defaults of other settings
being set.
This patch fixes the issue, now all defaults are correctly set, even those exposed
after other defaults are set.
2019-12-19 12:22:01 +11:00
Eloy Lafuente (stronk7) 754ecb5768 Merge branch 'MDL-67151-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2019-12-18 23:05:56 +01:00
David Mudrák e7a122bba9 MDL-67527 lang: Propagate the string fixes to Behat and other places 2019-12-18 21:22:15 +01:00
Helen Foster 13edb4f9f9 MDL-67527 lang: Import fixed English strings (en_fix) 2019-12-18 21:22:15 +01:00
Eloy Lafuente (stronk7) db394d5b08 Merge branch 'MDL-64695-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2019-12-18 19:56:10 +01:00
Eloy Lafuente (stronk7) d18802eb2f Merge branch 'MDL-67464-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2019-12-17 19:37:00 +01:00
Mikel Martín ead3a41240 MDL-67336 mod_forum: Fixing forum inline reply filtering before saving 2019-12-17 11:59:02 +01:00
Jake Dallimore ae7b1be0b6 Merge branch 'MDL-67304_38' of git://github.com/dmonllao/moodle into MOODLE_38_STABLE 2019-12-17 13:47:11 +08:00
Jake Dallimore cca393d2f6 Merge branch 'MDL-65735-38' of https://github.com/paulholden/moodle into MOODLE_38_STABLE 2019-12-17 13:25:24 +08:00
Eloy Lafuente (stronk7) 69430157a3 Merge branch 'MDL-67522-38' of git://github.com/marinaglancy/moodle into MOODLE_38_STABLE 2019-12-17 00:22:33 +01:00
Eloy Lafuente (stronk7) f077d9fbea Merge branch 'MDL-67410-38' of https://github.com/felicemcc/moodle into MOODLE_38_STABLE 2019-12-16 19:18:31 +01:00
Bas Brands 8c20e76d43 MDL-63107 mod_book: rewrite styles for book chapter block
* using flexbox to position titles
* fix for title overlap on edit mode
* show correct bullets, number or indent
2019-12-16 13:30:28 +01:00
Jake Dallimore a0ac535549 Merge branch 'MDL-67327-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2019-12-16 15:12:35 +08:00
Andrew Nicols 11260d5f3f MDL-63996 core/tags: Pending JS for all tag code 2019-12-16 14:03:46 +08:00
Andrew Nicols 67fc9943b9 MDL-63996 behat: Fix multi-tag autocomplete usage 2019-12-16 14:00:04 +08:00
Jake Dallimore 29a5f6eaa2 Merge branch 'MDL-66503-38' of git://github.com/abgreeve/moodle into MOODLE_38_STABLE 2019-12-16 09:11:33 +08:00
Marina Glancy a6fd7ada34 MDL-67522 core_lock: fix mistype in config-dist 2019-12-14 19:29:40 +01:00
AMOS bot c86c872db3 Automatically generated installer lang files 2019-12-14 00:10:53 +00:00
Jun Pataleta 7b4848ca80 MDL-67469 tool_dataprivacy: Put back missing test code
This patch simply brings back the missing test code for
\tool_dataprivacy_api_testcase::test_approve_data_request_non_dpo_user()
2019-12-13 10:05:24 +08:00
AMOS bot d9e3c11834 Automatically generated installer lang files 2019-12-13 00:11:09 +00:00
Felice Candilio 1437e35d2d MDL-67410 Enrolments: Cast the perpage parameter to integer in JS
The parameter called "perpage" on the call is treated as a string,
therefore, It could have a value 15001 resulting from a "+" operation
of the "1500" string and the number 1. That big number makes
the AJAX call extremely slow.

The proposed solution is to parse the number as an integer
when performing the addition.
2019-12-12 22:25:55 +01:00
Paul Holden 914d5ab82d MDL-65735 report_progress: reset URL start parameter in initials bars. 2019-12-12 18:24:12 +00:00
Paul Holden fbf0c8810b MDL-64695 tool_dataprivacy: filter site fullname in outgoing messages. 2019-12-12 18:20:22 +00:00
Paul Holden 25da0b49ea MDL-64695 privacy: filter site fullname in data export. 2019-12-12 18:20:22 +00:00
Sara Arjona 70e47fdc2a MDL-67464 core_h5p: use h5p.com URLs in behat tests
The H5P content used in behat for validating external URLs
behaviour shouldn't point h5p.org because it may stop working
(it's not for real content). These content have been moved to
moodle.h5p.com (payment account).
Besides, the scenarios loading content from external URLs
have been labelel with @external.
2019-12-12 16:07:17 +01:00
Eloy Lafuente (stronk7) 3bfdc05d3a weekly release 3.8+ 2019-12-12 13:26:31 +01:00
Eloy Lafuente (stronk7) d64a94713e NOBUG: Fixed SVG browser compatibility 2019-12-12 13:26:29 +01:00
Eloy Lafuente (stronk7) 8d7f1fd428 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2019-12-12 13:26:28 +01:00
Andrew Nicols a7268b4f8a MDL-67327 js: Make requirejs.php more fault tolerant 2019-12-12 16:37:08 +08:00
Jake Dallimore 4792cc508e Merge branch 'MDL-67154-38' of git://github.com/ferranrecio/moodle into MOODLE_38_STABLE 2019-12-12 09:05:11 +08:00
Ferran Recio 7bc625d846 MDL-67154 theme_classic: fixing firefox printing 2019-12-11 16:57:36 +01:00
AMOS bot 6dc25cc165 Automatically generated installer lang files 2019-12-11 13:50:07 +00:00
AMOS bot 747000a2fe Automatically generated installer lang files 2019-12-11 13:50:07 +00:00
Kiet.Chan bec0808b18 MDL-67417 theme_boost: Tooltip icon stop working after closing using ESC 2019-12-11 15:00:14 +07:00
Andrew Nicols 7f40272535 Merge branch 'MDL-67458-38' of https://github.com/snake/moodle into MOODLE_38_STABLE 2019-12-11 10:27:19 +08:00
Jake Dallimore f9735bbde7 MDL-67458 core: removing stale cohortroles and role assignments 2019-12-11 09:36:54 +08:00
Jake Dallimore 4dc1413cc7 MDL-67458 tool_cohortroles: remove role mapping for deleted roles
Before syncing anything, clean up records pointing to deleted roles.
2019-12-11 09:36:15 +08:00
Adrian Greeve 79b6a4acac MDL-66503 themes: Set the embed page to display block. 2019-12-11 09:32:54 +08:00
Andrew Nicols cf50c5f1cb Merge branch 'MDL-67434-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2019-12-10 17:29:02 +08:00
Marina Glancy fc74a6e6d2 MDL-66936 mod_url: revert MDL-65024 adding fullurl to modinfo
This reverts commit cc56e409c3, reversing
changes made to 01cdf16c0e.
2019-12-10 15:27:59 +08:00
Jonathon Fowler a48bd1c4e3 MDL-66936 url: fix error when modinfo cache is rebuilt non-interactively 2019-12-10 15:27:52 +08:00
Jake Dallimore ee215ddd43 Merge branch 'MDL-67179-38' of git://github.com/Chocolate-lightning/moodle into MOODLE_38_STABLE 2019-12-10 15:03:24 +08:00
Mathew May f3e7533b9d MDL-67179 core: Add missing grading pix 2019-12-10 14:38:55 +08:00
Andrew Nicols 921469db8f Merge branch 'MDL-67277-38-strongtopics' of git://github.com/mudrd8mz/moodle into MOODLE_38_STABLE 2019-12-10 12:49:18 +08:00
Jake Dallimore b99f2bce77 Merge branch 'MDL-67154-38' of git://github.com/ferranrecio/moodle into MOODLE_38_STABLE 2019-12-10 11:53:56 +08:00
Jake Dallimore 7df9eb36cd Merge branch 'MDL-67451-38' of git://github.com/sarjona/moodle into MOODLE_38_STABLE 2019-12-10 10:37:15 +08:00
Jake Dallimore aee09a6357 Merge branch 'MDL-66708-MOODLE_38_KeyGenCache' of https://github.com/Cengage/moodle into MOODLE_38_STABLE 2019-12-10 09:12:13 +08:00
David Monllaó 8ae7a4ad68 MDL-67304 analytics: Add missing png svg incorrect icon
Credit to jaked for the icons and the testing instructions
2019-12-10 09:01:43 +08:00
Andrew Nicols d911548cf4 Merge branch 'MDL-67152-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2019-12-10 08:21:20 +08:00
Paul Holden 7a4b6df0fe MDL-65649 backup: ensure valid course URL for async mode. 2019-12-09 23:34:30 +00:00
Shamim Rezaie c8435454a7 MDL-67152 calendar: The day view should start from the current day 2019-12-10 06:58:18 +11:00
Jake Dallimore df2bda2f00 Merge branch 'MDL-67392-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2019-12-09 14:46:56 +08:00
Andrew Nicols bf52b2a3bc Merge branch 'MDL-60975-38' of https://github.com/Kathrin84/moodle into MOODLE_38_STABLE 2019-12-09 13:12:59 +08:00
Frédéric Massart f130c810f9 MDL-67434 javascript: Use static get_string after recycling promise 2019-12-09 10:12:43 +08:00
Paul Holden f0a2800a3a MDL-66024 tool_uploadcourse: validate shortname/fullname field length. 2019-12-05 23:11:19 +00:00
Kathrin Osswald d294483e9c MDL-60975 behat tests: Added search for admin setting filepickers 2019-12-05 14:59:18 +01:00
Sara Arjona ca89aca702 MDL-65809 environment: mbstring extension required 2019-12-05 14:00:16 +01:00
Sara Arjona 7e561cc4a8 MDL-65809 environment: PHP 7.2 required 2019-12-05 14:00:16 +01:00
Sara Arjona 57d601bc23 MDL-65809 environment: postgres requirement up to 9.5 2019-12-05 14:00:16 +01:00
Sara Arjona 7cdc332930 MDL-65809 environment: mariadb requirement up to 10.2 2019-12-05 14:00:16 +01:00
Sara Arjona 484eab15e3 MDL-65809 environment: 3.5 (LTS) required 2019-12-05 14:00:16 +01:00
Sara Arjona 0a0d55a3e1 MDL-65809 environment: 3.9 base information
This is a direct copy of the 3.8 branch to have changes
under control easier in next commits.
2019-12-05 14:00:16 +01:00
Eloy Lafuente (stronk7) 773b1f738f weekly release 3.8+ 2019-12-05 13:24:15 +01:00
Eloy Lafuente (stronk7) 96475f49de NOBUG: Fixed SVG browser compatibility 2019-12-05 13:24:13 +01:00
Adrian Greeve 9a64cc2b0b Merge branch 'MDL-65620-38' of git://github.com/aanabit/moodle into MOODLE_38_STABLE 2019-12-05 09:26:43 +08:00
Sara Arjona 56c570f68a MDL-67451 badges: use the site OB version as default 2019-12-04 21:27:16 +01:00
Sara Arjona ab2bb07f2e Merge branch 'MDL-67404_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2019-12-04 11:24:56 +01:00
Amaia Anabitarte d0aa6bf098 MDL-65620 core_message: Notification preferences behat tests 2019-12-04 11:03:49 +01:00
Ferran Recio 132e638209 MDL-67154 theme_boost: fixing firefox printing 2019-12-04 10:53:53 +01:00
Amaia Anabitarte 6713912510 MDL-65620 core_message: User preference generator 2019-12-04 10:03:34 +01:00
Amaia Anabitarte 96c48a5058 MDL-65620 core_message: Default notification preferences 2019-12-04 10:03:34 +01:00
Adrian Greeve d3de95f446 Merge branch 'MDL-40360-38' of git://github.com/lucaboesch/moodle into MOODLE_38_STABLE 2019-12-04 11:50:48 +08:00
Andrew Nicols 6d98038c8f Merge branch 'MDL-67359-38' of git://github.com/Chocolate-lightning/moodle_forum-project into MOODLE_38_STABLE 2019-12-04 10:38:12 +08:00
David Mudrák 83e5983a88 MDL-67277 forum: Replace the HTML comments with Mustache comments
It does not seem necessary to have the actual HTML sent to browsers full
of these developer-focused comments.
2019-12-03 20:16:53 +01:00
David Mudrák 0ddd9c54bc MDL-67277 forum: Remove the pinned class from the first cell
There should be no need to have it, and the name is confusing here.
2019-12-03 20:16:53 +01:00
David Mudrák 39bd01c11a MDL-67277 forum: Do not display discussion topics in bold
The topics are now inside a table header cell, which shows them in bold
by default.
2019-12-03 20:15:50 +01:00
David Mudrák 1e58e180d4 MDL-67277 forum: Apply CSS class describing the discussion status
This is to allow the themes to style pinned, favourited, subscribed and
discussions with unread replies.
2019-12-03 20:15:08 +01:00
Shamim Rezaie 163bff4a18 MDL-67151 qtype_calculatedsimple: Support for the scientific format 2019-12-03 16:57:41 +11:00
Shamim Rezaie 910c2ab7b4 MDL-67151 qtype_calculated: Support for the scientific format 2019-12-03 16:57:41 +11:00
Shamim Rezaie fcf199b0ec MDL-67151 qtype_numerical: Support for the scientific format 2019-12-03 16:57:41 +11:00
Shamim Rezaie bb511f30d6 MDL-67151 core_question: Support scientific format at question preview 2019-12-03 16:57:41 +11:00
Shamim Rezaie 481ad40e0e MDL-67151 forms: Support for the scientific format in the float element 2019-12-03 16:57:41 +11:00
Shamim Rezaie 031f3a1d4b MDL-67151 core: format_float can auto detect number of decimal points 2019-12-03 16:57:36 +11:00
Mathew May 5548689ead MDL-67359 mod_forum: Relocate notification templates to reallign it 2019-12-03 12:57:41 +08:00
Sara Arjona f751a8edbe Merge branch 'wip-MDL-67339-38stable' of https://github.com/Beedell/moodle into MOODLE_38_STABLE 2019-12-02 18:06:31 +01:00
John Beedell 0de719024c MDL-67339 behat: Enhance Behat exception message 2019-12-02 09:53:35 +00:00
Shamim Rezaie ac084982cf MDL-67392 mod_forum: Fix unescaped quotes issue in template 2019-12-02 20:50:40 +11:00
Jake Dallimore d3158895a8 Merge branch 'MDL-66581-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2019-12-02 16:12:47 +08:00
Jun Pataleta 0e58303ea3 MDL-66581 auth: Properly assign the link attribute 2019-12-02 15:30:39 +08:00
Iñigo Zendegi f0d380703a MDL-66581 auth: Do string concatenation for the password change URL
This reverts the change introduced by MDL-59298 where the password
change URL data is being assigned with a moodle_url object instead
of concatenating it.
2019-12-02 15:30:39 +08:00
Jake Dallimore baf264ebc8 Merge branch 'MDL-66877-38' of git://github.com/jleyva/moodle into MOODLE_38_STABLE 2019-12-02 10:02:34 +08:00
Luca Bösch e61f7ba324 MDL-40360 gradingform_rubric: remove unused class 'label' for a label. 2019-11-30 10:28:22 +01:00
Shamim Rezaie afda296526 MDL-65849 mod_forum: Add course param to the author's profile url 2019-11-29 20:58:37 +11:00
Eloy Lafuente (stronk7) 6d6b14e8a4 weekly release 3.8+ 2019-11-29 00:45:52 +01:00
Juan Leyva 27d6bd5de1 MDL-66877 mod: Fix unfiltered activity names in page headings 2019-11-28 17:24:31 +01:00
Juan Leyva 907db7f06b MDL-66877 mod: Fix WebServices returning unfiltered activity names 2019-11-28 17:24:31 +01:00
Eloy Lafuente (stronk7) 33bfd161cd MDL-67404 composer: update to newer versions
(using php71 for this branch)

Without changing any requirement, just an update
to get latest versions onboard, some fixing known
php 7.4 issues.
2019-11-28 13:12:23 +01:00
Andrew Nicols f88b4e9f81 MDL-67348 theme: Return CSS from localcache if available 2019-11-27 10:38:52 +08:00
Eloy Lafuente (stronk7) 114f0b612f Merge branch 'MDL-67300-m38' of https://github.com/sammarshallou/moodle into MOODLE_38_STABLE
(fix trailing whitespace case)
2019-11-26 22:29:37 +01:00
Jun Pataleta a5f1dd6cb1 Merge branch 'MOODLE_38_MDL-56886' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2019-11-26 22:32:41 +08:00
Luca Bösch 283cd6db67 MDL-67210 tool_uploadcourse: Allow only 0 and 1 for visible value. 2019-11-26 08:30:34 +01:00
Eloy Lafuente (stronk7) 3eac4851e3 MDL-67307 core: Fix onject creation from empty value cases
The "creating default object from empty value" warning is now consistently
thrown if a falsy value is promoted into an stdClass object. Previously some
cases like `$null->prop[0] = $val` missed this warning.
2019-11-26 14:15:06 +08:00
Sara Arjona 006ec3c96f MDL-67042 customfield: Add behat tests to check hidden fields
Fields with the visibility different to Everyone should
be never displayed in the available filters custom field.
2019-11-26 11:59:41 +08:00
Sara Arjona cabc1dafa9 MDL-67042 customfield: Display only fields visible to everybody
When defining the available filters for the Dashboard, only the
fields visible to everyone should be displayed in the Custom field
filter.
2019-11-26 11:59:36 +08:00
Eloy Lafuente (stronk7) 1b4c878f48 MDL-66966 tcpdf: Update readme to point to manual commits to review
Apart from the main import of the library, there are a couple of
commits (with corresponding PRs upstream) that have been added to
provide php74 compatibility.

This commit addes them to the instructions, to ensure that they
will be reviewed on next import.
2019-11-26 11:43:34 +08:00
Eloy Lafuente (stronk7) 91286bb138 MDL-66966 tcpdf: Silence non-existing K_PATH_CACHE
I was fixing this adding a extra dir_exists() check that
is better than the silence operator but that was that already
there was a PR using @. So went to it.

This is https://git.io/JeKft
2019-11-26 11:43:25 +08:00
Eloy Lafuente (stronk7) 71af7accff MDL-66966 tcpdf: Some more curly braces to fix
This is https://git.io/JeKfT
2019-11-26 11:43:18 +08:00
Eloy Lafuente (stronk7) ce97501b2b MDL-66966 tcpdf: PHP 7.4 - cannot use array offset on integers
This is https://git.io/JeKfU
2019-11-26 11:43:10 +08:00
Eloy Lafuente (stronk7) dadb3cb372 MDL-66966 tcpdf: Bump to tcpdf 6.3.2
Bug fixes and php74 support.
2019-11-26 11:43:00 +08:00
Peter 5cb05d8b77 MDL-67233 mod_timeline: Allow events with only open dates in the future 2019-11-26 11:27:01 +08:00
Bas Brands e29b355121 MDL-67222 tool_lp: update css classes for Bootstrap 4.3 2019-11-26 10:12:46 +08:00
Mikhail Golenkov 95ca6f656e MDL-56886 navigation: Allow local plugins to modify navigation via AJAX. 2019-11-26 13:01:14 +11:00
Claude Vervoort fbd1829594 MDL-66708 lti adv: fix check for key in config 2019-11-25 14:17:08 -05:00
Marina Glancy 0c91305856 MDL-67342 theme_boost: Do not hardcode tooltip container 2019-11-25 15:59:25 +01:00
Sara Arjona c42b488aaf Merge branch 'MDL-66627-38' of git://github.com/mickhawkins/moodle into MOODLE_38_STABLE 2019-11-25 15:42:02 +01:00
David Monllaó 5bde4eb35e MDL-67217 unittest: usleep and windows don't get along well 2019-11-25 16:13:39 +08:00
Andrew Nicols 1943c03bbb MDL-67168 forum: Correct behaviour of viewfullnames 2019-11-25 08:56:37 +01:00
Jun Pataleta 0da427c800 Merge branch 'MDL-65956-38-1' of git://github.com/mihailges/moodle into MOODLE_38_STABLE 2019-11-25 14:23:11 +08:00
Mihail Geshoski 7045a22f3a MDL-65956 mod_assign: Add behat tests 2019-11-25 10:50:22 +08:00
Mihail Geshoski c7f9c7ae0f MDL-65956 mod_assign: Add proper capability checks and error handling 2019-11-25 10:50:22 +08:00
Andrew Nicols 751e4964b1 MDL-67285 core: YUI dialogues must use focuslock
YUI Dialogues were using an older method for locking focus to modals,
but this way conflicts with the way in which we lock focus for AMD
modules.

As a result, when an AMD dialogue launches a YUI dialogue the focus is
not correctly locked and it is not possible to focus on anything in the
YUI dialogue.

This includes a minor changes to the focuslock AMD module to ensure that
it is possible to loop the focus in both directions. Many of our older
YUI dialogues are themselves focusable. As a result we need to include
the lock region in the calculation when calculating the possible
descendants.
If we do not do so then the reverse looping does not work.
2019-11-25 10:35:08 +08:00
Eloy Lafuente (stronk7) 5a108a3064 MDL-67049 grading: options are array, ensure json_decode() knows it
By default json_decode() returns object for associative arrays. That
was not a problem till now becuause array_key_exists() worked with
objects too. But in php74 that emits a warning.

So we need to ensure that the information arriving to it is
an array, allowing everything to continue working ok.
2019-11-25 09:34:22 +08:00
Eloy Lafuente (stronk7) 417ff4f035 weekly release 3.8+ 2019-11-22 00:17:15 +01:00
sam marshall d3a5df14f7 MDL-67300 Calendar: Inconsistent behaviour of managegroupentries
When calling the calendar_get_allowed_event_types function with
no course id, it is supposed to return true if you have the
relevant permissions in any course.

For users who have the managegroupentries permission, this was not
the case - even though it works correctly if you call the function
with a supplied course id.

This change makes behaviour with and without a supplied course id
consistent.
2019-11-21 10:54:08 +00:00
Eloy Lafuente (stronk7) 82853489ca MDL-67035 tags: fix nested ternary operators to be php74 compliant
Nesting ternary operators without explicit parentheses is deprecated:

    // Code like
    $a ? $b : $c ? $d : $e
    // should be replaced by (current interpretation)
    ($a ? $b : $c) ? $d : $e
    // or (likely intended interpretation)
    $a ? $b : ($c ? $d : $e)
2019-11-21 11:55:27 +08:00
Eloy Lafuente (stronk7) 9eaea6a7bf MDL-66964 markdown: add details to readme
The commit to apply, from upstream repo, is:

https://github.com/michelf/php-markdown/commit/a35858f0409e5f01474f5cd562d17289fe8e5435

But it doesn't apply clean to our current 1.8.0 version.

So we have ended a slightly different version in core reproducing the same changes.
2019-11-21 11:37:50 +08:00
Eloy Lafuente (stronk7) f11b82df7c MDL-66964 markdown: php74 fixup for markdown lib 1.8.0
Note this is different from the upstream commit:

https://github.com/michelf/php-markdown/commit/a35858f0409e5f01474f5cd562d17289fe8e5435

because it was conflicting so only the cases corresponding
to our current 1.8.0 version have been modified.

This commit is trivial, just a pure curly to square replacement.
2019-11-21 11:37:50 +08:00
Tim Hunt 5d2f8bd98d MDL-48024 behat: allow plugins to have data generators
This extends the step
Given the following "users" exist:
to also support things like
Given the following "mod_quiz > user overrides" exist:

Instructions are on the behat_data_generators and
behat_generator_base classes.
2019-11-21 09:33:48 +08:00
Eloy Lafuente (stronk7) 023109f1b1 MDL-67030 htmlpurifier: add details to readme 2019-11-21 08:19:17 +08:00
Eloy Lafuente (stronk7) 51bedcee13 MDL-67030 htmlpurifier: php74 fixup for htmlpurifier v4.10.0
This simply applies this pull request:

https://github.com/ezyang/htmlpurifier/pull/224

straight to our library. Once there is some new htmlpurifier
release available (>v4.11.0) we'll be back upstream because
the fix will be included.
2019-11-21 08:19:11 +08:00
Eloy Lafuente (stronk7) 7cec76396f MDL-67031 s3: php74 fixup for class S3 v0.5.1 2019-11-20 16:22:07 +08:00
Eloy Lafuente (stronk7) daed88e656 MDL-67077 h5p: php74 fix (curly braces) for the H5P lib
This has been sent also upstream @ https://github.com/h5p/h5p-php-library/pull/69
2019-11-20 16:11:55 +08:00
Michael Hawkins 212595bbd0 MDL-66627 forumreport_summary: Added content access behat tests 2019-11-20 14:58:22 +08:00
Eloy Lafuente (stronk7) 6cff678c08 MDL-67034 lti_provider: php74 fix (curly braces) for LTI Provider lib 2019-11-20 13:17:09 +08:00
Eloy Lafuente (stronk7) 980193f55b MDL-67034 google: php74 fix (curly braces) for the Google-Client lib 2019-11-20 13:17:02 +08:00
Eloy Lafuente (stronk7) b4f9c2e906 MDL-67034 adodb: php74 fix (curly braces) for the AdoDB lib 2019-11-20 13:16:55 +08:00
Eloy Lafuente (stronk7) 93ed2a597c MDL-67034 horde: php74 fix (curly braces) for the Horde lib 2019-11-20 13:16:49 +08:00
Eloy Lafuente (stronk7) a2c6a69070 MDL-67029 bennu: add details to readme 2019-11-20 11:46:18 +08:00
Eloy Lafuente (stronk7) 7a68a37fda MDL-67029 bennu: php74 fixup for bennu lib 0.1-custom 2019-11-20 11:46:13 +08:00
Eloy Lafuente (stronk7) 3c1b6ed7bd MDL-67017 typo3: add details to readme 2019-11-20 10:01:13 +08:00
Eloy Lafuente (stronk7) 8ff55e3b1b MDL-67017 typo3: php74 fixup for typo3 lib 4.7.19
We are using a really outdated Typo3 library (2014) already patched
for php73 support. Plus, probably, we'll be soon removing it from core.

So we have decided to, instead of upgrade, apply the needed php74 fixes.
2019-11-20 10:01:02 +08:00
sam marshall 7d05f78363 MDL-67274 Tasks: Log display fails with memory errors 2019-11-19 10:51:22 +08:00
Jun Pataleta d0a9211f51 MDL-67148 tool_mobile: Set auth_cas|auth_name config value in unit test
Thanks to Renaat Debleu for the fix suggestion!
2019-11-18 18:50:11 +01:00
Marina Glancy e2a0a42003 MDL-67073 core_course: fix capability context 2019-11-18 16:02:46 +08:00
Jake Dallimore 7e24491f2c Merge branch 'MDL-67284_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2019-11-18 11:29:29 +08:00
Eloy Lafuente (stronk7) 4619c8a7e3 MDL-67284 mod_feedback: Add missing file phpdoc block 2019-11-17 12:47:05 +01:00
Eloy Lafuente (stronk7) 2aff0046c1 MDL-67284 upgrade: add 3.8.0 separation line to all upgrade scripts 2019-11-17 11:43:41 +01:00
28364 changed files with 1022810 additions and 2156110 deletions
+90
View File
@@ -0,0 +1,90 @@
# 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.*
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/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/mdn-polyfills/
lib/emoji-data/
lib/h5p/
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/alert.js
theme/boost/amd/src/button.js
theme/boost/amd/src/carousel.js
theme/boost/amd/src/collapse.js
theme/boost/amd/src/dropdown.js
theme/boost/amd/src/index.js
theme/boost/amd/src/modal.js
theme/boost/amd/src/popover.js
theme/boost/amd/src/sanitizer.js
theme/boost/amd/src/scrollspy.js
theme/boost/amd/src/tab.js
theme/boost/amd/src/toast.js
theme/boost/amd/src/tooltip.js
theme/boost/amd/src/util.js
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
+63 -63
View File
@@ -1,38 +1,52 @@
{
'plugins': [
'@babel',
'babel',
'promise',
'jsdoc'
],
'extends': [
'eslint:recommended',
'plugin:promise/recommended'
],
'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': {
'M': true,
'Y': true
},
// Warn about unused eslint-disable statements.
'reportUnusedDisableDirectives': true,
'rules': {
// See http://eslint.org/docs/rules/ for all rules and explanations of all
// rules.
// === Possible Errors ===
'comma-dangle': 'off',
'no-compare-neg-zero': 'error',
'no-cond-assign': 'error',
'no-console': 'error',
'no-constant-condition': 'error',
'no-control-regex': 'error',
'no-debugger': 'error',
'no-dupe-args': 'error',
'no-dupe-keys': 'error',
'no-duplicate-case': 'error',
'no-empty': 'warn',
'no-empty-character-class': 'error',
'no-ex-assign': 'error',
'no-extra-boolean-cast': 'error',
'no-extra-parens': 'off',
'no-extra-semi': 'error',
'no-func-assign': 'error',
'no-inner-declarations': 'error',
'no-invalid-regexp': 'error',
'no-irregular-whitespace': 'error',
'no-obj-calls': 'error',
'no-prototype-builtins': 'off',
'no-regex-spaces': 'error',
'no-sparse-arrays': 'error',
'no-unexpected-multiline': 'error',
'no-unreachable': 'warn',
'no-unsafe-finally': 'error',
'no-unsafe-negation': 'error',
'use-isnan': 'error',
'valid-jsdoc': ['warn', { 'requireReturn': false, 'requireParamDescription': false, 'requireReturnDescription': false }],
'valid-typeof': 'error',
// === Best Practices ===
// (these mostly match our jshint config)
@@ -44,12 +58,15 @@
'dot-notation': 'warn',
'no-alert': 'warn',
'no-caller': 'error',
'no-case-declarations': 'error',
'no-div-regex': 'error',
'no-empty-pattern': 'error',
'no-empty-function': 'warn',
'no-eq-null': 'error',
'no-eval': 'error',
'no-extend-native': 'error',
'no-extra-bind': 'warn',
'no-fallthrough': 'error',
'no-floating-decimal': 'warn',
'no-global-assign': 'warn',
'no-implied-eval': 'error',
@@ -61,22 +78,27 @@
'no-multi-str': 'error',
'no-new-func': 'error',
'no-new-wrappers': 'error',
'no-octal': 'error',
'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',
'no-self-compare': 'error',
'no-sequences': 'warn',
'no-throw-literal': 'warn',
'no-unmodified-loop-condition': 'error',
'no-unused-expressions': 'error',
'no-unused-labels': 'error',
'no-useless-call': 'warn',
'no-useless-escape': 'warn',
'no-with': 'error',
'wrap-iife': ['error', 'any'],
// === Variables ===
'no-delete-var': 'error',
'no-undef': 'error',
'no-undef-init': 'error',
'no-unused-vars': ['error', { 'caughtErrors': 'none' }],
@@ -109,6 +131,8 @@
'max-statements-per-line': ['warn', { max: 2 }],
'new-cap': ['warn', { 'properties': false }],
'new-parens': 'warn',
'newline-after-var': 'off',
'newline-before-return': 'off',
'newline-per-chained-call': 'off',
'no-array-constructor': 'off',
'no-bitwise': 'error',
@@ -116,6 +140,7 @@
'no-inline-comments': 'off',
'no-lonely-if': 'off',
'no-mixed-operators': 'off',
'no-mixed-spaces-and-tabs': 'error',
'no-multiple-empty-lines': 'warn',
'no-negated-condition': 'off',
'no-nested-ternary': 'warn',
@@ -137,6 +162,7 @@
'padded-blocks': 'off',
'quote-props': ['warn', 'as-needed', {'unnecessary': false, 'keywords': true, 'numbers': true}],
'quotes': 'off',
'require-jsdoc': 'warn',
'semi': 'error',
'semi-spacing': ['warn', {'before': false, 'after': true}],
'sort-vars': 'off',
@@ -149,58 +175,46 @@
'unicode-bom': 'error',
'wrap-regex': 'off',
// === Promises (override plugin:promise/recommended) ===
// === Promises ===
'promise/always-return': 'warn',
'promise/no-return-wrap': 'warn',
'promise/param-names': 'warn',
'promise/catch-or-return': ['warn', {terminationMethod: ['catch', 'fail', 'always'], allowFinally: true}],
'promise/catch-or-return': ['warn', {terminationMethod: ['catch', 'fail']}],
'promise/no-native': 'warn',
'promise/no-promise-in-callback': 'warn',
'promise/no-callback-in-promise': 'warn',
'promise/avoid-new': 'warn',
// === Deprecations ===
"no-restricted-properties": ['warn', {
'object': 'M',
'property': 'str',
'message': 'Use "core/str" module or M.util.get_string()'
'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',
'no-implicit-globals': 'error',
// Disable all of the rules that have babel versions.
'new-cap': 'off',
@@ -212,37 +226,23 @@
'semi': 'off',
'no-unused-expressions': 'off',
// Enable all of the babel version of these rules.
'@babel/new-cap': ['warn', { 'properties': false }],
'babel/new-cap': ['warn', { 'properties': false }],
// Not using this rule for the time being because it isn't
// compatible with jQuery and ES6.
'@babel/no-invalid-this': 'off',
'@babel/object-curly-spacing': 'warn',
'@babel/semi': 'error',
'@babel/no-unused-expressions': 'error',
'babel/no-invalid-this': 'off',
'babel/object-curly-spacing': 'warn',
// This is off in the original style int.
'babel/quotes': 'off',
'babel/semi': 'error',
'babel/no-unused-expressions': 'error',
// === 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'
}
}
]
+3 -7
View File
@@ -3,8 +3,6 @@
"Feature": 0,
"Background": 2,
"Scenario": 2,
"Examples": 4,
"example": 6,
"Step": 4,
"given": 4,
"and": 4
@@ -16,9 +14,7 @@
"no-multiple-empty-lines": "on",
"no-partially-commented-tag-lines": "on",
"no-trailing-spaces": "on",
"no-unnamed-features": "on",
"no-unnamed-scenarios": "on",
"no-scenario-outlines-without-examples": "on",
"no-examples-in-scenarios": "on",
"new-line-at-eof": ["on", "yes"]
"no-unamed-features": "on",
"no-unamed-scenarios": "on",
"no-scenario-outlines-without-examples": "on"
}
-3
View File
@@ -1,6 +1,3 @@
**/yui/build/** -diff
**/amd/build/** -diff
lib/dml/oci_native_moodle_package.sql text eol=lf
**.js.map -diff
**-min.js -diff
**.min.js -diff
-2
View File
@@ -1,2 +0,0 @@
# Primary donations pages.
custom: ["https://moodle.com/donations/", "https://fund.moodle.org"]
-7
View File
@@ -1,7 +0,0 @@
*** PLEASE DO NOT OPEN PULL REQUESTS VIA GITHUB ***
The moodle.git repository at Github is just a mirror of the official repository. We do not accept pull requests at Github.
See CONTRIBUTING.md guidelines for how to contribute patches for Moodle. Thank you.
--
-6
View File
@@ -1,6 +0,0 @@
> [!IMPORTANT]
> PLEASE DO NOT PUBLISH SECURITY FINDINGS PUBLICLY.
If you discover a potential security issue, please report it via our [Security Submission Form](https://moodle.org/security/report).
For more information about our security processes and responsible disclosure policy, see the [Security Procedures documentation](https://moodledev.io/general/development/process/security).
-1
View File
@@ -1 +0,0 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1231.24 314.44" preserveAspectRatio="xMinYMid meet"><defs><style>.cls-1{fill:#f48020;}.cls-2,.cls-3{fill:#383738;stroke:#4a4a4c;}.cls-2{stroke-width:2.37px;}.cls-3{stroke-width:2.38px;}.cls-4{fill:#585858;}</style></defs><title>Moodle_Logo_UseonBlack_RGB</title><path class="cls-1" d="M1086.3,235.34a53.42,53.42,0,0,0,16.71,29q13.26,12.27,29.48,12.27,11.29,0,24.56-5.89,16.23-6.88,16.22-16.22l58-.49q-12.29,29-41.76,45.2-27.52,15.23-60.43,15.24-42.25,0-70-26.29t-27.75-68.54q0-43.73,27.75-69.51t72-25.8q48.15,0,75.17,31.94,25.07,29.47,25.06,79.1Zm89.91-33.91q-3.43-17.69-14.73-29-12.8-12.28-29.49-12.29-17.21,0-28.74,11.79t-15.47,29.48Z"/><path class="cls-1" d="M965.45,308.54V0h55V308.54Z"/><path class="cls-1" d="M892.69,308.54V290.36q-7.38,9.83-25.06,15.72a92.31,92.31,0,0,1-30,5.41q-39.31,0-63.13-27T750.7,217.65q0-39.3,23.34-65.84t62.15-26.53q43.71,0,56.5,23.58V0h53.55V308.54Zm0-102.68q0-14.75-14-28.26t-28.74-13.51q-21.12,0-33.41,17.2-10.8,15.24-10.8,37.33,0,21.63,10.8,36.85,12.29,17.71,33.41,17.69,12.78,0,27.76-12t15-24.81Z"/><path class="cls-1" d="M647,313.45q-41.77,0-69-26.53t-27.27-68.3q0-41.73,27.27-68.28t69-26.53q41.75,0,69.27,26.53t27.52,68.28q0,41.79-27.52,68.3T647,313.45ZM647,168q-19.89,0-30.58,15.07t-10.68,35.79q0,20.73,9.94,35.05,11.43,16.31,31.32,16.28t31.32-16.28q10.44-14.31,10.44-35.05t-9.94-35Q667.42,168,647,168Z"/><path class="cls-1" d="M448.07,313.45q-41.76,0-69-26.53t-27.27-68.3q0-41.73,27.27-68.28t69-26.53q41.74,0,69.28,26.53t27.5,68.28q0,41.79-27.5,68.3T448.07,313.45Zm0-145.43q-19.89,0-30.59,15.07t-10.69,35.79q0,20.73,9.94,35.05,11.43,16.31,31.34,16.28t31.32-16.28q10.42-14.31,10.44-35.05t-9.94-35Q468.45,168,448.07,168Z"/><path class="cls-1" d="M288.89,309.11V201q0-33.9-28-33.9t-28,33.9V309.11h-55V201q0-33.9-27.52-33.9-28,0-28,33.9V309.11h-55V194.65q0-35.37,24.56-53.54,21.61-16.22,58.46-16.22,37.35,0,55,19.16,15.23-19.16,55.51-19.16,36.86,0,58.45,16.22,24.57,18.16,24.57,53.54V309.11Z"/><path class="cls-2" d="M.76,145.76"/><path class="cls-3" d="M1.73,145.32"/><path class="cls-4" d="M173.86,116.85l55.08-40.1-.7-2.44C135,83.92,80.42,96.44,0,144.13l.73,2.38,21-.67c15.17.52,30.85,1.26,46,1.32-1,24.09.83,32.65.83,32.65,51.92,17.58,101.22,1.53,127.14-43.9A248.72,248.72,0,0,0,173.86,116.85Z"/><path class="cls-4" d="M113.78,110c-.3-1.08-2.23-1.48-4.28-.9a4.73,4.73,0,0,0-3.14,2.19c-18.53,5-49.16,13.72-70.73,21l-1.33.45c-16.68,5.61-24.73,8.49-25.22,12.55-2.29,18.44-.87,42.18-.86,42.48l.19,6.4c-9.74,27.56.06,49.6,8.38,69.77.06-24.92,1.07-45.22-6-71-.2-3.82-1.49-30.36.61-47.34.34-2.75,11.65-6.56,23.63-10.59l1.33-.44c22-7.42,53.57-16.39,71.9-21.29a6.75,6.75,0,0,0,2.29-.25C112.64,112.43,114.08,111.09,113.78,110Z"/></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

-31
View File
@@ -1,31 +0,0 @@
name: 'Close Pull Requests'
on:
pull_request_target:
types: opened
workflow_dispatch:
jobs:
close:
# Avoid forks to run this job
if: github.repository_owner == 'moodle'
name: Close Pull Requests
runs-on: ubuntu-latest
steps:
- uses: dessant/repo-lockdown@v4
with:
process-only: prs
close-pr: true
skip-closed-pr-comment: true
pr-comment: >
**Please, don't open pull requests via GitHub.**
This repository (moodle.git) at GitHub is just a mirror of the official Moodle repository.
For how to contribute patches for Moodle see
[CONTRIBUTING.md](https://github.com/moodle/moodle/blob/main/CONTRIBUTING.md).
Closing this pull request.
-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');
-143
View File
@@ -1,143 +0,0 @@
name: One by One Testing
# Run all the individual unit tests one by one, with
# fully independent PHPUnit executions. Useful to
# detect issues with some tests that are using stuff
# that has been made available by others, but is not
# available when running individually.
#
# Note that we aren't using PHPUnit's own isolation
# here but completely separated runs, one for each
# test.
#
# The workflow will fail reporting all the tests
# that have failed (and will pass if no failure is
# detected, of course).
#
# It's only executed via workflow dispatch (automated
# or manual), not by push/tag. And acceptd configuration
# of phpunit, specially useful to run it with PHPUnit's
# own isolation or any other option.
on:
workflow_dispatch:
inputs:
phpunit_extra_options:
description: Additional options to apply to PHPUnit
required: false
default: ''
env:
chunks: 7
jobs:
collect:
name: Collect individual unit tests
runs-on: ubuntu-latest
outputs:
matrix: ${{steps.individual-tests.outputs.matrix }}
steps:
- name: Checking out code
uses: actions/checkout@v4
- name: Looking for all individual tests
id: individual-tests
run: |
count=0 # Number of individual tests found.
while read -r testfile; do # For each test file.
while read -r testname; do # For each unit test in a file.
count=$((count + 1))
# Sent it to the correct chunk file.
chunk=$(((($count % $chunks)) + 1))
echo "$testname $testfile" >> ./chunk_$chunk.txt
done < <(grep "function test_" "${testfile}" | sed -r "s/^.*function (test_[a-zA-Z0-9_]+).*/\1/")
done < <(find . -name "*_test.php")
# Generate the matrix to run tests.
echo "matrix=$(ls -1 chunk_*.txt | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT
echo "$count individual tests collected in $chunks files"
- name: Upload individual tests files
uses: actions/upload-artifact@v4
with:
name: individual_tests
path: chunk_*.txt
retention-days: 1
test:
name: Run tests
needs: collect
runs-on: ubuntu-latest
services:
exttests:
image: moodlehq/moodle-exttests
ports:
- 8080:80
redis:
image: redis
ports:
- 6379:6379
strategy:
fail-fast: false
matrix:
file: ${{ fromJson(needs.collect.outputs.matrix) }}
steps:
- name: Setting up DB pgsql
uses: m4nu56/postgresql-action@v1
with:
postgresql version: 13
postgresql db: test
postgresql user: test
postgresql password: test
- name: Setting up PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3
ini-values: max_input_vars=5000
coverage: none
- name: Checking out code
uses: actions/checkout@v4
- name: Download individual test files
uses: actions/download-artifact@v4
with:
name: individual_tests # Make all the chunk files available for the next steps.
- name: Setting up PHPUnit
env:
dbtype: pgsql
run: |
echo "pathtophp=$(which php)" >> $GITHUB_ENV
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: Run PHPUnit test (one by one)
env:
dbtype: pgsql
run: |
status=0
count=0
while read -r line; do # For each line in the chunk file
count=$((count + 1))
filter="${line% *}"
file="${line#* }"
# Run the individual unit test and report problems if needed to.
if ! php vendor/bin/phpunit \
--fail-on-empty-test-suite \
--fail-on-warning \
--fail-on-risky \
--filter "$filter" ${{ inputs.phpunit_extra_options }} \
"$file" >/dev/null 2>&1; then
if [ $status -eq 0 ]; then
echo "Problems found, list of PHPUnit commands failing:"
fi
echo "vendor/bin/phpunit --filter '${filter}' ${{ inputs.phpunit_extra_options }} $file"
status=$((status + 1))
fi
done < ${{ matrix.file }}
echo "Finished: $count individual tests executed, $status tests failed"
exit $status
-127
View File
@@ -1,127 +0,0 @@
name: Core
on:
push:
branches-ignore:
- main
- MOODLE_[0-9]+_STABLE
tags-ignore:
- v[0-9]+.[0-9]+.[0-9]+*
workflow_dispatch:
inputs:
phpunit_extra_options:
description: Additional options to apply to PHPUnit
required: false
default: ''
env:
php: 8.3
jobs:
Grunt:
runs-on: ubuntu-22.04
steps:
- name: Checking out code
uses: actions/checkout@v4
- name: Configuring node & npm
uses: actions/setup-node@v4
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:
# MySQL builds always run with the lowest PHP supported version.
- os: ubuntu-22.04
php: 8.1
extensions:
db: mysqli
# PostgreSQL builds always run with the highest PHP supported version.
- os: ubuntu-22.04
php: 8.3
db: pgsql
steps:
- name: Setting up DB mysql
if: ${{ matrix.db == 'mysqli' }}
uses: moodlehq/mysql-action@v1
with:
collation server: utf8mb4_bin
mysql version: 8.0
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: 13
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@v4
- 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 ${{ inputs.phpunit_extra_options }}
- name: Git status
run: git status
-23
View File
@@ -1,23 +0,0 @@
name: Web Installer Testing
on:
workflow_dispatch:
jobs:
InstallationTest:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
php: [8.1, 8.3]
steps:
- name: Construct repository URL
run: echo "REPOSITORY_URL=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" >> $GITHUB_ENV
shell: bash
- uses: moodlehq/moodle-webinstaller-test@main
with:
repository: ${{ env.REPOSITORY_URL }}
branch: ${{ github.ref_name }}
php: ${{ matrix.php }}
-149
View File
@@ -1,149 +0,0 @@
name: Windows Testing
on:
workflow_dispatch:
inputs:
phpunit_extra_options:
description: Additional options to apply to PHPUnit
required: false
default: ''
env:
php: 8.3
jobs:
Grunt:
runs-on: windows-latest
steps:
- name: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checking out code
uses: actions/checkout@v4
- name: Configuring node & npm
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- name: Installing node stuff
run: npm ci
- 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 }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
php: 8.3
# Ideally we should use mysql/mariadb, but they are 4x slower without tweaks and configuration
# so let's run only postgres (1.5h vs 6h) only, If some day we want to improve the mysql runs,
# this is the place to enable them.
# db: mysqli
db: pgsql
extensions: exif, fileinfo, gd, intl, pgsql, mysql, redis, soap, sodium, zip
- os: windows-latest
php: 8.1
db: pgsql
extensions: exif, fileinfo, gd, intl, pgsql, mysql, redis, soap, sodium
steps:
- name: Setting up DB mysql
if: ${{ matrix.db == 'mysqli' }}
uses: shogo82148/actions-setup-mysql@v1
with:
mysql-version: 8.0
user: test
password: test
- name: Creating DB mysql
if: ${{ matrix.db == 'mysqli' }}
run: mysql --host 127.0.0.1 -utest -ptest -e 'CREATE DATABASE IF NOT EXISTS test COLLATE = utf8mb4_bin;';
- name: Setting up DB pgsql
if: ${{ matrix.db == 'pgsql' }}
run: |
# TODO: Remove these conf. modifications when php74 or php80 are lowest.
# Change to old md5 auth, because php73 does not support it.
# #password_encryption = scram-sha-256
(Get-Content "$env:PGDATA\postgresql.conf"). `
replace('#password_encryption = scram-sha-256', 'password_encryption = md5') | `
Set-Content "$env:PGDATA\postgresql.conf"
(Get-Content "$env:PGDATA\pg_hba.conf"). `
replace('scram-sha-256', 'md5') | `
Set-Content "$env:PGDATA\pg_hba.conf"
$pgService = Get-Service -Name postgresql*
Set-Service -InputObject $pgService -Status running -StartupType automatic
Start-Process -FilePath "$env:PGBIN\pg_isready" -Wait -PassThru
& $env:PGBIN\psql --command="CREATE USER test PASSWORD 'test'" --command="\du"
- name: Creating DB pgsql
if: ${{ matrix.db == 'pgsql' }}
run: |
& $env:PGBIN\createdb --owner=test test
$env:PGPASSWORD = 'test'
& $env:PGBIN\psql --username=test --host=localhost --list 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: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
uses: actions/checkout@v4
# Needs to be done after php is available, git configured and Moodle checkout has happened.
- name: Setting up moodle-exttests service
run: |
git clone https://github.com/moodlehq/moodle-exttests.git
nssm install php-built-in C:\tools\php\php.exe -S localhost:8080 -t D:\a\moodle\moodle\moodle-exttests
nssm start php-built-in
- name: Setting up redis service
run: |
choco install redis --version 5.0.7 --no-progress
nssm install redis redis-server
nssm start redis
- name: Setting up PHPUnit
env:
dbtype: ${{ matrix.db }}
shell: bash
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
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 ${{ inputs.phpunit_extra_options }}
+1 -16
View File
@@ -20,15 +20,12 @@
*~
#
/config.php
/lib/editor/tinymce/extra/tools/temp/
/tags
/TAGS
/cscope.*
/.patches/
/.idea/
.phpstorm.*
!/.phpstorm.meta.php/
/.phpstorm.meta.php/*
!/.phpstorm.meta.php/di.php
/nbproject/
CVS
.DS_Store
@@ -36,7 +33,6 @@ CVS
/.project
/.buildpath
/.cache
.phpunit.result.cache
phpunit.xml
# Composer support. Do not ignore composer.json, or composer.lock. These should be shipped by us.
composer.phar
@@ -48,14 +44,3 @@ composer.phar
/lib/yuilib/*/*/*-coverage.js
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
UPGRADING-CURRENT.md
-169
View File
@@ -1,169 +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/>.
/**
* This is a babel plugin to add the Moodle module names to the AMD modules
* as part of the transpiling process.
*
* In addition it will also add a return statement for the default export if the
* module is using default exports. This is a highly specific Moodle thing because
* we're transpiling to AMD and none of the existing Babel 7 plugins work correctly.
*
* This will fix the issue where an ES6 module using "export default Foo" will be
* transpiled into an AMD module that returns {default: Foo}; Instead it will now
* just simply return Foo.
*
* Note: This means all other named exports in that module are ignored and won't be
* exported.
*
* @copyright 2018 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
/* eslint-env node */
module.exports = ({template, types}) => {
const fs = require('fs');
const path = require('path');
const cwd = process.cwd();
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
/**
* Search the list of components that match the given file name
* and return the Moodle component for that file, if found.
*
* Throw an exception if no matching component is found.
*
* @throws {Error}
* @param {string} searchFileName The file name to look for.
* @return {string} Moodle component
*/
function getModuleNameFromFileName(searchFileName) {
searchFileName = fs.realpathSync(searchFileName);
const relativeFileName = searchFileName.replace(`${cwd}${path.sep}`, '').replace(/\\/g, '/');
const [componentPath, file] = relativeFileName.split('/amd/src/');
const fileName = file.replace('.js', '');
// Check subsystems first which require an exact match.
const componentName = ComponentList.getComponentFromPath(componentPath);
if (componentName) {
return `${componentName}/${fileName}`;
}
// This matches the previous PHP behaviour that would throw an exception
// if it couldn't parse an AMD file.
throw new Error(`Unable to find module name for ${searchFileName} (${componentPath}::${file}}`);
}
/**
* This is heavily inspired by the babel-plugin-add-module-exports plugin.
* See: https://github.com/59naga/babel-plugin-add-module-exports
*
* This is used when we detect a module using "export default Foo;" to make
* sure the transpiled code just returns Foo directly rather than an object
* with the default property (i.e. {default: Foo}).
*
* Note: This means that we can't support modules that combine named exports
* with a default export.
*
* @param {String} path
* @param {String} exportObjectName
*/
function addModuleExportsDefaults(path, exportObjectName) {
const rootPath = path.findParent(path => {
return path.key === 'body' || !path.parentPath;
});
// HACK: `path.node.body.push` instead of path.pushContainer(due doesn't work in Plugin.post).
// This is hardcoded to work specifically with AMD.
rootPath.node.body.push(template(`return ${exportObjectName}.default`)());
}
return {
pre() {
this.seenDefine = false;
this.addedReturnForDefaultExport = false;
},
visitor: {
// Plugin ordering is only respected if we visit the "Program" node.
// See: https://babeljs.io/docs/en/plugins.html#plugin-preset-ordering
//
// We require this to run after the other AMD module transformation so
// let's visit the "Program" node.
Program: {
exit(path) {
path.traverse({
CallExpression(path) {
// If we find a "define" function call.
if (!this.seenDefine && path.get('callee').isIdentifier({name: 'define'})) {
// We only want to modify the first instance of define that we find.
this.seenDefine = true;
// Get the Moodle component for the file being processed.
var moduleName = getModuleNameFromFileName(this.file.opts.filename);
// The function signature of `define()` is:
// define = function (name, deps, callback) {...}
// Ensure that if the moduel supplied its own name that it is replaced.
if (path.node.arguments.length > 0) {
// Ensure that there is only one name.
if (path.node.arguments[0].type === 'StringLiteral') {
// eslint-disable-next-line
console.log(`Replacing module name '${path.node.arguments[0].extra.rawValue}' with ${moduleName}`);
path.node.arguments.shift();
}
}
// Add the module name as the first argument to the define function.
path.node.arguments.unshift(types.stringLiteral(moduleName));
// Add a space after the define function in the built file so that previous versions
// of Moodle will not try to add the module name to the file when it's being served
// by PHP. This forces the regex in PHP to not match for this file.
path.node.callee.name = 'define ';
}
// Check for any Object.defineProperty('exports', 'default') calls.
if (!this.addedReturnForDefaultExport && path.get('callee').matchesPattern('Object.defineProperty')) {
const [identifier, prop] = path.get('arguments');
const objectName = identifier.get('name').node;
const propertyName = prop.get('value').node;
if ((objectName === 'exports' || objectName === '_exports') && propertyName === 'default') {
addModuleExportsDefaults(path, objectName);
this.addedReturnForDefaultExport = true;
}
}
},
AssignmentExpression(path) {
// Check for an exports.default assignments.
if (
!this.addedReturnForDefaultExport &&
(
path.get('left').matchesPattern('exports.default') ||
path.get('left').matchesPattern('_exports.default')
)
) {
const objectName = path.get('left.object.name').node;
addModuleExportsDefaults(path, objectName);
this.addedReturnForDefaultExport = true;
}
}
}, this);
}
}
}
};
};
-419
View File
@@ -1,419 +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 = [];
componentData.components = {};
componentData.standardComponents = {};
// Fetch the component definiitions from the distributed JSON file.
const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`));
const pluginData = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/plugins.json`));
componentData.pluginTypes = components.plugintypes;
const standardPlugins = Object.entries(pluginData.standard).map(
([pluginType, pluginNames]) => {
return pluginNames.map(pluginName => `${pluginType}_${pluginName}`);
}
).reduce((acc, val) => acc.concat(val), []);
// 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 includes 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);
});
});
}
});
});
// Create a list of the standard subsystem and plugins.
componentData.standardComponents = Object.fromEntries(
Object.entries(componentData.components).filter(([, name]) => {
if (name === 'core' || name.startsWith('core_')) {
return true;
}
return standardPlugins.indexOf(name) !== -1;
})
);
componentData.componentMapping = Object.fromEntries(
Object.entries(componentData.components).map(([path, name]) => [name, path])
);
}
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;
};
/**
* Get the latest tag in a remote GitHub repository.
*
* @param {string} url The remote repository.
* @returns {Array}
*/
const getRepositoryTags = async(url) => {
const gtr = require('git-tags-remote');
try {
const tags = await gtr.get(url);
if (tags !== undefined) {
return tags;
}
} catch (error) {
return [];
}
return [];
};
/**
* Get the list of thirdparty libraries that could be upgraded.
*
* @returns {Array}
*/
const getThirdPartyLibsUpgradable = async() => {
const libraries = getThirdPartyLibsData().filter((library) => !!library.repository);
const upgradableLibraries = [];
const versionCompare = (a, b) => {
if (a === b) {
return 0;
}
const aParts = a.split('.');
const bParts = b.split('.');
for (let i = 0; i < Math.min(aParts.length, bParts.length); i++) {
const aPart = parseInt(aParts[i], 10);
const bPart = parseInt(bParts[i], 10);
if (aPart > bPart) {
// 1.1.0 > 1.0.9
return 1;
} else if (aPart < bPart) {
// 1.0.9 < 1.1.0
return -1;
} else {
// Same version.
continue;
}
}
if (aParts.length > bParts.length) {
// 1.0.1 > 1.0
return 1;
}
// 1.0 < 1.0.1
return -1;
};
for (let library of libraries) {
upgradableLibraries.push(
getRepositoryTags(library.repository).then((tagMap) => {
library.version = library.version.replace(/^v/, '');
const currentVersion = library.version.replace(/moodle-/, '');
const currentMajorVersion = library.version.split('.')[0];
const tags = [...tagMap]
.map((tagData) => tagData[0])
.filter((tag) => !tag.match(/(alpha|beta|rc)/))
.map((tag) => tag.replace(/^v/, ''))
.sort((a, b) => versionCompare(b, a));
if (!tags.length) {
library.warning = "Unable to find any comparable tags.";
return library;
}
library.latestVersion = tags[0];
tags.some((tag) => {
if (!tag) {
return false;
}
// See if the version part matches.
const majorVersion = tag.split('.')[0];
if (majorVersion === currentMajorVersion) {
library.latestSameMajorVersion = tag;
return true;
}
return false;
});
if (versionCompare(currentVersion, library.latestVersion) > 0) {
// Moodle somehow has a newer version than the latest version.
library.warning = `Newer version found: ${currentVersion} > ${library.latestVersion} for ${library.name}`;
return library;
}
if (library.version !== library.latestVersion) {
// Delete version and add it again at the end of the array. That way, current and new will stay closer.
delete library.version;
library.version = currentVersion;
return library;
}
return null;
})
);
}
return (await Promise.all(upgradableLibraries)).filter((library) => !!library);
};
/**
* Get the list of thirdparty libraries.
*
* @returns {Array}
*/
const getThirdPartyLibsData = () => {
const DOMParser = require('@xmldom/xmldom').DOMParser;
const fs = require('fs');
const xpath = require('xpath');
const path = require('path');
const libraryList = [];
const libraryFields = [
'location',
'name',
'version',
'repository',
];
const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./'));
thirdpartyfiles.forEach(function(libraryPath) {
const xmlContent = fs.readFileSync(libraryPath, 'utf8');
const doc = new DOMParser().parseFromString(xmlContent);
const libraries = xpath.select("/libraries/library", doc);
for (const library of libraries) {
const libraryData = [];
for (const field of libraryFields) {
libraryData[field] = xpath.select(`${field}/text()`, library)?.toString();
}
libraryData.location = path.join(path.dirname(libraryPath), libraryData.location);
libraryList.push(libraryData);
}
});
return libraryList.sort((a, b) => a.location.localeCompare(b.location));
};
module.exports = {
fetchComponentData,
getAmdSrcGlobList,
getComponentFromPath,
getComponentPaths,
getOwningComponentDirectory,
getYuiSrcGlobList,
getThirdPartyLibsList,
getThirdPartyPaths,
getThirdPartyLibsUpgradable,
};
-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://moodledev.io](https://moodledev.io) 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://moodledev.io",
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,
},
};
-138
View File
@@ -1,138 +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/>.
import * as Components from '../../components.js';
const componentData = Components.fetchComponentData();
/**
* The standard components shipped with core Moodle.
*
* @type {Object}
*/
export const standardComponents = componentData.standardComponents;
/**
* All components of the current Moodle instance.
*
* @type {Object}
*/
export const allComponents = componentData.components;
/**
* Get all components of the current Moodle instance.
*
* @returns {Array}
*/
export const getAllComponents = () => {
let components = new Map(Object.entries(componentData.pluginTypes).map(([value, path]) => ([path,{
path,
value,
name: `${value} (plugin type)`,
}])));
Object
.entries(componentData.components)
.filter(([path, value]) => Object.values(componentData.standardComponents).includes(value))
.forEach(([path, value]) => {
const entry = {
path,
value,
name: value,
};
if (Object.values(componentData.subsystems).includes(value)) {
if (components.has(path)) {
entry.name = `${value} (subsystem / plugintype)`;
} else {
entry.name = `${value} (subsystem)`;
}
}
components.set(path, entry);
});
return Array.from(components.values());
};
/**
* Whether the specified component is a standard component shipped with core Moodle.
*
* @param {string} componentName
* @returns {boolean}
*/
export const isStandardComponent = (componentName) => {
if (Object.values(componentData.standardComponents).includes(componentName)) {
return true;
}
if (Object.keys(componentData.pluginTypes).includes(componentName)) {
return true;
}
return false;
};
export const rewritePlugintypeAsSubsystem = (componentName) => {
if (Object.keys(componentData.pluginTypes).includes(componentName)) {
const pluginTypePath = componentData.pluginTypes[componentName];
if (Object.keys(componentData.subsystems).includes(pluginTypePath)) {
return true;
}
}
return false;
};
/**
* Whether the specified component is a community component.
*
* @param {string} componentName
* @returns {boolean}
*/
export const isCommunityComponent = (componentName) => {
if (isStandardComponent(componentName)) {
return false;
}
return Object.values(componentData.components).indexOf(componentName) !== -1;
};
/**
* Sort method for components.
*
* This method sorts components putting `core` first, followed by core subsystems, then everything else.
*
* @param {String} a
* @param {String} b
* @returns {Number}
*/
export const sortComponents = (a, b) => {
// Always put 'core' first.
if (a === 'core') {
return -1;
} else if (b === 'core') {
return 1;
}
// Put core subsystems next.
if (a.startsWith('core_') && !b.startsWith('core_')) {
return -1;
} else if (b.startsWith('core_') && !a.startsWith('core_')) {
return 1;
}
// Sort alphabetically for everything else.
return a.localeCompare(b);
};
-85
View File
@@ -1,85 +0,0 @@
#!/usr/bin/env node
// 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/>.
import inquirer from 'inquirer';
import chalk from 'chalk';
import { createNote } from './note.mjs';
import { getInitialValues } from './helpers.mjs';
import * as Prompts from './prompts.mjs';
import logger from './logger.mjs';
export default async (options) => {
// Processs the initial values.
const initialValues = getInitialValues(options);
// Fetch information.
const messages = [];
const { issueNumber } = await inquirer.prompt([
Prompts.getIssuePrompt(),
], initialValues);
let selection = {};
let notePath;
do {
selection = {};
selection = await inquirer.prompt([
Prompts.getComponentsPrompt(),
Prompts.getTypePrompt(),
Prompts.getMessagePromptInput(),
], initialValues);
if (selection.message === '') {
selection = Object.assign(
selection,
await inquirer.prompt([
Prompts.getMessagePromptEditor(),
]),
);
}
logger.info(`
Creating upgrade note with the following options:
- Issue: ${chalk.bold(issueNumber)}
- Component: ${chalk.bold(selection.components)}
- Type: ${chalk.bold(selection.type)}
- Message:
${chalk.bold(selection.message)}
`);
messages.push({
components: [selection.components],
type: selection.type,
message: selection.message,
});
// Save the note so far.
if (notePath) {
await createNote(issueNumber, messages, notePath);
logger.info(`Updated note at: ${chalk.underline(chalk.bold(notePath))}`);
} else {
notePath = await createNote(issueNumber, messages);
logger.info(`Note created at: ${chalk.underline(chalk.bold(notePath))}`);
}
selection = Object.assign(
selection,
await inquirer.prompt([
Prompts.getAddAnotherPrompt(),
], initialValues),
);
} while (selection.addAnother);
};
-357
View File
@@ -1,357 +0,0 @@
#!/usr/bin/env node
// 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/>.
import chalk from 'chalk';
import { getAllComponents } from './components.mjs';
import { getCombinedNotesByComponent, deleteAllNotes } from './note.mjs';
import { getNoteName } from './noteTypes.mjs';
import { writeFile, readFile, unlink } from 'fs/promises';
import { join as joinPath } from 'path';
import logger from './logger.mjs';
import { getCurrentVersion } from './helpers.mjs';
/**
* Helper to fetch the current notes from a file.
*
* @param {string} file
* @returns {Promise<string>}
*/
const getCurrentNotes = async (file) => {
try {
return await readFile(file, 'utf8');
} catch (error) {
return null;
}
}
/**
* Update the UPGRADING.md file.
*
* @param {string} upgradeNotes
* @param {Object} options
* @param {boolean} options.deleteNotes
* @returns {Promise<void>}
*/
const updateUpgradeNotes = async (upgradeNotes, options) => {
const fileName = 'UPGRADING.md';
// Write the notes to a file.
logger.info(`Writing notes to ${chalk.underline(chalk.bold(fileName))}`);
// Prepend to the existing file.
const existingContent = await getCurrentNotes(fileName);
if (existingContent) {
await writeFile(fileName, getUpdatedNotes(existingContent, upgradeNotes));
} else {
// This should not normally happen.
await writeFile(fileName, upgradeNotes);
}
if (options.deleteNotes) {
logger.warn(`>>> Deleting all notes <<<`)
// Delete the notes.
deleteAllNotes();
}
};
/**
* Create the current summary notes.
*
* @param {string} upgradeNotes
* @returns {Promise<void>}
*/
const createCurrentSummary = async (upgradeNotes) => {
const fileName = 'UPGRADING-CURRENT.md';
const notes = `# Moodle upgrade notes\n\n${upgradeNotes}`;
await writeFile(fileName, notes);
logger.info(`Running upgrade notes written to ${chalk.underline(chalk.bold(fileName))}`);
};
/**
* Get the indexes of the lines that contain the version headings.
*
* @param {array<string>} lines
* @returns {array<object>}
*/
const getVersionLineIndexes = (lines) => {
const h2Indexes = [];
lines.forEach((line, index) => {
const matches = line.match(/^##\s(?<version>.*)$/);
if (matches) {
h2Indexes.push({
index,
line,
version: matches.groups.version,
});
}
});
return h2Indexes;
};
/**
* Find the index of the Unreleased heading.
*
* @param {array<object>} versionHeadings
* @returns {number}
*/
const findUnreleasedHeadingIndex = (versionHeadings) => versionHeadings.findIndex((heading) => {
if (heading.version === 'Unreleased') {
// Used if version cannot be guessed.
return true;
}
if (heading.version.endsWith('+')) {
// Weekly release for a stable branch.
return true;
}
if (heading.version.match(/beta|rc\d/)) {
// Beta and RC rolls are treated as weeklies.
return true;
}
if (heading.version.endsWith('dev')) {
// Development version.
return true;
}
return false;
});
/**
* Get the before and after content, to facilitate replacing any existing Unreleased notes.
*
* @param {array<string>} lines
* @returns {Object} {beforeContent: string, afterContent: string}
*/
const getBeforeAndAfterContent = (lines) => {
const existingLines = lines.split('\n');
const versionHeadings = getVersionLineIndexes(existingLines);
if (versionHeadings.length > 0) {
const unreleasedHeadingIndex = findUnreleasedHeadingIndex(versionHeadings);
if (unreleasedHeadingIndex !== -1) {
const beforeContent = existingLines.slice(0, versionHeadings[unreleasedHeadingIndex].index).join('\n');
if (versionHeadings.length > unreleasedHeadingIndex + 1) {
const afterContent = existingLines.slice(versionHeadings[unreleasedHeadingIndex + 1].index).join('\n');
return {
beforeContent,
afterContent,
};
}
return {
beforeContent,
afterContent: '',
};
}
return {
beforeContent: existingLines.slice(0, versionHeadings[0].index).join('\n'),
afterContent: existingLines.slice(versionHeadings[0].index).join('\n'),
};
}
return {
beforeContent: existingLines.join('\n'),
afterContent: '',
}
};
/**
* Get the notes for the component.
*
* @param {string} types
* @param {Number} headingLevel
* @returns {string}
*/
const getNotesForComponent = (types, headingLevel) => {
let upgradeNotes = '';
Object.entries(types).forEach(([type, notes]) => {
upgradeNotes += '#'.repeat(headingLevel);
upgradeNotes += ` ${getNoteName(type)}\n\n`;
notes.forEach(({ message, issueNumber }) => {
// Split the message into lines, removing empty lines.
const messageLines = message
.split('\n')
// Remove empty lines between tables, and list entries, but not after lists.
.filter((line, index, lines) => {
if (line.trim().length === 0) {
// This line is empty.
// If it's the first line in the file, remove it.
if (index === 0) {
return false;
}
// This is the last line in the file, remove it.
if (index === lines.length - 1) {
return false;
}
// If the previous line relates to a table, remove this line.
if (lines[index - 1].match(/^\s*\|/)) {
return false;
}
// If the next line is also empty, do not remove this line.
if (lines[index + 1].trim().length === 0) {
return true;
}
// Do not remove the line if the previous line was a list item.
if (lines[index - 1].match(/^\s*[-*]\s/)) {
return true;
}
if (lines[index - 1].match(/^\s*\d+\.\s/)) {
return true;
}
// Preserve all other empty lines by default.
return true;
}
// Keep any line which has content.
return true;
});
const firstLine = messageLines.shift().trim();
upgradeNotes += `- ${firstLine}\n`;
messageLines
.forEach((line) => {
upgradeNotes += ` ${line}`.trimEnd() + `\n`;
});
upgradeNotes += `\n For more information see [${issueNumber}](https://tracker.moodle.org/browse/${issueNumber})\n`;
});
upgradeNotes += '\n';
});
return upgradeNotes;
};
/**
* Get the updated notes mixed with existing content.
*
* @param {string} existingContent
* @param {string} upgradeNotes
*/
const getUpdatedNotes = (existingContent, upgradeNotes) => {
const { beforeContent, afterContent } = getBeforeAndAfterContent(existingContent);
const newContent = `${beforeContent}\n${upgradeNotes}\n${afterContent}`
.split('\n')
.filter((line, index, lines) => {
if (line === '' && lines[index - 1] === '') {
// Remove multiple consecutive empty lines.
return false;
}
return true;
})
.join('\n');
return newContent;
};
/**
* Update the notes for each component.
*/
const updateComponentNotes = (
notes,
version,
notesFileName = 'UPGRADING.md',
removeEmpty = false,
) => {
return getAllComponents().map(async (component) => {
logger.verbose(`Updating notes for ${component.name} into ${component.path}`);
const fileName = joinPath(component.path, notesFileName);
const existingContent = await getCurrentNotes(fileName);
if (!existingContent) {
if (!notes[component.value]) {
// No existing notes, and no new notes to add.
return;
}
} else {
if (!notes[component.value]) {
// There is existing content, but nothing to add.
if (removeEmpty) {
logger.verbose(`Removing empty notes file ${fileName}`);
await unlink(fileName);
}
return;
}
}
const componentNotes = notes[component.value];
let upgradeNotes = `## ${version}\n\n`;
upgradeNotes += getNotesForComponent(componentNotes, 3);
if (existingContent) {
await writeFile(fileName, getUpdatedNotes(existingContent, upgradeNotes));
} else {
await writeFile(
fileName,
`# ${component.name} Upgrade notes\n\n${upgradeNotes}`,
);
}
});
}
/**
* Generate the upgrade notes for a new release.
*
* @param {string|undefined} version
* @param {Object} options
* @param {boolean} options.generateUpgradeNotes
* @param {boolean} options.deleteNotes
* @returns {Promise<void>}
*/
export default async (version, options = {}) => {
const notes = await getCombinedNotesByComponent();
if (Object.keys(notes).length === 0) {
logger.warn('No notes to generate');
return;
}
if (!version) {
version = await getCurrentVersion();
}
// Generate the upgrade notes for this release.
// We have
// - a title with the release name
// - the change types
// - which contain the components
// - which document each change
let upgradeNotes = `## ${version}\n\n`;
Object.entries(notes).forEach(([component, types]) => {
upgradeNotes += `### ${component}\n\n`;
upgradeNotes += getNotesForComponent(types, 4);
});
await Promise.all([
createCurrentSummary(upgradeNotes),
...updateComponentNotes(notes, version, 'UPGRADING-CURRENT.md', true),
]);
if (options.generateUpgradeNotes) {
await Promise.all(updateComponentNotes(notes, version));
await updateUpgradeNotes(upgradeNotes, options);
}
};
-230
View File
@@ -1,230 +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/>.
import chalk from 'chalk';
import { isStandardComponent, isCommunityComponent, rewritePlugintypeAsSubsystem } from './components.mjs';
import { isValidNoteName } from './noteTypes.mjs';
import logger from './logger.mjs';
import { readFile } from 'fs/promises';
/**
* Validate an issue number input
*
* @param {string} input
* @returns {string|boolean}
*/
export const validateIssueNumber = (input) => {
if (!input) {
return 'You must provide a tracker issue number';
}
if (input.match(/^[a-zA-Z]*-\d+$/)) {
return true;
}
if (input.match(/^\d+$/)) {
return true;
}
return 'The issue number was not recognised as a valid issue number';
};
/**
* Format an issue number input.
*
* @param {string} input
* @returns {string}
*/
export const formatIssueNumber = (input) => {
if (input.match(/^[a-zA-Z]*-\d+$/)) {
return input;
}
if (input.match(/^\d+$/)) {
return `MDL-${input}`;
}
return input;
};
/**
* Validate a component.
*
* @param {string} input
* @returns {string|boolean}
*/
export const validateComponent = (input) => {
if (isStandardComponent(input)) {
return true;
}
if (isCommunityComponent(input)) {
return 'Currently only core plugins are supported.';
}
return 'The component was not recognised as a standard component';
};
export const formatComponent = (input) => {
if (rewritePlugintypeAsSubsystem(input)) {
return `core_${input}`;
}
return input;
}
/**
* Get the initial values from the options.
*
* @param {object} options
* @returns {object}
*/
export const getInitialValues = (options) => {
const initialValues = {};
const type = getInitialTypeValue(options);
if (type) {
initialValues.type = type;
}
const issueNumber = getInitialIssueValue(options);
if (issueNumber) {
initialValues.issueNumber = issueNumber;
}
const component = getInitialComponentValue(options);
if (component) {
initialValues.components = component;
}
const message = getInitialMessageValue(options);
if (message) {
initialValues.message = message
initialValues.addAnother = false;
}
return initialValues;
};
/**
* Get the initial type value.
*
* @param {Object} options
* @returns {string|undefined}
*/
const getInitialTypeValue = (options) => {
if (!options.type) {
return;
}
options.type = options.type.trim().toLowerCase();
if (isValidNoteName(options.type)) {
return options.type;
}
logger.warn(`Note type "${chalk.underline(chalk.red(options.type))}" is not valid.`);
};
/**
* Get the initial issue number value.
*
* @param {Object} options
* @returns {string|undefined}
*/
const getInitialIssueValue = (options) => {
if (!options.issue) {
return;
}
options.issue = options.issue.trim().toUpperCase();
const issueNumberValidated = validateIssueNumber(options.issue);
if (issueNumberValidated === true) {
const issueNumber = formatIssueNumber(options.issue);
if (issueNumber !== options.issue) {
logger.warn(
`Issue number "${chalk.underline(chalk.red(options.issue))}" was updated to ` +
`"${chalk.underline(chalk.green(issueNumber))}"`
);
}
return issueNumber;
} else {
logger.warn(`Issue number "${chalk.underline(chalk.red(options.issue))}" is not valid: ${issueNumberValidated}`);
}
};
/**
* Get the initial component value.
*
* @param {Object} options
* @returns {string|undefined}
*/
const getInitialComponentValue = (options) => {
if (!options.component) {
return;
}
options.component = options.component.trim().toLowerCase();
const componentValidated = validateComponent(options.component);
if (componentValidated === true) {
const component = formatComponent(options.component);
if (component !== options.component) {
logger.warn(
`Component "${chalk.underline(chalk.red(options.component))}" was updated to ` +
`"${chalk.underline(chalk.green(component))}"`
);
}
return component;
} else {
logger.warn(`Component "${chalk.underline(chalk.red(options.component))}" is not valid: ${componentValidated}`);
}
};
/**
* Get the initial message value.
*
* @param {Object} options
* @returns {string|undefined}
*/
const getInitialMessageValue = (options) => {
if (!options.message) {
return;
}
return options.message.trim();
};
/**
* Get the current version from the project /version.php file.
*
* @returns {Promise<string>}
*/
export const getCurrentVersion = async () => {
const versionRegex = new RegExp(/^ *\$release *= *['\"](?<release>[^ \+]+\+?) *\(Build:.*/m);
try {
const versionFile = await readFile('version.php', 'utf8');
const match = versionFile.match(versionRegex);
if (match) {
return match.groups.release;
}
} catch(error) {
logger.error('Unable to read the version file');
}
return "Unreleased";
}
-30
View File
@@ -1,30 +0,0 @@
#!/usr/bin/env node
// 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/>.
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
),
transports: [
new winston.transports.Console(),
],
});
export default logger;
-194
View File
@@ -1,194 +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/>.
import yaml from 'js-yaml';
import path from 'path';
import { writeFile, mkdir, readdir, readFile, unlink } from 'fs/promises';
import { isValidNoteName, sortNoteTypes } from './noteTypes.mjs';
import { sortComponents } from './components.mjs';
const unreleasedPath = path.resolve('.upgradenotes');
/**
* Get the filename for the note.
*
* @param {string} issueNumnber The issue number
* @returns {string}
*/
const getFilename = (issueNumber) => {
const dateTimeFormat = new Intl.DateTimeFormat(undefined, {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
fractionalSecondDigits: 2,
timeZone: 'UTC',
});
const date = Object.fromEntries(
dateTimeFormat.formatToParts(new Date())
.filter((p) => p.type !== 'literal')
.map((p) => ([p.type, p.value]))
);
const dateString = [
date.year,
date.month,
date.day,
date.hour,
date.minute,
date.second,
date.fractionalSecond,
].join('');
return `${issueNumber}-${dateString}.yml`;
};
/**
* Create a new note.
*
* @param {string} issueNumber
* @param {[type: string]: {message: string}} messages
* @returns {string} The path to the note on disk
*/
export const createNote = async (
issueNumber,
messages,
notePath,
) => {
const note = {
issueNumber,
notes: {},
};
messages.forEach(({components, type, message}) => {
note.notes[components] = note.notes[components] || [];
note.notes[components].push({message, type});
});
if (!notePath) {
notePath = path.resolve(unreleasedPath, getFilename(issueNumber));
}
const noteContent = yaml.dump(note);
await mkdir(unreleasedPath, {recursive: true});
await writeFile(notePath, noteContent);
return notePath;
};
/**
* Get all unreleased notes.
*
* @returns {Promise<{issueNumber: string, components: string[], types: {[type: string]: {message: string}[]}}[]>
*/
export const getAllNotes = async () => {
const files = await readdir(unreleasedPath);
const notes = files
.filter((file) => file.endsWith('.yml'))
.map(async (file) => {
const filePath = path.resolve(unreleasedPath, file);
const fileContent = await readFile(filePath, 'utf8');
return {
...yaml.load(fileContent),
filePath,
};
});
return Promise.all(notes);
};
/**
* Get the list of notes, grouped by note type, then component.
*
* @returns {Promise<{[type: string]: {[components: string]: {message: string, issueNumber: string}[]}}>}
*/
export const getCombinedNotes = async () => {
const notes = await getAllNotes();
const combinedNotes = {};
notes.forEach((note) => {
Object.entries(note.notes).forEach(([components, data]) => {
data.forEach((entry) => {
if (!isValidNoteName(entry.type)) {
throw new Error(`Invalid note type: "${entry.type}" in file ${note.filePath}`);
}
combinedNotes[entry.type] = combinedNotes[entry.type] || {};
combinedNotes[entry.type][components] = combinedNotes[entry.type][components] || [];
combinedNotes[entry.type][components].push({message: entry.message, issueNumber: note.issueNumber});
});
});
});
return combinedNotes;
};
/**
* Get the list of notes, grouped by component, then by note type.
*
* @returns {Promise<{[component: string]: {[type: string]: {message: string, issueNumber: string}[]}}>}
*/
export const getCombinedNotesByComponent = async () => {
const notes = await getAllNotes();
const combinedNotes = {};
notes.forEach((note) => {
Object.entries(note.notes).forEach(([component, data]) => {
combinedNotes[component] = combinedNotes[component] || {};
data.forEach((entry) => {
if (!isValidNoteName(entry.type)) {
throw new Error(`Invalid note type: "${entry.type}" in file ${note.filePath}`);
}
combinedNotes[component][entry.type] = combinedNotes[component][entry.type] || [];
combinedNotes[component][entry.type].push({
component,
message: entry.message,
issueNumber: note.issueNumber,
type: entry.type,
});
});
});
});
// Sort notes by note type.
Object.entries(combinedNotes).forEach(([component, types]) => {
combinedNotes[component] = Object.fromEntries(
Object.entries(types).sort(([a], [b]) => sortNoteTypes(a, b))
);
});
// Sort components.
return Object.fromEntries(
Object.entries(combinedNotes).sort(([a], [b]) => sortComponents(a, b))
);
};
/**
* Delete all unreleased notes.
*
* @returns {Promise<void>}
*/
export const deleteAllNotes = async () => {
const files = await readdir(unreleasedPath);
return Promise.all(
files
.filter((item, index) => files.indexOf(item) === index)
.filter((file) => file.endsWith('.yml'))
.map((file) => unlink(`${unreleasedPath}/${file}`))
);
};
-80
View File
@@ -1,80 +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/>.
/**
* The note types.
*
* Matches the suggested order in https://keepachangelog.com/en/1.1.0/.
* @type {Object<string, string>}
*/
const noteTypes = {
'improved': 'Added',
'changed': 'Changed',
'deprecated': 'Deprecated',
'removed': 'Removed',
'fixed': 'Fixed',
};
/**
* The preferred order of note types.
*
* @type {string[]}
*/
const preferredOrder = Object.keys(noteTypes);
/**
* Comparison method to sort note types.
*
* @param {String} a
* @param {String} b
* @returns {Number}
*/
export const sortNoteTypes = (a, b) => {
const aIndex = preferredOrder.indexOf(a);
const bIndex = preferredOrder.indexOf(b);
if (aIndex === -1) {
return 1;
}
if (bIndex === -1) {
return -1;
}
return aIndex - bIndex;
};
/**
* Get the note names.
*
* @returns {string[]}
*/
export const getNoteNames = () => Object.keys(noteTypes);
/**
* Get the human-readable note name.
*
* @param {string} type
* @returns {string}
*/
export const getNoteName = (type) => noteTypes[type];
/**
* Whether the note name is valid.
*
* @param {string} type
* @returns {boolean}
*/
export const isValidNoteName = (type) => noteTypes[type] !== undefined;
-153
View File
@@ -1,153 +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/>.
import inquirer from 'inquirer';
import SearchList from 'inquirer-search-list';
import { getNoteNames } from './noteTypes.mjs';
import { getAllComponents } from './components.mjs';
import {
formatComponent,
formatIssueNumber,
validateComponent,
validateIssueNumber,
} from './helpers.mjs';
/**
* A Search List which accepts an initial value.
*/
class SearchListWithInitialValue extends SearchList {
constructor(options, ...args) {
super(options, ...args);
if (options.default) {
const pointer = this.filterList.findIndex((item) => {
return item.value === options.default;
});
if (pointer > -1) {
this.pointer = pointer;
}
}
}
}
inquirer.registerPrompt('search-list', SearchListWithInitialValue);
/**
* Get the issue type prompt.
*
* @param {string} defaultData The initially selected value
* @returns {Object}
*/
export const getTypePrompt = (defaultData) => ({
default: defaultData,
type: 'search-list',
message: 'Type of change',
name: 'type',
choices: getNoteNames(),
validate: (selection) => {
if (selection.length < 1) {
return 'You must select at least one type of change';
}
return true;
},
});
/**
* Get the component prompt.
*
* @param {string} [defaultValue='core'] The initally selected value.
* @returns
*/
export const getComponentsPrompt = (defaultValue) => {
if (!defaultValue ) {
defaultValue = 'core';
}
return {
choices: getAllComponents(),
default: defaultValue,
type: 'search-list',
message: 'Component',
name: 'components',
validate: validateComponent,
filter: formatComponent,
};
};
/**
* Get the issue number prompt as an inline input.
*
* @param {string} defaultData
* @returns {object}
*/
export const getIssuePrompt = (defaultData) => ({
default: defaultData,
type: 'input',
message: 'Tracker issue number',
name: 'issueNumber',
validate: validateIssueNumber,
filter: formatIssueNumber,
});
/**
* Get a message prompt.
*
* @param {string} defaultData
* @returns
*/
export const getMessagePromptEditor = (defaultData) => ({
default: defaultData,
type: process.stdin.isTTY ? 'editor' : 'input',
postfix: '.md',
message: 'Message',
name: 'message',
waitUserInput: false,
validate: (input) => {
if (!input) {
return 'You must provide a message';
}
return true;
},
// Remove any trailing whitespace.
filter: (input) => input.split('\n').map((line) => line.trimEnd()).join('\n'),
});
/**
* Get a message prompt.
*
* @param {string} defaultData
* @returns
*/
export const getMessagePromptInput = (defaultData) => ({
default: defaultData,
type: 'input',
message: 'Message (leave empty to use editor)',
name: 'message',
filter: (input) => input.trim(),
});
/**
* Get a prompt to ask the user if they wish to add another entry.
*
* @returns {Object}
*/
export const getAddAnotherPrompt = () => ({
type: 'confirm',
message: 'Do you want to add another note?',
default: false,
name: 'addAnother',
});
-142
View File
@@ -1,142 +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) {
grunt.log.error(result.stdout);
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/sass/sass.js',
'--style', 'expanded',
'--source-map',
'--embed-sources',
'--precision', 6,
'--load-path', process.cwd(),
getCLPath('hugo/scss/docs.scss'),
getCLPath('hugo/dist/css/docs.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;
};
-215
View File
@@ -1,215 +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 minification 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-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 => {
grunt.log.debug(`Item resolved. Kicking off next one.`);
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(options) => {
return new Promise(resolve => {
queue.push(resolve);
startQueue();
return options;
});
},
// When an item in the queue completes, start the next item in the queue.
generateBundle: (options, bundle) => {
grunt.log.debug(`Finished output phase for ${Object.keys(bundle).join(', ')}`);
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')
],
presets: [
['@babel/preset-env', {
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);
};
-52
View File
@@ -1,52 +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 path = require('path');
grunt.registerTask('jsdoc', 'Generate JavaScript documentation using jsdoc', function() {
const done = this.async();
const configuration = path.resolve('.grunt/jsdoc/jsdoc.conf.js');
grunt.util.spawn({
cmd: 'jsdoc',
args: [
'--configure',
configuration,
]
}, function(error, result, code) {
if (result.stdout) {
grunt.log.write(result.stdout);
}
if (result.stderr) {
grunt.log.error(result.stderr);
}
if (error) {
grunt.fail.fatal(`JSDoc failed with error code ${code}`);
} else {
grunt.log.write('JSDoc completed successfully'.green);
}
done();
});
});
};
-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('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');
};
-187
View File
@@ -1,187 +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: {
quietDeprecationWarnings: true,
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: {
quietDeprecationWarnings: true,
customSyntax: 'postcss-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']
},
},
});
};
-42
View File
@@ -1,42 +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 2023 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Generate upgradable third-party libraries (utilising thirdpartylibs.xml data)
*/
grunt.registerTask('upgradablelibs', 'Generate upgradable third-party libraries', async function() {
const done = this.async();
const path = require('path');
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
// An array of third party libraries that have a newer version in their repositories.
const thirdPartyLibs = await ComponentList.getThirdPartyLibsUpgradable({progress: true});
for (let library of thirdPartyLibs) {
grunt.log.ok(JSON.stringify(Object.assign({}, library), null, 4));
}
done();
});
};
-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;
};
-103
View File
@@ -1,103 +0,0 @@
#!/usr/bin/env node
// 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/>.
import { Argument, Option, program } from 'commander';
import chalk from 'chalk';
import { getNoteNames } from './notes/src/noteTypes.mjs';
import createAction from './notes/src/create.mjs';
import generateAction from './notes/src/generate.mjs';
import logger from './notes/src/logger.mjs';
console.log(`
${chalk.bold(chalk.underline(chalk.green('Moodle Upgrade Notes Generator')))}
This tool is used to generate the upgrade notes for changes you make in Moodle.
Please remember that the intended audience of these changes is
${chalk.italic('plugin developers')} who need to know how to update their plugins
for a new Moodle version.
Upgrade notes should not be used to document changes for site administrators, or
for internal API changes which are not expected to be used outside of the
relevant component.
`)
program.configureHelp({
helpWidth: 100,
});
program.on('option:verbose', () => {
logger.level = 'verbose';
});
program.addOption(
new Option(
'-v, --verbose',
'Output more information during the generation process',
)
.default(false)
);
// Define the command line options.
program
.command('create')
.summary('Generate a new upgrade note')
.addOption(
new Option('-t, --type <type>', `The type of change to document. Valid types are: ${getNoteNames().join(', ')}`)
)
.addOption(new Option('-i, --issue <issue>', 'The tracker issue number'))
.addOption(new Option('-c, --component <component>', 'The component to write a note for'))
.addOption(new Option(
'-m, --message <message>',
'The message to use for the upgrade note',
))
.action((options) => createAction(options));
program
.command('summary')
.summary('Generate a local copy of the upgrade notes summary')
.addArgument(
new Argument('[version]', 'The Moodle version to create the summary notes for')
)
.action((version) => generateAction(version));
program
.command('release')
.summary('Generate the markdown copies of the upgrade notes for a Moodle release')
.addArgument(
new Argument('[version]', 'The Moodle version to create the release notes for')
)
.addOption(
new Option(
'--generate-upgrade-notes',
'Generate the UPGRADING.md notes for the release. ' +
'Note: This option is intended for use by the release manager when generating the upgrade notes.',
)
.default(true)
)
.addOption(
new Option(
'-d, --delete-notes',
'Delete the notes after generating the UPGRADING.md notes for the release. ' +
'Note: This option is intended for use by the release manager when generating the upgrade notes.' +
'This option has no effect unless --generate-upgrade-notes is also set.'
)
.default(false)
)
.action((version, options) => generateAction(version, options));
program.parse();
+1 -1
View File
@@ -1 +1 @@
lts/jod
v14.0.0
-40
View File
@@ -1,40 +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/>.
/**
* Helper file for PhpStorm, and other IDEs, to provide better code completion.
*
* @package core
* @copyright 2024 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace PHPSTORM_META;
// Assume that anything returned by \core\di::get('...') is an instance of the first argument.
override(\core\di::get(0), map([
'' => '@',
]));
// Assume that anything returned by \Psr\Container\ContainerInterface::get('...') is an instance of the first argument.
override(\Psr\Container\ContainerInterface::get(0), map([
'' => '@',
]));
// Assume that anything returned by \DI\Container::get('...') is an instance of the first argument.
override(\DI\Container::get(0), map([
'' => '@',
]));
+91
View File
@@ -0,0 +1,91 @@
# 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.*
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/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/mdn-polyfills/
lib/emoji-data/
lib/h5p/
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/alert.js
theme/boost/amd/src/button.js
theme/boost/amd/src/carousel.js
theme/boost/amd/src/collapse.js
theme/boost/amd/src/dropdown.js
theme/boost/amd/src/index.js
theme/boost/amd/src/modal.js
theme/boost/amd/src/popover.js
theme/boost/amd/src/sanitizer.js
theme/boost/amd/src/scrollspy.js
theme/boost/amd/src/tab.js
theme/boost/amd/src/toast.js
theme/boost/amd/src/tooltip.js
theme/boost/amd/src/util.js
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
+4 -16
View File
@@ -1,14 +1,9 @@
{
"customSyntax": "postcss-scss",
"plugins": [
"stylelint-csstree-validator"
],
"rules": {
"csstree/validator": {
"syntaxExtensions": [
"sass"
]
},
"csstree/validator": true,
"at-rule-empty-line-before": [ "always",
{"except": [ "blockless-after-blockless"], ignore: ["after-comment", "inside-block"]}
],
@@ -50,7 +45,7 @@
"function-name-case": "lower",
"function-parentheses-newline-inside": "always-multi-line",
"function-parentheses-space-inside": "never-single-line",
"function-url-scheme-disallowed-list": ["data"],
"function-url-scheme-blacklist": ["data"],
"function-whitespace-after": "always",
"indentation": 4,
"keyframe-declaration-no-important": true,
@@ -89,19 +84,12 @@
"selector-type-no-unknown": true,
"string-no-newline": true,
"time-min-milliseconds": 100,
"unit-disallowed-list": ["pt"],
"unit-blacklist": ["pt"],
"unit-case": "lower",
"unit-no-unknown": true,
"value-keyword-case": ["lower", {"ignoreKeywords": ["/(@|$)/"]}],
"value-list-comma-newline-after": "always-multi-line",
"value-list-comma-space-after": "always-single-line",
"value-list-comma-space-before": "never",
},
"overrides": [
{
"files": ["**/yui/**/*.css"],
"rules": {
}
}
]
}
}
+302
View File
@@ -0,0 +1,302 @@
# PLEASE NOTE: Travis is not currently utilised by the Moodle core integration
# process (which uses our internal CI system) this file is here for the benefit
# of community developers git clones - see MDL-51458.
# We currently disable Travis notifications entirely until https://github.com/travis-ci/travis-ci/issues/4976
# is fixed.
notifications:
email: false
language: php
os: linux
dist: xenial
services:
- mysql
- docker
php:
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
- 7.4
- 7.1.30 # Make this sticky because current default version (7.1.11) has a bug with redis-extension output (MDL-66062)
addons:
postgresql: "9.6"
env:
# Although we want to run these jobs and see failures as quickly as possible, we also want to get the slowest job to
# start first so that the total run time is not too high.
#
# We only run MySQL on PHP 7.2, so run that first.
# CI Tests should be second-highest in priority as these only take <= 60 seconds to run under normal circumstances.
# Postgres is significantly is pretty reasonable in its run-time.
# Run CI Tests without running PHPUnit.
- DB=none TASK=CITEST
# Run unit tests on Postgres
- DB=pgsql TASK=PHPUNIT
# Perform an upgrade test too.
- DB=pgsql TASK=UPGRADE
jobs:
# Enable fast finish.
# This will fail the build if a single job fails (except those in allow_failures).
# It will not stop the jobs from running.
fast_finish: true
include:
# 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:
- $HOME/.composer/cache
- $HOME/.npm
before_install:
- docker run -d -p 127.0.0.1:8080:80 --name exttests moodlehq/moodle-exttests
# Avoid IPv6 default binding as service (causes redis not to start).
- sudo service redis-server start --bind 127.0.0.1
install:
- >
if [ "$DB" = 'mysqli' ];
then
sudo mkdir /mnt/ramdisk
sudo mount -t tmpfs -o size=1024m tmpfs /mnt/ramdisk
sudo service mysql stop
sudo mv /var/lib/mysql /mnt/ramdisk
sudo ln -s /mnt/ramdisk/mysql /var/lib/mysql
sudo service mysql restart
fi
- >
if [ "$DB" = 'pgsql' ];
then
sudo mkdir /mnt/ramdisk
sudo mount -t tmpfs -o size=1024m tmpfs /mnt/ramdisk
sudo service postgresql stop
sudo mv /var/lib/postgresql /mnt/ramdisk
sudo ln -s /mnt/ramdisk/postgresql /var/lib/postgresql
sudo service postgresql start 9.6
fi
- >
if [ "$TASK" = 'PHPUNIT' ];
then
if [ -n "$GITHUB_APITOKEN" ]; then
composer config github-oauth.github.com $GITHUB_APITOKEN;
echo 'auth.json' >> .git/info/exclude
fi
echo 'extension="redis.so"' > /tmp/redis.ini
phpenv config-add /tmp/redis.ini
# Install composer dependencies.
# We need --no-interaction in case we hit API limits for composer. This causes it to fall back to a standard clone.
# Typically it should be able to use the Composer cache if any other job has already completed before we started here.
travis_retry composer install --prefer-dist --no-interaction;
fi
- >
if [ "$TASK" = 'GRUNT' ];
then
nvm install $NVM_VERSION ;
nvm use $NVM_VERSION ;
fi
before_script:
- phpenv config-rm xdebug.ini
- >
if [ "$TASK" = 'PHPUNIT' -o "$TASK" = 'UPGRADE' ];
then
# Copy generic configuration in place.
cp config-dist.php config.php ;
# Create the moodledata directory.
mkdir -p "$HOME"/roots/base
# The database name and password.
sed -i \
-e "s%= 'moodle'%= 'travis_ci_test'%" \
-e "s%= 'password'%= ''%" \
config.php ;
# The wwwroot and dataroot.
sed -i \
-e "s%http://example.com/moodle%https://localhost%" \
-e "s%/home/example/moodledata%/home/travis/roots/base%" \
config.php ;
if [ "$DB" = 'pgsql' ];
then
# Postgres-specific setup.
sed -i \
-e "s%= 'username'%= 'postgres'%" \
config.php ;
psql -c 'CREATE DATABASE travis_ci_test;' -U postgres;
fi
if [ "$DB" = 'mysqli' ];
then
# MySQL-specific setup.
sed -i \
-e "s%= 'pgsql'%= 'mysqli'%" \
-e "s%= 'username'%= 'travis'%" \
-e "s%=> 'utf8mb4_unicode_ci'%=> 'utf8mb4_bin'%" \
config.php;
mysql -u root -e 'SET GLOBAL innodb_file_format=barracuda;' ;
mysql -u root -e 'SET GLOBAL innodb_file_per_table=ON;' ;
mysql -u root -e 'SET GLOBAL innodb_large_prefix=ON;' ;
mysql -e 'CREATE DATABASE travis_ci_test DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_bin;' ;
fi
fi
- >
if [ "$TASK" = 'PHPUNIT' ];
then
# Create a directory for the phpunit dataroot.
mkdir -p "$HOME"/roots/phpunit
# The phpunit dataroot and prefix..
sed -i \
-e "/require_once/i \\\$CFG->phpunit_dataroot = '\/home\/travis\/roots\/phpunit';" \
-e "/require_once/i \\\$CFG->phpunit_prefix = 'p_';" \
config.php ;
# Enable test external resources
sed -i \
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://127.0.0.1:8080');" \
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://127.0.0.1:8080');" \
config.php ;
# Redis cache store tests
sed -i \
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
config.php ;
# 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 \\${redissession}" \
config.php ;
# Initialise PHPUnit for Moodle.
php admin/tool/phpunit/cli/init.php
fi
- >
if [ "$TASK" = 'GRUNT' ];
then
npm install --no-spin;
npm install --no-spin -g grunt ;
fi
########################################################################
# CI Tests
########################################################################
- >
if [ "$TASK" = 'CITEST' ];
then
# Note - this is deliberately placed in the script section as we
# should not add any code until after phpunit has run.
# The following repositories are required.
# The local_ci repository does the actual checking.
git clone https://github.com/moodlehq/moodle-local_ci.git local/ci
# We need the official upstream for comparison
git remote add upstream https://github.com/moodle/moodle.git;
git fetch upstream MOODLE_38_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`
# Variables required by our linter.
export gitcmd=`which git`;
export gitdir="$TRAVIS_BUILD_DIR";
export phpcmd=`which php`;
fi
########################################################################
# Upgrade test
########################################################################
- >
if [ "$TASK" = 'UPGRADE' ];
then
# We need the official upstream.
git remote add upstream https://github.com/moodle/moodle.git;
# Checkout 30 STABLE branch (the first version compatible with PHP 7.x)
git fetch upstream MOODLE_30_STABLE;
git checkout MOODLE_30_STABLE;
# Perform the upgrade
php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
# Return to the previous commit
git checkout -;
# Perform the upgrade
php admin/cli/upgrade.php --non-interactive --allow-unstable ;
# The local_ci repository can be used to check upgrade savepoints.
git clone https://github.com/moodlehq/moodle-local_ci.git local/ci ;
fi
script:
- >
if [ "$TASK" = 'PHPUNIT' ];
then
vendor/bin/phpunit --fail-on-risky --disallow-test-output --verbose;
fi
- >
if [ "$TASK" = 'CITEST' ];
then
bash local/ci/php_lint/php_lint.sh;
fi
- >
if [ "$TASK" = 'GRUNT' ];
then
grunt ;
# 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.
git add . ;
git reset -- npm-shrinkwrap.json ;
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' ];
then
EXTTESTS_HITS=$(docker logs exttests 2>&1 | grep -Fv -e 'AH00558' -e '[pid 1]' | wc -l)
echo -e "\nTest local resources number of hits: ${EXTTESTS_HITS}.\n"
fi
-52
View File
@@ -1,52 +0,0 @@
# Contributing to Moodle
[Moodle][1] is made by people like you. We are members of a big worldwide community of developers, designers, teachers, testers, translators and many more. We work in universities, schools, companies and other places. You are very welcome to join us and contribute to the project.
There are many ways that you can contribute to Moodle, not just through development. See our [community contribution guide][2] for some of the many ways that you can help.
## Github
> [!NOTE]
> Please do not open pull requests via Github.
All issues should be reported via, and patched provided to the [Moodle Tracker][3].
The Moodle [Github][4] repository is a clone of the official Moodle repository, whcih can be found at https://git.moodle.org.
## Moodle core bug fixes and new features
Over the years, Moodle has developed a mature process for reporting, reviewing, and accepting patches. This is fully documented in our [documentation on development processes][6], but in summary:
- Every bug fix or new feature must have a tracker issue.
- You publish the branch implementing the fix or new feature in your public clone of the moodle.git repository (typically on Github).
- Your patch is peer-reviewed, discussed, integrated, tested and then released as a part of one of our weekly releases.
- New features are developed on the `main` branch. Bug fixes are also backported to currently supported maintenance (stable) branches.
> [!IMPORTANT]
> Please do not publish security issues, or patches releating to them publicly.
> See our [Responsible Disclosure Policy][5] for more information.
## Moodle plugins
Moodle has a framework for additional plugins to extend its functionality. We
have a Moodle plugins directory <https://moodle.org/plugins/> where you can
register and maintain your plugin. Plugins hosted in the plugins directory can
be easily installed and updated via the Moodle administration interface.
* You are expected to have a public source code repository with your plugin
code.
* After registering your plugin in the plugins directory it is reviewed before
being published.
* You are expected to continuously release updated versions of the plugin via
the plugins directory. We do not pull from your code repository; you must do
it explicitly.
For further details, see <https://moodledev.io/general/community/plugincontribution>.
[1]: https://moodle.org
[2]: https://moodledev.io/general/community/contribute
[3]: https://tracker.moodle.org
[4]: https://github.com/moodle/moodle
[5]: https://moodledev.io/general/development/process/security
[6]: https://moodledev.io/general/development/process
+56
View File
@@ -0,0 +1,56 @@
CONTRIBUTING TO MOODLE
======================
Moodle is made by people like you. We are members of a big worldwide community
of developers, designers, teachers, testers, translators and other users. We
work in universities, schools, companies and other places. You are very welcome
to join us and contribute to the project.
See <https://docs.moodle.org/dev/Contributing_to_Moodle> for the many ways you
can help, not only with coding.
Moodle is open to community contributions to core, though all code must go
through peer-review, automated behaviour testing, continuous integration and
human post-integration checks.
Pull requests
-------------
Please do not open pull requests via Github. The repository there is just a
mirror of the official repository at <https://git.moodle.org>. Issues are
reported and patches provided via <https://tracker.moodle.org>. See below for
more information.
Moodle core bug fixes and new features
--------------------------------------
During the years of intensive development, a mature process of including
submitted patches has evolved.
* Every bug fix or new feature must have a tracker issue.
* You publish the branch implementing the fix or new feature in your public
clone of the moodle.git repository (typically on Github).
* Your patch is peer-reviewed, discussed, integrated, tested and then released
as a part of moodle.git.
* New features are developed on the master branch. Bug fixes are also
backported to currently supported maintenance (stable) branches.
For further details, see <https://docs.moodle.org/dev/Process>.
Moodle plugins
--------------
Moodle has a framework for additional plugins to extend its functionality. We
have a Moodle plugins directory <https://moodle.org/plugins/> where you can
register and maintain your plugin. Plugins hosted in the plugins directory can
be easily installed and updated via the Moodle administration interface.
* You are expected to have a public source code repository with your plugin
code.
* After registering your plugin in the plugins directory it is reviewed before
being published.
* You are expected to continuously release updated versions of the plugin via
the plugins directory. We do not pull from your code repository; you must do
it explicitly.
For further details, see <https://docs.moodle.org/dev/Plugin_contribution>.
+613 -219
View File
@@ -16,200 +16,26 @@
/* eslint-env node */
/**
* Grunt configuration for Moodle.
*
* @copyright 2014 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Setup the Grunt Moodle environment.
*
* @param {Grunt} grunt
* @returns {Object}
* Grunt configuration
*/
const setupMoodleEnvironment = 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('..');
// Globbing pattern for matching all AMD JS source files.
let amdSrc = [];
if (inComponent) {
amdSrc.push(
componentDirectory + "/amd/src/*.js",
componentDirectory + "/amd/src/**/*.js"
);
} else {
amdSrc = ComponentList.getAmdSrcGlobList();
}
return {
inAMD,
amdSrc,
};
};
const getYuiConfiguration = () => {
let yuiSrc = [];
if (inComponent) {
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
} else {
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
}
return {
yuiSrc,
};
};
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);
} else {
ComponentList.getComponentPaths(`${gruntFilePath}/`).forEach(componentPath => {
checkComponentDirectory(componentPath);
});
}
return {
cssSrc,
scssSrc,
};
};
/**
* 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());
// 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');
}
}
return cwd;
};
// Detect directories:
// * gruntFilePath The real path on disk to this Gruntfile.js
// * cwd The current working directory, which can be overridden by the `root` option
// * relativeCwd The cwd, relative to the Gruntfile.js
// * componentDirectory The root directory of the component if the cwd is in a valid component
// * inComponent Whether the cwd is in a valid component
// * runDir The componentDirectory or cwd if not in a component, relative to Gruntfile.js
// * fullRunDir The full path to the runDir
const gruntFilePath = fs.realpathSync(process.cwd());
const cwd = getCwd(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}`);
grunt.log.debug(`= process.cwd: '` + process.cwd() + `'`);
grunt.log.debug(`= process.env.PWD: '${process.env.PWD}'`);
grunt.log.debug(`= path.sep '${path.sep}'`);
grunt.log.debug('============================================================================');
grunt.log.debug(`= gruntFilePath: '${gruntFilePath}'`);
grunt.log.debug(`= relativeCwd: '${relativeCwd}'`);
grunt.log.debug(`= componentDirectory: '${componentDirectory}'`);
grunt.log.debug(`= inComponent: '${inComponent}'`);
grunt.log.debug(`= runDir: '${runDir}'`);
grunt.log.debug(`= fullRunDir: '${fullRunDir}'`);
grunt.log.debug('============================================================================');
if (inComponent) {
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');
/* eslint-env node */
module.exports = function(grunt) {
var path = require('path'),
tasks = {},
cwd = process.env.PWD || process.cwd(),
async = require('async'),
DOMParser = require('xmldom').DOMParser,
xpath = require('xpath'),
semver = require('semver'),
watchman = require('fb-watchman'),
watchmanClient = new watchman.Client(),
gruntFilePath = process.cwd();
// Verify the node version is new enough.
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
@@ -217,50 +43,618 @@ const verifyNodeVersion = grunt => {
if (!semver.satisfies(actual, expected)) {
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
}
};
/**
* Grunt configuration.
*
* @param {Grunt} grunt
*/
module.exports = function(grunt) {
// Verify that the Node version meets our requirements.
verifyNodeVersion(grunt);
// 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')) {
var root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) {
cwd = path.join(__dirname, root);
grunt.log.ok('Setting root to ' + cwd);
} else {
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
// Setup the Moodle environemnt within the Grunt object.
grunt.moodleEnv = setupMoodleEnvironment(grunt);
var files = null;
if (grunt.option('files')) {
// Accept a comma separated list of files to process.
files = grunt.option('files').split(',');
}
var inAMD = path.basename(cwd) == 'amd';
// Globbing pattern for matching all AMD JS source files.
var amdSrc = [];
if (inAMD) {
amdSrc.push(cwd + "/src/*.js");
amdSrc.push(cwd + "/src/**/*.js");
} else {
amdSrc.push("**/amd/src/*.js");
amdSrc.push("**/amd/src/**/*.js");
}
/**
* 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() {
var thirdpartyfiles = grunt.file.expand('*/**/thirdpartylibs.xml');
var libs = ['node_modules/', 'vendor/'];
// Add Moodle task configuration.
addTask('gherkinlint', grunt);
addTask('ignorefiles', grunt);
thirdpartyfiles.forEach(function(file) {
var dirname = path.dirname(file);
addTask('javascript', grunt);
addTask('style', grunt);
addTask('componentlibrary', grunt);
var doc = new DOMParser().parseFromString(grunt.file.read(file));
var nodes = xpath.select("/libraries/library/location/text()", doc);
addTask('watch', grunt);
addTask('startup', grunt);
nodes.forEach(function(node) {
var lib = path.join(dirname, node.toString());
if (grunt.file.isDir(lib)) {
// Ensure trailing slash on dirs.
lib = lib.replace(/\/?$/, '/');
}
addTask('upgradablelibs', grunt);
// Look for duplicate paths before adding to array.
if (libs.indexOf(lib) === -1) {
libs.push(lib);
}
});
});
return libs;
};
// 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 : ['**/yui/src/**/*.js', '!*/**/yui/src/*/meta/*.js']}
},
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: {
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
}
},
watch: {
options: {
nospawn: true // We need not to spawn so config can be changed dynamically.
},
amd: {
files: ['**/amd/src/**/*.js'],
tasks: ['amd']
},
boost: {
files: ['**/theme/boost/scss/**/*.scss'],
tasks: ['scss']
},
rawcss: {
files: ['**/*.css', '**/theme/**/!(moodle.css|editor.css)'],
tasks: ['rawcss']
},
yui: {
files: ['**/yui/src/**/*.js'],
tasks: ['yui']
},
gherkinlint: {
files: ['**/tests/behat/*.feature'],
tasks: ['gherkinlint']
}
},
shifter: {
options: {
recursive: true,
paths: files ? files : [cwd]
}
},
gherkinlint: {
options: {
files: files ? files : ['**/tests/behat/*.feature'],
}
},
stylelint: {
scss: {
options: {syntax: 'scss'},
src: files ? files : ['*/**/*.scss']
},
css: {
src: files ? files : ['*/**/*.css'],
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
}
}
}
}
}
});
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
tasks.ignorefiles = function() {
// An array of paths to third party directories.
var thirdPartyPaths = getThirdPartyPathsFromXML();
// Generate .eslintignore.
var eslintIgnores = ['# Generated by "grunt ignorefiles"', '*/**/yui/src/*/meta/', '*/**/build/'].concat(thirdPartyPaths);
grunt.file.write('.eslintignore', eslintIgnores.join('\n'));
// Generate .stylelintignore.
var 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/src/linter.js');
const featureFinder = require('gherkin-lint/src/feature-finder.js');
const configParser = require('gherkin-lint/src/config-parser.js');
const formatter = require('gherkin-lint/src/formatters/stylish.js');
// Run the linter.
const results = linter.lint(
featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
configParser.getConfiguration(configParser.defaultConfigFileName)
);
// Print the results out uncondtionally.
formatter.printResults(results);
// Report on the results.
// The done function takes a bool whereby a falsey statement causes the task to fail.
done(results.every(result => result.errors.length === 0));
};
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: cwd,
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();
}
);
};
var watchConfig = grunt.config.get(['watch']);
watchConfig = Object.keys(watchConfig).reduce(function(carry, key) {
if (key == 'options') {
return carry;
}
var value = watchConfig[key];
var fileGlobs = value.files;
var taskNames = value.tasks;
taskNames.forEach(function(taskName) {
carry[taskName] = fileGlobs;
});
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 = cwd + '/' + file.name;
Object.keys(watchConfig).forEach(function(task) {
var fileGlobs = watchConfig[task];
var match = fileGlobs.every(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', cwd], 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;
}
// Use the matching patterns specified in the watch config.
var matches = Object.keys(watchConfig).map(function(task) {
var fileGlobs = watchConfig[task];
var fileGlobMatches = fileGlobs.map(function(fileGlob) {
return ['match', fileGlob, 'wholename'];
});
return ['allof'].concat(fileGlobMatches);
});
var sub = {
expression: ["anyof"].concat(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 ' + cwd);
});
});
});
};
// 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 taks.
grunt.registerTask('css', ['stylelint:scss', 'sass', 'stylelint:css']);
grunt.registerTask('scss', ['stylelint:scss', 'sass']);
grunt.registerTask('rawcss', ['stylelint:css']);
// 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']);
+7
View File
@@ -0,0 +1,7 @@
*** PLEASE DO NOT OPEN PULL REQUESTS VIA GITHUB ***
The moodle.git repository at Github is just a mirror of the official repository. We do not accept pull requests at Github.
See CONTRIBUTING.txt guidelines for how to contribute patches for Moodle. Thank you.
--
-48
View File
@@ -1,48 +0,0 @@
# Moodle
<p align="center"><a href="https://moodle.org" target="_blank" title="Moodle Website">
<img src="https://raw.githubusercontent.com/moodle/moodle/main/.github/moodlelogo.svg" alt="The Moodle Logo">
</a></p>
[Moodle][1] is the World's Open Source Learning Platform, widely used around the world by countless universities, schools, companies, and all manner of organisations and individuals.
Moodle is designed to allow educators, administrators and learners to create personalised learning environments with a single robust, secure and integrated system.
## Documentation
- Read our [User documentation][3]
- Discover our [developer documentation][5]
- Take a look at our [demo site][4]
## Community
[moodle.org][1] is the central hub for the Moodle Community, with spaces for educators, administrators and developers to meet and work together.
You may also be interested in:
- attending a [Moodle Moot][6]
- our regular series of [developer meetings][7]
- the [Moodle User Association][8]
## Installation and hosting
Moodle is Free, and Open Source software. You can easily [download Moodle][9] and run it on your own web server, however you may prefer to work with one of our experienced [Moodle Partners][10].
Moodle also offers hosting through both [MoodleCloud][11], and our [partner network][10].
## License
Moodle is provided freely as open source software, under version 3 of the GNU General Public License. For more information on our license see
[1]: https://moodle.org
[2]: https://moodle.com
[3]: https://docs.moodle.org/
[4]: https://sandbox.moodledemo.net/
[5]: https://moodledev.io
[6]: https://moodle.com/events/mootglobal/
[7]: https://moodledev.io/general/community/meetings
[8]: https://moodleassociation.org/
[9]: https://download.moodle.org
[10]: https://moodle.com/partners
[11]: https://moodle.com/cloud
[12]: https://moodledev.io/general/license
+28
View File
@@ -0,0 +1,28 @@
.-..-.
_____ | || |
/____/-.---_ .---. .---. .-.| || | .---.
| | _ _ |/ _ \/ _ \/ _ || |/ __ \
* | | | | | || |_| || |_| || |_| || || |___/
|_| |_| |_|\_____/\_____/\_____||_|\_____)
Moodle - the world's open source learning platform
Moodle <https://moodle.org> is a learning platform designed to provide
educators, administrators and learners with a single robust, secure and
integrated system to create personalised learning environments.
You can download Moodle <https://download.moodle.org> and run it on your own
web server, ask one of our Moodle Partners <https://moodle.com/partners/> to
assist you, or have a MoodleCloud site <https://moodle.com/cloud/> set up for
you.
Moodle is widely used around the world by universities, schools, companies and
all manner of organisations and individuals.
Moodle is provided freely as open source software, under the GNU General Public
License <https://docs.moodle.org/dev/License>.
Moodle is written in PHP and JavaScript and uses an SQL database for storing
the data.
See <https://docs.moodle.org> for details of Moodle's many features.
+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/>.
-1415
View File
File diff suppressed because it is too large Load Diff
-9
View File
@@ -1,9 +0,0 @@
# core_admin (subsystem) Upgrade notes
## 4.5rc1
### Removed
- The HTTP Server setting "Use slash arguments" (slasharguments) configuration setting and related to it has been removed. Calling the option with $CFG->slasharguments or get_config('slasharguments') is no longer available.
For more information see [MDL-62640](https://tracker.moodle.org/browse/MDL-62640)
+48
View File
@@ -0,0 +1,48 @@
<?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 settings search form
*
* @package admin
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once $CFG->libdir.'/formslib.php';
/**
* Admin settings search form
*
* @package admin
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_settings_search_form extends moodleform {
function definition () {
$mform = $this->_form;
//$mform->addElement('header', 'settingsheader', get_string('search', 'admin'));
$elements = [];
$elements[] = $mform->createElement('text', 'query', get_string('query', 'admin'));
$elements[] = $mform->createElement('submit', 'search', get_string('search'));
$mform->addGroup($elements);
$mform->setType('query', PARAM_RAW);
$mform->setDefault('query', optional_param('query', '', PARAM_RAW));
}
}
-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/>.
/**
* Manage AI subsystem plugins settings.
*
* @package core_admin
* @copyright 2024 Matt Porritt <matt.porritt@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once($CFG->libdir . '/adminlib.php');
$action = required_param('action', PARAM_ALPHANUMEXT);
$type = required_param('type', PARAM_PLUGIN); // Must be provider or placement.
$name = required_param('name', PARAM_PLUGIN); // Plugin name, e.g openai.
$syscontext = context_system::instance();
$PAGE->set_url('/admin/ai.php');
$PAGE->set_context($syscontext);
require_admin();
require_sesskey();
$return = new moodle_url('/admin/settings.php', ['section' => "aisettings$type"]);
$plugins = core_plugin_manager::instance()->get_plugins_of_type("ai$type");
$sortorder = array_flip(array_keys($plugins));
if (!isset($plugins[$name])) {
throw new moodle_exception('aipluginnotfound', 'core_ai', $return, $name);
}
$plugintypename = $plugins[$name]->type . '_' . $plugins[$name]->name;
switch ($action) {
case 'disable':
if ($plugins[$name]->is_enabled()) {
$class = core_plugin_manager::resolve_plugininfo_class("aisettings$type");
$class::enable_plugin($name, false);
}
break;
case 'enable':
if (!$plugins[$name]->is_enabled()) {
$class = core_plugin_manager::resolve_plugininfo_class("aisettings$type");
$class::enable_plugin($name, true);
}
break;
}
redirect($return);
-3
View File
@@ -1,3 +0,0 @@
define("core_admin/block_management_table",["exports","./plugin_management_table","core_table/dynamic","core/ajax","core/pending","core/notification"],(function(_exports,_plugin_management_table,_dynamic,_ajax,_pending,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_plugin_management_table=_interopRequireDefault(_plugin_management_table),_pending=_interopRequireDefault(_pending);class _default extends _plugin_management_table.default{constructor(){super(),this.addClickHandler(this.handleBlockProtectToggle)}setBlockProtectState(plugin,state){return(0,_ajax.call)([{methodname:"core_admin_set_block_protection",args:{plugin:plugin,state:state}}])[0]}async handleBlockProtectToggle(tableRoot,e){const stateToggle=e.target.closest('[data-action="toggleprotectstate"]');if(stateToggle){e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:processAction");await this.setBlockProtectState(stateToggle.dataset.plugin,"1"===stateToggle.dataset.targetState?1:0);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]);updatedRoot.querySelector('[data-action="toggleprotectstate"][data-plugin="'.concat(stateToggle.dataset.plugin,'"]')).focus(),pendingPromise.resolve()}}}return _exports.default=_default,_exports.default}));
//# sourceMappingURL=block_management_table.min.js.map
@@ -1 +0,0 @@
{"version":3,"file":"block_management_table.min.js","sources":["../src/block_management_table.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\nimport PluginManagementTable from './plugin_management_table';\nimport {refreshTableContent} from 'core_table/dynamic';\nimport {call as fetchMany} from 'core/ajax';\nimport Pending from 'core/pending';\nimport {fetchNotifications} from 'core/notification';\n\nexport default class extends PluginManagementTable {\n constructor() {\n super();\n this.addClickHandler(this.handleBlockProtectToggle);\n }\n\n /**\n * Set the block protection state.\n *\n * @param {string} plugin\n * @param {number} state\n * @returns {Promise}\n */\n setBlockProtectState(plugin, state) {\n return fetchMany([{\n methodname: 'core_admin_set_block_protection',\n args: {\n plugin,\n state,\n },\n }])[0];\n }\n\n /**\n * Handle toggling of block protection.\n *\n * @param {HTMLElement} tableRoot\n * @param {Event} e\n */\n async handleBlockProtectToggle(tableRoot, e) {\n const stateToggle = e.target.closest('[data-action=\"toggleprotectstate\"]');\n if (stateToggle) {\n e.preventDefault();\n const pendingPromise = new Pending('core_table/dynamic:processAction');\n\n await this.setBlockProtectState(\n stateToggle.dataset.plugin,\n stateToggle.dataset.targetState === '1' ? 1 : 0\n );\n\n const [updatedRoot] = await Promise.all([\n refreshTableContent(tableRoot),\n fetchNotifications(),\n ]);\n\n // Refocus on the link that as pressed in the first place.\n updatedRoot.querySelector(`[data-action=\"toggleprotectstate\"][data-plugin=\"${stateToggle.dataset.plugin}\"]`).focus();\n pendingPromise.resolve();\n }\n }\n}\n"],"names":["PluginManagementTable","constructor","addClickHandler","this","handleBlockProtectToggle","setBlockProtectState","plugin","state","methodname","args","tableRoot","e","stateToggle","target","closest","preventDefault","pendingPromise","Pending","dataset","targetState","updatedRoot","Promise","all","querySelector","focus","resolve"],"mappings":"uhBAqB6BA,iCACzBC,2BAESC,gBAAgBC,KAAKC,0BAU9BC,qBAAqBC,OAAQC,cAClB,cAAU,CAAC,CACdC,WAAY,kCACZC,KAAM,CACFH,OAAAA,OACAC,MAAAA,UAEJ,kCASuBG,UAAWC,SAChCC,YAAcD,EAAEE,OAAOC,QAAQ,yCACjCF,YAAa,CACbD,EAAEI,uBACIC,eAAiB,IAAIC,iBAAQ,0CAE7Bd,KAAKE,qBACPO,YAAYM,QAAQZ,OACgB,MAApCM,YAAYM,QAAQC,YAAsB,EAAI,SAG3CC,mBAAqBC,QAAQC,IAAI,EACpC,gCAAoBZ,YACpB,wCAIJU,YAAYG,wEAAiEX,YAAYM,QAAQZ,cAAYkB,QAC7GR,eAAeS"}
-10
View File
@@ -1,10 +0,0 @@
define("core_admin/bulk_user_actions",["exports","core_reportbuilder/local/selectors","core_table/local/dynamic/events","core_form/changechecker","core/custom_interaction_events","jquery"],(function(_exports,reportSelectors,tableEvents,FormChangeChecker,CustomEvents,_jquery){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}
/**
* Add bulk actions to the users list report
*
* @module core_admin/bulk_user_actions
* @copyright 2024 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,reportSelectors=_interopRequireWildcard(reportSelectors),tableEvents=_interopRequireWildcard(tableEvents),FormChangeChecker=_interopRequireWildcard(FormChangeChecker),CustomEvents=_interopRequireWildcard(CustomEvents),_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj};const Selectors_bulkActionsForm="form#user-bulk-action-form",Selectors_userReportWrapper='[data-region="report-user-list-wrapper"]',Selectors_checkbox='input[type="checkbox"][data-togglegroup="report-select-all"][data-toggle="slave"]',Selectors_masterCheckbox='input[type="checkbox"][data-togglegroup="report-select-all"][data-toggle="master"]',Selectors_checkedRows='[data-togglegroup="report-select-all"][data-toggle="slave"]:checked';_exports.init=()=>{var _userBulkForm$closest;const userBulkForm=document.querySelector(Selectors_bulkActionsForm),userReport=null==userBulkForm||null===(_userBulkForm$closest=userBulkForm.closest(Selectors_userReportWrapper))||void 0===_userBulkForm$closest?void 0:_userBulkForm$closest.querySelector(reportSelectors.regions.report);if(!userBulkForm||!userReport)return;const actionSelect=userBulkForm.querySelector("select");CustomEvents.define(actionSelect,[CustomEvents.events.accessibleChange]),(0,_jquery.default)(actionSelect).on(CustomEvents.events.accessibleChange,(event=>{if(event.target.value&&"0"!=="".concat(event.target.value)){const e=new Event("submit",{cancelable:!0});userBulkForm.dispatchEvent(e),e.defaultPrevented||(FormChangeChecker.markFormSubmitted(userBulkForm),userBulkForm.submit())}}));const updateUserIds=()=>{const selectedUsers=[...userReport.querySelectorAll(Selectors_checkedRows)],selectedUserIds=selectedUsers.map((check=>parseInt(check.value)));userBulkForm.querySelector('[name="userids"]').value=selectedUserIds.join(","),actionSelect.disabled=0===selectedUsers.length,actionSelect.disabled&&(actionSelect.value="0");const selectedUsersNames=selectedUsers.map((check=>document.querySelector('label[for="'.concat(check.id,'"]')).textContent));userBulkForm.data={userids:selectedUserIds,usernames:selectedUsersNames}};updateUserIds(),document.addEventListener("change",(event=>{(event.target.matches(Selectors_checkbox)||event.target.matches(Selectors_masterCheckbox))&&userReport.contains(event.target)&&updateUserIds()})),document.addEventListener(tableEvents.tableContentRefreshed,(event=>{userReport.contains(event.target)&&updateUserIds()}))}}));
//# sourceMappingURL=bulk_user_actions.min.js.map
File diff suppressed because one or more lines are too long
-12
View File
@@ -1,12 +0,0 @@
define("core_admin/expand_hash",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=_exports.expandSection=void 0;
/**
* Expand the collapse section element.
*
* @module core_admin/expand_hash
* @copyright Meirza <meirza.arson@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.5
*/
const SELECTORS_COLLAPSE_ELEMENTS='[data-toggle="collapse"]',SELECTORS_FOCUSTHENEXPAND_ELEMENTS=".focus-expand";_exports.init=()=>{const focusexpand=document.querySelector(SELECTORS_FOCUSTHENEXPAND_ELEMENTS);null==focusexpand||focusexpand.addEventListener("click",(()=>{expandSection("".concat(focusexpand.getAttribute("href")))}))};const expandSection=hash=>{const container=document.querySelector(hash),targetContainer=null==container?void 0:container.querySelector(SELECTORS_COLLAPSE_ELEMENTS);if("false"===(null==targetContainer?void 0:targetContainer.getAttribute("aria-expanded"))){const collapseId=targetContainer.getAttribute("aria-controls"),collapseContainer=document.getElementById(collapseId);collapseContainer.classList.remove("collapse"),collapseContainer.classList.add("show"),targetContainer.setAttribute("aria-expanded","true"),targetContainer.classList.remove("collapsed");const collapseElement=document.querySelector(".collapseexpand.collapsemenu");collapseElement.setAttribute("aria-expanded","true"),collapseElement.classList.remove("collapsed")}};_exports.expandSection=expandSection}));
//# sourceMappingURL=expand_hash.min.js.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"file":"expand_hash.min.js","sources":["../src/expand_hash.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Expand the collapse section element.\n *\n * @module core_admin/expand_hash\n * @copyright Meirza <meirza.arson@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.5\n */\n\nconst SELECTORS = {\n COLLAPSE_ELEMENTS: '[data-toggle=\"collapse\"]',\n FOCUSTHENEXPAND_ELEMENTS: '.focus-expand',\n};\n\n/**\n * Initializes the focus and expand functionality.\n */\nexport const init = () => {\n // Select all collapsible elements only.\n const focusexpand = document.querySelector(SELECTORS.FOCUSTHENEXPAND_ELEMENTS);\n\n // Add click event listener to the anchor element\n focusexpand?.addEventListener('click', () => {\n expandSection(`${focusexpand.getAttribute('href')}`);\n });\n};\n\n/**\n * Expands a section based on the provided URL hash.\n *\n * This function takes a hash string, finds the corresponding element in the DOM,\n * and expands it if it is currently collapsed. It updates the necessary ARIA\n * attributes and classes to reflect the expanded state.\n *\n * @param {string} hash - The hash (e.g., '#elementId') of the element to expand.\n */\nexport const expandSection = (hash) => {\n const container = document.querySelector(hash);\n const targetContainer = container?.querySelector(SELECTORS.COLLAPSE_ELEMENTS);\n\n if (targetContainer?.getAttribute('aria-expanded') === 'false') {\n const collapseId = targetContainer.getAttribute('aria-controls');\n const collapseContainer = document.getElementById(collapseId);\n\n // Show the content.\n collapseContainer.classList.remove('collapse');\n collapseContainer.classList.add('show');\n\n // Update aria-expanded attribute to reflect the new state.\n targetContainer.setAttribute('aria-expanded', 'true');\n targetContainer.classList.remove('collapsed');\n\n // Get collapse expand menu element.\n const collapseElement = document.querySelector('.collapseexpand.collapsemenu');\n // Ensure it gets noticed to make it work.\n collapseElement.setAttribute('aria-expanded', 'true');\n collapseElement.classList.remove('collapsed');\n }\n};\n"],"names":["SELECTORS","focusexpand","document","querySelector","addEventListener","expandSection","getAttribute","hash","container","targetContainer","collapseId","collapseContainer","getElementById","classList","remove","add","setAttribute","collapseElement"],"mappings":";;;;;;;;;MAwBMA,4BACiB,2BADjBA,mCAEwB,8BAMV,WAEVC,YAAcC,SAASC,cAAcH,oCAG3CC,MAAAA,aAAAA,YAAaG,iBAAiB,SAAS,KACnCC,wBAAiBJ,YAAYK,aAAa,oBAarCD,cAAiBE,aACpBC,UAAYN,SAASC,cAAcI,MACnCE,gBAAkBD,MAAAA,iBAAAA,UAAWL,cAAcH,gCAEM,WAAnDS,MAAAA,uBAAAA,gBAAiBH,aAAa,kBAA8B,OACtDI,WAAaD,gBAAgBH,aAAa,iBAC1CK,kBAAoBT,SAASU,eAAeF,YAGlDC,kBAAkBE,UAAUC,OAAO,YACnCH,kBAAkBE,UAAUE,IAAI,QAGhCN,gBAAgBO,aAAa,gBAAiB,QAC9CP,gBAAgBI,UAAUC,OAAO,mBAG3BG,gBAAkBf,SAASC,cAAc,gCAE/Cc,gBAAgBD,aAAa,gBAAiB,QAC9CC,gBAAgBJ,UAAUC,OAAO"}
-3
View File
@@ -1,3 +0,0 @@
define("core_admin/plugin_management_table",["exports","core_table/dynamic","core_table/local/dynamic/selectors","core/ajax","core/pending","core/notification"],(function(_exports,_dynamic,Selectors,_ajax,_pending,_notification){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,Selectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Selectors),_pending=(obj=_pending)&&obj.__esModule?obj:{default:obj};let watching=!1;return _exports.default=class{constructor(){!function(obj,key,value){key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}(this,"clickHandlers",[]),this.addClickHandler(this.handleStateToggle),this.addClickHandler(this.handleMoveUpDown),this.registerEventListeners()}static init(){watching||(watching=!0,new this)}addClickHandler(handler){this.clickHandlers.push(handler.bind(this))}registerEventListeners(){document.addEventListener("click",function(e){const tableRoot=this.getTableRoot(e);tableRoot&&this.clickHandlers.forEach((handler=>handler(tableRoot,e)))}.bind(this))}getTableRoot(e){const tableRoot=e.target.closest(Selectors.main.region);return tableRoot||!1}setPluginState(methodname,plugin,state){return(0,_ajax.call)([{methodname:methodname,args:{plugin:plugin,state:state}}])[0]}setPluginOrder(methodname,plugin,direction){return(0,_ajax.call)([{methodname:methodname,args:{plugin:plugin,direction:direction}}])[0]}async handleStateToggle(tableRoot,e){const stateToggle=e.target.closest('[data-action="togglestate"][data-toggle-method]');if(stateToggle){e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:togglestate");await this.setPluginState(stateToggle.dataset.toggleMethod,stateToggle.dataset.plugin,"1"===stateToggle.dataset.state?0:1);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]);updatedRoot.querySelector('[data-action="togglestate"][data-plugin="'.concat(stateToggle.dataset.plugin,'"]')).focus(),this.removeTooltips(),pendingPromise.resolve()}}async handleMoveUpDown(tableRoot,e){const actionLink=e.target.closest('[data-action="move"][data-method][data-direction]');if(!actionLink)return;e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:processAction");await this.setPluginOrder(actionLink.dataset.method,actionLink.dataset.plugin,"up"===actionLink.dataset.direction?-1:1);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]),exactMatch=updatedRoot.querySelector('[data-action="move"][data-plugin="'.concat(actionLink.dataset.plugin,'"][data-direction="').concat(actionLink.dataset.direction,'"]'));var _updatedRoot$querySel;exactMatch?exactMatch.focus():null===(_updatedRoot$querySel=updatedRoot.querySelector('[data-action="move"][data-plugin="'.concat(actionLink.dataset.plugin,'"]')))||void 0===_updatedRoot$querySel||_updatedRoot$querySel.focus();pendingPromise.resolve()}removeTooltips(){const tooltips=document.querySelectorAll('[id*="tooltip"]');tooltips.length>0&&tooltips.forEach((tooltip=>{tooltip.remove()}))}},_exports.default}));
//# sourceMappingURL=plugin_management_table.min.js.map
File diff suppressed because one or more lines are too long
-11
View File
@@ -1,11 +0,0 @@
define("core_admin/plugins_overview",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){const filters=document.querySelectorAll(SELECTORS_PLUGIN_FILTERS),pluginRows=document.querySelectorAll(SELECTORS_PLUGIN_ROWS),pluginTypeRows=document.querySelectorAll(SELECTORS_PLUGIN_TYPE_ROWS),filterPlugins=target=>{const filterBy=target.getAttribute("data-filterby"),headerVisibility={};for(const row of pluginRows){const type=[...row.classList].find((s=>s.startsWith("type-"))),visible="all"===filterBy||row.classList.contains(filterBy);row.style.display=visible?null:"none",visible&&type&&(headerVisibility[type]=!0)}for(const row of pluginTypeRows){const type=[...row.classList].find((s=>s.startsWith("type-")));if(type){const visible="all"===filterBy||headerVisibility[type];row.style.display=visible?null:"none"}}filters.forEach((el=>el.classList.remove("active"))),target.classList.add("active")};if(filters.forEach((target=>target.addEventListener("click",(e=>{e.preventDefault(),window.history.replaceState({},null,e.target.href),filterPlugins(target)})))),window.location.hash.length>1){const anchor=window.location.hash.substring(1),target=[...filters].find((t=>t.getAttribute("data-filterby")===anchor));target&&filterPlugins(target)}};
/**
* Allows to filter the plugin list on plugins overview page
*
* @module core_admin/plugins_overview
* @copyright 2024 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
const SELECTORS_PLUGIN_FILTERS="#plugins-overview-panel [data-filterby]",SELECTORS_PLUGIN_ROWS="table#plugins-control-panel tbody tr:not(.plugintypeheader)",SELECTORS_PLUGIN_TYPE_ROWS="table#plugins-control-panel tbody tr.plugintypeheader"}));
//# sourceMappingURL=plugins_overview.min.js.map
@@ -1 +0,0 @@
{"version":3,"file":"plugins_overview.min.js","sources":["../src/plugins_overview.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Allows to filter the plugin list on plugins overview page\n *\n * @module core_admin/plugins_overview\n * @copyright 2024 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst SELECTORS = {\n PLUGIN_FILTERS: '#plugins-overview-panel [data-filterby]',\n PLUGIN_ROWS: 'table#plugins-control-panel tbody tr:not(.plugintypeheader)',\n PLUGIN_TYPE_ROWS: 'table#plugins-control-panel tbody tr.plugintypeheader',\n};\n\n/**\n * Initialise filters for the \"Plugins overview\" page\n */\nexport function init() {\n const filters = document.querySelectorAll(SELECTORS.PLUGIN_FILTERS);\n const pluginRows = document.querySelectorAll(SELECTORS.PLUGIN_ROWS);\n const pluginTypeRows = document.querySelectorAll(SELECTORS.PLUGIN_TYPE_ROWS);\n\n const filterPlugins = (target) => {\n const filterBy = target.getAttribute('data-filterby');\n const headerVisibility = {};\n\n // Hide all plugin rows in the plugin table that do not match the filter and show all others.\n for (const row of pluginRows) {\n const type = [...row.classList].find(s => s.startsWith('type-'));\n const visible = filterBy === 'all' ? true : row.classList.contains(filterBy);\n row.style.display = visible ? null : 'none';\n if (visible && type) {\n headerVisibility[type] = true;\n }\n }\n\n // Hide all the plugin type headers that do not have any visible plugins and show all others.\n for (const row of pluginTypeRows) {\n const type = [...row.classList].find(s => s.startsWith('type-'));\n if (type) {\n const visible = filterBy === 'all' || headerVisibility[type];\n row.style.display = visible ? null : 'none';\n }\n }\n\n // Toggle 'active' class for the selected filter.\n filters.forEach(el => el.classList.remove('active'));\n target.classList.add('active');\n };\n\n // Add event listeners for the links changing plugins filters.\n filters\n .forEach(target => target.addEventListener('click', (e) => {\n e.preventDefault();\n window.history.replaceState({}, null, e.target.href);\n filterPlugins(target);\n }));\n\n // Pre-filter plugins based on the current url anchor.\n if (window.location.hash.length > 1) {\n const anchor = window.location.hash.substring(1);\n const target = [...filters].find(t => t.getAttribute('data-filterby') === anchor);\n if (target) {\n filterPlugins(target);\n }\n }\n}\n"],"names":["filters","document","querySelectorAll","SELECTORS","pluginRows","pluginTypeRows","filterPlugins","target","filterBy","getAttribute","headerVisibility","row","type","classList","find","s","startsWith","visible","contains","style","display","forEach","el","remove","add","addEventListener","e","preventDefault","window","history","replaceState","href","location","hash","length","anchor","substring","t"],"mappings":"4JAiCUA,QAAUC,SAASC,iBAAiBC,0BACpCC,WAAaH,SAASC,iBAAiBC,uBACvCE,eAAiBJ,SAASC,iBAAiBC,4BAE3CG,cAAiBC,eACbC,SAAWD,OAAOE,aAAa,iBAC/BC,iBAAmB,OAGpB,MAAMC,OAAOP,WAAY,OACpBQ,KAAO,IAAID,IAAIE,WAAWC,MAAKC,GAAKA,EAAEC,WAAW,WACjDC,QAAuB,QAAbT,UAA4BG,IAAIE,UAAUK,SAASV,UACnEG,IAAIQ,MAAMC,QAAUH,QAAU,KAAO,OACjCA,SAAWL,OACXF,iBAAiBE,OAAQ,OAK5B,MAAMD,OAAON,eAAgB,OACxBO,KAAO,IAAID,IAAIE,WAAWC,MAAKC,GAAKA,EAAEC,WAAW,cACnDJ,KAAM,OACAK,QAAuB,QAAbT,UAAsBE,iBAAiBE,MACvDD,IAAIQ,MAAMC,QAAUH,QAAU,KAAO,QAK7CjB,QAAQqB,SAAQC,IAAMA,GAAGT,UAAUU,OAAO,YAC1ChB,OAAOM,UAAUW,IAAI,cAIzBxB,QACCqB,SAAQd,QAAUA,OAAOkB,iBAAiB,SAAUC,IACjDA,EAAEC,iBACFC,OAAOC,QAAQC,aAAa,GAAI,KAAMJ,EAAEnB,OAAOwB,MAC/CzB,cAAcC,aAIdqB,OAAOI,SAASC,KAAKC,OAAS,EAAG,OAC3BC,OAASP,OAAOI,SAASC,KAAKG,UAAU,GACxC7B,OAAS,IAAIP,SAASc,MAAKuB,GAAKA,EAAE5B,aAAa,mBAAqB0B,SACtE5B,QACAD,cAAcC;;;;;;;;MAvDpBJ,yBACc,0CADdA,sBAEW,8DAFXA,2BAGgB"}
-10
View File
@@ -1,10 +0,0 @@
define("core_admin/themeselector/preview_modal",["exports","core/modal_events","core/modal_cancel","core/modal_save_cancel","core/notification","core/templates","core/str"],(function(_exports,_modal_events,_modal_cancel,_modal_save_cancel,_notification,_templates,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Modal for theme previews.
*
* @module core_admin/themeselector/preview_modal
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modal_events=_interopRequireDefault(_modal_events),_modal_cancel=_interopRequireDefault(_modal_cancel),_modal_save_cancel=_interopRequireDefault(_modal_save_cancel),_notification=_interopRequireDefault(_notification),_templates=_interopRequireDefault(_templates);const SELECTORS_THEMES_CONTAINER="themelist",SELECTORS_PREVIEW='[data-action="preview"]';_exports.init=()=>{registerListenerEvents()};const registerListenerEvents=()=>{document.addEventListener("click",(e=>{const preview=e.target.closest(SELECTORS_PREVIEW);preview&&buildModal(preview).catch(_notification.default.exception)}))},buildModal=async element=>{let description=await(0,_str.getString)("choosereadme","theme_"+element.getAttribute("data-choose"));const themesContainer=document.getElementById(SELECTORS_THEMES_CONTAINER),definedInConfig=parseInt(themesContainer.dataset.definedinconfig),data={name:element.getAttribute("data-name"),image:element.getAttribute("data-image"),description:description.replace(/<[^>]+>/g," "),current:element.getAttribute("data-current"),actionurl:element.getAttribute("data-actionurl"),choose:element.getAttribute("data-choose"),sesskey:element.getAttribute("data-sesskey"),definedinconfig:definedInConfig};let modalTemplate=_modal_save_cancel.default;(data.current||data.definedinconfig)&&(modalTemplate=_modal_cancel.default);const modal=await modalTemplate.create({title:data.name,body:_templates.default.render("core_admin/themeselector/theme_preview_modal",data),large:!0,buttons:{save:(0,_str.getString)("selecttheme","moodle"),cancel:(0,_str.getString)("closebuttontitle","moodle")},show:!0});modal.getRoot().on(_modal_events.default.save,(()=>{modal.getRoot().find("form").submit()}))}}));
//# sourceMappingURL=preview_modal.min.js.map
@@ -1 +0,0 @@
{"version":3,"file":"preview_modal.min.js","sources":["../../src/themeselector/preview_modal.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Modal for theme previews.\n *\n * @module core_admin/themeselector/preview_modal\n * @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalEvents from 'core/modal_events';\nimport ModalCancel from 'core/modal_cancel';\nimport ModalSaveCancel from 'core/modal_save_cancel';\nimport Notification from 'core/notification';\nimport Templates from 'core/templates';\nimport {getString} from 'core/str';\n\nconst SELECTORS = {\n THEMES_CONTAINER: 'themelist',\n PREVIEW: '[data-action=\"preview\"]',\n};\n\n/**\n * Entrypoint of the js.\n *\n * @method init\n */\nexport const init = () => {\n registerListenerEvents();\n};\n\n/**\n * Register theme related event listeners.\n *\n * @method registerListenerEvents\n */\nconst registerListenerEvents = () => {\n document.addEventListener('click', (e) => {\n const preview = e.target.closest(SELECTORS.PREVIEW);\n if (preview) {\n buildModal(preview).catch(Notification.exception);\n }\n });\n};\n\n/**\n * Build the modal with the provided data.\n *\n * @method buildModal\n * @param {object} element\n */\nconst buildModal = async(element) => {\n\n // This string can be long. We will fetch it with JS as opposed to passing it as an attribute.\n let description = await getString('choosereadme', 'theme_' + element.getAttribute('data-choose'));\n\n const themesContainer = document.getElementById(SELECTORS.THEMES_CONTAINER);\n const definedInConfig = parseInt(themesContainer.dataset.definedinconfig);\n // Prepare data for modal.\n const data = {\n name: element.getAttribute('data-name'),\n image: element.getAttribute('data-image'),\n description: description.replace(/<[^>]+>/g, ' '), // Strip out HTML tags.\n current: element.getAttribute('data-current'),\n actionurl: element.getAttribute('data-actionurl'),\n choose: element.getAttribute('data-choose'),\n sesskey: element.getAttribute('data-sesskey'),\n definedinconfig: definedInConfig,\n };\n\n // Determine which modal template we should use.\n let modalTemplate = ModalSaveCancel;\n if (data.current || data.definedinconfig) {\n modalTemplate = ModalCancel;\n }\n\n const modal = await modalTemplate.create({\n title: data.name,\n body: Templates.render('core_admin/themeselector/theme_preview_modal', data),\n large: true,\n buttons: {\n 'save': getString('selecttheme', 'moodle'),\n 'cancel': getString('closebuttontitle', 'moodle'),\n },\n show: true,\n });\n\n modal.getRoot().on(ModalEvents.save, () => {\n modal.getRoot().find('form').submit();\n });\n};\n"],"names":["SELECTORS","registerListenerEvents","document","addEventListener","e","preview","target","closest","buildModal","catch","Notification","exception","async","description","element","getAttribute","themesContainer","getElementById","definedInConfig","parseInt","dataset","definedinconfig","data","name","image","replace","current","actionurl","choose","sesskey","modalTemplate","ModalSaveCancel","ModalCancel","modal","create","title","body","Templates","render","large","buttons","show","getRoot","on","ModalEvents","save","find","submit"],"mappings":";;;;;;;gWA8BMA,2BACgB,YADhBA,kBAEO,wCAQO,KAChBC,gCAQEA,uBAAyB,KAC3BC,SAASC,iBAAiB,SAAUC,UAC1BC,QAAUD,EAAEE,OAAOC,QAAQP,mBAC7BK,SACAG,WAAWH,SAASI,MAAMC,sBAAaC,eAW7CH,WAAaI,MAAAA,cAGXC,kBAAoB,kBAAU,eAAgB,SAAWC,QAAQC,aAAa,sBAE5EC,gBAAkBd,SAASe,eAAejB,4BAC1CkB,gBAAkBC,SAASH,gBAAgBI,QAAQC,iBAEnDC,KAAO,CACTC,KAAMT,QAAQC,aAAa,aAC3BS,MAAOV,QAAQC,aAAa,cAC5BF,YAAaA,YAAYY,QAAQ,WAAY,KAC7CC,QAASZ,QAAQC,aAAa,gBAC9BY,UAAWb,QAAQC,aAAa,kBAChCa,OAAQd,QAAQC,aAAa,eAC7Bc,QAASf,QAAQC,aAAa,gBAC9BM,gBAAiBH,qBAIjBY,cAAgBC,4BAChBT,KAAKI,SAAWJ,KAAKD,mBACrBS,cAAgBE,6BAGdC,YAAcH,cAAcI,OAAO,CACrCC,MAAOb,KAAKC,KACZa,KAAMC,mBAAUC,OAAO,+CAAgDhB,MACvEiB,OAAO,EACPC,QAAS,OACG,kBAAU,cAAe,kBACvB,kBAAU,mBAAoB,WAE5CC,MAAM,IAGVR,MAAMS,UAAUC,GAAGC,sBAAYC,MAAM,KACjCZ,MAAMS,UAAUI,KAAK,QAAQC"}
-72
View File
@@ -1,72 +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/>.
import PluginManagementTable from './plugin_management_table';
import {refreshTableContent} from 'core_table/dynamic';
import {call as fetchMany} from 'core/ajax';
import Pending from 'core/pending';
import {fetchNotifications} from 'core/notification';
export default class extends PluginManagementTable {
constructor() {
super();
this.addClickHandler(this.handleBlockProtectToggle);
}
/**
* Set the block protection state.
*
* @param {string} plugin
* @param {number} state
* @returns {Promise}
*/
setBlockProtectState(plugin, state) {
return fetchMany([{
methodname: 'core_admin_set_block_protection',
args: {
plugin,
state,
},
}])[0];
}
/**
* Handle toggling of block protection.
*
* @param {HTMLElement} tableRoot
* @param {Event} e
*/
async handleBlockProtectToggle(tableRoot, e) {
const stateToggle = e.target.closest('[data-action="toggleprotectstate"]');
if (stateToggle) {
e.preventDefault();
const pendingPromise = new Pending('core_table/dynamic:processAction');
await this.setBlockProtectState(
stateToggle.dataset.plugin,
stateToggle.dataset.targetState === '1' ? 1 : 0
);
const [updatedRoot] = await Promise.all([
refreshTableContent(tableRoot),
fetchNotifications(),
]);
// Refocus on the link that as pressed in the first place.
updatedRoot.querySelector(`[data-action="toggleprotectstate"][data-plugin="${stateToggle.dataset.plugin}"]`).focus();
pendingPromise.resolve();
}
}
}
-97
View File
@@ -1,97 +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/>.
/**
* Add bulk actions to the users list report
*
* @module core_admin/bulk_user_actions
* @copyright 2024 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import * as tableEvents from 'core_table/local/dynamic/events';
import * as FormChangeChecker from 'core_form/changechecker';
import * as CustomEvents from 'core/custom_interaction_events';
import jQuery from 'jquery';
const Selectors = {
bulkActionsForm: 'form#user-bulk-action-form',
userReportWrapper: '[data-region="report-user-list-wrapper"]',
checkbox: 'input[type="checkbox"][data-togglegroup="report-select-all"][data-toggle="slave"]',
masterCheckbox: 'input[type="checkbox"][data-togglegroup="report-select-all"][data-toggle="master"]',
checkedRows: '[data-togglegroup="report-select-all"][data-toggle="slave"]:checked',
};
/**
* Initialise module
*/
export const init = () => {
const userBulkForm = document.querySelector(Selectors.bulkActionsForm);
const userReport = userBulkForm?.closest(Selectors.userReportWrapper)?.querySelector(reportSelectors.regions.report);
if (!userBulkForm || !userReport) {
return;
}
const actionSelect = userBulkForm.querySelector('select');
CustomEvents.define(actionSelect, [CustomEvents.events.accessibleChange]);
jQuery(actionSelect).on(CustomEvents.events.accessibleChange, event => {
if (event.target.value && `${event.target.value}` !== "0") {
const e = new Event('submit', {cancelable: true});
userBulkForm.dispatchEvent(e);
if (!e.defaultPrevented) {
FormChangeChecker.markFormSubmitted(userBulkForm);
userBulkForm.submit();
}
}
});
// Every time the checkboxes in the report are changed, update the list of users in the form values
// and enable/disable the action select.
const updateUserIds = () => {
const selectedUsers = [...userReport.querySelectorAll(Selectors.checkedRows)];
const selectedUserIds = selectedUsers.map(check => parseInt(check.value));
userBulkForm.querySelector('[name="userids"]').value = selectedUserIds.join(',');
// Disable the action selector if nothing selected, and reset the current selection.
actionSelect.disabled = selectedUsers.length === 0;
if (actionSelect.disabled) {
actionSelect.value = "0";
}
const selectedUsersNames = selectedUsers.map(check => document.querySelector(`label[for="${check.id}"]`).textContent);
// Add the user ids and names to the form data attributes so they can be available from the
// other JS modules that listen to the form submit event.
userBulkForm.data = {userids: selectedUserIds, usernames: selectedUsersNames};
};
updateUserIds();
document.addEventListener('change', event => {
// When checkboxes are checked next to individual users or the master toggle (Select all/none).
if ((event.target.matches(Selectors.checkbox) || event.target.matches(Selectors.masterCheckbox))
&& userReport.contains(event.target)) {
updateUserIds();
}
});
document.addEventListener(tableEvents.tableContentRefreshed, event => {
// When the report contents is updated (i.e. page is changed, filters applied, etc).
if (userReport.contains(event.target)) {
updateUserIds();
}
});
};
-74
View File
@@ -1,74 +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/>.
/**
* Expand the collapse section element.
*
* @module core_admin/expand_hash
* @copyright Meirza <meirza.arson@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.5
*/
const SELECTORS = {
COLLAPSE_ELEMENTS: '[data-toggle="collapse"]',
FOCUSTHENEXPAND_ELEMENTS: '.focus-expand',
};
/**
* Initializes the focus and expand functionality.
*/
export const init = () => {
// Select all collapsible elements only.
const focusexpand = document.querySelector(SELECTORS.FOCUSTHENEXPAND_ELEMENTS);
// Add click event listener to the anchor element
focusexpand?.addEventListener('click', () => {
expandSection(`${focusexpand.getAttribute('href')}`);
});
};
/**
* Expands a section based on the provided URL hash.
*
* This function takes a hash string, finds the corresponding element in the DOM,
* and expands it if it is currently collapsed. It updates the necessary ARIA
* attributes and classes to reflect the expanded state.
*
* @param {string} hash - The hash (e.g., '#elementId') of the element to expand.
*/
export const expandSection = (hash) => {
const container = document.querySelector(hash);
const targetContainer = container?.querySelector(SELECTORS.COLLAPSE_ELEMENTS);
if (targetContainer?.getAttribute('aria-expanded') === 'false') {
const collapseId = targetContainer.getAttribute('aria-controls');
const collapseContainer = document.getElementById(collapseId);
// Show the content.
collapseContainer.classList.remove('collapse');
collapseContainer.classList.add('show');
// Update aria-expanded attribute to reflect the new state.
targetContainer.setAttribute('aria-expanded', 'true');
targetContainer.classList.remove('collapsed');
// Get collapse expand menu element.
const collapseElement = document.querySelector('.collapseexpand.collapsemenu');
// Ensure it gets noticed to make it work.
collapseElement.setAttribute('aria-expanded', 'true');
collapseElement.classList.remove('collapsed');
}
};
-195
View File
@@ -1,195 +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/>.
import {refreshTableContent} from 'core_table/dynamic';
import * as Selectors from 'core_table/local/dynamic/selectors';
import {call as fetchMany} from 'core/ajax';
import Pending from 'core/pending';
import {fetchNotifications} from 'core/notification';
let watching = false;
export default class {
/**
* @property {function[]} clickHandlers a list of handlers to call on click.
*/
clickHandlers = [];
constructor() {
this.addClickHandler(this.handleStateToggle);
this.addClickHandler(this.handleMoveUpDown);
this.registerEventListeners();
}
/**
* Initialise an instance of the class.
*
* This is just a way of making it easier to initialise an instance of the class from PHP.
*/
static init() {
if (watching) {
return;
}
watching = true;
new this();
}
/**
* Add a click handler to the list of handlers.
*
* @param {Function} handler A handler to call on a click event
*/
addClickHandler(handler) {
this.clickHandlers.push(handler.bind(this));
}
/**
* Register the event listeners for this instance.
*/
registerEventListeners() {
document.addEventListener('click', function(e) {
const tableRoot = this.getTableRoot(e);
if (!tableRoot) {
return;
}
this.clickHandlers.forEach((handler) => handler(tableRoot, e));
}.bind(this));
}
/**
* Get the table root from an event.
*
* @param {Event} e
* @returns {HTMLElement|bool}
*/
getTableRoot(e) {
const tableRoot = e.target.closest(Selectors.main.region);
if (!tableRoot) {
return false;
}
return tableRoot;
}
/**
* Set the plugin state (enabled or disabled)
*
* @param {string} methodname The web service to call
* @param {string} plugin The name of the plugin to set the state for
* @param {number} state The state to set
* @returns {Promise}
*/
setPluginState(methodname, plugin, state) {
return fetchMany([{
methodname,
args: {
plugin,
state,
},
}])[0];
}
setPluginOrder(methodname, plugin, direction) {
return fetchMany([{
methodname,
args: {
plugin,
direction,
},
}])[0];
}
/**
* Handle state toggling.
*
* @param {HTMLElement} tableRoot
* @param {Event} e
*/
async handleStateToggle(tableRoot, e) {
const stateToggle = e.target.closest('[data-action="togglestate"][data-toggle-method]');
if (stateToggle) {
e.preventDefault();
const pendingPromise = new Pending('core_table/dynamic:togglestate');
await this.setPluginState(
stateToggle.dataset.toggleMethod,
stateToggle.dataset.plugin,
stateToggle.dataset.state === '1' ? 0 : 1
);
const [updatedRoot] = await Promise.all([
refreshTableContent(tableRoot),
fetchNotifications(),
]);
// Refocus on the link that as pressed in the first place.
updatedRoot.querySelector(`[data-action="togglestate"][data-plugin="${stateToggle.dataset.plugin}"]`).focus();
// When clicking the toggle and it remains focused, a new tooltip will be generated.
// Therefore, the old tooltip should be removed.
this.removeTooltips();
pendingPromise.resolve();
}
}
async handleMoveUpDown(tableRoot, e) {
const actionLink = e.target.closest('[data-action="move"][data-method][data-direction]');
if (!actionLink) {
return;
}
e.preventDefault();
const pendingPromise = new Pending('core_table/dynamic:processAction');
await this.setPluginOrder(
actionLink.dataset.method,
actionLink.dataset.plugin,
actionLink.dataset.direction === 'up' ? -1 : 1,
);
const [updatedRoot] = await Promise.all([
refreshTableContent(tableRoot),
fetchNotifications(),
]);
// Refocus on the link that as pressed in the first place.
const exactMatch = updatedRoot.querySelector(
`[data-action="move"][data-plugin="${actionLink.dataset.plugin}"][data-direction="${actionLink.dataset.direction}"]`
);
if (exactMatch) {
exactMatch.focus();
} else {
// The move link is not present anymore, so we need to focus on the other one.
updatedRoot.querySelector(`[data-action="move"][data-plugin="${actionLink.dataset.plugin}"]`)?.focus();
}
pendingPromise.resolve();
}
/**
* Remove tooltips.
*/
removeTooltips() {
const tooltips = document.querySelectorAll('[id*="tooltip"]');
if (tooltips.length > 0) {
tooltips.forEach(tooltip => {
tooltip.remove();
});
}
}
}
-82
View File
@@ -1,82 +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/>.
/**
* Allows to filter the plugin list on plugins overview page
*
* @module core_admin/plugins_overview
* @copyright 2024 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
const SELECTORS = {
PLUGIN_FILTERS: '#plugins-overview-panel [data-filterby]',
PLUGIN_ROWS: 'table#plugins-control-panel tbody tr:not(.plugintypeheader)',
PLUGIN_TYPE_ROWS: 'table#plugins-control-panel tbody tr.plugintypeheader',
};
/**
* Initialise filters for the "Plugins overview" page
*/
export function init() {
const filters = document.querySelectorAll(SELECTORS.PLUGIN_FILTERS);
const pluginRows = document.querySelectorAll(SELECTORS.PLUGIN_ROWS);
const pluginTypeRows = document.querySelectorAll(SELECTORS.PLUGIN_TYPE_ROWS);
const filterPlugins = (target) => {
const filterBy = target.getAttribute('data-filterby');
const headerVisibility = {};
// Hide all plugin rows in the plugin table that do not match the filter and show all others.
for (const row of pluginRows) {
const type = [...row.classList].find(s => s.startsWith('type-'));
const visible = filterBy === 'all' ? true : row.classList.contains(filterBy);
row.style.display = visible ? null : 'none';
if (visible && type) {
headerVisibility[type] = true;
}
}
// Hide all the plugin type headers that do not have any visible plugins and show all others.
for (const row of pluginTypeRows) {
const type = [...row.classList].find(s => s.startsWith('type-'));
if (type) {
const visible = filterBy === 'all' || headerVisibility[type];
row.style.display = visible ? null : 'none';
}
}
// Toggle 'active' class for the selected filter.
filters.forEach(el => el.classList.remove('active'));
target.classList.add('active');
};
// Add event listeners for the links changing plugins filters.
filters
.forEach(target => target.addEventListener('click', (e) => {
e.preventDefault();
window.history.replaceState({}, null, e.target.href);
filterPlugins(target);
}));
// Pre-filter plugins based on the current url anchor.
if (window.location.hash.length > 1) {
const anchor = window.location.hash.substring(1);
const target = [...filters].find(t => t.getAttribute('data-filterby') === anchor);
if (target) {
filterPlugins(target);
}
}
}
@@ -1,104 +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/>.
/**
* Modal for theme previews.
*
* @module core_admin/themeselector/preview_modal
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import ModalEvents from 'core/modal_events';
import ModalCancel from 'core/modal_cancel';
import ModalSaveCancel from 'core/modal_save_cancel';
import Notification from 'core/notification';
import Templates from 'core/templates';
import {getString} from 'core/str';
const SELECTORS = {
THEMES_CONTAINER: 'themelist',
PREVIEW: '[data-action="preview"]',
};
/**
* Entrypoint of the js.
*
* @method init
*/
export const init = () => {
registerListenerEvents();
};
/**
* Register theme related event listeners.
*
* @method registerListenerEvents
*/
const registerListenerEvents = () => {
document.addEventListener('click', (e) => {
const preview = e.target.closest(SELECTORS.PREVIEW);
if (preview) {
buildModal(preview).catch(Notification.exception);
}
});
};
/**
* Build the modal with the provided data.
*
* @method buildModal
* @param {object} element
*/
const buildModal = async(element) => {
// This string can be long. We will fetch it with JS as opposed to passing it as an attribute.
let description = await getString('choosereadme', 'theme_' + element.getAttribute('data-choose'));
const themesContainer = document.getElementById(SELECTORS.THEMES_CONTAINER);
const definedInConfig = parseInt(themesContainer.dataset.definedinconfig);
// Prepare data for modal.
const data = {
name: element.getAttribute('data-name'),
image: element.getAttribute('data-image'),
description: description.replace(/<[^>]+>/g, ' '), // Strip out HTML tags.
current: element.getAttribute('data-current'),
actionurl: element.getAttribute('data-actionurl'),
choose: element.getAttribute('data-choose'),
sesskey: element.getAttribute('data-sesskey'),
definedinconfig: definedInConfig,
};
// Determine which modal template we should use.
let modalTemplate = ModalSaveCancel;
if (data.current || data.definedinconfig) {
modalTemplate = ModalCancel;
}
const modal = await modalTemplate.create({
title: data.name,
body: Templates.render('core_admin/themeselector/theme_preview_modal', data),
large: true,
buttons: {
'save': getString('selecttheme', 'moodle'),
'cancel': getString('closebuttontitle', 'moodle'),
},
show: true,
});
modal.getRoot().on(ModalEvents.save, () => {
modal.getRoot().find('form').submit();
});
};
+7 -15
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;
@@ -102,12 +99,7 @@ switch ($action) {
break;
}
if ($needsupdate) {
$new = implode(',', $activeantiviruses);
add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core');
set_config('antiviruses', $new);
core_plugin_manager::reset_caches();
}
set_config('antiviruses', implode(',', $activeantiviruses));
core_plugin_manager::reset_caches();
redirect ($returnurl);
redirect ($returnurl);
+27 -15
View File
@@ -28,7 +28,7 @@ if (empty($CFG->auth)) {
}
if (!empty($auth) and !exists_auth_plugin($auth)) {
throw new \moodle_exception('pluginnotinstalled', 'auth', $returnurl, $auth);
print_error('pluginnotinstalled', 'auth', $returnurl, $auth);
}
////////////////////////////////////////////////////////////////////////////////
@@ -40,31 +40,43 @@ 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':
$key = array_search($auth, $authsenabled);
// check auth plugin is valid
if ($key === false) {
throw new \moodle_exception('pluginnotenabled', 'auth', $returnurl, $auth);
print_error('pluginnotenabled', 'auth', $returnurl, $auth);
}
// move down the list
if ($key < (count($authsenabled) - 1)) {
$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;
@@ -72,16 +84,14 @@ switch ($action) {
$key = array_search($auth, $authsenabled);
// check auth is valid
if ($key === false) {
throw new \moodle_exception('pluginnotenabled', 'auth', $returnurl, $auth);
print_error('pluginnotenabled', 'auth', $returnurl, $auth);
}
// move up the list
if ($key >= 1) {
$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);
+212
View File
@@ -0,0 +1,212 @@
<?php
/**
* Edit configuration for an individual auth plugin
*/
require_once '../config.php';
require_once $CFG->libdir.'/adminlib.php';
$auth = required_param('auth', PARAM_PLUGIN);
$PAGE->set_pagetype('admin-auth-' . $auth);
admin_externalpage_setup('authsetting'.$auth);
$authplugin = get_auth_plugin($auth);
$err = array();
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageauths";
debugging("Use of config.html files in authentication plugins have been deprecated. " .
" Please migrate your plugin to use the admin settings API", DEBUG_DEVELOPER);
// save configuration changes
if ($frm = data_submitted() and confirm_sesskey()) {
$authplugin->validate_form($frm, $err);
if (count($err) == 0) {
// save plugin config
if ($authplugin->process_config($frm)) {
// save field lock configuration
foreach ($frm as $name => $value) {
if (preg_match('/^lockconfig_(.+?)$/', $name, $matches)) {
$plugin = "auth/$auth";
$name = $matches[1];
set_config($name, $value, $plugin);
}
}
redirect($returnurl);
exit;
}
} else {
foreach ($err as $key => $value) {
$focus = "form.$key";
}
}
} else {
$frmlegacystyle = get_config('auth/'.$auth);
$frmnewstyle = get_config('auth_'.$auth);
$frm = (object)array_merge((array)$frmlegacystyle, (array)$frmnewstyle);
}
$user_fields = $authplugin->userfields;
//$user_fields = array("firstname", "lastname", "email", "phone1", "phone2", "institution", "department", "address", "city", "country", "description", "idnumber", "lang");
/// Get the auth title (from core or own auth lang files)
$authtitle = $authplugin->get_title();
/// Get the auth descriptions (from core or own auth lang files)
$authdescription = $authplugin->get_description();
// output configuration form
echo $OUTPUT->header();
// choose an authentication method
echo "<form id=\"authmenu\" method=\"post\" action=\"auth_config.php\">\n";
echo "<div>\n";
echo "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n";
echo "<input type=\"hidden\" name=\"auth\" value=\"".$auth."\" />\n";
// auth plugin description
echo $OUTPUT->box_start();
echo $OUTPUT->heading($authtitle);
echo $OUTPUT->box_start('informationbox');
echo $authdescription;
echo $OUTPUT->box_end();
echo "<hr />\n";
$authplugin->config_form($frm, $err, $user_fields);
echo $OUTPUT->box_end();
echo '<p style="text-align: center"><input type="submit" value="' . get_string("savechanges") . "\" /></p>\n";
echo "</div>\n";
echo "</form>\n";
$PAGE->requires->string_for_js('unmaskpassword', 'core_form');
$PAGE->requires->yui_module('moodle-auth-passwordunmask', 'M.auth.passwordunmask');
echo $OUTPUT->footer();
exit;
/// Functions /////////////////////////////////////////////////////////////////
/**
* auth field locking
* Good enough for most auth plugins
* but some may want a custom one if they are offering
* other options
* Note: lockconfig_ fields have special handling.
*
* @param string $auth authentication plugin shortname
* @param array $user_fields user profile fields
* @param string $helptext help text to be displayed at top of form
* @param boolean $retrieveopts Map fields or lock only.
* @param boolean $updateopts Allow remote updates
* @param array $customfields list of custom profile fields
* @deprecated since Moodle 3.3
*/
function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts, $updateopts, $customfields = array()) {
global $DB, $OUTPUT;
debugging("The function 'print_auth_lock_options' has been deprecated, " .
"Please migrate your code to use the admin settings API and use the function 'display_auth_lock_options' instead. ",
DEBUG_DEVELOPER);
echo '<tr><td colspan="3">';
if ($retrieveopts) {
echo $OUTPUT->heading(get_string('auth_data_mapping', 'auth'));
} else {
echo $OUTPUT->heading(get_string('auth_fieldlocks', 'auth'));
}
echo '</td></tr>';
$lockoptions = array ('unlocked' => get_string('unlocked', 'auth'),
'unlockedifempty' => get_string('unlockedifempty', 'auth'),
'locked' => get_string('locked', 'auth'));
$updatelocaloptions = array('oncreate' => get_string('update_oncreate', 'auth'),
'onlogin' => get_string('update_onlogin', 'auth'));
$updateextoptions = array('0' => get_string('update_never', 'auth'),
'1' => get_string('update_onupdate', 'auth'));
$pluginconfig = get_config("auth/$auth");
// Helptext is on a field with rowspan.
if (empty($helptext)) {
$helptext = '&nbsp;';
}
// If we have custom fields then merge them with user fields.
if (!empty($customfields)) {
$user_fields = array_merge($user_fields, $customfields);
}
if (!empty($customfields)) {
$customfieldname = $DB->get_records('user_info_field', null, '', 'shortname, name');
}
foreach ($user_fields as $field) {
// Define some vars we'll work with.
if (!isset($pluginconfig->{"field_map_$field"})) {
$pluginconfig->{"field_map_$field"} = '';
}
if (!isset($pluginconfig->{"field_updatelocal_$field"})) {
$pluginconfig->{"field_updatelocal_$field"} = '';
}
if (!isset($pluginconfig->{"field_updateremote_$field"})) {
$pluginconfig->{"field_updateremote_$field"} = '';
}
if (!isset($pluginconfig->{"field_lock_$field"})) {
$pluginconfig->{"field_lock_$field"} = '';
}
// Define the fieldname we display to the user.
$fieldname = $field;
if ($fieldname === 'lang') {
$fieldname = get_string('language');
} elseif (!empty($customfields) && in_array($field, $customfields)) {
// If custom field then pick name from database.
$fieldshortname = str_replace('profile_field_', '', $fieldname);
$fieldname = $customfieldname[$fieldshortname]->name;
if (core_text::strlen($fieldshortname) > 67) {
// If custom profile field name is longer than 67 characters we will not be able to store the setting
// such as 'field_updateremote_profile_field_NOTSOSHORTSHORTNAME' in the database because the character
// limit for the setting name is 100.
continue;
}
} elseif ($fieldname == 'url') {
$fieldname = get_string('webpage');
} else {
$fieldname = get_string($fieldname);
}
if ($retrieveopts) {
$varname = 'field_map_' . $field;
echo '<tr valign="top"><td align="right">';
echo '<label for="lockconfig_'.$varname.'">'.$fieldname.'</label>';
echo '</td><td>';
echo "<input id=\"lockconfig_{$varname}\" name=\"lockconfig_{$varname}\" type=\"text\" size=\"30\" value=\"{$pluginconfig->$varname}\" />";
echo '<div style="text-align: right">';
echo '<label for="menulockconfig_field_updatelocal_'.$field.'">'.get_string('auth_updatelocal', 'auth') . '</label>&nbsp;';
echo html_writer::select($updatelocaloptions, "lockconfig_field_updatelocal_{$field}", $pluginconfig->{"field_updatelocal_$field"}, false);
echo '<br />';
if ($updateopts) {
echo '<label for="menulockconfig_field_updateremote_'.$field.'">'.get_string('auth_updateremote', 'auth') . '</label>&nbsp;';
echo html_writer::select($updateextoptions, "lockconfig_field_updateremote_{$field}", $pluginconfig->{"field_updateremote_$field"}, false);
echo '<br />';
}
echo '<label for="menulockconfig_field_lock_'.$field.'">'.get_string('auth_fieldlock', 'auth') . '</label>&nbsp;';
echo html_writer::select($lockoptions, "lockconfig_field_lock_{$field}", $pluginconfig->{"field_lock_$field"}, false);
echo '</div>';
} else {
echo '<tr valign="top"><td align="right">';
echo '<label for="menulockconfig_field_lock_'.$field.'">'.$fieldname.'</label>';
echo '</td><td>';
echo html_writer::select($lockoptions, "lockconfig_field_lock_{$field}", $pluginconfig->{"field_lock_$field"}, false);
}
echo '</td>';
if (!empty($helptext)) {
echo '<td rowspan="' . count($user_fields) . '">' . $helptext . '</td>';
$helptext = '';
}
echo '</tr>';
}
}
+223 -79
View File
@@ -1,94 +1,238 @@
<?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/>.
/**
* Allows the admin to configure blocks (hide/show, uninstall and configure)
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// Allows the admin to configure blocks (hide/show, uninstall and configure)
require_once('../config.php');
require_once("{$CFG->libdir}/adminlib.php");
require_once("{$CFG->libdir}/blocklib.php");
require_once("{$CFG->libdir}/tablelib.php");
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/blocklib.php');
require_once($CFG->libdir.'/tablelib.php');
admin_externalpage_setup('manageblocks');
admin_externalpage_setup('manageblocks');
$plugin = optional_param('plugin', '', PARAM_PLUGIN);
$action = optional_param('action', '', PARAM_ALPHA);
$unprotect = optional_param('unprotect', 0, PARAM_PLUGIN);
$protect = optional_param('protect', 0, PARAM_PLUGIN);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$hide = optional_param('hide', 0, PARAM_INT);
$show = optional_param('show', 0, PARAM_INT);
$unprotect = optional_param('unprotect', 0, PARAM_INT);
$protect = optional_param('protect', 0, PARAM_INT);
$strmanageblocks = get_string('manageblocks');
/// Print headings
// If data submitted, then process and store.
if (!empty($plugin) && !empty($action) && confirm_sesskey()) {
$manager = \core_plugin_manager::resolve_plugininfo_class('block');
$pluginname = get_string('pluginname', "block_{$plugin}");
$strmanageblocks = get_string('manageblocks');
$struninstall = get_string('uninstallplugin', 'core_admin');
$strversion = get_string('version');
$strhide = get_string('hide');
$strshow = get_string('show');
$strsettings = get_string('settings');
$strcourses = get_string('blockinstances', 'admin');
$strname = get_string('name');
$strshowblockcourse = get_string('showblockcourse');
$strprotecthdr = get_string('blockprotect', 'admin'). $OUTPUT->help_icon('blockprotect','admin');
$strprotect = get_string('blockprotect', 'admin');
$strunprotect = get_string('blockunprotect', 'admin');
if ($action === 'disable' && $manager::enable_plugin($plugin, 0)) {
\core\notification::add(
get_string('plugin_disabled', 'core_admin', $pluginname),
\core\notification::SUCCESS
);
// Settings not required - only pages.
admin_get_root(true, false);
} else if ($action === 'enable' && $manager::enable_plugin($plugin, 1)) {
\core\notification::add(
get_string('plugin_enabled', 'core_admin', $pluginname),
\core\notification::SUCCESS
);
/// If data submitted, then process and store.
// Settings not required - only pages.
admin_get_root(true, false);
if (!empty($hide) && confirm_sesskey()) {
if (!$block = $DB->get_record('block', array('id'=>$hide))) {
print_error('blockdoesnotexist', 'error');
}
$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
}
// Redirect back to the page with out any params.
redirect(new moodle_url('/admin/blocks.php'));
}
if (!empty($show) && confirm_sesskey() ) {
if (!$block = $DB->get_record('block', array('id'=>$show))) {
print_error('blockdoesnotexist', 'error');
}
$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()) {
block_manager::protect_block($protect);
$pluginname = get_string('pluginname', "block_{$protect}");
\core\notification::add(
get_string('blockprotected', 'core_admin', $pluginname),
\core\notification::SUCCESS
);
// Settings not required - only pages.
admin_get_root(true, false);
}
if (!empty($protect) && confirm_sesskey()) {
block_manager::protect_block((int)$protect);
admin_get_root(true, false); // settings not required - only pages
}
if (!empty($unprotect) && confirm_sesskey()) {
block_manager::unprotect_block($unprotect);
$pluginname = get_string('pluginname', "block_{$unprotect}");
\core\notification::add(
get_string('blockunprotected', 'core_admin', $pluginname),
\core\notification::SUCCESS
);
// Settings not required - only pages.
admin_get_root(true, false);
}
if (!empty($unprotect) && confirm_sesskey()) {
block_manager::unprotect_block((int)$unprotect);
admin_get_root(true, false); // settings not required - only pages
}
$undeletableblocktypes = block_manager::get_undeletable_block_types();
echo $OUTPUT->header();
echo $OUTPUT->heading($strmanageblocks);
/// Main display starts here
/// Get and sort the existing blocks
if (!$blocks = $DB->get_records('block', array(), 'name ASC')) {
print_error('noblocks', 'error'); // Should never happen
}
$incompatible = array();
/// Print the table of all blocks
$table = new flexible_table('admin-blocks-compatible');
$table->define_columns(array('name', 'instances', 'version', 'hideshow', 'undeletable', 'settings', 'uninstall'));
$table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strprotecthdr, $strsettings, $struninstall));
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
$table->set_attribute('class', 'admintable blockstable generaltable');
$table->set_attribute('id', 'compatibleblockstable');
$table->setup();
$tablerows = array();
// Sort blocks using current locale.
$blocknames = array();
foreach ($blocks as $blockid=>$block) {
$blockname = $block->name;
if (file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
$blocknames[$blockid] = get_string('pluginname', 'block_'.$blockname);
} else {
$blocknames[$blockid] = $blockname;
}
}
core_collator::asort($blocknames);
foreach ($blocknames as $blockid=>$strblockname) {
$block = $blocks[$blockid];
$blockname = $block->name;
$dbversion = get_config('block_'.$block->name, 'version');
if (!file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
$blockobject = false;
$strblockname = '<span class="notifyproblem">'.$strblockname.' ('.get_string('missingfromdisk').')</span>';
$plugin = new stdClass();
$plugin->version = $dbversion;
} else {
$plugin = new stdClass();
$plugin->version = '???';
if (file_exists("$CFG->dirroot/blocks/$blockname/version.php")) {
include("$CFG->dirroot/blocks/$blockname/version.php");
}
if (!$blockobject = block_instance($block->name)) {
$incompatible[] = $block;
continue;
}
}
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$blockname, 'manage')) {
$uninstall = html_writer::link($uninstallurl, $struninstall);
} else {
$uninstall = '';
}
$settings = ''; // By default, no configuration
if ($blockobject and $blockobject->has_config()) {
$blocksettings = admin_get_root()->locate('blocksetting' . $block->name);
if ($blocksettings instanceof admin_externalpage) {
$settings = '<a href="' . $blocksettings->url . '">' . get_string('settings') . '</a>';
} else if ($blocksettings instanceof admin_settingpage) {
$settings = '<a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=blocksetting'.$block->name.'">'.$strsettings.'</a>';
} else if (!file_exists($CFG->dirroot.'/blocks/'.$block->name.'/settings.php')) {
// If the block's settings node was not found, we check that the block really provides the settings.php file.
// Note that blocks can inject their settings to other nodes in the admin tree without using the default locations.
// This can be done by assigning null to $setting in settings.php and it is a valid case.
debugging('Warning: block_'.$block->name.' returns true in has_config() but does not provide a settings.php file',
DEBUG_DEVELOPER);
}
}
// MDL-11167, blocks can be placed on mymoodle, or the blogs page
// and it should not show up on course search page
$totalcount = $DB->count_records('block_instances', array('blockname'=>$blockname));
$count = $DB->count_records('block_instances', array('blockname'=>$blockname, 'pagetypepattern'=>'course-view-*'));
if ($count>0) {
$blocklist = "<a href=\"{$CFG->wwwroot}/course/search.php?blocklist=$blockid&amp;sesskey=".sesskey()."\" ";
$blocklist .= "title=\"$strshowblockcourse\" >$totalcount</a>";
}
else {
$blocklist = "$totalcount";
}
$class = ''; // Nothing fancy, by default
if (!$blockobject) {
// ignore
$visible = '';
} else if ($blocks[$blockid]->visible) {
$visible = '<a href="blocks.php?hide='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strhide.'">'.
$OUTPUT->pix_icon('t/hide', $strhide) . '</a>';
} else {
$visible = '<a href="blocks.php?show='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strshow.'">'.
$OUTPUT->pix_icon('t/show', $strshow) . '</a>';
$class = 'dimmed_text';
}
if ($dbversion == $plugin->version) {
$version = $dbversion;
} else {
$version = "$dbversion ($plugin->version)";
}
if (!$blockobject) {
// ignore
$undeletable = '';
} else if (in_array($blockname, $undeletableblocktypes)) {
$undeletable = '<a href="blocks.php?unprotect='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strunprotect.'">'.
$OUTPUT->pix_icon('t/unlock', $strunprotect) . '</a>';
} else {
$undeletable = '<a href="blocks.php?protect='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strprotect.'">'.
$OUTPUT->pix_icon('t/lock', $strprotect) . '</a>';
}
$row = array(
$strblockname,
$blocklist,
$version,
$visible,
$undeletable,
$settings,
$uninstall,
);
$table->add_data($row, $class);
}
$table->print_html();
if (!empty($incompatible)) {
echo $OUTPUT->heading(get_string('incompatibleblocks', 'blockstable', 'admin'));
$table = new flexible_table('admin-blocks-incompatible');
$table->define_columns(array('block', 'uninstall'));
$table->define_headers(array($strname, $struninstall));
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
$table->set_attribute('class', 'incompatibleblockstable generaltable');
$table->setup();
foreach ($incompatible as $block) {
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$block->name, 'manage')) {
$uninstall = html_writer::link($uninstallurl, $struninstall);
} else {
$uninstall = '';
}
$table->add_data(array(
$block->name,
$uninstall,
));
}
$table->print_html();
}
echo $OUTPUT->footer();
echo $OUTPUT->header();
echo $OUTPUT->heading($strmanageblocks);
echo $OUTPUT->notification(get_string('noteunneededblocks', 'admin'), 'info', false);
// Print the table of all blocks.
$table = new \core_admin\table\block_management_table();
$table->out();
echo $OUTPUT->footer();
+12 -14
View File
@@ -41,19 +41,13 @@ $adminroot = admin_get_root(); // need all settings
$settingspage = $adminroot->locate($category, true);
if (empty($settingspage) or !($settingspage instanceof admin_category)) {
throw new \moodle_exception('categoryerror', 'error', "$CFG->wwwroot/$CFG->admin/");
print_error('categoryerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
}
if (!($settingspage->check_access())) {
throw new \moodle_exception('accessdenied', 'admin');
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');
@@ -131,7 +125,8 @@ if ($savebutton) {
$outputhtml .= html_writer::end_tag('div');
}
$PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $settingspage->visiblepath));
$visiblepathtosection = array_reverse($settingspage->visiblepath);
$PAGE->set_title("$SITE->shortname: " . implode(": ",$visiblepathtosection));
$PAGE->set_heading($SITE->fullname);
if ($buttons) {
$PAGE->set_button($buttons);
@@ -145,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');
@@ -157,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();
@@ -1,127 +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\admin;
use admin_setting;
use core_plugin_manager;
use core_text;
/**
* Admin setting plugin manager.
*
* @package core_admin
* @subpackage admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_setting_plugin_manager extends admin_setting {
/** @var core_plugin_manager The plugin manager instance */
protected core_plugin_manager $pluginmanager;
/** @var string The plugintype that this manager covers */
protected string $plugintype;
/** @var string The class of the management table to use */
protected string $tableclass;
public function __construct(
string $plugintype,
string $tableclass,
string $name,
string $visiblename,
string $description = '',
string $defaultsetting = '',
) {
$this->nosave = true;
$this->pluginmanager = core_plugin_manager::instance();
$this->plugintype = $plugintype;
$this->tableclass = $tableclass;
parent::__construct($name, $visiblename, $description, $defaultsetting);
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_setting(): bool {
return true;
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_defaultsetting(): bool {
return true;
}
/**
* Always returns '', does not write anything
*
* @return string Always returns ''
*/
// phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
public function write_setting($data): string {
// Do not write any setting.
return '';
}
/**
* Checks if $query is one of the available editors
*
* @param string $query The string to search for
* @return bool Returns true if found, false if not
*/
public function is_related($query) {
if (parent::is_related($query)) {
return true;
}
$plugins = $this->pluginmanager->get_installed_plugins($this->plugintype);
foreach (array_keys($plugins) as $plugin) {
$plugin = "{$this->plugintype}_{$plugin}";
if (str_contains($plugin, $query)) {
return true;
}
$pluginname = get_string('pluginname', $plugin);
if (strpos(core_text::strtolower($pluginname), $query) !== false) {
return true;
}
}
return false;
}
/**
* Builds the XHTML to display the control
*
* @param string $data Unused
* @param string $query
* @return string
*/
public function output_html($data, $query = ''): string {
$table = new $this->tableclass();
if (!($table instanceof \core_admin\table\plugin_management_table)) {
throw new \coding_exception("{$this->tableclass} must be an instance of \\core_admin\\table\\plugin_management_table");
}
return highlight($query, $table->get_content());
}
}
-97
View File
@@ -1,97 +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\external;
use block_manager;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
/**
* Web Service to control the state of a plugin.
*
* @package core_admin
* @category external
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class set_block_protection extends external_api {
/**
* Returns description of method parameters
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
'state' => new external_value(PARAM_INT, 'The target state', VALUE_REQUIRED),
]);
}
/**
* Set the block protection state.
*
* @param string $plugin The name of the plugin
* @param int $state The target state
* @return null
*/
public static function execute(
string $plugin,
int $state,
): array {
[
'plugin' => $plugin,
'state' => $state,
] = self::validate_parameters(self::execute_parameters(), [
'plugin' => $plugin,
'state' => $state,
]);
$context = \context_system::instance();
self::validate_context($context);
require_capability('moodle/site:config', $context);
[, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
$displayname = get_string('pluginname', $plugin);
if ($state) {
block_manager::protect_block($pluginname);
\core\notification::add(
get_string('blockprotected', 'core_admin', $displayname),
\core\notification::SUCCESS
);
} else {
block_manager::unprotect_block($pluginname);
\core\notification::add(
get_string('blockunprotected', 'core_admin', $displayname),
\core\notification::SUCCESS
);
}
return [];
}
/**
* Describe the return structure of the external service.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([]);
}
}
-84
View File
@@ -1,84 +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\external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
/**
* Web Service to control the order of a plugin.
*
* @package core_admin
* @category external
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class set_plugin_order extends external_api {
/**
* Returns description of method parameters
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
'direction' => new external_value(PARAM_INT, 'The direction to move', VALUE_REQUIRED),
]);
}
/**
* Set the plugin state.
*
* @param string $plugin The name of the plugin
* @param int $direction The direction to move the plugin
* @return array
*/
public static function execute(
string $plugin,
int $direction,
): array {
[
'plugin' => $plugin,
'direction' => $direction,
] = self::validate_parameters(self::execute_parameters(), [
'plugin' => $plugin,
'direction' => $direction,
]);
$context = \context_system::instance();
self::validate_context($context);
require_capability('moodle/site:config', $context);
[$plugintype, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
$manager::change_plugin_order($pluginname, $direction);
return [];
}
/**
* Describe the return structure of the external service.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([]);
}
}
-98
View File
@@ -1,98 +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\external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
/**
* Web Service to control the state of a plugin.
*
* @package core_admin
* @category external
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class set_plugin_state extends external_api {
/**
* Returns description of method parameters
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
'state' => new external_value(PARAM_INT, 'The target state', VALUE_REQUIRED),
]);
}
/**
* Set the plugin state.
*
* @param string $plugin The name of the plugin
* @param int $state The target state
* @return null
*/
public static function execute(
string $plugin,
int $state,
): array {
[
'plugin' => $plugin,
'state' => $state,
] = self::validate_parameters(self::execute_parameters(), [
'plugin' => $plugin,
'state' => $state,
]);
$context = \context_system::instance();
self::validate_context($context);
require_capability('moodle/site:config', $context);
[$plugintype, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
$displayname = get_string('pluginname', $plugin);
if ($manager::enable_plugin($pluginname, $state)) {
if (!empty($state)) {
\core\notification::add(
get_string('plugin_enabled', 'core_admin', $displayname),
\core\notification::SUCCESS
);
} else {
\core\notification::add(
get_string('plugin_disabled', 'core_admin', $displayname),
\core\notification::SUCCESS
);
}
}
return [];
}
/**
* Describe the return structure of the external service.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([]);
}
}
@@ -43,22 +43,11 @@ class testoutgoingmailconf_form extends \moodleform {
$mform = $this->_form;
// Recipient.
$options = ['maxlength' => '100', 'size' => '25', 'autocomplete' => 'email'];
$options = ['maxlength' => '100', 'size' => '25'];
$mform->addElement('text', 'recipient', get_string('testoutgoingmailconf_toemail', 'admin'), $options);
$mform->setType('recipient', PARAM_EMAIL);
$mform->addRule('recipient', get_string('required'), 'required');
// 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;
}
}
@@ -1,71 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* External admin page class that allows a callback to be provided to determine whether page can be accessed
*
* @package core_admin
* @copyright 2019 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\externalpage;
use admin_externalpage;
defined('MOODLE_INTERNAL') || die();
require_once("{$CFG->libdir}/adminlib.php");
/**
* Admin externalpage class
*
* @package core_admin
* @copyright 2019 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class accesscallback extends admin_externalpage {
/** @var callable $accesscheckcallback */
protected $accesscheckcallback;
/**
* Class constructor
*
* @param string $name
* @param string $visiblename
* @param string $url
* @param callable $accesscheckcallback The callback method that will be executed to check whether user has access to
* this page. The setting instance ($this) is passed as an argument to the callback. Should return boolean value
* @param bool $hidden
*/
public function __construct(string $name, string $visiblename, string $url, callable $accesscheckcallback,
bool $hidden = false) {
$this->accesscheckcallback = $accesscheckcallback;
parent::__construct($name, $visiblename, $url, [], $hidden);
}
/**
* Determines if the current user has access to this external page based on access callback
*
* @return bool
*/
public function check_access() {
return ($this->accesscheckcallback)($this);
}
}
@@ -1,206 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Auto complete admin setting.
*
* @package core_admin
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/adminlib.php');
/**
* Auto complete setting class.
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @copyright 2020 The Open University
*/
class autocomplete extends \admin_setting_configmultiselect {
/** @var boolean Should we allow typing new entries to the field? */
protected $tags = false;
/** @var string Name of an AMD module to send/process ajax requests. */
protected $ajax = '';
/** @var string Placeholder text for an empty list. */
protected $placeholder = '';
/** @var bool Whether the search has to be case-sensitive. */
protected $casesensitive = false;
/** @var bool Show suggestions by default - but this can be turned off. */
protected $showsuggestions = true;
/** @var string String that is shown when there are no selections. */
protected $noselectionstring = '';
/** @var string Delimiter to store values in database. */
protected $delimiter = ',';
/** @var string Should be multiple choices? */
protected $multiple = true;
/** @var string The link to manage choices. */
protected $manageurl = true;
/** @var string The text to display in manage link. */
protected $managetext = true;
/**
* Constructor
*
* @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting'
* for ones in config_plugins.
* @param string $visiblename localised
* @param string $description long localised info
* @param array $defaultsetting array of selected items
* @param array $choices options for autocomplete field
* @param array $attributes settings for autocomplete field
*/
public function __construct($name, $visiblename, $description, $defaultsetting, $choices, $attributes = null) {
if ($attributes === null) {
$attributes = [];
}
$this->placeholder = get_string('search');
$this->noselectionstring = get_string('noselection', 'form');
$defaultattributes = [
'tags',
'showsuggestions',
'placeholder',
'noselectionstring',
'ajax',
'casesensitive',
'delimiter',
'multiple',
'manageurl',
'managetext'
];
foreach ($defaultattributes as $attributename) {
if (isset($attributes[$attributename])) {
$this->$attributename = $attributes[$attributename];
}
}
parent::__construct($name, $visiblename, $description, $defaultsetting, $choices);
}
/**
* Returns the select setting(s)
*
* @return mixed null or array. Null if no settings else array of setting(s)
*/
public function get_setting() {
$result = $this->config_read($this->name);
if (is_null($result)) {
return null;
}
if ($result === '') {
return [];
}
return explode($this->delimiter, $result);
}
/**
* Saves setting(s) provided through $data
*
* @param array $data
*/
public function write_setting($data) {
if (!is_array($data)) {
return ''; // Ignore it.
}
if (!$this->load_choices() || empty($this->choices)) {
return '';
}
unset($data['xxxxx']);
$save = [];
foreach ($data as $value) {
if (!array_key_exists($value, $this->choices)) {
continue; // Ignore it.
}
$save[] = $value;
}
return ($this->config_write($this->name, implode($this->delimiter, $save)) ? '' : get_string('errorsetting', 'admin'));
}
/**
* Returns XHTML autocomplete field
*
* @param array $data Array of values to select by default
* @param string $query
* @return string XHTML autocomplete field
*/
public function output_html($data, $query = '') {
global $OUTPUT;
if (!$this->load_choices() or empty($this->choices)) {
return '';
}
$default = $this->get_defaultsetting();
if (empty($default)) {
$default = [];
}
if (is_null($data)) {
$data = [];
}
$context = [
'id' => $this->get_id(),
'name' => $this->get_full_name()
];
$defaults = [];
$options = [];
$template = 'core_admin/local/settings/autocomplete';
foreach ($this->choices as $value => $name) {
if (in_array($value, $default)) {
$defaults[] = $name;
}
$options[] = [
'value' => $value,
'text' => $name,
'selected' => in_array($value, $data),
'disabled' => false
];
}
$context['options'] = $options;
$context['tags'] = $this->tags;
$context['placeholder'] = $this->placeholder;
$context['casesensitive'] = $this->casesensitive;
$context['multiple'] = $this->multiple;
$context['showsuggestions'] = $this->showsuggestions;
$context['manageurl'] = $this->manageurl;
$context['managetext'] = $this->managetext;
if (is_null($default)) {
$defaultinfo = null;
} if (!empty($defaults)) {
$defaultinfo = implode(', ', $defaults);
} else {
$defaultinfo = get_string('none');
}
$element = $OUTPUT->render_from_template($template, $context);
return format_admin_setting($this, $this->visiblename, $element, $this->description, true, '', $defaultinfo, $query);
}
}
+3 -6
View File
@@ -62,7 +62,7 @@ class filesize extends \admin_setting {
* @param int|null $defaultunit GB, MB, etc. (in bytes)
*/
public function __construct(string $name, string $visiblename, string $description,
?int $defaultvalue = null, ?int $defaultunit = null) {
int $defaultvalue = null, int $defaultunit = null) {
$defaultsetting = self::parse_bytes($defaultvalue);
@@ -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'));
}
@@ -180,7 +178,6 @@ class filesize extends \admin_setting {
'id' => $this->get_id(),
'name' => $this->get_full_name(),
'value' => $data['v'],
'readonly' => $this->is_readonly(),
'options' => array_map(function($unit, $title) use ($data, $defaultunit) {
return [
'value' => $unit,
@@ -1,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,74 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Payment gateway admin setting.
*
* @package core_admin
* @copyright 2020 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
/**
* Generic class for managing plugins in a table that allows re-ordering and enable/disable of each plugin.
*/
class manage_payment_gateway_plugins extends \admin_setting_manage_plugins {
/**
* Get the admin settings section title (use get_string).
*
* @return string
*/
public function get_section_title() {
return get_string('type_paygw_plural', 'plugin');
}
/**
* Get the type of plugin to manage.
*
* @return string
*/
public function get_plugin_type() {
return 'paygw';
}
/**
* Get the name of the second column.
*
* @return string
*/
public function get_info_column_name() {
return get_string('supportedcurrencies', 'core_payment');
}
/**
* Get the type of plugin to manage.
*
* @param plugininfo The plugin info class.
* @return string
*/
public function get_info_column($plugininfo) {
$codes = $plugininfo->get_supported_currencies();
$currencies = [];
foreach ($codes as $c) {
$currencies[$c] = new \lang_string($c, 'core_currencies');
}
return implode(get_string('listsep', 'langconfig') . ' ', $currencies);
}
}
@@ -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));
}
}
-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/>.
namespace core_admin\output;
use moodle_url;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Theme selector renderable.
*
* @package core_admin
* @copyright 2023 David Woloszyn <david.woloszyn@moodle.com>
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class theme_selector implements renderable, templatable {
/** @var array $themedata Theme data to pass to the template. */
private $themedata = null;
/** @var bool Whether $CFG->theme is defined in config.php. */
private $definedinconfig;
/**
* Constructor.
*
* @param array $themedata Theme data used for template.
* @param bool $definedinconfig Whether $CFG->theme is defined in config.php.
*/
public function __construct(array $themedata, bool $definedinconfig = false) {
$this->themedata = $themedata;
$this->definedinconfig = $definedinconfig;
}
/**
* Export this data so it can be used as the context for a mustache template.
*
* @param renderer_base $output Renderer base.
* @return stdClass
*/
public function export_for_template(renderer_base $output): stdClass {
$data = new stdClass();
// Theme data used to populate cards and modal.
$data->themes = $this->themedata;
// Reset theme caches button.
$reseturl = new moodle_url('/admin/themeselector.php', ['sesskey' => sesskey(), 'reset' => 1]);
$resetbutton = new \single_button($reseturl, get_string('themeresetcaches', 'admin'), 'post',
\single_button::BUTTON_SECONDARY);
$data->resetbutton = $resetbutton->export_for_template($output);
$data->definedinconfig = $this->definedinconfig;
return $data;
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason(): string {
public static function get_reason() : string {
return 'privacy:metadata';
}
}
@@ -1,128 +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/>.
declare(strict_types=1);
namespace core_admin\reportbuilder\datasource;
use core_admin\reportbuilder\local\entities\task_log;
use core_reportbuilder\datasource;
use core_reportbuilder\local\entities\user;
use core_reportbuilder\local\filters\select;
/**
* Task logs datasource
*
* @package core_admin
* @copyright 2022 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_logs extends datasource {
/**
* Return user friendly name of the report source
*
* @return string
*/
public static function get_name(): string {
return get_string('tasklogs', 'core_admin');
}
/**
* Initialise report
*/
protected function initialise(): void {
$tasklogentity = new task_log();
$tasklogalias = $tasklogentity->get_table_alias('task_log');
$this->set_main_table('task_log', $tasklogalias);
$this->add_entity($tasklogentity);
// Join the user entity to represent the associated user.
$userentity = new user();
$useralias = $userentity->get_table_alias('user');
$this->add_entity($userentity->add_join("
LEFT JOIN {user} {$useralias}
ON {$useralias}.id = {$tasklogalias}.userid")
);
// Add report elements from each of the entities we added to the report.
$this->add_all_from_entities();
}
/**
* Return the columns that will be added to the report upon creation
*
* @return string[]
*/
public function get_default_columns(): array {
return [
'task_log:name',
'task_log:starttime',
'task_log:duration',
'task_log:result',
];
}
/**
* Return the column sorting that will be added to the report upon creation
*
* @return int[]
*/
public function get_default_column_sorting(): array {
return [
'task_log:starttime' => SORT_DESC,
];
}
/**
* Return the filters that will be added to the report upon creation
*
* @return string[]
*/
public function get_default_filters(): array {
return [
'task_log:timestart',
'task_log:result',
];
}
/**
* Return the conditions that will be added to the report upon creation
*
* @return string[]
*/
public function get_default_conditions(): array {
return [
'task_log:type',
'task_log:timestart',
'task_log:result',
];
}
/**
* Return the condition values that will be set for the report upon creation
*
* @return array
*/
public function get_default_condition_values(): array {
return [
'task_log:type_operator' => select::EQUAL_TO,
'task_log:type_value' => \core\task\database_logger::TYPE_SCHEDULED,
];
}
}
@@ -1,415 +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\reportbuilder\local\entities;
use core_reportbuilder\local\filters\date;
use core_reportbuilder\local\filters\duration;
use core_reportbuilder\local\filters\number;
use core_reportbuilder\local\filters\select;
use core_reportbuilder\local\filters\text;
use core_reportbuilder\local\filters\autocomplete;
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;
use core_collator;
/**
* 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
*
* @return string[]
*/
protected function get_default_tables(): array {
return [
'task_log',
];
}
/**
* 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');
}
/**
* Initialise the entity
*
* @return base
*/
public function initialise(): base {
$columns = $this->get_all_columns();
foreach ($columns as $column) {
$this->add_column($column);
}
// All the filters defined by the entity can also be used as conditions.
$filters = $this->get_all_filters();
foreach ($filters as $filter) {
$this
->add_filter($filter)
->add_condition($filter);
}
return $this;
}
/**
* Returns list of all available columns
*
* @return column[]
*/
protected function get_all_columns(): array {
global $DB;
$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 $classname): string {
$output = '';
if (class_exists($classname)) {
$task = new $classname;
if ($task instanceof \core\task\task_base) {
$output = $task->get_name();
}
}
$output .= \html_writer::tag('div', "\\{$classname}", [
'class' => 'small text-muted',
]);
return $output;
});
// Component column.
$columns[] = (new column(
'component',
new lang_string('plugin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_field("{$tablealias}.component")
->set_is_sortable(true);
// Type column.
$columns[] = (new column(
'type',
new lang_string('tasktype', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_field("{$tablealias}.type")
->set_is_sortable(true)
->add_callback(static function($value): string {
if (\core\task\database_logger::TYPE_SCHEDULED === (int) $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'));
// End time column.
$columns[] = (new column(
'endtime',
new lang_string('task_endtime', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TIMESTAMP)
->add_field("{$tablealias}.timeend")
->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([format::class, 'format_time'], 2);
// 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())
->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())
->add_fields("{$tablealias}.dbreads, {$tablealias}.dbwrites")
->set_is_sortable(true, ["{$tablealias}.dbreads", "{$tablealias}.dbwrites"])
->add_callback(static function($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;
});
// Database reads column.
$columns[] = (new column(
'dbreads',
new lang_string('task_dbreads', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_fields("{$tablealias}.dbreads")
->set_is_sortable(true);
// Database writes column.
$columns[] = (new column(
'dbwrites',
new lang_string('task_dbwrites', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_fields("{$tablealias}.dbwrites")
->set_is_sortable(true);
// 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_BOOLEAN)
// For accurate aggregation, we need to return boolean success = true by xor'ing the field value.
->add_field($DB->sql_bitxor("{$tablealias}.result", 1), 'success')
->set_is_sortable(true)
->add_callback(static function(bool $success): string {
if (!$success) {
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 {
global $DB;
$tablealias = $this->get_table_alias('task_log');
// Name filter (Filter by classname).
$filters[] = (new filter(
autocomplete::class,
'name',
new lang_string('classname', 'tool_task'),
$this->get_entity_name(),
"{$tablealias}.classname"
))
->add_joins($this->get_joins())
->set_options_callback(static function(): array {
global $DB;
$classnames = $DB->get_fieldset_sql('SELECT DISTINCT classname FROM {task_log} ORDER BY classname ASC');
$options = [];
foreach ($classnames as $classname) {
if (class_exists($classname)) {
$task = new $classname;
$options[$classname] = $task->get_name();
}
}
core_collator::asort($options);
return $options;
});
// Component filter.
$filters[] = (new filter(
text::class,
'component',
new lang_string('plugin'),
$this->get_entity_name(),
"{$tablealias}.component"
))
->add_joins($this->get_joins());
// Type filter.
$filters[] = (new filter(
select::class,
'type',
new lang_string('tasktype', 'admin'),
$this->get_entity_name(),
"{$tablealias}.type"
))
->add_joins($this->get_joins())
->set_options([
\core\task\database_logger::TYPE_ADHOC => new lang_string('task_type:adhoc', 'admin'),
\core\task\database_logger::TYPE_SCHEDULED => new lang_string('task_type:scheduled', 'admin'),
]);
// Output filter (Filter by task output).
$filters[] = (new filter(
text::class,
'output',
new lang_string('task_logoutput', 'admin'),
$this->get_entity_name(),
$DB->sql_cast_to_char("{$tablealias}.output")
))
->add_joins($this->get_joins());
// 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,
]);
// End time.
$filters[] = (new filter(
date::class,
'timeend',
new lang_string('task_endtime', 'admin'),
$this->get_entity_name(),
"{$tablealias}.timeend"
))
->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());
// Database reads.
$filters[] = (new filter(
number::class,
'dbreads',
new lang_string('task_dbreads', 'admin'),
$this->get_entity_name(),
"{$tablealias}.dbreads"
))
->add_joins($this->get_joins());
// Database writes.
$filters[] = (new filter(
number::class,
'dbwrites',
new lang_string('task_dbwrites', 'admin'),
$this->get_entity_name(),
"{$tablealias}.dbwrites"
))
->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'),
]);
return $filters;
}
}
@@ -1,108 +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/>.
declare(strict_types=1);
namespace core_admin\reportbuilder\local\filters;
use core\context\system;
use core_course_category;
use MoodleQuickForm;
use core_reportbuilder\local\filters\base;
use core_reportbuilder\local\helpers\database;
/**
* Course role report filter (by role, category, course)
*
* The provided filter field SQL must refer/return an expression for the user ID (e.g. "{$user}.id")
*
* @package core_admin
* @copyright 2023 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class courserole extends base {
/**
* Setup form
*
* @param MoodleQuickForm $mform
*/
public function setup_form(MoodleQuickForm $mform): void {
$elements = [];
// Role.
$elements['role'] = $mform->createElement('select', "{$this->name}_role", get_string('rolefullname', 'core_role'),
[0 => get_string('anyrole', 'core_filters')] + get_default_enrol_roles(system::instance()));
// Category.
$elements['category'] = $mform->createElement('select', "{$this->name}_category", get_string('category'),
[0 => get_string('anycategory', 'core_filters')] + core_course_category::make_categories_list());
// Course.
$elements['course'] = $mform->createElement('text', "{$this->name}_course", get_string('shortnamecourse'));
$mform->setType("{$this->name}_course", PARAM_RAW_TRIMMED);
$mform->addGroup($elements, "{$this->name}_group", $this->get_header(), '', false)
->setHiddenLabel(true);
}
/**
* Return filter SQL
*
* @param array $values
* @return array
*/
public function get_sql_filter(array $values): array {
[$fieldsql, $params] = $this->filter->get_field_sql_and_params();
[$contextalias, $rolealias, $coursealias] = database::generate_aliases(3);
[$roleparam, $categoryparam, $courseparam] = database::generate_param_names(3);
// Role.
$role = (int) ($values["{$this->name}_role"] ?? 0);
if ($role > 0) {
$selects[] = "{$rolealias}.roleid = :{$roleparam}";
$params[$roleparam] = $role;
}
// Category.
$category = (int) ($values["{$this->name}_category"] ?? 0);
if ($category > 0) {
$selects[] = "{$coursealias}.category = :{$categoryparam}";
$params[$categoryparam] = $category;
}
// Course.
$course = trim($values["{$this->name}_course"] ?? '');
if ($course !== '') {
$selects[] = "{$coursealias}.shortname = :{$courseparam}";
$params[$courseparam] = $course;
}
// Filter values are not set.
if (empty($selects)) {
return ['', []];
}
return ["{$fieldsql} IN (
SELECT {$rolealias}.userid
FROM {role_assignments} {$rolealias}
JOIN {context} {$contextalias} ON {$contextalias}.id = {$rolealias}.contextid AND {$contextalias}.contextlevel = 50
JOIN {course} {$coursealias} ON {$coursealias}.id = {$contextalias}.instanceid
WHERE " . implode(' AND ', $selects) . "
)", $params];
}
}
@@ -1,165 +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\reportbuilder\local\systemreports;
use context_system;
use core_admin\reportbuilder\local\entities\task_log;
use core_reportbuilder\local\entities\user;
use core_reportbuilder\local\report\action;
use core_reportbuilder\system_report;
use html_writer;
use lang_string;
use moodle_url;
use pix_icon;
use stdClass;
/**
* 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 {
$entitymainalias = $this->get_entity('task_log')->get_table_alias('task_log');
$this->add_columns_from_entities([
'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',
]);
// Wrap the task name in a link.
$this->get_column('task_log:name')
->add_field("{$entitymainalias}.id")
->add_callback(static function(string $output, stdClass $row): string {
return html_writer::link(new moodle_url('/admin/tasklogs.php', ['logid' => $row->id]), $output);
});
// Rename the user fullname column.
$this->get_column('user:fullname')
->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 {
$this->add_filters_from_entities([
'task_log:name',
'task_log:type',
'task_log:output',
'task_log:result',
'task_log:timestart',
'task_log:duration',
]);
}
/**
* 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', ''),
[],
false,
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'),
)));
}
}
@@ -1,417 +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\reportbuilder\local\systemreports;
use core_admin\reportbuilder\local\filters\courserole;
use core\context\system;
use core_cohort\reportbuilder\local\entities\cohort;
use core_cohort\reportbuilder\local\entities\cohort_member;
use core_reportbuilder\local\entities\user;
use core_reportbuilder\local\filters\boolean_select;
use core_reportbuilder\local\helpers\database;
use core_reportbuilder\local\helpers\user_profile_fields;
use core_reportbuilder\local\report\action;
use core_reportbuilder\local\report\filter;
use core_reportbuilder\system_report;
use core_role\reportbuilder\local\entities\role;
use core_user\fields;
use lang_string;
use moodle_url;
use pix_icon;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/authlib.php');
require_once($CFG->libdir.'/enrollib.php');
require_once($CFG->dirroot.'/user/lib.php');
/**
* Browse users system report class implementation
*
* @package core_admin
* @copyright 2023 David Carrillo <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class users extends system_report {
/**
* Initialise report, we need to set the main table, load our entities and set columns/filters
*/
protected function initialise(): void {
global $CFG;
// Our main entity, it contains all of the column definitions that we need.
$entityuser = new user();
$entityuseralias = $entityuser->get_table_alias('user');
$this->set_main_table('user', $entityuseralias);
$this->add_entity($entityuser);
// Any columns required by actions should be defined here to ensure they're always available.
$fullnamefields = array_map(fn($field) => "{$entityuseralias}.{$field}", fields::get_name_fields());
$this->add_base_fields("{$entityuseralias}.id, {$entityuseralias}.confirmed, {$entityuseralias}.mnethostid,
{$entityuseralias}.suspended, {$entityuseralias}.username, " . implode(', ', $fullnamefields));
if ($this->get_parameter('withcheckboxes', false, PARAM_BOOL)) {
$canviewfullnames = has_capability('moodle/site:viewfullnames', \context_system::instance());
$this->set_checkbox_toggleall(static function(\stdClass $row) use ($canviewfullnames): array {
return [$row->id, fullname($row, $canviewfullnames)];
});
}
$paramguest = database::generate_param_name();
$this->add_base_condition_sql("{$entityuseralias}.deleted <> 1 AND {$entityuseralias}.id <> :{$paramguest}",
[$paramguest => $CFG->siteguest]);
$entitycohortmember = new cohort_member();
$entitycohortmemberalias = $entitycohortmember->get_table_alias('cohort_members');
$this->add_entity($entitycohortmember
->add_joins($entitycohortmember->get_joins())
->add_join("LEFT JOIN {cohort_members} {$entitycohortmemberalias}
ON {$entityuseralias}.id = {$entitycohortmemberalias}.userid")
);
$entitycohort = new cohort();
$entitycohortalias = $entitycohort->get_table_alias('cohort');
$this->add_entity($entitycohort
->add_joins($entitycohort->get_joins())
->add_joins($entitycohortmember->get_joins())
->add_join("LEFT JOIN {cohort} {$entitycohortalias}
ON {$entitycohortalias}.id = {$entitycohortmemberalias}.cohortid")
);
// Join the role entity (Needed for the system role filter).
$roleentity = new role();
$role = $roleentity->get_table_alias('role');
$this->add_entity($roleentity
->add_join("LEFT JOIN (
SELECT DISTINCT r0.id, ras.userid
FROM {role} r0
JOIN {role_assignments} ras ON ras.roleid = r0.id
WHERE ras.contextid = ".SYSCONTEXTID."
) {$role} ON {$role}.userid = {$entityuseralias}.id")
);
// 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);
}
/**
* Validates access to view this report
*
* @return bool
*/
protected function can_view(): bool {
return has_any_capability(['moodle/user:update', 'moodle/user:delete'], system::instance());
}
/**
* 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 {
$entityuser = $this->get_entity('user');
$entityuseralias = $entityuser->get_table_alias('user');
$this->add_column($entityuser->get_column('fullnamewithpicturelink'));
// Include identity field columns.
$identitycolumns = $entityuser->get_identity_columns($this->get_context());
foreach ($identitycolumns as $identitycolumn) {
$this->add_column($identitycolumn);
}
// Add "Last access" column.
$this->add_column(($entityuser->get_column('lastaccess'))
->set_callback(static function ($value, \stdClass $row): string {
if ($row->lastaccess) {
return format_time(time() - $row->lastaccess);
}
return get_string('never');
})
);
if ($column = $this->get_column('user:fullnamewithpicturelink')) {
$column
->add_fields("{$entityuseralias}.suspended, {$entityuseralias}.confirmed")
->add_callback(static function(string $fullname, \stdClass $row): string {
if ($row->suspended) {
$fullname .= ' ' . \html_writer::tag('span', get_string('suspended', 'moodle'),
['class' => 'badge badge-secondary ms-1']);
}
if (!$row->confirmed) {
$fullname .= ' ' . \html_writer::tag('span', get_string('confirmationpending', 'admin'),
['class' => 'badge badge-danger ms-1']);
}
return $fullname;
});
}
$this->set_initial_sort_column('user:fullnamewithpicturelink', SORT_ASC);
$this->set_default_no_results_notice(new lang_string('nousersfound', 'moodle'));
}
/**
* 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 {
$entityuser = $this->get_entity('user');
$entityuseralias = $entityuser->get_table_alias('user');
$filters = [
'user:fullname',
'user:firstname',
'user:lastname',
'user:username',
'user:idnumber',
'user:email',
'user:department',
'user:institution',
'user:city',
'user:country',
'user:confirmed',
'user:suspended',
'user:timecreated',
'user:lastaccess',
'user:timemodified',
'user:auth',
'user:lastip',
'cohort:idnumber',
'role:name',
];
$this->add_filters_from_entities($filters);
// Enrolled in any course filter.
$ue = database::generate_alias();
[$now1, $now2] = database::generate_param_names(2);
$now = time();
$sql = "CASE WHEN ({$entityuseralias}.id IN (
SELECT userid FROM {user_enrolments} {$ue}
WHERE {$ue}.status = " . ENROL_USER_ACTIVE . "
AND ({$ue}.timestart = 0 OR {$ue}.timestart < :{$now1})
AND ({$ue}.timeend = 0 OR {$ue}.timeend > :{$now2})
)) THEN 1 ELSE 0 END";
$this->add_filter((new filter(
boolean_select::class,
'enrolledinanycourse',
new lang_string('anycourses', 'filters'),
$this->get_entity('user')->get_entity_name(),
))
->set_field_sql($sql, [
$now1 => $now,
$now2 => $now,
])
);
// Course role filter.
$this->add_filter((new filter(
courserole::class,
'courserole',
new lang_string('courserole', 'filters'),
$this->get_entity('user')->get_entity_name(),
))
->set_field_sql("{$entityuseralias}.id")
);
// Add user profile fields filters.
$userprofilefields = new user_profile_fields($entityuseralias . '.id', $entityuser->get_entity_name());
foreach ($userprofilefields->get_filters() as $filter) {
$this->add_filter($filter);
}
// Set options for system role filter.
if ($filter = $this->get_filter('role:name')) {
$filter
->set_header(new lang_string('globalrole', 'role'))
->set_options(get_assignable_roles(system::instance()));
}
}
/**
* 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 {
global $DB, $USER;
$contextsystem = system::instance();
// Action to edit users.
$this->add_action((new action(
new moodle_url('/user/editadvanced.php', ['id' => ':id', 'course' => get_site()->id]),
new pix_icon('t/edit', ''),
[],
false,
new lang_string('edit', 'moodle'),
))->add_callback(static function(\stdclass $row) use ($USER, $contextsystem): bool {
return has_capability('moodle/user:update', $contextsystem) && (is_siteadmin($USER) || !is_siteadmin($row));
}));
// Action to suspend users (non mnet remote users).
$this->add_action((new action(
new moodle_url('/admin/user.php', ['suspend' => ':id', 'sesskey' => sesskey()]),
new pix_icon('t/show', ''),
[],
false,
new lang_string('suspenduser', 'admin'),
))->add_callback(static function(\stdclass $row) use ($USER, $contextsystem): bool {
return has_capability('moodle/user:update', $contextsystem) && !$row->suspended && !is_mnet_remote_user($row) &&
!($row->id == $USER->id || is_siteadmin($row));
}));
// Action to unsuspend users (non mnet remote users).
$this->add_action((new action(
new moodle_url('/admin/user.php', ['unsuspend' => ':id', 'sesskey' => sesskey()]),
new pix_icon('t/hide', ''),
[],
false,
new lang_string('unsuspenduser', 'admin'),
))->add_callback(static function(\stdclass $row) use ($USER, $contextsystem): bool {
return has_capability('moodle/user:update', $contextsystem) && $row->suspended && !is_mnet_remote_user($row) &&
!($row->id == $USER->id || is_siteadmin($row));
}));
// Action to unlock users (non mnet remote users).
$this->add_action((new action(
new moodle_url('/admin/user.php', ['unlock' => ':id', 'sesskey' => sesskey()]),
new pix_icon('t/unlock', ''),
[],
false,
new lang_string('unlockaccount', 'admin'),
))->add_callback(static function(\stdclass $row) use ($contextsystem): bool {
return has_capability('moodle/user:update', $contextsystem) && !is_mnet_remote_user($row) &&
login_is_lockedout($row);
}));
// Action to suspend users (mnet remote users).
$this->add_action((new action(
new moodle_url('/admin/user.php', ['acl' => ':id', 'sesskey' => sesskey(), 'accessctrl' => 'deny']),
new pix_icon('t/show', ''),
[],
false,
new lang_string('denyaccess', 'mnet'),
))->add_callback(static function(\stdclass $row) use ($DB, $contextsystem): bool {
if (!$accessctrl = $DB->get_field(table: 'mnet_sso_access_control', return: 'accessctrl',
conditions: ['username' => $row->username, 'mnet_host_id' => $row->mnethostid]
)) {
$accessctrl = 'allow';
}
return has_capability('moodle/user:update', $contextsystem) && !$row->suspended &&
is_mnet_remote_user($row) && $accessctrl == 'allow';
}));
// Action to unsuspend users (mnet remote users).
$this->add_action((new action(
new moodle_url('/admin/user.php', ['acl' => ':id', 'sesskey' => sesskey(), 'accessctrl' => 'allow']),
new pix_icon('t/hide', ''),
[],
false,
new lang_string('allowaccess', 'mnet'),
))->add_callback(static function(\stdclass $row) use ($DB, $contextsystem): bool {
if (!$accessctrl = $DB->get_field(table: 'mnet_sso_access_control', return: 'accessctrl',
conditions: ['username' => $row->username, 'mnet_host_id' => $row->mnethostid]
)) {
$accessctrl = 'allow';
}
return has_capability('moodle/user:update', $contextsystem) && !$row->suspended &&
is_mnet_remote_user($row) && $accessctrl == 'deny';
}));
// Action to delete users.
$this->add_action((new action(
new moodle_url('/admin/user.php', ['delete' => ':id', 'sesskey' => sesskey()]),
new pix_icon('t/delete', ''),
[
'class' => 'text-danger',
'data-modal' => 'confirmation',
'data-modal-title-str' => json_encode(['deleteuser', 'admin']),
'data-modal-content-str' => ':deletestr',
'data-modal-yes-button-str' => json_encode(['delete', 'core']),
'data-modal-destination' => ':deleteurl',
],
false,
new lang_string('delete', 'moodle'),
))->add_callback(static function(\stdclass $row) use ($USER, $contextsystem): bool {
// Populate deletion modal attributes.
$row->deletestr = json_encode([
'deletecheckfull',
'moodle',
fullname($row, true),
]);
$row->deleteurl = (new moodle_url('/admin/user.php', [
'delete' => $row->id,
'confirm' => md5($row->id),
'sesskey' => sesskey(),
]))->out(false);
return has_capability('moodle/user:delete', $contextsystem) &&
!is_mnet_remote_user($row) && $row->id != $USER->id && !is_siteadmin($row);
}));
$this->add_action_divider();
// Action to confirm users.
$this->add_action((new action(
new moodle_url('/admin/user.php', ['confirmuser' => ':id', 'sesskey' => sesskey()]),
new pix_icon('t/check', ''),
[],
false,
new lang_string('confirmaccount', 'moodle'),
))->add_callback(static function(\stdclass $row) use ($contextsystem): bool {
return has_capability('moodle/user:update', $contextsystem) && !$row->confirmed;
}));
// Action to resend email.
$this->add_action((new action(
new moodle_url('/admin/user.php', ['resendemail' => ':id', 'sesskey' => sesskey()]),
new pix_icon('t/email', ''),
[],
false,
new lang_string('resendemail', 'moodle'),
))->add_callback(static function(\stdclass $row): bool {
return !$row->confirmed && !is_mnet_remote_user($row);
}));
}
/**
* Row class
*
* @param \stdClass $row
* @return string
*/
public function get_row_class(\stdClass $row): string {
return $row->suspended ? 'text-muted' : '';
}
}
@@ -1,118 +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\table;
use core_plugin_manager;
use dml_exception;
use html_writer;
use moodle_url;
use stdClass;
/**
* Activity Module admin settings.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class activity_management_table extends plugin_management_table {
public function setup() {
$this->set_attribute('id', 'modules');
$this->set_attribute('class', 'admintable generaltable');
parent::setup();
}
protected function get_table_id(): string {
return 'module-administration-table';
}
protected function get_plugintype(): string {
return 'mod';
}
public function guess_base_url(): void {
$this->define_baseurl(
new moodle_url('/admin/modules.php')
);
}
protected function get_action_url(array $params = []): moodle_url {
return new moodle_url('/admin/modules.php', $params);
}
protected function get_column_list(): array {
$columns = parent::get_column_list();
return array_merge(
array_slice($columns, 0, 1, true),
['activities' => get_string('activities')],
array_slice($columns, 1, null, true),
);
}
protected function col_name(stdClass $row): string {
global $OUTPUT;
$status = $row->plugininfo->get_status();
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
return html_writer::span(
get_string('pluginmissingfromdisk', 'core', $row->plugininfo),
'notifyproblem'
);
}
return html_writer::span(
html_writer::img(
$OUTPUT->image_url('monologo', $row->plugininfo->name),
'',
[
'class' => 'icon',
],
) . get_string('modulename', $row->plugininfo->name)
);
}
/**
* Show the number of activities present, with a link to courses containing activity if relevant.
*
* @param mixed $row
* @return string
*/
protected function col_activities(stdClass $row): string {
global $DB, $OUTPUT;
try {
$count = $DB->count_records_select($row->plugininfo->name, "course <> 0");
} catch (dml_exception $e) {
$count = -1;
}
if ($count > 0) {
return $OUTPUT->action_link(
new moodle_url('/course/search.php', [
'modulelist' => $row->plugininfo->name,
]),
$count,
null,
['title' => get_string('showmodulecourse')]
);
} else if ($count < 0) {
return get_string('error');
} else {
return $count;
}
}
}

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