Compare commits

..

967 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) de301d4237 Moodle release 3.9.4 2021-01-16 16:58:25 +01:00
Sara Arjona e2c8f4ad1b weekly release 3.9.3+ 2021-01-15 08:25:45 +01:00
Sara Arjona 8c1455d220 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2021-01-15 08:25:44 +01:00
Sara Arjona 7b85e141da Merge branch 'MDL-69308_39' of https://github.com/stronk7/moodle into MOODLE_39_STABLE 2021-01-14 12:04:13 +01:00
Jake Dallimore cd744ba504 Merge branch 'MDL-69877-39' of git://github.com/mickhawkins/moodle into MOODLE_39_STABLE 2021-01-14 14:52:36 +08:00
Michael Hawkins 974c63505b MDL-69877 core: Added security.txt 2021-01-14 14:31:01 +08:00
AMOS bot 724210c4f7 Automatically generated installer lang files 2021-01-14 00:07:44 +00:00
Eloy Lafuente (stronk7) ae9d510288 MDL-69308 environment: Apply agreed changes
- PHP 7.3 required.
- Moodle 3.6 required.
- SQL*Server 2017 (aka, 14.0) required.
- Sodium PHP extension required.
2021-01-13 19:30:15 +01:00
Eloy Lafuente (stronk7) 981f750b81 MDL-69308 environment: 3.11 base information
This is a direct copy of the 3.10 branch to have
the changes under control in next commits.
2021-01-13 19:30:10 +01:00
Mihail Geshoski 721d57228f MDL-68486 auth_shibboleth: Reset convert_data if it uses dataroot file
Upgrade step that resets the 'Data modification API' (convert_data)
setting to its default value if this setting is currently configured
to use a file located within the $CFG->dataroot directory.
2021-01-13 12:35:42 +08:00
Mihail Geshoski 3c25c373d9 MDL-68486 auth_shibboleth: Prevent using dataroot files in convert_data
Prevents configuring the 'Data modification API' (convert_data) setting
to use files located within the $CFG->dataroot directory as it exposes
the site to security risks.
2021-01-13 12:35:42 +08:00
AMOS bot 17eb41c270 Automatically generated installer lang files 2021-01-13 00:07:45 +00:00
Michael Hawkins af6e65f221 MDL-69911 core: Clean content passed through TeX filter 2021-01-12 10:27:31 +01:00
Ferran Recio 8bbc064e29 MDL-67782 message: fix messages max length 2021-01-12 10:27:31 +01:00
Juan Segarra Montesinos 78b18c00bf MDL-69797 core_grades: Implement authorization into fetch method 2021-01-12 10:27:31 +01:00
Juan Segarra Montesinos 4b3b4b7d78 MDL-69797 core_grades: Implement authorization into fetch method 2021-01-12 10:27:31 +01:00
Juan Segarra Montesinos 557d1c8820 MDL-69797 gradingform_rubric: Implement authorization into fetch method 2021-01-12 10:27:31 +01:00
Juan Segarra Montesinos 698e1f7823 MDL-69797 gradingform_guide: Implement authorization into fetch method 2021-01-12 10:27:31 +01:00
Sara Arjona 5b4702a6b6 Merge branch 'MDL-70009-39' of git://github.com/ilyatregubov/moodle into MOODLE_39_STABLE 2021-01-12 10:21:20 +01:00
Jake Dallimore 77c0b16613 Merge branch 'MDL-69431_Validate_section_arg_modedit' of git://github.com/watson8/moodle into MOODLE_39_STABLE 2021-01-12 17:09:29 +08:00
Ilya Tregubov 9adef8af21 MDL-70009 h5pactivity: Split get_pluginfile_hash in two methods. 2021-01-12 09:11:04 +02:00
AMOS bot cc45df637f Automatically generated installer lang files 2021-01-12 00:07:54 +00:00
Sara Arjona 13655cd5ea Merge branch 'MDL-70034_39' of git://github.com/mdjnelson/moodle into MOODLE_39_STABLE 2021-01-11 15:19:39 +01:00
Sara Arjona ea3f1d19b9 Merge branch 'MDL-70567-MOODLE_39_STABLE' of https://github.com/dmitriim/moodle into MOODLE_39_STABLE 2021-01-11 13:09:56 +01:00
Sara Arjona 8256ebd431 Merge branch 'MDL-70578-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2021-01-11 12:58:28 +01:00
Sara Arjona 8ba97d0104 Merge branch 'MDL-70352-MOODLE_39_STABLE' of https://github.com/dmitriim/moodle into MOODLE_39_STABLE 2021-01-11 12:24:12 +01:00
AMOS bot 71ee378a69 Automatically generated installer lang files 2021-01-11 00:08:59 +00:00
David Watson 8208453a14 MDL-69431 course: validate section url param against maxsections 2021-01-10 17:11:50 +00:00
Eloy Lafuente (stronk7) 7c6e9b37b3 Merge branch 'MDL-70550-39-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2021-01-09 13:18:02 +01:00
Mark Nelson 19dc872bca MDL-70034 gradingform_guide: use new API to retrieve grade item name 2021-01-09 14:31:18 +08:00
AMOS bot 0a51214fb3 Automatically generated installer lang files 2021-01-09 00:07:50 +00:00
Sara Arjona 6910afa56f Merge branch 'MDL-70558-39' of git://github.com/paulholden/moodle into MOODLE_39_STABLE 2021-01-08 17:07:29 +01:00
Sara Arjona 5e5e82621c Merge branch 'MDL-70102-m39' of https://github.com/sammarshallou/moodle into MOODLE_39_STABLE 2021-01-08 15:51:14 +01:00
David Mudrák 2edff57e63 MDL-70550 lang: Use the fixed strings in Behat tests, too 2021-01-08 09:17:03 +01:00
Helen Foster 3b8bb4d4c1 MDL-70550 lang: Import fixed English strings (en_fix) 2021-01-08 09:16:38 +01:00
Jun Pataleta 920763ad00 Merge branch 'MDL-70310-39' of git://github.com/ilyatregubov/moodle into MOODLE_39_STABLE 2021-01-08 14:47:05 +08:00
Luca Bösch 1acd3cac07 MDL-70578 cohorts: Add bootstrap classes to buttons 2021-01-08 07:28:02 +01:00
Jun Pataleta 7de4119fe2 weekly release 3.9.3+ 2021-01-08 12:14:52 +08:00
Jun Pataleta 6fb2fa9859 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2021-01-08 12:14:51 +08:00
AMOS bot 1d54d21ec0 Automatically generated installer lang files 2021-01-08 00:07:44 +00:00
Eloy Lafuente (stronk7) c87ed01b17 Merge branch 'MDL-70245-MOODLE_39_STABLE' of https://github.com/TomoTsuyuki/moodle into MOODLE_39_STABLE 2021-01-07 23:50:05 +01:00
Eloy Lafuente (stronk7) 23541c936a Merge branch 'MDL-70584-39' of git://github.com/marinaglancy/moodle into MOODLE_39_STABLE 2021-01-07 23:30:53 +01:00
sam marshall b7490a205f MDL-70102 PHPunit: Core test fails with weird added modules
Specifically it fails if the modules have unusual default capabilities
so that editingteacher doesn't have addinstance.
2021-01-07 16:12:30 +00:00
Marina Glancy 8415e0461b MDL-70584 core_iplookup: increase tolerance in test 2021-01-07 14:23:33 +01:00
Ilya Tregubov 9ee41118b0 MDL-70310 user: Remove yahoo icon since domain no longer exists. 2021-01-07 09:15:35 +02:00
Jun Pataleta 137b10b378 Merge branch 'MDL-70374_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2021-01-07 12:23:34 +08:00
Eloy Lafuente (stronk7) bb9e3ec1ff Merge branch 'MDL-70476_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2021-01-07 00:28:16 +01:00
Eloy Lafuente (stronk7) 7152b05700 Merge branch 'MOODLE_39_MDL-70520' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2021-01-07 00:19:23 +01:00
Dmitrii Metelkin 087ccaff4f MDL-70567 task: fix broken result filter on logs page 2021-01-06 14:28:38 +11:00
Dmitrii Metelkin 3fb245f481 MDL-70352 core: attach modal to a specific element 2021-01-06 11:09:01 +11:00
Paul Holden 8de31cf961 MDL-70558 tool_langimport: sort available language packs. 2021-01-04 23:56:05 +00:00
AMOS bot 88e7da61cd Automatically generated installer lang files 2020-12-27 00:07:46 +00:00
AMOS bot 3648b629ed Automatically generated installer lang files 2020-12-24 00:07:52 +00:00
Eloy Lafuente (stronk7) 0d833e248a weekly release 3.9.3+ 2020-12-23 20:24:49 +01:00
Eloy Lafuente (stronk7) 783fba428f Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-12-23 20:24:46 +01:00
Eloy Lafuente (stronk7) 514c7ee639 Merge branch 'MDL-56119-390' of https://github.com/inigozendegi/moodle into MOODLE_39_STABLE 2020-12-23 01:07:59 +01:00
Eloy Lafuente (stronk7) fa35b9506f Merge branch 'MDL-70279-39' of git://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-12-23 00:47:09 +01:00
Eloy Lafuente (stronk7) 29f7630b75 Merge branch 'MDL-70436-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-12-22 18:30:03 +01:00
Eloy Lafuente (stronk7) 7a2a47d9e8 Merge branch 'MDL-70386-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-12-22 18:22:10 +01:00
Jake Dallimore 17211224a1 Merge branch 'MDL-69422-39-2' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-12-22 16:03:33 +08:00
Jake Dallimore 2394a675dd Merge branch 'MDL-70426-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE 2020-12-22 15:17:02 +08:00
Mikhail Golenkov 449c835fe2 MDL-70520 mod_assign: Use task API to get scheduled task lastruntime 2020-12-22 15:31:42 +11:00
Mikhail Golenkov 322afa9f4f MDL-70520 tasks: Keep lastruntime when a scheduled task is reset 2020-12-22 15:31:38 +11:00
AMOS bot 1d0777dbe4 Automatically generated installer lang files 2020-12-22 00:07:45 +00:00
Víctor Déniz cd94f2bc2e Merge branch 'MDL-70355-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-12-21 23:18:49 +00:00
Sara Arjona e899fd5c02 Merge branch 'MDL-69107-39-2' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-12-18 15:22:41 +01:00
Tim Hunt 438b2ac8c2 MDL-70374 qtype_multichoice: improve alignment of choices 2020-12-18 13:09:41 +00:00
Tim Hunt f6ae03bf41 MDL-70476 permission overrides: role names double-escaped in tool tip 2020-12-18 13:09:02 +00:00
Luca Bösch fc52aaf319 MDL-70355 calendar: Filter popuptext for calendar entries. 2020-12-17 17:42:42 +01:00
Sara Arjona ef8eb8ef1a weekly release 3.9.3+ 2020-12-17 15:52:48 +01:00
Sara Arjona f1c6cf8b26 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-12-17 15:52:46 +01:00
Víctor Déniz e68cea5747 Merge branch 'MDL-70261-39' of git://github.com/ilya-catalyst/moodle into MOODLE_39_STABLE 2020-12-16 12:36:13 +00:00
Sara Arjona 3f797704ea Merge branch 'MDL-70373_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-12-16 12:40:58 +01:00
Jun Pataleta aae57db8d2 Merge branch 'MDL-54907_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-12-16 10:01:04 +08:00
Andrew Nicols 8c3091e5f3 MDL-69107 user: Fix autocomplete usages 2020-12-16 07:50:56 +08:00
Sara Arjona b52ad05038 Merge branch 'MDL-70422-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-12-15 16:43:14 +01:00
Sara Arjona ec5d807139 Merge branch 'MDL-70409-39' of git://github.com/merrill-oakland/moodle into MOODLE_39_STABLE 2020-12-15 16:15:59 +01:00
Sara Arjona 1f00b5d9bb Merge branch 'MDL-70342-39' of git://github.com/abias/moodle into MOODLE_39_STABLE 2020-12-15 15:29:28 +01:00
Sara Arjona 0f53bd6b8e Merge branch 'MDL-70357-39-cronlibthrowables' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-12-15 14:56:12 +01:00
Ilya Tregubov bf29fea4bb MDL-70261 course: Allow update locked course custom fields
on course upload.
2020-12-15 14:43:18 +02:00
Jake Dallimore 8a733bc85f Merge branch 'MDL-67623-39_blocks_myoverview_pagination_regression' of https://github.com/tomdickman/moodle into MOODLE_39_STABLE 2020-12-15 18:22:28 +08:00
Andrew Nicols 1b87f634a8 MDL-69107 form_autocomplete: Rewrite item selection
The form_autocomplete is essentially a custom element. Unfortunately the
`setValue()` function in Mink has undesired actions so it is necessary
to write our own handling for it.

The standard Mink `setValue()` function focuses the element, sets a
value, and then blurs the element. In the case of the autocomplete this
can cause the autocomplete suggestions list to be closed in some
situations. Instead of using the setValue we click, and type the value,
but do not immediately blur.
2020-12-15 09:08:05 +08:00
AMOS bot 9260dad3b3 Automatically generated installer lang files 2020-12-15 00:07:45 +00:00
Sara Arjona 6002a1454f Merge branch 'MDL-70397-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-12-14 17:12:15 +01:00
Jake Dallimore cef3216f2a Merge branch 'MDL-70324-3.9' of https://github.com/JBThong/moodle into MOODLE_39_STABLE 2020-12-14 11:30:32 +08:00
Tom Dickman bed6bfe7d4 MDL-67623 block overview: fix pagination regression
Fixed a regression caused by MDL-64194 resulting in Dashboard - Course
overview pagination not working from second page of courses onwards.

Course overview block should now do the following:
- Display no pagination controls when user has no courses
- Display no pagination controls when less than 12 courses to display
- Only display pagination controls up to the number of courses user is
enrolled in
- Work correctly when on a page greater than the second page.
2020-12-14 13:34:38 +11:00
AMOS bot 1c39517553 Automatically generated installer lang files 2020-12-13 00:07:45 +00:00
AMOS bot e92846ce18 Automatically generated installer lang files 2020-12-12 00:07:55 +00:00
AMOS bot 31d0ccb078 Merge branch 'MOODLE_39_STABLE' into install_39_STABLE 2020-12-12 00:07:54 +00:00
AMOS bot fc7fa7f72c Automatically generated installer lang files 2020-12-11 00:07:53 +00:00
Víctor Déniz 6994f63eef weekly release 3.9.3+ 2020-12-10 21:10:36 +00:00
Víctor Déniz c28c0ed466 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-12-10 21:10:30 +00:00
Huong Nguyen 479b0f0eaa MDL-70426 qtype_ddmarker: infinite markers keep duplicating 2020-12-10 15:55:24 +07:00
Shamim Rezaie 7b96e8a413 MDL-69301 theme_boost: Remove the special handling of Escape key 2020-12-10 14:56:46 +08:00
Tomo Tsuyuki 2321fe4da9 MDL-70245 core_grade: Fix grade_get_setting unit test failures
To fix the phpunit issue, change from static variable to use cache
2020-12-10 16:46:54 +11:00
Jake Dallimore 3aa05048cf Merge branch 'MDL-70320-39' of https://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-12-10 12:02:53 +08:00
Andrew Nicols 17d6ecd26d MDL-70320 behat: User full path to page admin node 2020-12-10 07:56:58 +08:00
Bas Brands 7d5c5fad77 MDL-70386 theme_boost: quizes correctness badges 2020-12-09 18:09:27 +01:00
Bas Brands c1296560bf MDL-70436 theme_boost: closebutton styles in moodle-dialog-fullscreen 2020-12-09 14:59:50 +01:00
Víctor Déniz 93e25f8657 Merge branch 'MDL-63683-39' of https://github.com/dravek/moodle into MOODLE_39_STABLE 2020-12-09 12:46:18 +00:00
Jake Dallimore f43de821c6 Merge branch 'MDL-70151-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-12-09 14:46:36 +08:00
Andrew Nicols 1b0690a7f1 Merge branch 'MDL-70320_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-12-09 12:07:32 +08:00
Andrew Nicols e003e8a6ff Merge branch 'MDL-62707-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-12-09 08:58:12 +08:00
Jake Dallimore 1e8f432437 Merge branch 'MDL-70285_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-12-08 16:34:10 +08:00
AMOS bot 51d7849f08 Automatically generated installer lang files 2020-12-08 00:07:43 +00:00
Paul Holden ede7d22dc7 MDL-70422 restore: fix for undefined question answer ordering in test. 2020-12-07 10:15:55 +00:00
Adrian Greeve 4355451e2f Merge branch 'MDL-69301-39' of git://github.com/rezaies/moodle into MOODLE_39_STABLE 2020-12-07 09:23:27 +08:00
AMOS bot 5e102fa8c3 Automatically generated installer lang files 2020-12-06 00:07:50 +00:00
Eric Merrill 1925b641e2 MDL-70409 chat: Use require_once to import lib.php 2020-12-04 10:46:16 -05:00
Paul Holden 377da86151 MDL-70279 tool_templatelibrary: preserve component search field value. 2020-12-04 14:55:28 +00:00
Paul Holden 9a2db9e2ec MDL-62707 search: account for no matching courses when listing areas.
When limiting the list of courses during retrieval of the search areas
the user can access, make sure we have some contexts before looking
for blocks.
2020-12-04 09:43:27 +00:00
inigozendegi 844637b880 MDL-56119 gradingform_rubric: Rubric display layout issue 2020-12-04 09:41:40 +01:00
David Matamoros 9e597d3658 MDL-63683 enrol: Fix plugin settings when no role has student archetype 2020-12-04 09:27:20 +01:00
Andrew Nicols 0e25936c0d MDL-70397 behat: Prevent browser restarting after initial start 2020-12-04 12:07:36 +08:00
Jake Dallimore 627e14727e weekly release 3.9.3+ 2020-12-04 08:42:43 +08:00
Jake Dallimore ffe84e977f Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-12-04 08:42:40 +08:00
Andrew Nicols 7bc67e92e2 Merge branch 'MDL-70080-39' of git://github.com/jleyva/moodle into MOODLE_39_STABLE 2020-12-03 11:55:54 +08:00
Andrew Nicols dd96341354 Merge branch 'MDL-70327-39' of git://github.com/cescobedo/moodle into MOODLE_39_STABLE 2020-12-03 11:52:06 +08:00
Andrew Nicols 1714cb74b3 Merge branch 'MDL-70321_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-12-03 11:40:24 +08:00
Jake Dallimore c94c579aa6 Merge branch 'MDL-69411-39' of git://github.com/dravek/moodle into MOODLE_39_STABLE 2020-12-03 11:37:17 +08:00
Jake Dallimore 16bcd8f057 Merge branch 'MDL-67460-39_profile_secure' of https://github.com/beenet-dev/moodle into MOODLE_39_STABLE 2020-12-03 11:16:52 +08:00
Andrew Nicols 5e65d02eab Merge branch 'MDL-70157_39' of https://github.com/rlorenzo/moodle into MOODLE_39_STABLE 2020-12-03 11:01:21 +08:00
Adrian Greeve 1b8bfedaa9 Merge branch 'wip_MDL-70267_m39' of git://github.com/gjb2048/moodle into MOODLE_39_STABLE 2020-12-03 10:55:54 +08:00
Adrian Greeve 7b920d2d7b Merge branch 'MDL-70167-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-12-03 09:56:42 +08:00
AMOS bot 63b0a865dd Automatically generated installer lang files 2020-12-03 00:07:48 +00:00
Andrew Nicols 7766af18a5 Merge branch 'MDL-69868-39' of git://github.com/ilya-catalyst/moodle into MOODLE_39_STABLE 2020-12-03 07:48:59 +08:00
Tim Hunt 14d68d98b5 MDL-70373 qtype_essay: missing border on atto input 2020-12-02 20:10:15 +00:00
Shamim Rezaie 8676a67888 MDL-69301 course: Remove custom keyboard navigation code 2020-12-02 23:11:27 +11:00
Shamim Rezaie 8af16c5709 MDL-69301 core: Enhanced WAI-ARIA support for tab elements 2020-12-02 23:08:13 +11:00
Shamim Rezaie 7f74dc1c16 MDL-69301 theme_boost: convert aria.js to es6 module 2020-12-02 23:08:13 +11:00
Jake Dallimore 5bdc07a3b6 Merge branch 'MDL-67514-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-12-02 16:24:30 +08:00
AMOS bot bccfc48b94 Automatically generated installer lang files 2020-12-02 00:07:44 +00:00
Thong Bui 95c3de0877 MDL-70324 Question: get_all_response_file_areas() not work correctly 2020-12-01 16:16:45 +07:00
AMOS bot d833fc2131 Automatically generated installer lang files 2020-12-01 00:07:51 +00:00
David Mudrák 6e04f9f294 MDL-70357 cron: Catch Throwables not just Exceptions when running tasks
Starting from PHP 7, most language errors throw Error exceptions. We
want to deal with those equally as with any other exception so we need
to catch all Throwables here.
2020-11-30 17:37:39 +01:00
Alexander Bias 7f45f9ab3e MDL-70342 block_timeline: Get rid of double quotes
This commit gets rid of double quotes around the activity name and course name
which have sneaked into block_timeline's view in MDL-65183.
2020-11-30 13:18:40 +01:00
Gareth Barnard 547a6dcdde MDL-70267 ux, theme: Course user profile inconsistent page layout. 2020-11-29 23:52:32 +00:00
AMOS bot 28fff43d2b Automatically generated installer lang files 2020-11-29 00:07:54 +00:00
Tim Hunt 7565cda9c6 MDL-54907 quiz unit tests: clean up code style in attempts_test.php 2020-11-27 18:30:19 +00:00
Tim Hunt 90fa490de7 MDL-54907 quiz: better timefinish for attempts finished asynchronously
There are serveral ways a quiz attempt can be submitted:

1. The student click the Submit and finish button. In this case,
   no problem. We record the current time as the finish time
   for the quiz attempt.

2. The student is activly working away at the quiz, and the
   count-down timer reachers zero. In this case, we also record
   the current time. Note that, if the server is under high load,
   then this could well end up being a few seconds after the
   theoretical end time, so you could have a quiz with a 30 minute
   time limit, with an attempt that lasted 30:07. However, this
   is just an accurate reflection of what happened, so should
   be recorded like this.

3. If the student is offline when the time expires, then
   (depending on the quiz settings) the attempt may be
   automatically submitted by cron, but this will happen with
   at least some delay (to prevent race conditions between cron
   and a student working online) and if cron is running slow
   on the server, it could be a lot later. Previously, this led
   to, say, a 30 minute quiz where an attempt seemed to have
   lasted 67 minutes, which confused people.

   Now, in this situation, the finsh time for the quiz attempt is
   recorded as the time when the time limit ran out. This is not
   just less confusing for teachers looking at the quiz report,
   it is also more accurate. That is the latest time at which
   students could have made any changes to their responses.
2020-11-27 18:30:19 +00:00
Tim Hunt 5f9ddb348e MDL-54907 quiz generator: defaults should match a new Moodle install 2020-11-27 18:30:18 +00:00
Tim Hunt ff8da7e008 MDL-54907 dml: Correct incorrect PHPdoc 2020-11-27 18:30:18 +00:00
Jun Pataleta a6ab91786f MDL-69422 mod_data: Export form accessibility fixes
* Set appropriate heading element IDs
* Replace usages of deprecated HTML tag acronym with abbr instead.
* Add a label for the export fields fieldset.
* Move the CSV delimiter list outside the radio group.
* Fix div under a label element and duplicate labels
for the checkboxes of the fields to be exported by showing the field
name and type together.
* Group the fields to be exported as a fieldset.
* Move unsupported fields into a separate list.
* Move export options into its own section and group the options as a
fieldset.
2020-11-27 23:24:26 +08:00
Jun Pataleta 0a43bdcc6c MDL-69422 core: Convert required and help button container to div
* A span element cannot have a div as a child.
2020-11-27 23:24:26 +08:00
Juan Leyva b1a4bd579a MDL-70080 tool_mobile: Return support contact information via WS 2020-11-27 10:19:15 +01:00
Sara Arjona 4825c139ef weekly release 3.9.3+ 2020-11-27 07:50:43 +01:00
Sara Arjona d207a2ad02 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-11-27 07:50:40 +01:00
AMOS bot ccc6b4d00b Automatically generated installer lang files 2020-11-27 06:21:32 +00:00
Tim Hunt cc3a909810 MDL-70320 permission overrides: role names were double-escaped 2020-11-26 20:37:18 +00:00
Sara Arjona c93de36436 Merge branch 'MDL-70276_39' of https://github.com/stronk7/moodle into MOODLE_39_STABLE 2020-11-26 15:04:48 +01:00
Ilya Tregubov da3ebf216e MDL-69868 h5pactivity: Prevent breaking $USER when seeing
attempt report.
2020-11-26 12:40:33 +02:00
Andrew Nicols 7c8fd0d417 Merge branch 'MDL-70242-39' of git://github.com/marinaglancy/moodle into MOODLE_39_STABLE 2020-11-26 10:49:32 +08:00
Andrew Nicols 558ace5997 Merge branch 'MDL-65852-39' of git://github.com/ilya-catalyst/moodle into MOODLE_39_STABLE 2020-11-26 10:04:23 +08:00
Eloy Lafuente (stronk7) 98254ccd1a MDL-70276 github actions: First cut, phpunit and grunt checks
First working version, supports phpunit (using build matrix):

- php72 (lowest), running mysql.
- php74 (highest), running postgres.

Also verifies that the branch has been "gruntified" and there
isn't any missing change (build js/css files).

TODO: Verify the remaining checks currently in .travis.yml, namely:
 - CITEST
 - Add caching
 - Better health-check for DB images.
 - Support from the tracker (satus badges and enable check).
 - Support from CiBoT (status and enable check).
 - Consider moving both the common setup (git, composer...)
   and the database (mysql, postgres) to own actions for
   easier tweaking.
2020-11-26 00:23:49 +01:00
cescobedo 5be02868af MDL-70327 core_h5p: Add preventredirect to the player 2020-11-25 16:30:50 +01:00
Sara Arjona a36b3ec48f Merge branch 'MDL-70248-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE 2020-11-25 16:23:07 +01:00
Sara Arjona ea4e0ae3cb Merge branch 'MDL-70265_39' of https://github.com/stronk7/moodle into MOODLE_39_STABLE 2020-11-25 15:47:01 +01:00
Ilya Tregubov 68c3eb8aa9 MDL-65852 user: Fix permission check to download course participants. 2020-11-25 11:27:31 +02:00
Tim Hunt 331b9947a3 MDL-70321 question backup: fix MDL-47178 unit tests
They were failing if you had CodeRunner installed
2020-11-24 15:29:55 +00:00
Simon Mok 4e8d58374e MDL-67460 profile: User profile link to use HTTPS 2020-11-24 20:49:35 +08:00
Tim Hunt 86669b0564 MDL-70285 completion upgrade: fix performance of the MDL-69687 code 2020-11-23 21:02:08 +00:00
David Matamoros e80e613f65 MDL-69411 core_message: Fix return structure for empty result set
Passing a timefrom higher than last message timecreated needs to
return a formatted response so it does not break ws.
2020-11-23 19:25:44 +01:00
Eloy Lafuente (stronk7) 81410615ed MDL-70265 travis: Completely remove the UPGRADE check
It was broken since ages ago, see MDL-64874, so no sense
to keep it eating minutes for nothing.
2020-11-23 13:43:15 +01:00
Adrian Greeve 1d0bd0cfdf Merge branch 'MDL-67668-39-2' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-11-23 15:36:55 +08:00
Jake Dallimore b4f40ae78e Merge branch 'MDL-70160-function-cache-39' of https://github.com/Peterburnett/moodle into MOODLE_39_STABLE 2020-11-23 15:23:10 +08:00
Andrew Nicols 556611a864 MDL-70151 assign: Fix bulk change for behat
Behat does not play well with confirmation dialogues and in some
situations it does not wait for the page to reload before starting the
next step.

This change adds a pending_js call which is only resolved if the cancel
button was pressed, otherwise it remains in-progress until the page
reloads resetting the entire state of it.
2020-11-23 11:12:15 +08:00
Andrew Nicols 7ce8e4cde2 MDL-70167 behat: Rewrite attribute check steps
This commit updates the following steps to use the
`the_attribute_of_should_be_set` step under the hood:
- the [element] [type] should be disabled
- the [element] [type] should be enabled
- the [element] [type] should be readonly
- the [element] [type] should not be readonly

This reduces unnecssary code duplication.
2020-11-23 11:03:43 +08:00
Andrew Nicols bde7f5d734 MDL-70167 behat: Boolean attributes should either exist or not 2020-11-23 11:03:42 +08:00
Andrew Nicols e08f640061 MDL-67668 behat: Update tests for inplace editable field type 2020-11-23 09:00:46 +08:00
Andrew Nicols 4f01d454a7 MDL-67668 behat: Add inplace editable field type
This commit promotes the Inplace Editable field to a first-class form
element by introducing a new partial selector for inplace editable
fields, and teaching the field manager how to recognise these, then
introducing a new field type which can handle setting values for this
field.
2020-11-23 09:00:46 +08:00
Andrew Nicols 35cc7cad05 MDL-67668 behat: Share behat_behat functionality with forms
Behat form fields are implemented in a way completely isolated from the
rest of the Behat Context system. Whereas regular step definitions have
access to execute steps, to call `find`, check for JS running, and other
related functionality, the Moodle implementation of a field type does
not have any access to this.

By moving the core functionality of behat_base to a new trait, and the
constants to a new interface, the functionality can also be used in
behat form fields in the same way as elsewhere.
2020-11-23 09:00:46 +08:00
Andrew Nicols 7b5fa603dd MDL-67668 behat: Correct js pending check
Pending checks should only run when JS is running, but some uses were
not apply this check.
2020-11-23 09:00:46 +08:00
Andrew Nicols 4e72b72720 MDL-67668 behat: Support NodeElement when fetching node in container
This is similar to change made in MDL-69136 to allow an already-fetched
NodeElement to be provided to the get_node_in_container() function and
makes it easier to be deterministic when writing steps.
2020-11-23 09:00:46 +08:00
Eloy Lafuente (stronk7) eaf24d71f2 MDL-70265 travis: Only run highest phpunit if configured via env
By default only lowest php version will be executed, and only pgsql.

This default behavior can be changed with a new variable:

MOODLE_PHP = [all]
MOODLE_DATABASE = [pgsql | mysqli | all]
2020-11-21 11:28:27 +01:00
Charles Fulton ed46bff4ae MDL-70157 dml: add support for aurora mysql 2020-11-20 15:21:22 -08:00
Eloy Lafuente (stronk7) 87bcff8c6e weekly release 3.9.3+ 2020-11-20 23:17:02 +01:00
Huong Nguyen 81c2fe97a3 MDL-70248 qtype_ddimageortext: Drop zones have UI issue in Editing form 2020-11-19 17:16:23 +07:00
Adrian Greeve 8b53812c8f Merge branch 'MOODLE_39_STABLE-MDL-67636' of https://github.com/yao9394/moodle into MOODLE_39_STABLE 2020-11-19 11:56:28 +08:00
John Yao 78aeaf17e7 MDL-67636 gradebook: Prevent exposing hidden grade in locked category 2020-11-19 14:34:43 +11:00
Adrian Greeve 662d20869a Merge branch 'MDL-56653-39' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-11-19 11:02:18 +08:00
Jun Pataleta f66c4fa42d Merge branch 'MDL-70094-39' of https://github.com/SangNguyen2601/moodle into MOODLE_39_STABLE 2020-11-19 09:35:43 +08:00
Eloy Lafuente (stronk7) 76a830b058 Merge branch 'MDL-69201-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-11-18 23:00:30 +01:00
sangnguyen 2f9582d754 MDL-70094 Question: Technical info section expands if click help icon 2020-11-18 17:30:49 +07:00
Vitaly 12d4c82f98 MDL-56653 enrol_meta: a single DB query in edit_instance_validation
The 'edit_instance_validation()' method checks for existing meta enrolment instances.
The fix replaces DB queries in a loop for each course with a single query for all courses.
Also, a new testing method 'test_edit_instance_validation_with_existing_courses()'
was added to /enrol/meta/tests/plugin_test.php to test if the new implementation
returns an error in case of trying to save the already linked courses in the 'customint1' field.
2020-11-18 15:05:31 +08:00
Andrew Nicols 3648ffdc8e Merge branch '39_MDL-68896' of git://github.com/danmarsden/moodle into MOODLE_39_STABLE 2020-11-18 10:06:41 +08:00
Eloy Lafuente (stronk7) 1194dde152 Merge branch 'MDL-70148-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-11-17 23:13:27 +01:00
Paul Holden f727dad657 MDL-67514 customfield: correct external usescategories return type. 2020-11-17 22:13:19 +00:00
Marina Glancy 985d5a5824 MDL-70242 auth_oauth2: set page context and url 2020-11-17 16:48:06 +01:00
Andrew Nicols 0210ab0005 MDL-70148 gradereport_grader: Improve reliability of keyboard usage
In some browsers the ajax grade select does not properly update the
grade after setting values. The previous solution was to press the
[enter] key, but doing this with the new key type step opens the select
box again. This is what happens when a real user presses enter on the
select.

This is the last possible field in the report, so pressing the tab key
to move to the next gradable element does not work.

The solution uses a shift-tab to move the focus away to the previous
gradale element. In this case it must also be moved to an earlier step
because the previously selected value must be checked in the Then
section of the test and if it is selected then its value cannot be
checked.
2020-11-17 15:14:43 +08:00
Andrew Nicols 99cf35e681 MDL-70148 qtype: Update qtype steps to new key interaction
Note: The ddmarker question type was previously getting the number of
keypresses wrong. This was because it was using both keyDown/keyUp, and
also keyPress. As a result each keypress was essentially happening two
times.
2020-11-17 15:14:43 +08:00
Andrew Nicols 61d0134488 MDL-70148 behat: Update steps for keyboard 2020-11-17 15:14:43 +08:00
Andrew Nicols 2369ad7737 MDL-70148 behat: Add steps to send keys without an element 2020-11-17 15:14:43 +08:00
Andrew Nicols 71dcd85182 Merge branch 'MDL-69526-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-11-17 14:55:32 +08:00
Adrian Greeve f5d19447e0 Merge branch 'MDL-50955-39' of git://github.com/peterRd/moodle into MOODLE_39_STABLE 2020-11-17 13:10:08 +08:00
Andrew Nicols b276f33850 Merge branch 'MDL-69964-39' of git://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-11-17 10:23:01 +08:00
Paul Holden b932b798f1 MDL-69964 course: toggle participant checkboxes in root element.
For a given toggleGroup, the relevant action elements are not
necessarily descendants of the same tableRoot element, on the
course participants page.
2020-11-16 17:44:26 +00:00
Andrew Nicols 14cecfa4c0 MDL-67513 core: Only move modal to body if currently attached
A previous change as part of this commitset was intended to move the
modal to the document.body, but where the modal had been destroyed it
was instead added back to the body.
2020-11-16 09:40:43 +01:00
Peter Dias 9582b85c16 MDL-50955 core: Reset lessons completion criteria if grade type is none 2020-11-16 16:37:28 +08:00
Andrew Nicols f920fdced0 Merge branch 'MDL-67513-m39' of https://github.com/NeillM/moodle into MOODLE_39_STABLE 2020-11-16 08:39:21 +08:00
Luca Bösch 53836d2035 MDL-69526 block_myoverview: custom course fields natural sorting 2020-11-13 00:56:26 +01:00
Eloy Lafuente (stronk7) ff2b655928 weekly release 3.9.3+ 2020-11-12 22:11:37 +01:00
Eloy Lafuente (stronk7) 706f6c93ae Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-11-12 22:11:34 +01:00
Neill Magill 6028dc3924 MDL-67513 forum: View conversations while fullscreen grading
Before this change when a modal was shown and an element on the page
was fullscreen the modal would be created behind it.

This change ensures that the modal will be inside an element that is
fullscreen so that it will be correctly displayed.
2020-11-12 08:34:59 +00:00
Adrian Greeve fd34a36514 Merge branch 'MDL-69453-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-11-12 12:00:36 +08:00
Andrew Nicols 27da8851f6 Merge branch 'MDL-70067-39_theme_classic' of https://github.com/alexmorrisnz/moodle into MOODLE_39_STABLE 2020-11-12 10:30:45 +08:00
Adrian Greeve 248ab7a4b3 Merge branch 'MOODLE_39_MDL-70117' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2020-11-12 09:25:39 +08:00
Eloy Lafuente (stronk7) fcf07d64c8 Merge branch 'MDL-65941-39' of https://github.com/snake/moodle into MOODLE_39_STABLE 2020-11-12 00:18:51 +01:00
Eloy Lafuente (stronk7) 897cfd7c81 Merge branch 'MDL-70023-39' of git://github.com/marinaglancy/moodle into MOODLE_39_STABLE 2020-11-11 23:57:35 +01:00
Alex Morris 193aa32b88 MDL-70067 report_insights: Replace BS3 column naming
Bootstrap 4 removed col-xs- and replaced it with col-
2020-11-12 08:57:29 +13:00
Sara Arjona 78908d7757 Merge branch 'MDL-70063-39-1' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-11-11 16:30:34 +01:00
Jun Pataleta 896c962160 Merge branch 'MDL-68257-M39' of https://github.com/ised-isde-canada/moodle into MOODLE_39_STABLE 2020-11-11 22:12:53 +08:00
Jun Pataleta 1178406516 Merge branch 'MDL-70072-39' of git://github.com/rezaies/moodle into MOODLE_39_STABLE 2020-11-11 22:09:21 +08:00
Mihail Geshoski 409f92b75d MDL-70063 block_tag_youtube: Add behat tests 2020-11-11 21:49:38 +08:00
Mihail Geshoski 6ea0b003d7 MDL-70063 block_tag_youtube: Fix category config in existing instances
Upgrade step that fixes the category configuration of existing
tag_youtube block instances.
2020-11-11 21:49:38 +08:00
Mihail Geshoski 918b60d700 MDL-70063 block_tag_youtube: Update category config to use category ID
In YouTube Data API v3, the API call to fetch the videos related to a
certain category expects the category ID to be passed to the
videoCategoryId parameter, instead of the category name. Therefore, the
category config should store the category ID.
2020-11-11 21:49:37 +08:00
Bas Brands b997786180 MDL-69453 core_form: improve form UI icons and alignment 2020-11-11 14:05:00 +01:00
Sara Arjona 3e8447fe9a Merge branch 'MDL-70141-m39' of https://github.com/sammarshallou/moodle into MOODLE_39_STABLE 2020-11-11 08:39:37 +01:00
Michael Aherne 28a1f0943d MDL-65941 cache: Prevent cache config failure on redis problems. 2020-11-11 14:50:43 +08:00
Andrew Nicols 7a2d0fb5dc Merge branch 'MDL-70126-39' of git://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-11-11 10:26:14 +08:00
Andrew Nicols 28de3d7db9 Merge branch 'MDL-70065_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-11-11 10:10:45 +08:00
AMOS bot 9fa04e3f2e Automatically generated installer lang files 2020-11-11 00:07:45 +00:00
Mikhail Golenkov 1d41237ae8 MDL-70117 dataformat_pdf: Fix content overflow when headers are involved 2020-11-11 10:53:20 +11:00
Sara Arjona b0a9faf1c6 Merge branch 'MDL-70106-icon-cache-39' of https://github.com/Peterburnett/moodle into MOODLE_39_STABLE 2020-11-10 16:53:46 +01:00
Peter Burnett e9961085eb MDL-70160 cache: plugin_functions checks for function_exists() 2020-11-10 16:04:49 +10:00
Jun Pataleta 766376261a Merge branch 'MDL-69930-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE
# Conflicts:
#	question/type/ddimageortext/amd/build/question.min.js
#	question/type/ddimageortext/amd/build/question.min.js.map
#	question/type/ddimageortext/amd/src/question.js
2020-11-10 14:03:19 +08:00
Jun Pataleta 8e2e459daa Merge branch 'MDL-68349-39' of git://github.com/marinaglancy/moodle into MOODLE_39_STABLE 2020-11-10 10:14:28 +08:00
Jake Dallimore fedd703ce1 Merge branch 'MDL-69841-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE 2020-11-10 09:33:47 +08:00
Víctor Déniz a1216eb05b Merge branch 'MDL-69955-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE 2020-11-09 21:47:45 +00:00
Paul Holden e49e58a924 MDL-69201 core: consistent table primary sort column/order. 2020-11-09 19:45:28 +00:00
Paul Holden 97a03ba74d MDL-70126 tag: correct thrown exception class name. 2020-11-09 19:43:31 +00:00
Neill Magill ba43374d96 MDL-67513 forum: Test that discussions can be viewed while grading 2020-11-09 14:26:21 +00:00
AMOS bot 09d078c3b8 Automatically generated installer lang files 2020-11-09 00:07:54 +00:00
Eloy Lafuente (stronk7) a8e089a8c8 Moodle release 3.9.3 2020-11-07 16:48:07 +01:00
AMOS bot 3e8043f3f4 Automatically generated installer lang files 2020-11-07 00:07:48 +00:00
Eloy Lafuente (stronk7) 70f695d068 weekly release 3.9.2+ 2020-11-06 22:55:50 +01:00
Eloy Lafuente (stronk7) e83cad80b1 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-11-06 22:55:47 +01:00
Víctor Déniz d727c1eafd Merge branch 'MDL-70137-39-2' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-11-06 19:17:44 +00:00
Andrew Nicols 463b232453 MDL-70137 cache: Write config to temp file and move into place 2020-11-06 19:17:43 +00:00
Andrew Nicols 02a8be1f80 MDL-70137 cache: Use sensible default when reading MUC config
When we read the MUC configuration, a file which exists but is empty
will not error, but will cause all configuration to be empty.

We already perform an {{is_array()}} check on the {{$configuration}}
variable, but the default value for {{$configuration}} is an empty
array. In the case where the file exists, but is empty, no errors occur
when the file is loaded, and the initial {{$configuration}} value is
not overwritten, leading to the file being replaced with an empty copy.
2020-11-06 19:17:34 +00:00
Eloy Lafuente (stronk7) 7bc714ac09 Merge branch 'MDL-70139-39' of git://github.com/sarjona/moodle into MOODLE_39_STABLE 2020-11-06 19:24:40 +01:00
sam marshall 3accc543ec MDL-70141 core_block: Web service set $PAGE url to avoid warnings 2020-11-06 17:40:02 +00:00
Sara Arjona 481c57cabe MDL-70139 core_badges: fix invalid request when sending to backpack
Having mixed $data in badge exporters is causing some issues.
As all these exporters are using $data as an object, $data can be
converted to object in the constructor, to avoid errors and get
the expected behaviour always.
2020-11-06 16:21:34 +01:00
Shamim Rezaie c0256a7351 MDL-70072 core: Fix always displaying date in Gregorian 2020-11-06 19:23:22 +11:00
AMOS bot f8287cb170 Automatically generated installer lang files 2020-11-06 00:09:55 +00:00
Eloy Lafuente (stronk7) 621cd70b4c weekly release 3.9.2+ 2020-11-05 12:16:29 +01:00
Marina Glancy 7e2acbfb55 MDL-70023 core_course: improve performance of recently accessed courses 2020-11-05 09:54:54 +01:00
Jun Pataleta c87ccd3111 Merge branch 'MDL-70075-39-2' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-11-05 12:45:24 +08:00
Andrew Nicols 06be826b2e Merge branch 'MDL-70066-39' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-11-05 10:09:48 +08:00
Simey Lameze 06a4390060 MDL-70066 badges: change usages of array_key_exists to isset 2020-11-05 10:06:39 +08:00
Andrew Nicols 126cbbff7c MDL-70075 core: Autocomplete selection should always have an active item
Ensure that there is always one active element in the list of selected
autocomplete elements.

Without this we have issues beacuse clicking on the link makes the first
one active if one is not already active, and this turns a click event
into a drag event, which means that it is not deleted.
2020-11-05 09:05:40 +08:00
Sara Arjona f252b08433 Merge branch 'MDL-70114-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-11-04 20:15:21 +01:00
Víctor Déniz fae048b402 Merge branch 'MDL-68749-39-2' of git://github.com/mickhawkins/moodle into MOODLE_39_STABLE 2020-11-04 15:24:23 +00:00
Sara Arjona 0408008fbe Merge branch 'MDL-70119-39' of git://github.com/ferranrecio/moodle into MOODLE_39_STABLE 2020-11-04 15:20:03 +01:00
Bas Brands 0ff5242a3c MDL-70114 mod_data: add border for to textarea 2020-11-04 13:30:19 +00:00
Ferran Recio 2488fe37ca MDL-70119 core_badges: fix tab names 2020-11-04 12:57:24 +01:00
Andrew Nicols 4edad07619 MDL-70075 core: Do not return a value in an event handler
Returning a value of `false` in an event handler has the effect of
calling event.preventDefault() and event.stopPropagation().

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

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

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

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

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

There should be no functional change with this patch, except to support
Firefox fully.
2020-11-04 15:09:35 +08:00
Peter Burnett d8bfd5b747 MDL-70106 cache: Set icon localstorage cache to use theme localisation 2020-11-04 13:36:14 +10:00
Huong Nguyen 0d9c49d8d6 MDL-69955 qtype_ddimageortext: drop zone disappear in special case 2020-11-04 09:53:23 +07:00
Jake Dallimore 4d9ffaae34 Merge branch 'MOODLE_39_MDL-70093' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2020-11-04 09:00:49 +08:00
Mihail Geshoski 21cfc35074 MDL-67837 backup: Add unit tests 2020-11-03 12:27:34 +01:00
Mihail Geshoski 5d0b569ba1 MDL-67837 backup: Verify caps before unenrolling users on course restore 2020-11-03 12:27:34 +01:00
andreasschenkel fd7db38d8b MDL-69844 user: Fix no email in download_participants_table
Only include eMail in download_participants_table 
if selected in showuseridentity 
($identityfieldsselect)
2020-11-03 12:27:34 +01:00
Juan Leyva 2f9f0b0fcc MDL-67015 mod_data: Prevent users adding entries to other groups 2020-11-03 12:27:34 +01:00
Amaia Anabitarte 14aaba1b72 MDL-69046 core_contentbank: Escape quotes when showing name 2020-11-03 12:27:34 +01:00
Ferran Recio 629657363d MDL-69378 tool_uploadcourse: fix enrolment methods uploads 2020-11-03 12:27:34 +01:00
Peter Dias 498c54d1de MDL-56310 restore: Confirm user has permission to change capabilities 2020-11-03 12:27:34 +01:00
Eloy Lafuente (stronk7) a3f72b3972 weekly release 3.9.2+ 2020-11-03 12:21:21 +01:00
Michael Hawkins 098f09b638 MDL-68749 theme: Fix bootstrap toggle switches in RTL layout
Co-authored-by: Bas Brands <bas@moodle.com>
2020-11-03 15:24:48 +08:00
Eloy Lafuente (stronk7) 99732c4c3b Merge branch 'MDL-70081-39' of git://github.com/jleyva/moodle into MOODLE_39_STABLE 2020-11-03 01:26:11 +01:00
Sara Arjona 905d3939f5 Merge branch 'MDL-69973_39' of https://github.com/stronk7/moodle into MOODLE_39_STABLE 2020-11-02 15:45:09 +01:00
Mikhail Golenkov 051cad238b MDL-70093 dataformat_pdf: Fix row height calculation with high cells 2020-11-02 22:27:08 +11:00
Alexander 6a4bf785cc MDL-70067 theme_classic: Use col-12 as col-xs-12 was removed in BS4 2020-11-02 09:07:05 +13:00
Juan Leyva 223f7cc0b4 MDL-70081 airnotifier: Add missing device type in token registration 2020-10-31 13:08:05 +01:00
Eloy Lafuente (stronk7) 287ed73429 MDL-69973 xmldb: Ensure all reports use fresh metadata (not cached) 2020-10-30 19:27:18 +01:00
Eloy Lafuente (stronk7) db1368926a MDL-69973 xmldb: Fix problem with MariaDB >= 10.2.7 metadata defaults
With MariaDB 10.2.7 the driver was incorrectly returning '' (empty
string) as default for all the columns having null (meaning, no
default).

Also, cover the case in unit tests, it seems that we were already
testing other defaults but not the null case.
2020-10-30 19:27:18 +01:00
Marina Glancy ec19837b79 MDL-68349 auth_db: user_created event should be triggered later 2020-10-30 14:18:41 +01:00
Eloy Lafuente (stronk7) 3b0d958065 weekly release 3.9.2+ 2020-10-30 13:49:12 +01:00
Eloy Lafuente (stronk7) 6722a6b105 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-10-30 13:49:09 +01:00
Jun Pataleta 920b4dd6ab Merge branch 'MDL-68167-39' of git://github.com/rezaies/moodle into MOODLE_39_STABLE 2020-10-30 13:16:48 +08:00
Shamim Rezaie 898bdfdd67 MDL-68167 lib: autocomplete focos should not be removed on blur
See https://www.w3.org/TR/wai-aria-practices-1.1/examples/listbox/listbox-rearrangeable.html
2020-10-30 16:11:16 +11:00
Shamim Rezaie ed7485277e MDL-68167 lib: Do not set aria-expanded if it should not be set 2020-10-30 16:11:16 +11:00
Shamim Rezaie eb238722da MDL-68167 user: Fix missing label for participants filter input fields 2020-10-30 16:11:16 +11:00
Shamim Rezaie da1f204a0a MDL-68167 lib: Clear single-select autocomplete elements with keyboard
Following MDL-57680, it should be possible to clear the selected option
using keyboard as well.
2020-10-30 16:11:16 +11:00
Shamim Rezaie 5dd385d522 MDL-68167 user: Fix a hardcoded string to be read from lang pack 2020-10-30 16:11:16 +11:00
Shamim Rezaie dca6513b8a MDL-68167 lib: Fix label for autocomplete selection/suggestion box
The content of the autocomplete selection div is purged by javascript
so we have to move its label outside of it. aria-labeledby is the way
to go.

Each time the suggestion box is expanded, autocomplete js renders the
autocomplete suggestions template. So the label cannot be outside the
suggestions ul.
2020-10-30 16:11:08 +11:00
Shamim Rezaie 6484e89188 MDL-68167 user: filter elements should listen to accessibleChange event 2020-10-30 14:58:54 +11:00
Shamim Rezaie 9312e7389a MDL-68167 lib: The accessibleChange custom event now supports bubbling
The change event bubbles so the accessibleChange shoud bubble as well.
2020-10-30 14:58:54 +11:00
Shamim Rezaie 0218859c3e MDL-68167 theme_boost: make focus outline accessible for autocompletes 2020-10-30 14:58:53 +11:00
Shamim Rezaie 18702b5869 MDL-68167 lib: Autocomplete selection to use listbox aria role
The aria-selected state cannot be used for the listitem role. The
autocomplete widget highly uses the aria-selected state internally.
2020-10-30 14:56:39 +11:00
Shamim Rezaie d0ab1d1540 MDL-68167 user: Improve keyboard navigation on autocomplete fields 2020-10-30 14:56:39 +11:00
Shamim Rezaie 7d25143979 Merge branch 'MDL-69390-39' of git://github.com/bmbrands/moodle into MDL-69390-39-test 2020-10-30 14:56:03 +11:00
Andrew Nicols a067cc5ada Merge branch 'MDL-69156_39' of https://github.com/ffhs/moodle into MOODLE_39_STABLE 2020-10-30 11:52:35 +08:00
Huong Nguyen ea68407895 MDL-69841 Quiz: Review options 'Help' icons do not work correctly 2020-10-30 10:28:59 +07:00
AMOS bot 03f5e32712 Automatically generated installer lang files 2020-10-30 00:09:48 +00:00
Víctor Déniz c0b0649582 Merge branch 'MDL-70032-39-2' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-10-29 22:24:21 +00:00
Tim Hunt 72cd24d3c9 MDL-70065 quiz: fix paging when adding questions from the bank 2020-10-29 20:29:58 +00:00
Paul Holden d16aa74359 MDL-69156 backup: correct behaviour of course copy idnumber field.
When a given user doesn't have the capability to change the idnumber
field during course copy, freeze the field value.
2020-10-29 14:10:09 +01:00
Adrian Perez 7e52e95d8d MDL-69156 course_copy: set defaults for idnumber when not permitted 2020-10-29 13:52:48 +01:00
Jun Pataleta 42f3862b91 MDL-70032 qtype_multichoice: Use custom partial named selector
* With the removal of the label element, Behat now has to click on the
answer text. In order to achieve this, the custom partial named selector
"qtype_multichoice > Answer" was now added and have replaced the
instances where the label of the answer's checkbox/radio button is
being clicked.
2020-10-29 16:22:08 +08:00
Jun Pataleta 556648db0b MDL-70032 qtype_multichoice: Fix answer labelling
* Discard the use of the label element in order to be able to render
multiple choice answers as they are and have these act as the radio
button/checkbox' label through the aria-labelledby attribute.
* New JS module qtype_multichoice/answers that listens for click events
on the answer text container and selects the appropriate answer radio
button/checkbox.
2020-10-29 16:22:08 +08:00
Andrew Nicols 6026aa7b3c Merge branch 'MDL-68722-39' of https://github.com/matt-catalyst/moodle into MOODLE_39_STABLE 2020-10-29 14:03:29 +08:00
Jake Dallimore 8e5782b848 Merge branch 'MDL-69716-39' of git://github.com/aanabit/moodle into MOODLE_39_STABLE 2020-10-29 12:40:23 +08:00
Jake Dallimore f38e17f16f Merge branch 'MDL-70041-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-10-29 11:49:40 +08:00
Adrian Greeve 465cc9e91a Merge branch 'm39_MDL-70042_Progress_Bar_Upgrade_Message_Popup' of https://github.com/scara/moodle into MOODLE_39_STABLE 2020-10-29 08:32:16 +08:00
Matteo Scaramuccia faa76ee29a MDL-70042 message_popup: Trivial savepoint comment cleanup 2020-10-28 23:03:34 +01:00
Matteo Scaramuccia d6491a67c8 MDL-70042 message_popup: progress bar on upgrade only when necessary 2020-10-28 23:03:26 +01:00
Jun Pataleta 27db5c5024 Merge branch 'MDL-69390-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-10-28 22:44:02 +08:00
Bas Brands e6b274a542 MDL-69390 theme_boost: dropdown menu accessibility
- display a dot before the active element
- use the active colour for the hover colour
2020-10-28 14:10:45 +01:00
Jun Pataleta 6f317a983e Merge branch 'MDL-69815-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-10-28 14:19:09 +08:00
Andrew Nicols a5293c4ed8 Merge branch 'MDL-70004-39' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-10-28 13:14:23 +08:00
Jake Dallimore 66e77f8173 Merge branch 'MDL-64723-39' of git://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-10-28 12:12:52 +08:00
Mihail Geshoski 4ba58ac02f MDL-70041 filepicker: Make sure the user has a recently used license 2020-10-28 12:06:43 +08:00
Jake Dallimore 21f5c148fc Merge branch 'MDL-65792-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-10-28 12:00:34 +08:00
Andrew Nicols 2e026689c6 MDL-69815 core: Bump Node to v14.15.0 (LTS/Fermium) 2020-10-28 09:34:31 +08:00
Eloy Lafuente (stronk7) 3a718d620e Merge branch 'MDL-69998-39-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-10-28 00:42:25 +01:00
Eloy Lafuente (stronk7) beff06190a weekly release 3.9.2+ 2020-10-27 23:47:40 +01:00
David Mudrák 975081c367 MDL-69998 lang: Fix reworded strings in Behat test scenarios 2020-10-27 11:29:12 +01:00
Helen Foster 9417cedd78 MDL-69998 lang: Import fixed English strings (en_fix) 2020-10-27 11:29:12 +01:00
Bas Brands 19343c7bd1 MDL-65792 mod_forum: show release time on timed posts 2020-10-27 08:41:38 +01:00
Jun Pataleta 64dd473559 MDL-70004 qtype_multichoice: Set appropriate clear my choice role 2020-10-27 09:57:48 +08:00
Paul Holden 9e4a19af6c MDL-64723 tool_mobile: workaround for invalid certificate parsing.
This is to account for specific server configuration that are affected
by one of the following issues, which results in certificate signature
algorithms being incorrectly parsed:

 * https://bugs.php.net/bug.php?id=77548
 * https://github.com/curl/curl/issues/3706
2020-10-26 23:06:14 +00:00
Matt Clarkson eeba9c1dc5 MDL-68722 atto_equation: fix for form elements with special characters
Element id's containing characters such as ':' would break the tab
selector in bootstrap.

This specifically affects the essay question type.
2020-10-27 11:08:47 +13:00
Eloy Lafuente (stronk7) 55a465c445 Merge branch 'MDL-69993-39' of git://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-10-26 10:43:02 +01:00
Andrew Nicols d1d52a3399 Merge branch 'MDL-69995-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-10-26 16:01:07 +08:00
Huong Nguyen ad7b38f3ff MDL-69930 qtype_ddimageortext: Duplication items in drag-onto-image question 2020-10-25 20:15:27 +07:00
Luca Bösch a22b74872c MDL-69995 backup: padding before activity icons. 2020-10-25 02:04:52 +02:00
Amaia Anabitarte 1af998d32c MDL-69716 mod_quiz: No timestamp for in progress attempts 2020-10-23 16:03:03 +02:00
Eloy Lafuente (stronk7) 4d9ab4ca48 weekly release 3.9.2+ 2020-10-23 14:40:50 +02:00
Eloy Lafuente (stronk7) 55189f02ee Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-10-23 14:40:45 +02:00
Paul Holden 115f703440 MDL-69993 output: correct navigation node type for user reports. 2020-10-23 08:25:47 +01:00
Adrian Greeve 5cd7b5cad0 Merge branch 'MDL-67650-forced-checkbox-textarea-MOODLE_39_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_39_STABLE 2020-10-23 09:01:07 +08:00
Eloy Lafuente (stronk7) fb81664dc3 Merge branch 'MDL-69729-39' of git://github.com/sarjona/moodle into MOODLE_39_STABLE 2020-10-22 19:05:22 +02:00
Víctor Déniz 8cbc470f2a Merge branch 'MDL-68664-39' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-10-22 12:25:43 +01:00
Sara Arjona 1bc92d37f2 Merge branch 'MDL-69553-m39' of https://github.com/NeillM/moodle into MOODLE_39_STABLE 2020-10-22 08:56:19 +02:00
Brendan Heywood 348e338a21 MDL-67650 admin: Consistently show forced config settings 2020-10-22 13:17:17 +11:00
Jake Dallimore bf854f5f24 Merge branch 'MDL-68438_39' of https://github.com/t-schroeder/moodle into MOODLE_39_STABLE 2020-10-22 09:31:02 +08:00
Jun Pataleta b861165753 Merge branch 'MDL-69657-39' of git://github.com/merrill-oakland/moodle into MOODLE_39_STABLE 2020-10-22 09:24:08 +08:00
Adrian Greeve 3c2208cc24 Merge branch 'MDL-69788-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-10-22 09:06:53 +08:00
AMOS bot 2d1fcf6cce Automatically generated installer lang files 2020-10-22 00:08:01 +00:00
Eloy Lafuente (stronk7) 2f502066cb Merge branch 'MDL-66392-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-10-21 19:48:20 +02:00
Sara Arjona 41cd0c4d3a Merge branch 'm39_MDL-68536_Notice_Undefined_Property_CFG_branch' of https://github.com/scara/moodle into MOODLE_39_STABLE 2020-10-21 18:33:15 +02:00
Paul Holden 0efc7095e3 MDL-66392 analytics: make model output directory default to empty.
Falling back to path within $CFG->dataroot/models.
2020-10-21 17:32:29 +01:00
Víctor Déniz 6178388d94 Merge branch 'MDL-69392-39' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-10-21 16:26:35 +01:00
Tim Schroeder f0e9fa2a7b MDL-68438 message: fixed email format change with messaging disabled 2020-10-21 12:47:53 +02:00
Paul Holden c651779095 MDL-69788 admin: validate language menu configuration. 2020-10-21 11:24:18 +01:00
Jun Pataleta ce5efbc1da Merge branch 'MDL-37226-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-10-21 17:46:38 +08:00
Neill Magill e9506c638b MDL-69553 output: Handle pre-loading multiline string defines
Before this patch strings that were declared over multiple lines in
a template would not be parsed correctly.

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

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

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

would have been been parsed to get_string('', 'core')
2020-10-21 10:08:23 +01:00
Neill Magill bb3f9ee492 MDL-69553 output: Unit tests for loading multiline string defines 2020-10-21 10:08:22 +01:00
Jun Pataleta 14017f40b9 Merge branch 'MDL-69945-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-10-21 16:03:04 +08:00
Jun Pataleta 413736095b MDL-69392 question: Fix Try again button styling 2020-10-21 14:57:58 +08:00
Jun Pataleta f78101f638 MDL-69392 theme_boost: Improve question colour contrast
* Lighten info container.
* Fix colour contrast for the question container by
  - Lightening the background a bit
  - Darkening the text colour a bit
  - Making sure the link colour has good colour contrast against the
  question text.
* Fix colour contrast for the comments container by
  - Lightening the text colour a bit
  - Darkening the link colour a bit for better colour contrast against
  the feedback text.
2020-10-21 14:57:57 +08:00
Jun Pataleta 105e40d377 MDL-69392 theme_classic: Darken red, blue and green colours
The current red, blue, and green colours achieve the minimum colour
contrast against a white background. However, when they're against
coloured background, text with these colours will easily fail the
4.5:1 contrast ratio requirement for Level AA.
The updated colours now have the following contrast ratio against a
white background:
* Blue  - #0f6fc5 (5.12:1, from 4.58:1)
* Green - #357a32 (5.27:1, from 4.63:1)
* Red   - #ca3120 (5.29:1, from 4.59:1)
2020-10-21 14:57:57 +08:00
Jun Pataleta ce2f6179cd MDL-69392 theme_boost: Darken red, blue and green colours
The current red, blue, and green colours achieve the minimum colour
contrast against a white background. However, when they're against
coloured background, text with these colours will easily fail the
4.5:1 contrast ratio requirement for Level AA.
The updated colours now have the following contrast ratio against a
white background:
* Blue  - #0f6fc5 (5.12:1, from 4.58:1)
* Green - #357a32 (5.27:1, from 4.63:1)
* Red   - #ca3120 (5.29:1, from 4.59:1)
2020-10-21 14:57:57 +08:00
Adrian Greeve 47ff67ec29 \Merge branch 'MDL-69807-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-10-21 14:22:19 +08:00
Adrian Greeve 3fb1660734 Merge branch 'MDL-68766-M39' of https://github.com/ised-isde-canada/moodle into MOODLE_39_STABLE 2020-10-21 12:49:18 +08:00
Jake Dallimore 6e7c392d84 Merge branch 'MDL-68983-recent-session-lock-ro-MOODLE_39_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_39_STABLE 2020-10-21 12:46:11 +08:00
Jake Dallimore 806e6bec59 Merge branch 'MDL-69902-39' of https://github.com/marinaglancy/moodle into MOODLE_39_STABLE 2020-10-21 10:57:53 +08:00
Jake Dallimore 8d7fe960a0 Merge branch 'MDL-69751-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-10-21 10:04:31 +08:00
Eloy Lafuente (stronk7) 8d1cbe3a35 weekly release 3.9.2+ 2020-10-21 00:50:42 +02:00
Sara Arjona 197ec7e822 MDL-69729 h5p: move temporary editor files to draft area
This is a backport of MDL-68909
2020-10-20 09:59:09 +02:00
Sara Arjona fbab65f86b MDL-69729 h5p: upgrade step to remove files in editor filearea
As temporary editor files have been moved from core_h5p/editor to
user/draft, they can be removed (to clean unused DB entries).

This is a backport of MDL-68909
2020-10-20 09:18:16 +02:00
Adrian Greeve cd054d77f1 MDL-68284 gradebook: Fix use of get_recordset in upgrade code. 2020-10-20 14:15:20 +08:00
Jake Dallimore 6168569323 Merge branch 'MDL-67695-MOODLE_39_STABLE_get_lti_proxies' of https://github.com/andrewmadden/moodle into MOODLE_39_STABLE 2020-10-20 11:09:11 +08:00
Mihail Geshoski 5da2fa002e MDL-69751 core: Restore deleted guest user and add missing context
This upgrade step fixes the cases where the current guest user is
labelled as 'deleted' and the related user context is missing.
2020-10-20 08:43:52 +08:00
Adrian Greeve 4b137eb20c Merge branch 'MOODLE_39_STABLE-MDL-68284' of https://github.com/yao9394/moodle into MOODLE_39_STABLE 2020-10-20 08:41:09 +08:00
Mihail Geshoski 34ffdc2c81 MDL-69751 course: Handle missing guest user context
Makes sure the guest user context exists when fetching
the recommended modules. If the context does not exist
an exception is being thrown describing the problem.
2020-10-20 08:39:24 +08:00
Simey Lameze 83d478ce93 MDL-68664 theme: remove right margin from form-inline class 2020-10-20 08:32:57 +08:00
Andrew Nicols 565bc965b1 Merge branch 'MDL-69687-m39' of https://github.com/sammarshallou/moodle into MOODLE_39_STABLE 2020-10-20 08:02:46 +08:00
Jake Dallimore e2cdcc563d Merge branch 'MDL-69726_39' of git://github.com/aolley/moodle into MOODLE_39_STABLE 2020-10-20 07:46:23 +08:00
Paul Holden ae61985191 MDL-69807 blocks: remove redundant sesskey loading edit/delete page. 2020-10-19 22:40:43 +01:00
Eloy Lafuente (stronk7) 2b169e9b31 Merge branch 'MDL-69906-39-searchsimpledb' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-10-19 22:56:40 +02:00
Eloy Lafuente (stronk7) ccbd35915c Merge branch 'MDL-57756-text-customparams-39' of https://github.com/cengage/moodle into MOODLE_39_STABLE 2020-10-19 22:32:10 +02:00
Sara Arjona 114d1a051e Merge branch 'MDL-69897-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-10-19 18:15:07 +02:00
Sara Arjona 856c31cc32 Merge branch 'MDL-69900-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-10-19 13:42:13 +02:00
sam marshall 25049f4f19 MDL-69687 Course: remove_course_contents orphaned completion data
The remove_course_contents function did not delete data from
course_module_completion table in most cases, resulting in large
quantities of orphaned data.
2020-10-19 10:21:12 +01:00
Sara Arjona 00a46671fa Merge branch 'MOODLE_39_MDL-69791' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2020-10-19 10:08:08 +02:00
Sara Arjona d008aa7c99 Merge branch 'MDL-69736-39' of git://github.com/ferranrecio/moodle into MOODLE_39_STABLE 2020-10-19 09:04:06 +02:00
Sagar Ghimire 2d462ee8bd MDL-68284 gradebook: Prevent exposing hidden quiz grade item 2020-10-19 16:22:37 +11:00
Andrew Nicols 3f50f83dc1 Merge branch 'MDL-69687-m39' of https://github.com/sammarshallou/moodle into MOODLE_39_STABLE 2020-10-19 13:20:25 +08:00
Andrew Madden 41121d705f MDL-67695 mod_lti: Use correct return structure for get_tool_proxies.
* Use tool_proxy_return_structure for each proxy.
* Added tests for getting all proxies and orphaned proxies.
2020-10-19 15:16:44 +11:00
sam marshall cc2faa2c90 MDL-69687 Course: Improve removal of completion data on MySQL 2020-10-16 18:23:41 +01:00
sam marshall ae4f9b31f7 MDL-69687 DB: Add API for deleting data based on subquery
The new API works on normal databases (by deleting data based on the
subquery) and also on MySQL (by deleting the data using a weird join
on the subquery).
2020-10-16 18:23:41 +01:00
Luca Bösch 01f3495a46 MDL-37226 assign: align select all header checkbox 2020-10-16 16:08:48 +02:00
Paul Holden c4c328565d MDL-69788 lang: fallback to all translations if misconfigured.
If given translation list contains only invalid entries, fallback
to returning the complete list of available language translations.
2020-10-16 14:38:07 +01:00
Luca Bösch 7961a36b76 MDL-69945 core_calendar: let circles appear as circles 2020-10-16 14:15:56 +02:00
Sara Arjona eda7eb44b3 weekly release 3.9.2+ 2020-10-16 13:18:43 +02:00
Jake Dallimore 6589c3cdd6 Merge branch 'MOODLE_39_MDL-47178' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2020-10-16 11:52:58 +08:00
Jun Pataleta eeb76ddd3f Merge branch 'MDL-69266-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE 2020-10-16 10:09:30 +08:00
Huong Nguyen 14ea69c07c MDL-69266 qtype_ddwtos: 'unlimited' options fail in 3.9 2020-10-15 20:07:02 +07:00
Eloy Lafuente (stronk7) 9f0400b74d Merge branch 'MDL-69813-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-10-14 22:47:23 +02:00
Eloy Lafuente (stronk7) f68a64d50b MDL-68070 messaging: Ensure that error is shown on first messages
Before there is a conversation, messages between users are sent
using core_message_send_instant_messages instead of
core_message_send_messages_to_conversation.

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

This just adds the same error than already existing conversations do,
but returning it as warning, for BC, JS will show it.
2020-10-14 18:57:43 +02:00
Eloy Lafuente (stronk7) d82acd309b MDL-68070 messaging: Amend lang string to be clearer for any user.
Credit goes to Helen Foster for the improvement, thanks!
2020-10-14 16:54:48 +02:00
Víctor Déniz 22f34e807d Merge branch 'MDL-68900-m39' of https://github.com/sumitnegi933/moodle into MOODLE_39_STABLE 2020-10-14 12:22:49 +01:00
Jake Dallimore 31d3a656d6 Merge branch 'MOODLE_39_MDL-69848' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2020-10-14 09:43:03 +08:00
Eloy Lafuente (stronk7) 3d41104fab Merge branch 'MDL-68070-39_messaging_fix' of https://github.com/beenet-dev/moodle into MOODLE_39_STABLE 2020-10-13 23:41:03 +02:00
Sara Arjona 523f308a9a weekly release 3.9.2+ 2020-10-13 13:24:20 +02:00
Sara Arjona e4d03a9257 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-10-13 13:24:17 +02:00
Brendan Heywood cedf141cc3 MDL-68983 cache: Fix bug with readonly session combined with lock debug 2020-10-13 14:53:11 +11:00
Andrew Nicols b4d51d67a9 Merge branch 'MDL-67654-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-10-13 08:01:08 +08:00
Jenkins Automation 9763c99f87 MDL-69726 calendar: fix raw event fetcher under postgres
Without this, there's a code path that under the right circumstances is hit and
results in a query with `FROM (mdl_event) ev` in it - which is not valid syntax
under postgres.
2020-10-13 09:35:03 +10:30
Paul Holden 56be61d4f6 MDL-67654 mod_forum: formchangechecker for discussion inline replies. 2020-10-12 23:32:38 +01:00
Simon Mok 6de6fe9590 MDL-68070 messaging: Fix error when personal notification is disabled 2020-10-12 21:43:48 +08:00
Michael Milette 754440d796 MDL-68766 auth: Login form: 'Log in using...' should be h3, not h6 2020-10-12 09:32:25 -04:00
Michael Milette 1ddaad70ad MDL-68257 book: Fix display of table of contents in IE11. 2020-10-12 09:21:28 -04:00
Adrian Greeve c954e18a99 Merge branch 'MOODLE_39_MDL-69818' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2020-10-12 14:47:52 +08:00
Jake Dallimore e0a366fa0a Merge branch 'MDL-68292-admin-sesskey-MOODLE_39_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_39_STABLE 2020-10-12 14:37:40 +08:00
Brendan Heywood 2e5daf9108 MDL-68292 core: Remove sesskey leakage on module pages 2020-10-12 17:11:48 +11:00
Adrian Greeve 5281e10e77 Merge branch 'MDL-69649-39' of git://github.com/rezaies/moodle into MOODLE_39_STABLE 2020-10-12 10:16:15 +08:00
Jake Dallimore aae7a2b206 Merge branch 'MDL-69910-calendar-protectusername-MOODLE_39_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_39_STABLE 2020-10-12 10:06:06 +08:00
AMOS bot 419ff44b78 Automatically generated installer lang files 2020-10-11 00:08:29 +00:00
Brendan Heywood c4a8787574 MDL-69910 calendar: Fix export exception when both params are sent 2020-10-11 09:20:21 +11:00
David Mudrák 834a1d64c5 MDL-69906 admin: Display Setup search engine as link only if it is valid
We use auto-generated admin section name here so we need to check that
the target section actually exists.
2020-10-09 14:04:55 +02:00
Sara Arjona 496e6ac804 weekly release 3.9.2+ 2020-10-09 11:11:56 +02:00
Sara Arjona 7eb0f97113 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-10-09 11:11:53 +02:00
Marina Glancy 9f1df0f2e4 MDL-69902 core_search: fix error in the custom fields indexing 2020-10-09 08:47:28 +02:00
Adrian Greeve 8fc60dd25d Merge branch 'MDL-68384-fix-spec-violations-39' of https://github.com/cengage/moodle into MOODLE_39_STABLE 2020-10-09 12:04:22 +08:00
Jun Pataleta 558a30dc7d Merge branch 'MDL-69257-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-10-09 11:12:08 +08:00
Mihail Geshoski 9773b4b079 MDL-69257 core_h5p: Move $maxsize outside the foreach loop
There is no reason to repeatedly obtain the maximum size for uploading
files as a part of foreach loop.
2020-10-09 10:36:11 +08:00
Martin Gauk d686ee8faa MDL-69257 H5P: Check size of uploaded files and virus scan 2020-10-09 10:36:11 +08:00
Stephen Bourget 5cb1cf7695 MDL-69900 core_backup: Allow IMSCC v1.0 restore to finish 2020-10-09 09:06:37 +08:00
Paul Holden 465f3b477b MDL-69897 repository: add heading to delete file modal. 2020-10-08 20:29:51 +01:00
Amaia Anabitarte ad00d91851 MDL-69712 core_h5p: Remove 'whitelist' key uses 2020-10-08 16:27:57 +02:00
Sara Arjona 1eed96dec7 Merge branch 'MDL-64657-39' of git://github.com/jleyva/moodle into MOODLE_39_STABLE 2020-10-08 14:15:50 +02:00
Sumit Negi 2e21c78006 MDL-68900 mod_forum: permission check for user who is viewing timed post
Pass current user object to post builder as argument, so that the permission to view timed post
will check with current user, who is viewing the posts instead of user who made that post.
2020-10-08 12:45:33 +05:30
Adrian Greeve aba9644393 Merge branch 'MDL-69805-39' of https://github.com/dravek/moodle into MOODLE_39_STABLE 2020-10-08 14:59:28 +08:00
Adrian Greeve 4aa6b89ead Merge branch 'MDL-69798_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-10-08 13:32:23 +08:00
Víctor Déniz f8bce36ef2 Merge branch 'MDL-69759-m39' of https://github.com/sammarshallou/moodle into MOODLE_39_STABLE 2020-10-07 22:26:06 +01:00
Victor Deniz Falcon fce2b0008c MDL-52407 travis: use Travis default notifications(email) 2020-10-07 16:32:58 +08:00
Andrew Nicols c2bd0a7d31 Merge branch 'MDL-67275-39-post_noun_verb' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-10-07 12:38:55 +08:00
AMOS bot 2d7a59d060 Automatically generated installer lang files 2020-10-07 00:07:45 +00:00
Eloy Lafuente (stronk7) 57e0a20dec Merge branch 'wip-MDL-68808-MOODLE_39_STABLE' of https://github.com/jason-platts/moodle into MOODLE_39_STABLE 2020-10-06 23:12:19 +02:00
Ferran Recio 3fe455fab4 MDL-69736 core_h5p: enable player reporting 2020-10-06 13:05:24 +02:00
Paul Holden ca743b6a95 MDL-69813 h5p: fix undefined addon ordering in framework test. 2020-10-06 10:48:10 +01:00
Eloy Lafuente (stronk7) 5ea37637b7 weekly release 3.9.2+ 2020-10-06 10:20:46 +02:00
Eloy Lafuente (stronk7) 75bae1a55b Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-10-06 10:20:43 +02:00
Mikhail Golenkov f3db3d30e0 MDL-47178 question: Retain question authors when restoring backups. 2020-10-06 09:36:42 +11:00
Eloy Lafuente (stronk7) 7714ea42ec Merge branch 'MDL-69772-39-allcountrycodes' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-10-06 00:04:13 +02:00
Eloy Lafuente (stronk7) 12c103b21a Merge branch 'MDL-65074-39' of https://github.com/hitteshahuja/moodle into MOODLE_39_STABLE 2020-10-05 23:12:33 +02:00
Sara Arjona ec157a3052 Merge branch 'MDL-69355-39-filebuffer' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-10-05 18:34:02 +02:00
Jun Pataleta 57bb2fdaac Merge branch 'MDL-69704-39' of git://github.com/sarjona/moodle into MOODLE_39_STABLE 2020-10-05 23:12:50 +08:00
Sara Arjona e437183098 Merge branch 'MDL-69641-MOODLE_39_STABLE' of https://github.com/dmitriim/moodle into MOODLE_39_STABLE 2020-10-05 13:38:06 +02:00
Eloy Lafuente (stronk7) 3af8f89e58 Merge branch 'MOODLE_39-MDL-69752' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2020-10-05 10:55:10 +02:00
Mikhail Golenkov 52b1184468 MDL-69791 gradereport: Fix error message when invalid grade is entered 2020-10-05 15:00:20 +11:00
Mikhail Golenkov 99d0308e4b MDL-69848 upgrade: Delete notifications in chunks 2020-10-05 13:14:26 +11:00
Mikhail Golenkov 3ae46b2a93 MDL-69818 mod_feedback: Fix item dependency during activity restoration 2020-10-04 18:29:45 +11:00
Mikhail Golenkov 5fce0b3f5d MDL-69752 mod_data: Format module intro on Database activities page 2020-10-04 13:49:35 +11:00
AMOS bot b3ebbb61f4 Automatically generated installer lang files 2020-10-03 00:08:29 +00:00
Sara Arjona 16689245e8 weekly release 3.9.2+ 2020-10-02 13:43:27 +02:00
Eloy Lafuente (stronk7) 98280a4c8c Merge branch 'MDL-69758-m39' of https://github.com/sammarshallou/moodle into MOODLE_39_STABLE 2020-10-01 23:44:26 +02:00
Claude Vervoort 171e55f304 MDL-57756 mod_lti: params change to text type 2020-10-01 17:34:39 -04:00
Sara Arjona f1fed72bda MDL-69704 course: catch exception when calling get_course_content_items
When plugins are removed from disk, an exception is thrown when
calling component_callback_exists.
This exception should be catched here in order to load properly
the activity chooser (otherwise, the exception will be displayed
and no activity will appear).
2020-10-01 19:56:41 +02:00
Tim Hunt 07674eb12f MDL-69798 XML question export: excape special chars in idnumbers 2020-10-01 17:10:58 +01:00
Amaia Anabitarte 2308a02324 MDL-69672 core_contentbank: is_context_allowed unit tests 2020-10-01 17:56:38 +02:00
Eloy Lafuente (stronk7) 1da6703d6d Merge branch 'MDL-69672-39' of git://github.com/aanabit/moodle into MOODLE_39_STABLE 2020-10-01 17:49:23 +02:00
Eloy Lafuente (stronk7) 27a62292ad Merge branch 'MDL-69586-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-10-01 17:12:53 +02:00
David Mudrák 271b94ff4f MDL-69772 admin: Better validation for the allcountrycodes setting
The patch introduces a new admin_setting fiela type that can be used for
specifying comma separated list of countries. The field has inbuilt
validation so that only valid country codes can be inserted.
2020-10-01 13:37:51 +02:00
Jason Platts 315ec3bad6 MDL-68808 forms: autocomplete throwing error in IE11 2020-10-01 12:11:11 +01:00
Sara Arjona 4cb342ef34 Merge branch 'MDL-68098-39' of git://github.com/dpalou/moodle into MOODLE_39_STABLE 2020-10-01 12:56:31 +02:00
Dani Palou e7bb7aa9a2 MDL-68098 tests: Reset FILTERLIB_PRIVATE after tests 2020-10-01 12:50:00 +02:00
Dani Palou 7aca3ebb3c MDL-68098 ws: Add unit tests to test mathjax in WS 2020-10-01 12:50:00 +02:00
David Matamoros 61bb2c70c2 MDL-69805 mod_data: Freeze comment field if comments disabled 2020-09-30 15:53:29 +02:00
Matteo Scaramuccia d84da184c5 MDL-68536 core: Fix notice about undefined prop 'branch' in $CFG 2020-09-30 14:47:20 +02:00
Adrian Greeve f612465b53 Merge branch 'MDL-37802-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-09-30 13:50:03 +08:00
Dan Marsden 4727970abd MDL-69641 grade: fix slow query.
This is a backport of MDL-69190
2020-09-30 15:00:35 +10:00
Adrian Greeve 88c700bd2c Merge branch 'MDL-69359_39' of https://github.com/adpe/moodle into MOODLE_39_STABLE 2020-09-30 11:43:16 +08:00
Sara Arjona b354694012 Merge branch 'MDL-69342-39_profile_picture_deletion' of https://github.com/vtos/moodle into MOODLE_39_STABLE 2020-09-29 19:01:19 +02:00
Amaia Anabitarte a9bccc9dbc MDL-69672 core_contentbank: Check used context level 2020-09-29 12:44:48 +02:00
Eloy Lafuente (stronk7) 7c52a27375 weekly release 3.9.2+ 2020-09-29 10:48:33 +02:00
Eloy Lafuente (stronk7) 300d9ca23d Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-09-29 10:48:29 +02:00
Claude Vervoort 00b2219fd4 MDL-68384 mod_lti: fix spec violations bo claim name and dl value type 2020-09-28 17:04:07 -04:00
Víctor Déniz 8b9d73dad8 Merge branch 'MDL-69644-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-09-28 20:34:26 +01:00
Shamim Rezaie 9029eb0e71 MDL-69649 form: Fix labels for defaultcustom form elements 2020-09-28 23:21:50 +10:00
Shamim Rezaie d54b3447e6 MDL-69649 backup: Fix missing labels
- The backup details page uses a table to show a sumary of the backup
  content. Used role attribute to denote the tabular format of the
  summary.
- The backup details page displays activity name next to each activity
  icon. Therefore the icons are only decorative and do not need to have
  any title or even alt text.
- Form labels should be associated with form controls.  A div element is
  not a form control.
- The from attribute of the form labels should be equal to the id
  attribute of an element. Therefore, we first create a label and an
  input elements and associate them to each other, and then pass them to
  backup_detail_pair() when a label is needed.
2020-09-28 23:21:50 +10:00
sam marshall 39d542eeb4 MDL-69759 Web services: app checks to token.php cause log errors 2020-09-28 11:55:56 +01:00
AMOS bot 2cf6b7cc41 Automatically generated installer lang files 2020-09-26 00:07:59 +00:00
adpe 5651e88dc9 MDL-69359 admin_cli: show only contributed plugins in uninstall plugins 2020-09-25 17:03:31 +02:00
Hittesh Ahuja 5a90580646 MDL-65074 mod_quiz: Quiz navigation buttons shouldnt use btn-secondary
Removing .btn-secondary as plain.scss and default.scss in bootstrap hide the button from view.
2020-09-25 15:17:10 +01:00
Paul Holden c98428aab3 MDL-37802 repository: return error if unzipping files fails.
For instance, when a user tried to unzip a password protected zip
archive using the file manager.
2020-09-25 09:34:01 +01:00
Paul Holden dc780e3eb1 MDL-69586 tool_usertours: use specified user in privacy prefs export. 2020-09-25 09:13:39 +01:00
David Mudrák d75844ea12 MDL-69772 admin: Fix legacy coding style on Location settings admin page
No actual change here. Just polishing the coding style and adding
fulltree check.
2020-09-24 18:14:12 +02:00
David Mudrák 11e5003bd6 MDL-69772 lang: Ignore misconfigured allcountrycodes filter
If the allcountrycodes filter contains only invalid values, ignore the
whole filter setting and make get_list_of_countries() return the full
list of all known countries, rather than empty list.
2020-09-24 18:14:12 +02:00
Víctor Déniz a348c5f420 weekly release 3.9.2+ 2020-09-24 16:27:32 +01:00
Víctor Déniz 4b651226d5 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-09-24 16:27:27 +01:00
Eloy Lafuente (stronk7) e33c554aaa Merge branch 'MDL-69698-39-licensecache' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-09-24 16:50:47 +02:00
Paul Holden 31937c4b0e MDL-69644 tool_dataprivacy: fix focus outline of contact DPO link.
The link class attribute is a leftover from 7258bf0b, which was mostly
removed in 3b2f691f. It no longer serves a purpose and interferes with
the element focus outline.
2020-09-24 11:51:15 +01:00
Vitaly 141216f94c MDL-69342 core_user: fixed user picture updating
When editing a user and checking the 'Delete picture' checkbox to delete
the old picture and uploading a new one at a time, the new one didn't appear
in the user profile. This happened due to the 'if/else' statement
in the 'core_user::update_picture()' method which allowed either to delete
the old picture or to upload a new one.
The fix removes the 'else' part of the 'if/else' statement to force
checking for a new uploaded picture no matter if a user checked
the 'Delete picture' checkbox or not.
2020-09-24 10:55:29 +03:00
Dani Palou fba96f096b MDL-68098 ws: Fix WebServices broken by filters HTML 2020-09-23 16:23:19 +02:00
Eloy Lafuente (stronk7) 7148c9d35e Merge branch 'MDL-68229-39' of git://github.com/jleyva/moodle into MOODLE_39_STABLE 2020-09-23 11:51:30 +02:00
Eloy Lafuente (stronk7) 8193ba9da9 Merge branch 'MDL-69014-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-09-22 23:10:53 +02:00
Juan Leyva 6bf314500a MDL-64657 course: Return hidden section names when configured 2020-09-22 12:25:58 +02:00
AMOS bot ee034c39e5 Automatically generated installer lang files 2020-09-22 00:07:13 +00:00
Eloy Lafuente (stronk7) 46aea33b69 Merge branch 'MDL-66648-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-09-21 23:36:30 +02:00
Eloy Lafuente (stronk7) e0f9ca6787 Merge branch 'MDL-69667-MOODLE_39_STABLE' of https://github.com/comete-upn/moodle into MOODLE_39_STABLE 2020-09-21 23:20:35 +02:00
David Mudrák 976f8f0c52 MDL-67275 forum: Fix language and accessibility issues with buttons
There were inconsistencies with the text shown on the submit button,
depending on the where the button was shown.

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

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

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

* Inline reply textarea's title was hard-coded English "post" text.
  Changed to "Message" to provide advisory information related to the
  element.
* Buttons contained title attribute with the same value as the explicit
  button text. This goes against accessibility guidelines.
2020-09-21 22:48:20 +02:00
sam marshall 767be5d8c1 MDL-69758 Web services: core_get_course_contents PHP warnings
Calls to core_get_course_contents can cause PHP warnings in the server
log if there are any URL instances in the course with sketchy URLs.
This is because url_export_contents incorrectly returns null instead
of an empty array if there is an error.
2020-09-21 15:28:47 +01:00
Juan Leyva 94140b11e8 MDL-68229 tool_mobile: Add missing option to disable tags in the app 2020-09-18 15:30:55 +02:00
Eloy Lafuente (stronk7) a45e6838ef weekly release 3.9.2+ 2020-09-17 19:04:23 +02:00
Eloy Lafuente (stronk7) ae17678a1c Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-09-17 19:04:20 +02:00
Eloy Lafuente (stronk7) 3ae39301b9 Merge branch 'MDL-69395_39' of github.com:stronk7/moodle into MOODLE_39_STABLE 2020-09-17 17:03:10 +02:00
Eloy Lafuente (stronk7) 422fcb70ca MDL-69395 theme_classic: remove superfluous selector already in boost 2020-09-17 13:06:06 +02:00
David Mudrák 29a396fe4e MDL-69355 file: Do not attempt to set headers after output started
It was found out that in certain situations there may be some content
in to output handlers buffers. Let's allow that to happen given that:

* default handler's buffer is not sent as a part of the file and an
  error is reported into the server log.
* other handlers' buffer is sent with the assumption that it is required
  for the correct serving of the file.
2020-09-17 11:42:33 +02:00
Eloy Lafuente (stronk7) af777f92a0 Merge branch 'MDL-62387-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-09-17 08:58:46 +02:00
Eloy Lafuente (stronk7) 6f35d6536d Merge branch 'MDL-69395-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-09-17 08:58:46 +02:00
Jun Pataleta 36cde1e295 Merge branch 'MDL-69663-m39' of https://github.com/sammarshallou/moodle into MOODLE_39_STABLE 2020-09-17 08:58:46 +02:00
AMOS bot 05a1532e88 Automatically generated installer lang files 2020-09-16 00:07:11 +00:00
David Mudrák 91ae4ab5db MDL-69698 licenses: Improve the performance of the licenses cache
The cache uses a single simple key and there is no need to hash it.
2020-09-15 10:22:57 +02:00
David Mudrák 2cc3588b77 MDL-69698 licenses: Do not cache the localised licenses fullnames
The localisation must happen only after loading the list of licenses
from cache so that the name is displayed in the current user's preferred
language, not in the language of the user who initiated the cache
rebuild.
2020-09-15 10:19:46 +02:00
Paul Holden 222aefb456 MDL-62387 tool_lp: switch to core 'cohort' form element.
The autocomplete AJAX is identical to the version in tool_lp, but also
includes support for excluding suggestions (i.e. cohorts already
synced with the current learning plan).
2020-09-15 08:06:37 +01:00
comete-upn 94160c9ad0 MDL-69667 competencies: fix competencies count always 0 in frameworks. 2020-09-15 08:37:50 +02:00
Jun Pataleta 9c7ab777d9 Merge branch 'MDL-42012-39-alt' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-09-15 11:52:50 +08:00
Andrew Nicols 7818990010 MDL-42012 cache: Fix missing return value 2020-09-15 11:46:31 +08:00
Eloy Lafuente (stronk7) 17a035ac59 Merge branch 'MDL-42012-39-alt' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-09-14 23:29:04 +02:00
Eloy Lafuente (stronk7) abe11a9ace Merge branch 'MDL-69658-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-09-14 22:56:55 +02:00
Paul Holden bfab0d603c MDL-69014 tool_usertours: clean up user preferences of deleted tours. 2020-09-14 20:36:26 +01:00
Paul Holden 070454489f MDL-66648 user: consistent checks for linking to full profile.
The access checks for displaying a link to a users' full profile
now match the checks performed on the full profile page itself.
2020-09-14 20:22:03 +01:00
AMOS bot e32a114998 Automatically generated installer lang files 2020-09-13 00:07:51 +00:00
AMOS bot 3db28cdebd Automatically generated installer lang files 2020-09-12 00:07:33 +00:00
Jun Pataleta ccd4ef8ddd Moodle release 3.9.2 2020-09-11 10:41:59 +08:00
sam marshall 51b0a67bd2 MDL-69663 Web services: override_webservice_execution not honoured
If two different plugin types (e.g. theme, local) implement
override_webservice_execution callbacks, then all of them except
the 'last' plugin type do not work correctly.
2020-09-10 09:51:16 +01:00
Sara Arjona b9371d7bf6 weekly release 3.9.1+ 2020-09-10 08:52:10 +02:00
Sara Arjona 1ec406cbd7 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-09-10 08:52:07 +02:00
Sara Arjona b1c1119743 Merge branch 'MDL-69466-3.9' of https://github.com/JBThong/moodle into MOODLE_39_STABLE 2020-09-09 11:39:30 +02:00
Sara Arjona 3d45f2c083 Merge branch 'MDL-69645-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-09-09 11:01:00 +02:00
Thong Bui 1f5da975e2 MDL-69466 Autocomplete widget: Improve keyboard accessibility 2020-09-09 13:50:04 +07:00
Andrew Nicols 7156a01a0c MDL-42012 cache: Valid definitions are required even when disabled 2020-09-09 14:05:19 +08:00
Andrew Nicols db22846df6 MDL-42012 cache: Fully disable cache for disabled cache factory 2020-09-09 14:05:19 +08:00
Andrew Nicols ef6e3bfd77 MDL-42012 cache: Allow data sources to work when caching is disabled 2020-09-09 14:05:19 +08:00
Eloy Lafuente (stronk7) ee0106f70b Merge branch 'MDL-69116-39' of git://github.com/rezaies/moodle into MOODLE_39_STABLE 2020-09-08 23:16:43 +02:00
Paul Holden 36ee886a12 MDL-69658 quizaccess_seb: progress bar on install only when necessary. 2020-09-08 19:32:36 +01:00
Sara Arjona 97e0452344 MDL-69657 mod_h5pactivity: component passed always
The $component = 'mod_h5pactivity' will be passed always to the H5P
player because it's required for being able to call these activities
from outside using embed code. The xAPI implementation checks whether
the information should be tracked or not.

Backport of MDL-69174
2020-09-08 13:08:44 -04:00
Sara Arjona 874bdf2035 MDL-69657 h5p: add component to the embed H5P code
When the Moodle component is passed to the player, xAPI tracking
is enabled so, if the component implements required xAPI API methods
(for instance, mod_h5pactivity does), grades and responses are sent.
Adding this component to the embed code will help to add
the embed code from a mod_h5pactivity to any other place (such as label,
page or book), and being able to track the responses to the original
mod_h5pactivity.

Backport from MDL-69174
2020-09-08 13:08:13 -04:00
Sara Arjona ab43412ae9 Merge branch 'MDL-69525-39-1' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-09-08 14:22:04 +02:00
Michael Hawkins 3d01fc77de MDL-69340 tag: Correct the filter input HTML in the tag manager 2020-09-08 08:47:20 +02:00
Mihail Geshoski 08d7552f4d MDL-69048 book: Sanitize previous chapter value in add new chapter page 2020-09-08 08:47:20 +02:00
Andrew Nicols 8983d50bd1 MDL-68974 calendar: Use page context for block check 2020-09-08 08:47:20 +02:00
Andrew Nicols 9fb8221fb3 MDL-68974 blocks: Check permission before generating content 2020-09-08 08:47:20 +02:00
Mihail Geshoski 4b60cede1e MDL-65115 repository: Prevent unzipping if it will exceed allowed quota 2020-09-08 08:47:20 +02:00
Mihail Geshoski 4514918c33 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:47:20 +02:00
Andrew Nicols 86d6bdf079 MDL-68974 admin: Unit tests for context parent/child test 2020-09-08 08:47:20 +02:00
Andrew Nicols f5d75c8e24 MDL-68974 admin: Unit tests for loginas 2020-09-08 08:47:20 +02:00
Andrew Nicols bfeb6f3bac MDL-68974 admin: Prevent login as outside of the desired context 2020-09-08 08:47:20 +02:00
Sara Arjona ec52cca8b1 Merge branch 'MDL-68344-3.9' of https://github.com/JBThong/moodle into MOODLE_39_STABLE 2020-09-08 08:45:19 +02:00
Jun Pataleta 6bbb402129 Merge branch 'MDL-69492-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-09-08 12:56:19 +08:00
AMOS bot 7375466f51 Automatically generated installer lang files 2020-09-08 00:07:50 +00:00
Eloy Lafuente (stronk7) 8635e2cefa Merge branch 'MDL-69262-39-2' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-09-07 23:43:04 +02:00
Eloy Lafuente (stronk7) 52bad33356 Merge branch 'MDL-69448-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-09-07 23:26:21 +02:00
Luca Bösch 5c155ba8f7 MDL-69645 quizaccess: Set allowPreferencesWindow to false in manual conf
Signed-off-by: Luca Bösch <luca.boesch@bfh.ch>
2020-09-07 21:26:11 +02:00
Mathew May ffa17ad17d MDL-69240 tool_moodlenet: Clean MoodleNet profile field
Amended by: Eloy Lafuente (stronk7) <stronk7@moodle.org>
- adjust versions for every branch.
- modify verify_webfinger->profileurl external to PARAM_NOTAGS.
2020-09-07 17:25:13 +02:00
Sara Arjona 5d6fcc67cf Merge branch 'MDL-67468-MOODLE_39_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_39_STABLE 2020-09-07 13:20:06 +02:00
Paul Holden a37dc94598 MDL-69492 auth_cas: normalise member distinguished name config. 2020-09-04 08:36:13 +01:00
Paul Holden 1e08e046e2 MDL-69492 auth_ldap: normalise member distinguished name config. 2020-09-04 08:36:13 +01:00
Paul Holden 4ff5d5ef17 MDL-69448 backup: fix capability checks when unable to copy user data.
When a given user doesn't have the capability to "Include user data"
during course copying, freeze the form element rather than not adding
it at all.

This caused problems as the element was required before preceding with
the course copy.
2020-09-04 08:20:13 +01:00
Nathan Nguyen 84ef6eb8d9 MDL-67468 filter_activitynames: use MUC 2020-09-04 15:41:46 +10:00
Thong Bui 3b45e0db41 MDL-68344 filepicker: File Picker focus lost on upload 2020-09-04 10:09:22 +07:00
Sara Arjona 535523f21f weekly release 3.9.1+ 2020-09-03 17:09:26 +02:00
Sara Arjona 9c50ccbf7e NOBUG: Fixed SVG browser compatibility 2020-09-03 17:09:24 +02:00
Bas Brands 6c39b7890e MDL-69395 theme_boost: improve colour contrast for form input fields
- for this issue the atto styles.css was moved into theme boost so
we can use our preset variable for $gray-500
2020-09-03 11:09:02 +02:00
Andrew Nicols b676817a64 Merge branch 'MDL-69391-39' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-09-03 11:48:49 +08:00
Andrew Nicols 8eca15c5f1 Merge branch 'MDL-69360-39' of git://github.com/NoelDeMartin/moodle into MOODLE_39_STABLE 2020-09-03 10:52:15 +08:00
Andrew Nicols 1bb4c59adc Merge branch 'MDL-69246_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-09-03 10:40:12 +08:00
Andrew Nicols 2332ac5f87 Merge branch 'MDL-55340-39' of git://github.com/sarjona/moodle into MOODLE_39_STABLE 2020-09-03 10:14:13 +08:00
Andrew Nicols 0700b8510f Merge branch 'MDL-69069-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-09-03 09:34:08 +08:00
Eloy Lafuente (stronk7) 7bc82ad672 Merge branch 'MDL-69608-39' of https://github.com/marinaglancy/moodle into MOODLE_39_STABLE 2020-09-02 23:50:09 +02:00
Sara Arjona 92b9900d6e Merge branch 'MDL-68680-MOODLE_39_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_39_STABLE 2020-09-02 17:16:09 +02:00
Marina Glancy 312ca07bb7 MDL-69608 core_form: frozen forms do not have form tag 2020-09-02 11:40:22 +02:00
Noel De Martin bea621d6c6 MDL-69360 behat: Fix js ready checks for non-moodle sites 2020-09-02 10:20:52 +02:00
Andrew Nicols 28a8eb3856 Merge branch 'MDL-68892-39' of git://github.com/ferranrecio/moodle into MOODLE_39_STABLE 2020-09-02 09:49:21 +08:00
Eloy Lafuente (stronk7) fb39317a64 Merge branch 'wip_MDL-69491_m39' of git://github.com/gjb2048/moodle into MOODLE_39_STABLE 2020-09-02 00:27:43 +02:00
Sara Arjona 6e7f80363b Merge branch 'MDL-64525-m39' of https://github.com/NeillM/moodle into MOODLE_39_STABLE 2020-09-01 14:18:20 +02:00
Sara Arjona 82bd2ff5a9 Merge branch 'MDL-51709-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-09-01 09:04:24 +02:00
Mihail Geshoski e657192d31 MDL-69525 core: Publish a single event when toggling slave checkboxes 2020-09-01 14:54:07 +08:00
Sara Arjona 85782cffd7 Merge branch 'MDL-69394-39' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-09-01 06:45:26 +02:00
Tim Hunt fac004cfe9 MDL-69507 duration form field: should return an int number of seconds 2020-09-01 11:31:36 +08:00
Tim Hunt 221c293ac7 MDL-69507 duration form field: modernise coding style 2020-09-01 11:31:10 +08:00
Andrew Nicols 5ad20a0633 Merge branch 'MDL-69387-39-2' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-09-01 10:59:51 +08:00
Andrew Nicols d63bdf9bb9 Merge branch 'MDL-69505-39' of https://github.com/snake/moodle into MOODLE_39_STABLE 2020-09-01 07:29:23 +08:00
Andrew Nicols bc29f1c98a Merge branch 'MDL-56595-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-09-01 07:29:23 +08:00
Luca Bösch 4830f55122 MDL-51709 gradebook: Name display in single view. 2020-08-31 18:18:26 +02:00
Shamim Rezaie 48508e4ecc MDL-69116 qtype_multichoice: accessibility improvement
- Screen-readers should not see 'clear my choice' when it is not visible
- 'clear my choice' option should only become visible when a choice is
selected
2020-08-31 23:55:49 +10:00
Shamim Rezaie fbb2d6592d MDL-69116 qtype_mutichoice: Use label for the "clear my choice" link 2020-08-31 23:55:49 +10:00
Bas Brands 581a497189 MDL-69069 theme_boost: color contrast for custom alerts 2020-08-31 08:46:39 +02:00
Jake Dallimore 3d3314d433 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:05:37 +08:00
Gareth Barnard a1f21bad0d MDL-69491 themes: No 'fontsize' setting in Boost causes unit conflict. 2020-08-28 14:10:54 +01:00
Marina Glancy 189810269a 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:17 +02:00
Andrew Nicols e592c6dd9d Merge branch 'MDL-69112-39' of git://github.com/merrill-oakland/moodle into MOODLE_39_STABLE 2020-08-28 13:26:05 +08:00
Nathan Nguyen 563cfa0e1e MDL-68680 core_grades: check grade item before trigger delete event 2020-08-28 11:40:24 +10:00
Paul Holden 863fb96ffa MDL-56595 tool_usertours: set page params when configuring tours/steps. 2020-08-27 23:08:07 +01:00
Tim Hunt 10f03d2a99 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:41:02 +01:00
Sara Arjona b3b04e083b weekly release 3.9.1+ 2020-08-27 17:36:31 +02:00
Sara Arjona 9262b490ee Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-08-27 17:36:29 +02:00
Jun Pataleta f37d0629ea MDL-69262 core: Use core/action_menu_link in core/action_menu_trigger
* Introduce the "actionmenulinkclasses" block in the action_menu_link
template so other templates importing it can have the option to override
its classes.
* Have the action menu trigger template use the action menu link
template to reduce code duplication.
2020-08-27 13:30:46 +08:00
Jun Pataleta 6d9518cf56 MDL-69262 core: Make instance count variable as a static class variable
With the static function variable $instance, calls to
\action_menu_link::export_for_template() from its subclasses are stored
in different variables. This causes duplicate IDs when different
implementations of action menu links are rendered on the action menu
trigger/link template. (e.g. action_menu_link and
action_menu_link_secondary both rendered on the same page).
To make the incrementing uniform for the action_menu_link class and its
implementations, the $instance variable is moved out of the
export_to_template() method and is now made to a static class variable.
2020-08-27 13:30:46 +08:00
Andrew Nicols 0d8bf37407 Merge branch 'MDL-69458-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-08-27 12:43:10 +08:00
Andrew Nicols 159115b7c7 Merge branch 'MDL-69501-39-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-08-27 11:31:17 +08:00
eWallah 930dba73c3 MDL-67413 competencies: do nothing upon activity completion 2020-08-27 11:09:57 +08:00
Andrew Nicols 22217ac42f Merge branch 'MOODLE_39_MDL-69358' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2020-08-27 10:57:57 +08:00
Justin Hunt d46ee17722 MDL-66810 mod_lti: Reinstate deprecated default permissions on iframe
microphone, webcam, camera, midi, encrypted-media, geolocation
2020-08-27 10:26:38 +08:00
Adrian Greeve 5f1d9df828 Merge branch 'MDL-69419-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-08-27 08:07:18 +08:00
AMOS bot 95cc0d562b Automatically generated installer lang files 2020-08-27 00:07:08 +00:00
Sara Arjona 3584cd786a Merge branch 'MDL-69389-39' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-08-26 18:03:06 +02:00
Sara Arjona fa92e6a809 Merge branch 'MDL-69114-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-08-26 16:28:49 +02:00
Jun Pataleta 1257e39d92 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:08:28 +08:00
Jun Pataleta 65c7339199 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:08:28 +08:00
Jun Pataleta 2cb720a3d2 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:18 +08:00
Jun Pataleta 138ed9c1fa 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:18 +08:00
Jun Pataleta 3c7a4833e5 MDL-69394 calendar: Fix event colour indicator contrast
* Darkened the link and clickable icon colours inside coloured events.
* Added borders around event colour indicators inside the month-view of
  the calendar for better contrast against the white background.
2020-08-26 11:00:34 +08:00
Andrew Nicols 0400b5ef3f 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:35 +08:00
AMOS bot 122ed3beaf Automatically generated installer lang files 2020-08-26 00:07:28 +00:00
Jun Pataleta b58a45df37 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:40:34 +08:00
Jun Pataleta 2d450e9a3b 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:40:34 +08:00
Adrian Greeve 3513964883 Merge branch 'MDL-68921-39' of git://github.com/vmdef/moodle into MOODLE_39_STABLE 2020-08-25 10:37:58 +08:00
Victor Deniz Falcon fde9d44286 MDL-68921 core_h5p: Add H5P libraries metadata settings
An upgrade step updates installed H5P libraries
2020-08-25 00:35:59 +01:00
Neill Magill ba8185cb2a MDL-64525 comments: Should not be able to delete frozen comments
Before this change in a frozen context a user would be able to delete
their own comments.

After this change a user will only be able to delete their own comments
if they still have the capability to post new comments or the capability
to delete comments from any user.
2020-08-24 08:00:36 +01:00
Neill Magill 362c598d1b MDL-64525 comments: Tests for deleting frozen comments 2020-08-24 08:00:35 +01:00
Mihail Geshoski 185fc93ed5 MDL-69458 report_insights: Respect perpage value in pagination bar 2020-08-24 09:30:46 +08:00
Eloy Lafuente (stronk7) 8b254440d6 Merge branch 'MDL-69493-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-22 17:09:43 +02:00
AMOS bot 5989a94787 Automatically generated installer lang files 2020-08-22 00:07:52 +00:00
Eloy Lafuente (stronk7) e290345cd6 weekly release 3.9.1+ 2020-08-21 20:43:20 +02:00
Helen Foster 4c48bccbad 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 14:06:31 +02:00
Jun Pataleta ef1bb2b193 Merge branch 'MDL-66818-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-08-21 11:32:35 +08:00
Andrew Nicols 9e103451e2 MDL-66818 mod_forum: Use cap manager to check exportability 2020-08-21 08:17:16 +08:00
Andrew Nicols 832f5f7019 MDL-42434 chat: Disable stylelint important check 2020-08-21 07:38:06 +08:00
Sara Arjona 40f92ac55d 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:42:56 +01:00
Sara Arjona 887efbd939 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:42:56 +01:00
Ferran Recio 6305c7b83c MDL-68892 mod_h5pactivity: add required to package 2020-08-20 17:20:13 +02:00
Adrian Greeve 6bbb4e4df2 Merge branch 'MDL-69055-39' of git://github.com/sarjona/moodle into MOODLE_39_STABLE 2020-08-20 12:02:49 +08:00
Andrew Nicols 79e98f6ac4 Merge branch 'MDL-69375_39' of https://github.com/Cvmcosta/moodle into MOODLE_39_STABLE 2020-08-20 11:51:08 +08:00
Adrian Greeve 1c1a96981d Merge branch 'MDL-68964-39' of git://github.com/ferranrecio/moodle into MOODLE_39_STABLE 2020-08-20 11:42:30 +08:00
Adrian Greeve 6e9d203e52 Merge branch 'MDL-42434-39' of git://github.com/sarjona/moodle into MOODLE_39_STABLE 2020-08-20 11:24:43 +08:00
Adrian Greeve c02fc98d06 Merge branch 'MDL-68683-39-fix' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-08-20 10:24:42 +08:00
Andrew Nicols 895e5748e1 Merge branch 'MDL-69449-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-20 09:25:19 +08:00
Andrew Nicols 96805ec18e Merge branch 'MDL-68889-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-08-20 09:19:22 +08:00
Simey Lameze 010f1eff60 MDL-68683 competencies: fix query to delete stale files 2020-08-20 09:13:15 +08:00
Simey Lameze a713a68af8 MDL-68683 competencies: step to delete orphaned evidence files 2020-08-20 09:09:37 +08:00
Simey Lameze 1547225e52 MDL-68683 core: fix DML exception on upgrade step 2020-08-20 09:02:50 +08:00
Andrew Nicols cc52ff7703 Merge branch 'MDL-67415_39' of https://github.com/stronk7/moodle into MOODLE_39_STABLE 2020-08-20 08:30:11 +08:00
Andrew Nicols 3f51798192 Merge branch 'MDL-66818-39' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-08-20 08:17:01 +08:00
Simey Lameze 8578e19aff MDL-66818 mod_forum: remove unnecessary behat steps 2020-08-20 08:05:00 +08:00
gthomas2 e4ffa5f3f6 MDL-66818 mod_forum: hide portfolio export button based on caps 2020-08-20 08:05:00 +08:00
Andrew Nicols 8cc9ebea1e Merge branch 'MDL-66900-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-20 07:54:30 +08:00
Andrew Nicols 2cb5248ac3 Merge branch 'MDL-69473-39' of git://github.com/sarjona/moodle into MOODLE_39_STABLE 2020-08-20 07:44:12 +08:00
Andrew Nicols 43a9717a33 Merge branch 'MDL-69271_39' of https://github.com/stronk7/moodle into MOODLE_39_STABLE 2020-08-20 07:35:40 +08:00
Andrew Nicols 4fd5a7bfcb Merge branch 'MDL-69054-39' of git://github.com/sarjona/moodle into MOODLE_39_STABLE 2020-08-20 07:32:03 +08:00
Andrew Nicols 3c2c15d4dc Merge branch 'MDL-61215-39' of git://github.com/sarjona/moodle into MOODLE_39_STABLE 2020-08-20 07:17:13 +08:00
Andrew Nicols 7969cfb39f Merge branch 'MDL-69401-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-08-20 07:03:36 +08:00
Victor Deniz Falcon f2fe8b1664 Merge branch 'MDL-69297-39' of git://github.com/peterRd/moodle into MOODLE_39_STABLE 2020-08-19 23:45:32 +01:00
Eloy Lafuente (stronk7) 23dc056578 MDL-63375 workshop: apply specific IE10/11 fix
Credit goes to Matt Davidson (Syxton)
2020-08-19 17:54:45 +02:00
Sam Hemelryk 3e9dadc85e MDL-68896 mod_scorm: improved sendBeacon use when unloading 2020-08-19 20:30:49 +12:00
Peter Dias 6e37e120fc 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:42 +08:00
Adrian Greeve 091a6ca62e Merge branch 'MDL-66665-39-POC2' of git://github.com/peterRd/moodle into MOODLE_39_STABLE 2020-08-19 14:29:06 +08:00
Peter Dias a8cdc38272 MDL-66665 assign: Check whether a modified user could actually grade 2020-08-19 13:41:12 +08:00
Adrian Greeve 2296b4b16e Merge branch 'MDL-68683-39' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-08-19 12:57:04 +08:00
Adrian Greeve 4e873c2ab6 Merge branch 'MDL-69475_39' of https://github.com/stronk7/moodle into MOODLE_39_STABLE 2020-08-19 10:44:23 +08:00
Andrew Nicols 130d29bb5f Merge branch 'MDL-26401-39' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-08-19 08:52:02 +08:00
Andrew Nicols 3ae4d6e824 Merge branch 'MDL-69089-39' of git://github.com/aanabit/moodle into MOODLE_39_STABLE 2020-08-19 08:20:00 +08:00
Eloy Lafuente (stronk7) be1847d075 Merge branch 'MDL-65847-auth_db_error_handling-39' of git://github.com/leonstr/moodle into MOODLE_39_STABLE 2020-08-19 00:35:37 +02:00
Eloy Lafuente (stronk7) 68810e04c6 Merge branch 'MDL-69095-39' of git://github.com/jleyva/moodle into MOODLE_39_STABLE 2020-08-19 00:19:51 +02:00
Eloy Lafuente (stronk7) b8b894dd36 Merge branch 'MDL-63375-39' of https://github.com/syxton/moodle into MOODLE_39_STABLE 2020-08-19 00:13:13 +02:00
Eloy Lafuente (stronk7) a12b0aff07 Merge branch 'MDL-68444-39' of git://github.com/rezaies/moodle into MOODLE_39_STABLE 2020-08-18 19:15:13 +02:00
Eloy Lafuente (stronk7) 3523edfd90 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:24:57 +02:00
Eloy Lafuente (stronk7) fbaab99733 Merge branch 'MDL-69273-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-08-18 10:59:37 +02:00
Simey Lameze 6408db6427 MDL-68683 competencies: step to delete orphaned evidence files 2020-08-18 16:05:59 +08:00
Simey Lameze 2cd36e8ea0 MDL-68683 core: fix DML exception on upgrade step 2020-08-18 16:04:32 +08:00
Andrew Nicols 6a930e2c88 MDL-69273 travis: Use exttests for https too 2020-08-18 07:50:48 +08:00
Andrew Nicols 78079c3f2b 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 a88c706d98 MDL-69493 cohort: remove escaping of return URL params. 2020-08-17 21:30:14 +01:00
Amaia Anabitarte b9d20f8481 MDL-69089 core_contentbank: Tests for empty content names 2020-08-17 15:56:35 +02:00
Amaia Anabitarte 545b24fa52 MDL-69089 core_contentbank: Empty content names are not allowed 2020-08-17 15:56:35 +02:00
Andrew Nicols 2f6437ec5c Merge branch 'MDL-69414_M39' of https://github.com/nadavkav/moodle into MOODLE_39_STABLE 2020-08-17 14:52:46 +08:00
Mihail Geshoski 806042d58a MDL-69401 book: Limit character length in chapter title 2020-08-17 09:04:02 +08:00
carlos 58e66823a2 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:15:47 -03:00
Sara Arjona 119010b16d 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:06 +02:00
Sara Arjona c6895d7dd4 MDL-69055 core_badges: display password/oauth fields properly 2020-08-14 17:10:33 +02:00
Sara Arjona 1f7f5e368d MDL-69054 core_badges: allow editing OBv1.0 backpacks 2020-08-14 17:09:45 +02:00
Sara Arjona b80006b600 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:57 +02:00
Sara Arjona 9e42721660 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:57 +02:00
Sara Arjona 0f13aee6fb 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:57 +02:00
Eloy Lafuente (stronk7) 8cc4708c2a 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:09 +02:00
Sara Arjona 507d51eebf MDL-69473 contentbank: change incorrect ref to size in type column 2020-08-14 08:54:20 +02:00
Andrew Nicols 89d8f73703 weekly release 3.9.1+ 2020-08-14 14:42:37 +08:00
Andrew Nicols f0f37cb2e7 NOBUG: Fixed SVG browser compatibility 2020-08-14 14:42:35 +08:00
Andrew Nicols 62cd827dc5 Merge branch 'MDL-68666-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-08-13 15:21:28 +08:00
Bas Brands 1b682b3b6a MDL-68666 core_pix: add missing fallback icons 2020-08-13 08:49:27 +02:00
Andrew Nicols 5e372ecd61 Merge branch 'MDL-69253_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-08-13 11:52:32 +08:00
Andrew Nicols 4401c891e8 Merge branch 'MDL-60492-tagcloud_html-39' of https://github.com/leonstr/moodle into MOODLE_39_STABLE 2020-08-13 11:45:10 +08:00
Andrew Nicols 61a17c94be Merge branch 'MDL-69381-39' of https://github.com/marinaglancy/moodle into MOODLE_39_STABLE 2020-08-13 11:29:09 +08:00
Adrian Greeve 75911e67bd Merge branch 'MDL-68423-39' of git://github.com/ferranrecio/moodle into MOODLE_39_STABLE 2020-08-13 11:05:37 +08:00
Andrew Nicols 3a2eb35800 Merge branch 'MDL-68932-39' of git://github.com/rezaies/moodle into MOODLE_39_STABLE 2020-08-13 10:52:26 +08:00
Andrew Nicols 5ae88aba9d Merge branch 'MDL-69421-39' of git://github.com/noeldemartin/moodle into MOODLE_39_STABLE 2020-08-13 09:35:59 +08:00
Andrew Nicols dbd0a1dbf7 Merge branch 'MDL-67991-39' of git://github.com/aanabit/moodle into MOODLE_39_STABLE 2020-08-13 09:04:15 +08:00
Andrew Nicols d1e4c0fecc Merge branch 'MDL-69241-39' of git://github.com/mickhawkins/moodle into MOODLE_39_STABLE 2020-08-13 08:47:03 +08:00
Andrew Nicols 522dd18e62 Merge branch 'MDL-60260-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-13 07:55:21 +08:00
Andrew Nicols 563bfb4582 Merge branch 'MDL-69143-39' of git://github.com/ferranrecio/moodle into MOODLE_39_STABLE 2020-08-13 07:45:44 +08:00
Eloy Lafuente (stronk7) f03d9e1aab MDL-67415 environment: change requirements
- mysql requirement up to 5.7
- postgres requirement up to 9.6
2020-08-13 01:30:01 +02:00
Eloy Lafuente (stronk7) 454a93cbbf 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:00 +02:00
Eloy Lafuente (stronk7) a64f376595 Merge branch 'MDL-68860-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-13 01:08:32 +02:00
Eloy Lafuente (stronk7) f620bbf2f5 Merge branch 'MDL-68558-39-plugindepscheckdeadend' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-08-13 00:40:17 +02:00
Eloy Lafuente (stronk7) 4ddbc1ee38 Merge branch 'MDL-67394-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-13 00:29:15 +02:00
Eloy Lafuente (stronk7) f9bd169b6e Merge branch 'MDL-67002_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-08-13 00:26:09 +02:00
Ferran Recio 332fdda507 MDL-68964 mod_chat: fix theme param 2020-08-12 17:30:02 +02:00
Ferran Recio 77f46da53a MDL-69143 contentbank: catching Exception on file upload 2020-08-12 16:58:26 +02:00
Bas Brands ebacd8353f MDL-68889 block_recentlyaccessedcourses: small viewport issues
- on small devices the recentlyaccessedcourses does not show any courses
2020-08-12 13:05:13 +02:00
Paul Holden a97c45a15d MDL-66900 course: don't clean category description when editing. 2020-08-12 11:48:29 +01:00
Simey Lameze f307dc23d7 MDL-26401 group: change import to use csv_import_reader class 2020-08-12 16:35:56 +08:00
Simey Lameze b21f182106 MDL-26401 group: add delimiter and encoding fields to import 2020-08-12 16:35:56 +08:00
Paul Holden 0991b0a091 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:29 +01:00
Andrew Nicols 54eb1f8f23 Merge branch 'MDL-68618-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-12 13:41:00 +08:00
Andrew Nicols 97df1db020 Merge branch 'MDL-69353-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-12 11:22:40 +08:00
Andrew Nicols 8c1eb6cfd3 Merge branch 'MDL-68334-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-08-12 11:14:05 +08:00
Andrew Nicols 4eeb1bbd8f Merge branch 'MDL-69296-m39' of https://github.com/NeillM/moodle into MOODLE_39_STABLE 2020-08-12 10:29:58 +08:00
Mikhail Golenkov 5778aa1fa1 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:07:28 +10:00
Andrew Nicols a0c582342c Merge branch 'MDL-68731_39' of https://github.com/jonof/moodle into MOODLE_39_STABLE 2020-08-12 09:11:25 +08:00
Andrew Nicols cf13f285e4 Merge branch 'MDL-69143-39' of git://github.com/ferranrecio/moodle into MOODLE_39_STABLE 2020-08-11 14:34:10 +08:00
Andrew Nicols 08d7dd1db4 Merge branch 'MDL-69168_recently-accessed-items-block-uses-stock-lti-icon__MOODLE_39_STABLE' of https://github.com/stopfstedt/moodle into MOODLE_39_STABLE 2020-08-11 13:00:36 +08:00
Adrian Greeve a6908c3ee8 Merge branch 'MDL-69204-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-11 08:45:14 +08:00
Paul Holden cc91fe0988 MDL-68618 mod_forum: stop reverting idnumber when updating instance. 2020-08-10 09:11:12 +01:00
Paul Holden f66e6749ae MDL-68860 mod_lti: Oracle support for retrieving shared secrets.
Thanks to Mark van Hoek!
2020-08-10 09:06:07 +01:00
Adrian Greeve f3fd372584 Merge branch 'MDL-60493-grader_span_tag-39' of https://github.com/leonstr/moodle into MOODLE_39_STABLE 2020-08-10 09:22:18 +08:00
Nadav Kavalerchik e29a887814 MDL-69414 qtype/ddimageortext: Fix dropzones display in RTL mode 2020-08-09 11:45:21 +03:00
Luca Bösch f1743d9179 MDL-68334 user: Display name in footer as elsewhere. 2020-08-08 10:38:40 +02:00
Stefan Topfstedt 73827e8eda MDL-69168 block_recentlyaccesseditems: apply custom icon
Overwrite the default mod icon with the configured icon url if
applicable.
2020-08-07 09:15:05 -07:00
Matt Davidson abb81c79d7 MDL-63375 workshop: fix rubric grid view 2020-08-07 08:48:41 -04:00
Amaia Anabitarte 8b55712485 MDL-67991 availability: Fix access restrictions labels 2020-08-07 10:02:25 +02:00
Michael Hawkins f967acc533 MDL-69241 lib: Reset dynamic tables to page 1 when filtering or sorting
This ensures consistency and that the page will always exist, which may
not be true for later pages if applying filters returns fewer results.
2020-08-07 12:53:26 +08:00
Eloy Lafuente (stronk7) 61d4bf3f88 weekly release 3.9.1+ 2020-08-06 20:51:32 +02:00
Noel De Martin 94dc00614c MDL-69421 behat: Revert app behat navigation to call session visit 2020-08-06 12:15:51 +02:00
Jun Pataleta 976ec609bc Merge branch 'MDL-60501-h4_close_tag-39' of https://github.com/leonstr/moodle into MOODLE_39_STABLE 2020-08-06 12:11:18 +08:00
Jun Pataleta 7cc4f8883a Merge branch 'MDL-69111-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-08-06 11:36:48 +08:00
Adrian Greeve 9b48e7420e Merge branch 'MDL-40227-39-1' of git://github.com/peterRd/moodle into MOODLE_39_STABLE 2020-08-06 11:28:34 +08:00
Peter eae4f24877 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:59 +08:00
Adrian Greeve 72e24ec057 Merge branch 'MDL-69311-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-06 09:49:32 +08:00
Adrian Greeve da2cb39c15 Merge branch 'MOODLE_39_MDL-66626' of https://github.com/golenkovm/moodle into MOODLE_39_STABLE 2020-08-06 09:07:26 +08:00
Eloy Lafuente (stronk7) 695b470305 Merge branch 'MDL-66670-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-08-06 00:58:26 +02:00
Leon Stringer 076bbff5a7 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:55:02 +01:00
Shamim Rezaie 023064558f MDL-68932 core: showhidesettings to work with multiple hideIf()s 2020-08-05 19:08:27 +10:00
Adrian Greeve a934784741 Merge branch 'MDL-68647-39-forumprivacysql' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-08-05 14:22:22 +08:00
Adrian Greeve 13a31a6b83 Merge branch 'MDL-60932-39' of git://github.com/aanabit/moodle into MOODLE_39_STABLE 2020-08-05 10:08:50 +08:00
Eloy Lafuente (stronk7) f29c1bee74 Merge branch 'MDL-67831-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-08-05 00:47:33 +02:00
Tim Hunt 3c5ba23f7f MDL-69253 mod_quiz: unit test for the last commit 2020-08-04 14:50:57 +01:00
Josh Ebarvia 777c810671 MDL-69253 mod_quiz: Fix timecreated is 0 when creating a quiz activity 2020-08-04 14:50:57 +01:00
Jun Pataleta 9a642c49e1 Merge branch 'MDL-60574_39' of https://github.com/t-schroeder/moodle into MOODLE_39_STABLE 2020-08-04 19:51:20 +08:00
Eloy Lafuente (stronk7) a5708767a0 Merge branch 'MDL-55299-39' of git://github.com/ferranrecio/moodle into MOODLE_39_STABLE 2020-08-04 12:34:06 +02:00
Jun Pataleta 1117eb6579 Merge branch 'MDL-69336-39' of git://github.com/mickhawkins/moodle into MOODLE_39_STABLE 2020-08-04 16:54:21 +08:00
Tim Schroeder f131e22bc4 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:00 +02:00
Michael Hawkins 76fd40f2f9 MDL-69336 lib: Correctly return promises when table show/hide columns
Previously showColumn and HideColumn were returning nothing, so
attempts to catch exceptions were themselves throwing errors in the
browser console.
2020-08-04 15:20:29 +08:00
Michael Hawkins 52925cb9df MDL-69336 lib: Reinstating tablelib column show/hide functionality
Also added behat testing for hide/show columns in participants table.
2020-08-04 15:20:29 +08:00
Eloy Lafuente (stronk7) 3d68237956 Merge branch 'MDL-69367-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-03 16:29:09 +02:00
Leon Stringer b79b33c664 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:49:55 +01:00
Eloy Lafuente (stronk7) 8a6b5024a1 Merge branch 'MDL-62980-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-08-03 12:38:25 +02:00
Bas Brands f51dcd3c96 MDL-69114 theme_boost: improve the color contrast for .*-info classes 2020-08-03 11:36:48 +02:00
Eric Merrill 7a4f10ddda MDL-69112 assign: Improve parsing of uploaded feedback names 2020-07-31 19:08:27 -04:00
Marina Glancy 2d7f517b5b MDL-69381 core_backup: make progressbar selector more specific 2020-07-31 13:30:07 +02:00
Amaia Anabitarte 3161583d89 MDL-60932 core_user: Fix docs link for participants page
Co-authored by: David Mudrák <david@moodle.com>
2020-07-31 10:30:18 +02:00
Neill Magill 9e3b1f2d7e 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:57:29 +01:00
Paul Holden ff2d425711 MDL-67394 dml: improve thrown exception when Oracle can't parse query. 2020-07-30 16:23:00 +01:00
Victor Deniz Falcon 95c4f624c8 weekly release 3.9.1+ 2020-07-30 12:54:18 +01:00
Victor Deniz Falcon 7882fff01a Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-07-30 12:54:12 +01:00
Paul Holden d68848383e MDL-62980 tool_dataprivacy: show persistent errors inside form. 2020-07-30 08:23:19 +01:00
AMOS bot f395c5b238 Automatically generated installer lang files 2020-07-30 00:09:02 +00:00
Eloy Lafuente (stronk7) a9782addfc Merge branch 'MDL-63252-39' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-07-30 00:47:57 +02:00
Victor Deniz Falcon d093887447 Merge branch 'MDL-66707-39' of git://github.com/rezaies/moodle into MOODLE_39_STABLE 2020-07-29 23:17:25 +01:00
Victor Deniz Falcon f0be299db3 Merge branch 'MDL-68968-39' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-07-29 22:02:28 +01:00
Paul Holden 6a3edc34bd MDL-60260 course: validate external fields on create/update course.
Ensure course fullname/shortname fields are not empty.
2020-07-29 19:57:22 +01:00
Victor Deniz Falcon 135dfe2144 Merge branch 'MDL-68706-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-07-29 19:05:02 +01:00
Ferran Recio 13de4b94dc MDL-69143 contentbank: fix tests when extra plugins installed 2020-07-29 17:52:26 +02:00
Ferran Recio c6ec3c048e MDL-69143 contentbank: add import file method to content 2020-07-29 17:52:26 +02:00
Victor Deniz Falcon 6d1680998d Merge branch 'MDL-69199-39' of git://github.com/aanabit/moodle into MOODLE_39_STABLE 2020-07-29 11:54:46 +01:00
Jonathon Fowler bbfcb91b1f MDL-68731 forum: fix digests not correctly updating post read statuses 2020-07-29 15:41:31 +10:00
Jun Pataleta 7d1f5e81ea Merge branch 'MDL-69252-close_tag-39' of https://github.com/leonstr/moodle into MOODLE_39_STABLE 2020-07-29 11:17:40 +08:00
Eloy Lafuente (stronk7) 5f9d183b46 Merge branch 'MDL-69319-39' of https://github.com/snake/moodle into MOODLE_39_STABLE 2020-07-29 00:20:37 +02:00
Paul Holden 646ebff5dd MDL-69367 quizaccess_seb: correct foreign key table reference. 2020-07-28 13:33:59 +01:00
Juan Leyva 8f6f312d65 MDL-69095 tool_mobile: Display warning if not allowed to use qr login 2020-07-28 13:55:21 +02:00
Juan Leyva 5762e5ec3e MDL-69095 tool_mobile: Avoid non-https sites using qrlogin by default 2020-07-28 13:55:21 +02:00
Leon Stringer 52dbe51339 MDL-60493 mod_assign: Unused JS variables
Removed unused JavaScript variables fixing CI warning "ESLint error
[no-unused-vars]".
2020-07-28 12:04:03 +01:00
Leon Stringer dfaad3e8ca 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:03:29 +01:00
Jun Pataleta 7da6f2675d Merge branch 'MDL-65453-39' of git://github.com/lameze/moodle into MOODLE_39_STABLE 2020-07-28 11:42:17 +08:00
Simey Lameze 9ae2623d89 MDL-65453 core: fix behaviour of --skip-database option on install 2020-07-28 11:27:30 +08:00
Paul Holden e64f37c3c5 MDL-69204 tool_dataprivacy: summary link only on current user profile. 2020-07-27 17:25:02 +01:00
Jun Pataleta b39ed13500 Merge branch 'MDL-66755-39' of https://github.com/SergioComeron/moodle into MOODLE_39_STABLE 2020-07-27 16:55:43 +08:00
Adrian Greeve 532a81f846 Merge branch 'MDL-69079-39-1' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-07-27 08:54:26 +08:00
AMOS bot 2b96f7b343 Automatically generated installer lang files 2020-07-27 00:07:30 +00:00
AMOS bot 6a07b3c08c Automatically generated installer lang files 2020-07-27 00:07:30 +00:00
Mikhail Golenkov 744726275d MDL-66626 assignfeedback_editpdf: Check page count for attempt.
Co-Authored-By: John Yao <johnyao@catalyst-au.net>
2020-07-27 09:51:11 +10:00
Mikhail Golenkov 07afdeedac MDL-66626 assignfeedback_editpdf: Count files outside of foreach loop.
Co-Authored-By: John Yao <johnyao@catalyst-au.net>
2020-07-27 09:51:11 +10:00
AMOS bot b8c3fefd02 Automatically generated installer lang files 2020-07-25 00:07:55 +00:00
Paul Holden ac7cb0921b MDL-68706 customfield_textarea: allow field content to be cleared. 2020-07-24 13:44:48 +01:00
Paul Holden 6b6a083916 MDL-69353 admin: set page title when prompting for upgrade key. 2020-07-24 13:30:27 +01:00
Tim Hunt 6acd719f0f MDL-67002 quiz reports: fix sorting on Oracle in the responses report 2020-07-24 11:45:02 +01:00
Sergio Comerón 455e7f50d8 MDL-66755 forum: Subscription cancel when edit a message 2020-07-24 09:04:25 +02:00
Mihail Geshoski f49fe84488 MDL-69079 core: Restore and set missing guest user 2020-07-24 11:11:42 +08:00
Mihail Geshoski 5ce4bd05df MDL-69079 course: Handle missing guest when fetching recommended modules 2020-07-24 11:09:31 +08:00
Mihail Geshoski b9f2e3d99b MDL-69079 course: Handle fetch module data failures in activity chooser 2020-07-24 11:09:28 +08:00
AMOS bot 42bcf62000 Automatically generated installer lang files 2020-07-24 00:09:19 +00:00
Sam Marshall 86f5acdc88 MDL-63252 tool_xmldb: convert default to float to avoid false positives 2020-07-24 07:53:52 +08:00
Simey Lameze 45aa8db99d MDL-68968 core: fix wrong phpdoc on admin_externalpage 2020-07-24 07:46:22 +08:00
Amaia Anabitarte d35fc78761 MDL-69199 mod_quiz: Show timefinish in user Complete report 2020-07-23 18:54:05 +02:00
Victor Deniz Falcon d8b0be3eb3 weekly release 3.9.1+ 2020-07-23 16:10:40 +01:00
Victor Deniz Falcon 12e884c5b3 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-07-23 16:10:34 +01:00
David Mudrák 115d6033fc 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:02:31 +02:00
Bas Brands 9ffeab1ad1 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:44 +02:00
AMOS bot 7bad9a9f15 Automatically generated installer lang files 2020-07-23 00:07:49 +00:00
Victor Deniz Falcon 5a003a1da9 Merge branch 'MDL-65819-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-07-22 19:00:14 +01:00
Ferran Recio 9e96129104 MDL-55299 mod_feedback: fix quoted values donwload 2020-07-22 19:23:46 +02:00
Paul Holden 5068d59b13 MDL-69311 dataformat: correct license docblock.
When this class was implemented in 8844cb82, it incorrectly set the
license to Moodle Workplace.
2020-07-22 10:44:38 +01:00
Andrew Nicols bf9c4ab68a MDL-69138 behat: Update session->visit() to use visit step 2020-07-22 16:46:51 +08:00
Andrew Nicols 44022305cc MDL-69138 behat: Add "I visit :localurl" step 2020-07-22 16:46:51 +08:00
Jun Pataleta 0595cfb07d Merge branch 'MDL-52052-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-07-22 13:47:06 +08:00
Jun Pataleta c8098c7a80 Merge branch 'MDL-68178-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-07-22 12:58:58 +08:00
Eloy Lafuente (stronk7) 2e71c132fe Merge branch 'MDL-69160-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-21 23:29:36 +02:00
Bas Brands 7c3522f902 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:43:03 +02:00
David Mudrák 4dcb3165e7 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:51:20 +02:00
David Mudrák 4fbe8bec4a 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:48:35 +02:00
David Mudrák 4a723a329e 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:48:35 +02:00
Adrian Greeve 592b8980aa Merge branch 'MDL-67657-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-21 14:48:10 +08:00
Ferran Recio 1e63a97698 MDL-68423 message: avoid self-xss when send a message 2020-07-20 19:52:58 +02:00
Eloy Lafuente (stronk7) 9d41810bed Merge branch 'm39_MDL-67440' of https://github.com/danmarsden/moodle into MOODLE_39_STABLE 2020-07-20 17:08:21 +02:00
Leon Stringer 8cdebcf4e0 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:48:50 +01:00
Bas Brands 9744e6e8cb MDL-66670 theme_boost: list bullet styling
Ensure lists with bullets are not cut off
2020-07-20 14:49:08 +02:00
Jake Dallimore f4d6bd1188 MDL-69319 mod_lti: style and docs changes in external tests 2020-07-20 15:00:25 +08:00
Jake Dallimore d8c8c75ec4 MDL-69319 mod_lti: replace try/catch with expectException in ext tests 2020-07-20 15:00:25 +08:00
Jake Dallimore 9eaaa8997b MDL-69319 mod_lti: remove unused vars from externallib_test 2020-07-20 15:00:24 +08:00
Jake Dallimore ef2a7d7302 MDL-69319 mod_lti: move test data generation out of common setup 2020-07-20 15:00:24 +08:00
Jake Dallimore b660b92b3f MDL-69319 mod_lti: call clean_returnvalue in external tests 2020-07-20 15:00:24 +08:00
Mihail Geshoski 87ae4833c4 MDL-68178 auth: CSRF protection for the resend confirmation email form
Credit to Chandra Kishor.
2020-07-20 12:36:29 +08:00
Adrian Greeve 4f9d34da81 Merge branch 'MDL-69113_39' of https://github.com/jonof/moodle into MOODLE_39_STABLE 2020-07-20 10:37:03 +08:00
Mihail Geshoski 13ad9d1f5b MDL-52052 gradeimport_csv: Do not skip rows with blank user fields 2020-07-20 08:55:05 +08:00
Eloy Lafuente (stronk7) 8cf328dc54 Merge branch 'MDL-69278-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-18 11:56:01 +02:00
Paul Holden af1f371aa7 MDL-65819 message: send contact requests using recipient language. 2020-07-17 13:33:20 +01:00
Sara Arjona 3e78b603a5 weekly release 3.9.1+ 2020-07-16 21:28:34 +02:00
Andrew Nicols 50da793d5b 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 4affbe94be MDL-67657 behat: Convert existing uses of executeScript 2020-07-16 11:06:31 +08:00
Andrew Nicols d18eacbd35 MDL-67657 behat: Add wrapper for JS execution 2020-07-16 11:05:32 +08:00
Jun Pataleta 3de3755281 Merge branch 'MDL-69215-39-2' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-16 09:42:52 +08:00
Andrew Nicols 04a1611139 MDL-69278 behat: Correct variable name 2020-07-16 08:29:57 +08:00
Andrew Nicols 0b5889d299 MDL-69278 behat: Mark tests as failed when unable to start Session 2020-07-16 08:29:57 +08:00
Andrew Nicols aa6bf0f367 MDL-69215 output: Correct use of icon_system::instance 2020-07-16 07:30:32 +08:00
Andrew Nicols 7164e1626e MDL-69215 output: Correct font awesome for themes 2020-07-16 07:30:32 +08:00
Eloy Lafuente (stronk7) a869415180 Merge branch 'MDL-69214-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-07-16 00:01:19 +02:00
Eloy Lafuente (stronk7) b39f2de8ad Merge branch 'MDL-69165-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE 2020-07-15 23:47:24 +02:00
Charles Fulton b02b1f3ea9 MDL-69074 admin: ensure consistent default for getremoteaddrconf 2020-07-15 19:05:52 +02:00
Sara Arjona 72ad5d94ea Merge branch 'MDL-68605_39' of https://github.com/t-schroeder/moodle into MOODLE_39_STABLE 2020-07-15 18:52:46 +02:00
Sara Arjona 1c2358de43 Merge branch 'MDL-68210-39' of https://github.com/snake/moodle into MOODLE_39_STABLE 2020-07-15 18:19:44 +02:00
Shamim Rezaie ba56dfb574 MDL-66707 mod_forum: do not blindly mark discussion replies as read 2020-07-15 22:27:10 +10:00
Sara Arjona da48e72353 Merge branch 'MDL-67671_39_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_39_STABLE 2020-07-15 14:11:46 +02:00
Sara Arjona 3c5757b0e2 Merge branch 'MDL-57678-39' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-07-15 12:56:20 +02:00
Jun Pataleta e1a310bde7 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:27:02 +08:00
Sara Arjona a040f29f03 Merge branch 'MDL-69068-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-15 12:20:30 +02:00
Andrew Nicols 3f3262c76e MDL-69068 behat: Allow singular, pivotted data generators 2020-07-15 15:27:31 +08:00
Andrew Nicols 5018c4e4db MDL-69068 behat: New step to support singular generators 2020-07-15 15:27:31 +08:00
Jake Dallimore 6e5ae126af Merge branch 'MDL-69206-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-07-15 10:29:28 +08:00
Sara Arjona a0b8d8c0ff Merge branch 'MDL-68715-39' of https://github.com/paulholden/moodle into MOODLE_39_STABLE 2020-07-14 14:31:55 +02:00
Shamim Rezaie 1636ee5980 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:49 +10:00
Shamim Rezaie a092131b73 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:49 +10:00
Paul Holden b4a73ff47f 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:58 +01:00
Sara Arjona 73c4f6c2a5 Merge branch 'MDL-69228-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-14 12:41:23 +02:00
Mihail Geshoski d8a886d75a MDL-69206 course: Tidy up behat test to avoid potential failures 2020-07-14 12:11:50 +08:00
Mihail Geshoski 480f26720d MDL-69206 course: Tidy up unit test to avoid potential failures 2020-07-14 12:11:50 +08:00
Sara Arjona 333d17b8e1 Merge branch 'MDL-69115-39' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-07-13 14:24:15 +02:00
Andrew Nicols f78caa59d2 MDL-69160 workshop: Ensure steps are chained 2020-07-13 14:22:32 +08:00
Andrew Nicols 1f09dea479 MDL-69160 behat: Add form field setter step 2020-07-13 14:22:31 +08:00
Eloy Lafuente (stronk7) 8e619076cb Moodle release 3.9.1 2020-07-12 12:13:02 +02:00
Leon Stringer d80e9d463d 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:52:28 +01:00
AMOS bot 6a17f29147 Automatically generated installer lang files 2020-07-10 19:52:47 +00:00
Eloy Lafuente (stronk7) cafc042bf6 weekly release 3.9+ 2020-07-10 20:22:25 +02:00
Eloy Lafuente (stronk7) d2e303436b Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-07-10 20:22:18 +02:00
Jake Dallimore fb0d5acf4c Merge branch 'MDL-69232-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-10 15:12:29 +08:00
Andrew Nicols 376d34142f 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 8eb7f7e366 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 762e8afa6f MDL-67671 backup: Fix modname display on backup form 2020-07-09 10:11:52 +01:00
Jake Dallimore c3018e9ee7 Merge branch 'MDL-69135-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-09 10:38:21 +08:00
Michael Hawkins 996c94fd08 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:23:44 +08:00
Andrew Nicols fd7c3c4834 MDL-69232 behat: Add debugging information to Selenium fails 2020-07-09 09:45:32 +08:00
Andrew Nicols c3b7f2f974 MDL-69232 behat: Move suite tests to BeforeSuite hook 2020-07-09 09:45:32 +08:00
Eloy Lafuente (stronk7) 8589fbda8c Merge branch 'MDL-69134-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-08 20:53:22 +02:00
Jake Dallimore f1a681c983 Merge branch 'MDL-69104-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE 2020-07-08 13:07:01 +08:00
Huong Nguyen a17188f51c MDL-69165 Questions: Incorrect id used in init_submit_button function 2020-07-08 11:47:24 +07:00
Andrew Nicols 8a66849a57 Merge branch 'MDL-68784-39' of https://github.com/Peterburnett/moodle into MOODLE_39_STABLE 2020-07-08 12:37:27 +08:00
Andrew Nicols 20318b8b7d Merge branch 'm39_MDL-66322_Travis_Run_Using_Docker_ExtTests-v2' of https://github.com/scara/moodle into MOODLE_39_STABLE 2020-07-08 12:20:52 +08:00
Peter Burnett d84d6f57a3 MDL-68784: Updated variable for graph report 2020-07-08 14:06:23 +10:00
Andrew Nicols 619e11c07a MDL-69228 tool_mobile: Hide dependant settings 2020-07-08 11:44:31 +08:00
Juan Leyva 01ec0ee85b MDL-69031 tool_mobile: Add missing features that can be disabled in 3.9 2020-07-08 09:36:44 +08:00
Andrew Nicols 91b23a2caa Merge branch 'MDL-60494-stray_img_end-39' of https://github.com/leonstr/moodle into MOODLE_39_STABLE 2020-07-08 09:24:05 +08:00
Andrew Nicols 053a433d74 MDL-69134 competencies: Behat fails randomly opening dialogues 2020-07-08 09:21:51 +08:00
Jake Dallimore 3725a41b39 MDL-68210 mod_lesson: fix random failure in override behat test 2020-07-08 09:07:06 +08:00
Jake Dallimore fe5ca8e768 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:06:58 +08:00
Marina Glancy b1a2e67326 MDL-69109 theme: try to load icons from the current theme 2020-07-08 08:40:52 +08:00
Marina Glancy 40553ed459 MDL-69109 core: use different cache keys for FA icon maps 2020-07-08 08:40:51 +08:00
Matt Clarkson ae9e1f1888 MDL-67440 analytics: optimse delete's in clean up task. 2020-07-08 11:18:20 +12:00
Matteo Scaramuccia 9127c17778 MDL-66322 travis: Configure a local copy of 'exttests' 2020-07-07 21:34:06 +02:00
Andrew Nicols 8f28fbee11 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-07-07 20:01:02 +02:00
Eloy Lafuente (stronk7) be7bda671e Merge branch 'm39_MDL-68588_Hide_Backuptempdir_From_Message_And_Debuginfo' of https://github.com/scara/moodle into MOODLE_39_STABLE 2020-07-07 19:10:41 +02:00
Eloy Lafuente (stronk7) c58101cde3 Merge branch 'MDL-68784-39' of https://github.com/Peterburnett/moodle into MOODLE_39_STABLE 2020-07-07 18:52:27 +02:00
Paul Holden 4a16804df7 MDL-69214 user: correct participant table forced group SQL. 2020-07-07 14:37:23 +01:00
Tim Schroeder ff92024ec2 MDL-68605 mod_assign: return grp submissns from ws
Co-authored-by: Septatrix <24257556+Septatrix@users.noreply.github.com>
2020-07-07 12:55:54 +02:00
Víctor Déniz Falcón 6e5b0b5c20 MDL-69093 enrol_manual: added check for allowed roles a user can assign 2020-07-07 08:33:08 +02:00
Andrew Nicols c201456f20 Merge branch 'MDL-69106-39' of git.in.moodle.com:cameron/moodle into MOODLE_39_STABLE 2020-07-07 14:15:54 +08:00
Eloy Lafuente (stronk7) 02b3d5aacf Merge branch 'MDL-60827-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-07-07 00:17:26 +02:00
Andrew Nicols dde1ead9fe MDL-69110 table: Remove commented code 2020-07-06 13:26:28 +08:00
Andrew Nicols 3915147b9b Merge branch 'MDL-69110-39' of git://github.com/junpataleta/moodle into MOODLE_39_STABLE 2020-07-06 13:26:00 +08:00
Andrew Nicols 55c7fe15a0 Merge branch 'MDL-69158-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-07-06 12:12:12 +08:00
Jake Dallimore 82dba4d510 Merge branch 'MDL-69136-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-06 10:44:34 +08:00
Mihail Geshoski 9ecff3766a MDL-60827 oauth2: Consider requireconfirmation setting on login 2020-07-06 10:05:16 +08:00
Michael Hawkins 4fb85c9c9f MDL-69128 admin: Convert HTML entities when populating tasklogs filter 2020-07-06 10:04:17 +08:00
AMOS bot 6ea5922916 Automatically generated installer lang files 2020-07-06 00:08:30 +00:00
Leon Stringer 287e8f16e6 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:57:42 +01:00
Matteo Scaramuccia 846422a90f MDL-68588 Backup: Hide ->backuptempdir in exception info 2020-07-03 21:18:30 +02:00
Jun Pataleta ea6621e00e MDL-69110 core: Unset the correct sort data element 2020-07-04 00:50:21 +08:00
Eloy Lafuente (stronk7) 44ffa8a801 weekly release 3.9+ 2020-07-03 18:41:38 +02:00
Eloy Lafuente (stronk7) a1d5911159 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-07-03 18:41:32 +02:00
Jake Dallimore c38e38d6b4 Merge branch 'MDL-69130-39-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-07-02 12:08:37 +08:00
Jake Dallimore f5b5f97f56 Merge branch 'MDL-69149-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-02 11:57:18 +08:00
Jake Dallimore 5528302282 Merge branch 'MDL-69122-39' of git://github.com/bmbrands/moodle into MOODLE_39_STABLE 2020-07-02 11:49:19 +08:00
AMOS bot 995f0a3a58 Automatically generated installer lang files 2020-07-02 00:08:08 +00:00
Eloy Lafuente (stronk7) 894ebe38a2 Merge branch 'MDL-69072-39' of git://github.com/andrewnicols/moodle into MOODLE_39_STABLE 2020-07-01 23:23:45 +02:00
Andrew Nicols 0609febf16 MDL-69072 behat: Remove restart_browser_after feature
This is no longer required as the Mink session is restarted after every
test regardless.
2020-07-01 23:23:39 +02:00
Luca Bösch 1d6c1cc0ae 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-07-01 16:42:50 +08:00
Jun Pataleta 50b076c4af 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:26 +08:00
Paul Holden d783f12861 MDL-69150 message_airnotifier: correct apps portal link. 2020-07-01 08:39:47 +08:00
Paul Holden f324c2d16c 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:32:34 +08:00
Huong Nguyen 5486975097 MDL-69104 Questions: Drag and drop question family don't work with iOS
- Drag and Drop marker question type
 - Drag and Drop onto image question type
 - Drag and Drop into text question type
2020-06-30 14:48:47 +07:00
Cameron Ball d4b6b26f4f 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:56:57 +08:00
Peter Burnett 996dd0b0b9 MDL-68784 scorm: Removed limit on allowed scorm users in report 2020-06-30 15:17:51 +10:00
Luca Bösch b44588aaba MDL-69158 block_blog_menu: format search form. 2020-06-29 11:13:55 +02:00
Andrew Nicols 95fbf4d8e5 MDL-69136 behat: Improve reliability of navigation steps 2020-06-29 11:36:36 +08:00
Andrew Nicols 6f78024717 MDL-69136 behat: Support find on a NodeElement 2020-06-29 11:36:30 +08:00
Andrew Nicols 7b2e257157 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:23 +08:00
Andrew Nicols bb344d07e7 MDL-69072 behat: Relaunch browser session between scenarios 2020-06-26 21:17:22 +08:00
Andrew Nicols 959c2cb84e MDL-69149 core_grade: Correct xpath attribute selector 2020-06-26 19:59:56 +08:00
Andrew Nicols ee7b438f61 MDL-69135 core_calendar: PendingJS for event filtering 2020-06-26 07:58:36 +08:00
Helen Foster dc0241306b MDL-69130 lang: Import fixed English strings (en_fix)
Significant string change:

- presentationoraltrequired,atto_image - wording changed to mention
  'decorative only' checkbox
2020-06-25 21:52:35 +02:00
Eloy Lafuente (stronk7) 89ce4db476 weekly release 3.9+ 2020-06-25 18:06:36 +02:00
Eloy Lafuente (stronk7) 55a1405a84 Merge branch 'install_39_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_39_STABLE 2020-06-25 18:06:31 +02:00
Jonathon Fowler fb21fc9274 MDL-69113 assign: save grader app workflow/marker filters correctly 2020-06-25 14:40:07 +10:00
Bas Brands 57b920b8b7 MDL-69122 report_competency: fix clearfix
- a misplaced clearfix caused part of the recontrols to be
inaccessible
2020-06-24 09:15:28 +02:00
Nicolas Martignoni bae07c1bfb 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-24 10:14:53 +08:00
Peter Dias 4f7016f2da MDL-69065 course: Provide the id for the sr param
* Pass the section return id to the activity chooser
* Additional behat test to cover the case
2020-06-24 10:14:51 +08:00
Andrew Nicols 7af8441403 MDL-66568 behat: Reset theme CSS between scenarios 2020-06-23 18:03:52 +02:00
Andrew Nicols 7ba95339a6 MDL-66568 behat: Support building of themes for behat 2020-06-23 18:03:52 +02:00
Andrew Nicols b6c37f2926 MDL-66568 core_output: Return built theme CSS 2020-06-23 18:03:52 +02:00
AMOS bot b8408c3582 Automatically generated installer lang files 2020-06-23 12:25:17 +00:00
Bas Brands fb625069cf 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-23 11:31:23 +08:00
hiendinh d4297993a4 MDL-68841 Modal dialogs: Wrong behavior of popup 2020-06-23 09:45:44 +08:00
Víctor Déniz Falcón 2104324ded Merge branch 'MDL-69099-39-disabledtasks' of git://github.com/mudrd8mz/moodle into MOODLE_39_STABLE 2020-06-22 17:20:10 +01:00
David Mudrák 153b2cb484 MDL-69099 tasks: Do not mark the non-enabled plugin's task as disabled
The `core\plugininfo\base::is_enabled()` uses three-state logic for its
return value. It can return null as a valid value as per its
documentation. We need to test for the explicit false value in this
case.

To make the attached Behat test able to identify the table, the caption
is added. It seems to be helpful for all users so I leave it displayed
without using the accesshide mechanism.
2020-06-22 10:10:15 +02:00
Jake Dallimore c72adaa749 Merge branch 'MDL-69047-39' of git://github.com/aanabit/moodle into MOODLE_39_STABLE 2020-06-22 12:41:28 +08:00
Adrian Greeve 3c2ed1533c Merge branch 'MDL-69077_39' of https://github.com/timhunt/moodle into MOODLE_39_STABLE 2020-06-22 10:41:47 +08:00
Jun Pataleta b9518bf811 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-19 16:49:03 +02:00
Amaia Anabitarte 4f0f1bd84f MDL-69047 core_contentbank: Hard coding status messages 2020-06-18 18:07:41 +02:00
Sara Arjona e2ef786003 weekly release 3.9+ 2020-06-18 14:14:00 +02:00
Russell Boyatt 5b134b5de5 MDL-66899 quiz: Adding test for regrading quiz event. 2020-06-18 04:52:47 +01:00
Russell Boyatt 62c4da281a MDL-66899 quiz: Log a regrading event when quiz attempt is regraded. 2020-06-18 04:52:47 +01:00
Víctor Déniz Falcón 4c27f858b9 Merge branch 'MDL-69060-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-06-17 23:44:40 +01:00
Tim Hunt 6ced5c26d0 MDL-69077 questions: question tag capabilties are relevant 2020-06-17 13:07:30 +01:00
hiendinh ccd504115d MDL-68890 progressbar: prevent display exist file's progress bar 2020-06-17 19:54:06 +08:00
Jake Dallimore 647e5d8021 Merge branch 'MDL-68215-39' of git://github.com/lucaboesch/moodle into MOODLE_39_STABLE 2020-06-17 14:58:35 +08:00
Tim Hunt 6a7042d980 MDL-68971 webservice: errors should give enough info to find the problem 2020-06-17 11:36:46 +08:00
Jun Pataleta 7532b032bb Merge branch 'MDL-67294-39' of git://github.com/mihailges/moodle into MOODLE_39_STABLE 2020-06-17 10:36:14 +08:00
Jun Pataleta b5c1d17da5 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-16 17:59:03 +01:00
Mihail Geshoski 56a7d91066 MDL-67294 assignsubmission_file: Make sure record exists before updating 2020-06-17 00:55:46 +08:00
Tim Hunt 93d636a95b MDL-68436 atto_recordrtc: only works once per page 2020-06-16 14:40:35 +08:00
Víctor Déniz Falcón 7ca771e4ac Merge branch 'MDL-69044_39' of https://github.com/stronk7/moodle into MOODLE_39_STABLE 2020-06-15 17:36:32 +01:00
Luca Bösch 6e7e7e1241 MDL-68215 block_activity_result: Format elements more nicely. 2020-06-15 15:26:13 +02:00
Luca Bösch 8b43f32f8c MDL-69060 core_contentbank: fix contenbank typos. 2020-06-15 13:37:00 +02:00
Eloy Lafuente (stronk7) a30eb7d16c MDL-69044 upgrade: add 3.9.0 separation line to all upgrade scripts 2020-06-14 13:09:13 +02:00
4840 changed files with 95768 additions and 223470 deletions
+3 -7
View File
@@ -1,5 +1,4 @@
# Generated by "grunt ignorefiles"
!/.grunt
*/**/yui/src/*/meta/
*/**/build/
node_modules/
@@ -20,7 +19,6 @@ lib/editor/tinymce/plugins/spellchecker/rpc.php
lib/editor/tinymce/tiny_mce/
lib/mlbackend/php/phpml/
lib/adodb/
lib/behat/axe/
lib/bennu/
lib/evalmath/
lib/phpspreadsheet/
@@ -68,9 +66,6 @@ lib/babel-polyfill/
lib/polyfills/
lib/emoji-data/
lib/plist/
lib/zipstream/
lib/php-enum/
lib/http-message/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
@@ -84,6 +79,7 @@ theme/boost/amd/src/bootstrap/button.js
theme/boost/amd/src/bootstrap/carousel.js
theme/boost/amd/src/bootstrap/collapse.js
theme/boost/amd/src/bootstrap/dropdown.js
theme/boost/amd/src/bootstrap/index.js
theme/boost/amd/src/bootstrap/modal.js
theme/boost/amd/src/bootstrap/popover.js
theme/boost/amd/src/bootstrap/tools/sanitizer.js
@@ -92,5 +88,5 @@ theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/amd/src/index.js
theme/boost/scss/fontawesome/
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
+1 -1
View File
@@ -204,7 +204,7 @@
}
},
{
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile.js", ".grunt/*.js", ".grunt/tasks/*.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
+4 -14
View File
@@ -1,15 +1,9 @@
name: Core
on:
push:
branches-ignore:
- master
- MOODLE_[0-9]+_STABLE
tags-ignore:
- v[0-9]+.[0-9]+.[0-9]+*
on: [push]
env:
php: 8.0
php: 7.4
jobs:
Grunt:
@@ -54,13 +48,11 @@ jobs:
matrix:
include:
- os: ubuntu-18.04
php: 7.3
extensions:
php: 7.2
db: mysqli
- os: ubuntu-18.04
php: 8.0
php: 7.4
db: pgsql
extensions: xmlrpc-beta
steps:
- name: Setting up DB mysql
@@ -90,8 +82,6 @@ jobs:
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 }}
-3
View File
@@ -33,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
@@ -45,5 +44,3 @@ composer.phar
/lib/yuilib/*/*/*-coverage.js
atlassian-ide-plugin.xml
/node_modules/
/.vscode/
moodle-plugin-ci.phar
-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();
});
};
-89
View File
@@ -1,89 +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'],
},
},
});
return handler;
};
-59
View File
@@ -1,59 +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');
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',
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n') + '\n');
};
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', handler);
return handler;
};
-141
View File
@@ -1,141 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Function to generate the destination for the uglify task
* (e.g. build/file.min.js). This function will be passed to
* the rename property of files array when building dynamically:
* http://gruntjs.com/configuring-tasks#building-the-files-object-dynamically
*
* @param {String} destPath the current destination
* @param {String} srcPath the matched src path
* @return {String} The rewritten destination path.
*/
const babelRename = function(destPath, srcPath) {
destPath = srcPath.replace('src', 'build');
destPath = destPath.replace('.js', '.min.js');
return destPath;
};
module.exports = grunt => {
// Load the Shifter tasks.
require('./shifter')(grunt);
// Load ESLint.
require('./eslint')(grunt);
const path = require('path');
// Register JS tasks.
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
grunt.registerTask('amd', ['eslint:amd', 'babel']);
grunt.registerTask('js', ['amd', 'yui']);
// Register NPM tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
// Load the Babel tasks and config.
grunt.loadNpmTasks('grunt-babel');
grunt.config.merge({
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('.grunt/babel-plugin-add-module-to-define.js'),
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-syntax-import-meta',
['@babel/plugin-proposal-class-properties', {'loose': false}],
'@babel/plugin-proposal-json-strings'
],
presets: [
['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: 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']
},
},
});
// 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('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();
});
return {
babelRename,
};
};
-40
View File
@@ -1,40 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
grunt.loadNpmTasks('grunt-sass');
grunt.config.merge({
sass: {
dist: {
files: {
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss",
"theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss"
}
},
options: {
implementation: require('node-sass'),
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
}
},
});
};
-155
View File
@@ -1,155 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/* eslint-env node */
module.exports = grunt => {
/**
* Shifter task. Is configured with a path to a specific file or a directory,
* in the case of a specific file it will work out the right module to be built.
*
* Note that this task runs the invidiaul shifter jobs async (becase it spawns
* so be careful to to call done().
*/
const handler = function() {
const done = this.async();
const options = grunt.config('shifter.options');
const async = require('async');
const path = require('path');
// Run the shifter processes one at a time to avoid confusing output.
async.eachSeries(options.paths, function(src, filedone) {
var args = [];
args.push(path.normalize(process.cwd() + '/node_modules/shifter/bin/shifter'));
// Always ignore the node_modules directory.
args.push('--excludes', 'node_modules');
// Determine the most appropriate options to run with based upon the current location.
if (grunt.file.isMatch('**/yui/**/*.js', src)) {
// When passed a JS file, build our containing module (this happen with
// watch).
grunt.log.debug('Shifter passed a specific JS file');
src = path.dirname(path.dirname(src));
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src', src)) {
// When in a src directory --walk all modules.
grunt.log.debug('In a src directory');
args.push('--walk');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*', src)) {
// When in module, only build our module.
grunt.log.debug('In a module directory');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*/js', src)) {
// When in module src, only build our module.
grunt.log.debug('In a source directory');
src = path.dirname(src);
options.recursive = false;
}
if (grunt.option('watch')) {
grunt.fail.fatal('The --watch option has been removed, please use `grunt watch` instead');
}
// Add the stderr option if appropriate
if (grunt.option('verbose')) {
args.push('--lint-stderr');
}
if (grunt.option('no-color')) {
args.push('--color=false');
}
var execShifter = function() {
grunt.log.ok("Running shifter on " + src);
grunt.util.spawn({
cmd: "node",
args: args,
opts: {cwd: src, stdio: 'inherit', env: process.env}
}, function(error, result, code) {
if (code) {
grunt.fail.fatal('Shifter failed with code: ' + code);
} else {
grunt.log.ok('Shifter build complete.');
filedone();
}
});
};
// Actually run shifter.
if (!options.recursive) {
execShifter();
} else {
// Check that there are yui modules otherwise shifter ends with exit code 1.
if (grunt.file.expand({cwd: src}, '**/yui/src/**/*.js').length > 0) {
args.push('--recursive');
execShifter();
} else {
grunt.log.ok('No YUI modules to build.');
filedone();
}
}
}, done);
};
// Register the shifter task.
grunt.registerTask('shifter', 'Run Shifter against the current directory', handler);
// Configure it.
grunt.config.set('shifter', {
options: {
recursive: true,
// Shifter takes a relative path.
paths: grunt.moodleEnv.files ? grunt.moodleEnv.files : [grunt.moodleEnv.runDir]
}
});
grunt.config.merge({
watch: {
yui: {
files: grunt.moodleEnv.inComponent
? ['yui/src/*.json', 'yui/src/**/*.js']
: ['**/yui/src/**/*.js'],
tasks: ['yui']
},
},
});
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
let changedFiles = Object.create(null);
const onChange = grunt.util._.debounce(function() {
const files = Object.keys(changedFiles);
grunt.config('shifter.options.paths', files);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', (action, filepath) => {
changedFiles[filepath] = action;
onChange();
});
return handler;
};
-48
View File
@@ -1,48 +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 them all!.
grunt.task.run('css');
grunt.task.run('js');
grunt.task.run('gherkinlint');
}
};
// Register the startup task.
grunt.registerTask('startup', 'Run the correct tasks for the current directory', handler);
return handler;
};
-29
View File
@@ -1,29 +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 Style Lint tasks.
require('./stylelint')(grunt);
// Load the SASS tasks.
require('./sass')(grunt);
};
-181
View File
@@ -1,181 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
const getCssConfigForFiles = files => {
return {
stylelint: {
css: {
// Use a fully-qualified path.
src: files,
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
}
}
}
},
},
};
};
const getScssConfigForFiles = files => {
return {
stylelint: {
scss: {
options: {syntax: 'scss'},
src: files,
},
},
};
};
/**
* Register any stylelint tasks.
*
* @param {Object} grunt
* @param {Array} files
* @param {String} fullRunDir
*/
const registerStyleLintTasks = () => {
const glob = require('glob');
// The stylelinters do not handle the case where a configuration was provided but no files were included.
// Keep track of whether any files were found.
let hasCss = false;
let hasScss = false;
// The stylelint processors do not take a path argument. They always check all provided values.
// As a result we must check through each glob and determine if any files match the current directory.
const scssFiles = [];
const cssFiles = [];
const requestedFiles = grunt.moodleEnv.files;
if (requestedFiles) {
// Grunt was called with a files argument.
// Check whether each of the requested files matches either the CSS or SCSS source file list.
requestedFiles.forEach(changedFilePath => {
let matchesGlob;
// Check whether this watched path matches any watched SCSS file.
matchesGlob = grunt.moodleEnv.scssSrc.some(watchedPathGlob => {
return glob.sync(watchedPathGlob).indexOf(changedFilePath) !== -1;
});
if (matchesGlob) {
scssFiles.push(changedFilePath);
hasScss = true;
}
// Check whether this watched path matches any watched CSS file.
matchesGlob = grunt.moodleEnv.cssSrc.some(watchedPathGlob => {
return glob.sync(watchedPathGlob).indexOf(changedFilePath) !== -1;
});
if (matchesGlob) {
cssFiles.push(changedFilePath);
hasCss = true;
}
});
} else {
// Grunt was called without a list of files.
// The start directory (runDir) may be a child dir of the project.
// Check each scssSrc file to see if it's in the start directory.
// This means that we can lint just mod/*/styles.css if started in the mod directory.
grunt.moodleEnv.scssSrc.forEach(path => {
if (path.startsWith(grunt.moodleEnv.runDir)) {
scssFiles.push(path);
hasScss = true;
}
});
grunt.moodleEnv.cssSrc.forEach(path => {
if (path.startsWith(grunt.moodleEnv.runDir)) {
cssFiles.push(path);
hasCss = true;
}
});
}
// Register the tasks.
const scssTasks = ['sass'];
if (hasScss) {
grunt.config.merge(getScssConfigForFiles(scssFiles));
scssTasks.unshift('stylelint:scss');
}
const cssTasks = [];
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',
],
tasks: ['rawcss']
},
scss: {
files: getCoreThemeMatches(),
tasks: ['scss']
},
},
});
};
-272
View File
@@ -1,272 +0,0 @@
/**
* This is a wrapper task to handle the grunt watch command. It attempts to use
* Watchman to monitor for file changes, if it's installed, because it's much faster.
*
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
* watcher for backwards compatibility.
*/
/* eslint-env node */
module.exports = grunt => {
/**
* This is a wrapper task to handle the grunt watch command. It attempts to use
* Watchman to monitor for file changes, if it's installed, because it's much faster.
*
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
* watcher for backwards compatibility.
*/
const watchHandler = function() {
const async = require('async');
const watchTaskDone = this.async();
let watchInitialised = false;
let watchTaskQueue = {};
let processingQueue = false;
const watchman = require('fb-watchman');
const watchmanClient = new watchman.Client();
// Grab the tasks and files that have been queued up and execute them.
var processWatchTaskQueue = function() {
if (!Object.keys(watchTaskQueue).length || processingQueue) {
// If there is nothing in the queue or we're already processing then wait.
return;
}
processingQueue = true;
// Grab all tasks currently in the queue.
var queueToProcess = watchTaskQueue;
// Reset the queue.
watchTaskQueue = {};
async.forEachSeries(
Object.keys(queueToProcess),
function(task, next) {
var files = queueToProcess[task];
var filesOption = '--files=' + files.join(',');
grunt.log.ok('Running task ' + task + ' for files ' + filesOption);
// Spawn the task in a child process so that it doesn't kill this one
// if it failed.
grunt.util.spawn(
{
// Spawn with the grunt bin.
grunt: true,
// Run from current working dir and inherit stdio from process.
opts: {
cwd: grunt.moodleEnv.fullRunDir,
stdio: 'inherit'
},
args: [task, filesOption]
},
function(err, res, code) {
if (code !== 0) {
// The grunt task failed.
grunt.log.error(err);
}
// Move on to the next task.
next();
}
);
},
function() {
// No longer processing.
processingQueue = false;
// Once all of the tasks are done then recurse just in case more tasks
// were queued while we were processing.
processWatchTaskQueue();
}
);
};
const originalWatchConfig = grunt.config.get(['watch']);
const watchConfig = Object.keys(originalWatchConfig).reduce(function(carry, key) {
if (key == 'options') {
return carry;
}
const value = originalWatchConfig[key];
const taskNames = value.tasks;
const files = value.files;
let excludes = [];
if (value.excludes) {
excludes = value.excludes;
}
taskNames.forEach(function(taskName) {
carry[taskName] = {
files,
excludes,
};
});
return carry;
}, {});
watchmanClient.on('error', function(error) {
// We have to add an error handler here and parse the error string because the
// example way from the docs to check if Watchman is installed doesn't actually work!!
// See: https://github.com/facebook/watchman/issues/509
if (error.message.match('Watchman was not found')) {
// If watchman isn't installed then we should fallback to the other watch task.
grunt.log.ok('It is recommended that you install Watchman for better performance using the "watch" command.');
// Fallback to the old grunt-contrib-watch task.
grunt.renameTask('watch-grunt', 'watch');
grunt.task.run(['watch']);
// This task is finished.
watchTaskDone(0);
} else {
grunt.log.error(error);
// Fatal error.
watchTaskDone(1);
}
});
watchmanClient.on('subscription', function(resp) {
if (resp.subscription !== 'grunt-watch') {
return;
}
resp.files.forEach(function(file) {
grunt.log.ok('File changed: ' + file.name);
var fullPath = grunt.moodleEnv.fullRunDir + '/' + file.name;
Object.keys(watchConfig).forEach(function(task) {
const fileGlobs = watchConfig[task].files;
var match = fileGlobs.some(function(fileGlob) {
return grunt.file.isMatch(`**/${fileGlob}`, fullPath);
});
if (match) {
// If we are watching a subdirectory then the file.name will be relative
// to that directory. However the grunt tasks expect the file paths to be
// relative to the Gruntfile.js location so let's normalise them before
// adding them to the queue.
var relativePath = fullPath.replace(grunt.moodleEnv.gruntFilePath + '/', '');
if (task in watchTaskQueue) {
if (!watchTaskQueue[task].includes(relativePath)) {
watchTaskQueue[task] = watchTaskQueue[task].concat(relativePath);
}
} else {
watchTaskQueue[task] = [relativePath];
}
}
});
});
processWatchTaskQueue();
});
process.on('SIGINT', function() {
// Let the user know that they may need to manually stop the Watchman daemon if they
// no longer want it running.
if (watchInitialised) {
grunt.log.ok('The Watchman daemon may still be running and may need to be stopped manually.');
}
process.exit();
});
// Initiate the watch on the current directory.
watchmanClient.command(['watch-project', grunt.moodleEnv.fullRunDir], function(watchError, watchResponse) {
if (watchError) {
grunt.log.error('Error initiating watch:', watchError);
watchTaskDone(1);
return;
}
if ('warning' in watchResponse) {
grunt.log.error('warning: ', watchResponse.warning);
}
var watch = watchResponse.watch;
var relativePath = watchResponse.relative_path;
watchInitialised = true;
watchmanClient.command(['clock', watch], function(clockError, clockResponse) {
if (clockError) {
grunt.log.error('Failed to query clock:', clockError);
watchTaskDone(1);
return;
}
// Generate the expression query used by watchman.
// Documentation is limited, but see https://facebook.github.io/watchman/docs/expr/allof.html for examples.
// We generate an expression to match any value in the files list of all of our tasks, but excluding
// all value in the excludes list of that task.
//
// [anyof, [
// [allof, [
// [anyof, [
// ['match', validPath, 'wholename'],
// ['match', validPath, 'wholename'],
// ],
// [not,
// [anyof, [
// ['match', invalidPath, 'wholename'],
// ['match', invalidPath, 'wholename'],
// ],
// ],
// ],
var matchWholeName = fileGlob => ['match', fileGlob, 'wholename'];
var matches = Object.keys(watchConfig).map(function(task) {
const matchAll = [];
matchAll.push(['anyof'].concat(watchConfig[task].files.map(matchWholeName)));
if (watchConfig[task].excludes.length) {
matchAll.push(['not', ['anyof'].concat(watchConfig[task].excludes.map(matchWholeName))]);
}
return ['allof'].concat(matchAll);
});
matches = ['anyof'].concat(matches);
var sub = {
expression: matches,
// Which fields we're interested in.
fields: ["name", "size", "type"],
// Add our time constraint.
since: clockResponse.clock
};
if (relativePath) {
/* eslint-disable camelcase */
sub.relative_root = relativePath;
}
watchmanClient.command(['subscribe', watch, 'grunt-watch', sub], function(subscribeError) {
if (subscribeError) {
// Probably an error in the subscription criteria.
grunt.log.error('failed to subscribe: ', subscribeError);
watchTaskDone(1);
return;
}
grunt.log.ok('Listening for changes to files in ' + grunt.moodleEnv.fullRunDir);
});
});
});
};
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
grunt.renameTask('watch', 'watch-grunt');
// Register the new watch handler.
grunt.registerTask('watch', 'Run tasks on file changes', watchHandler);
grunt.config.merge({
watch: {
options: {
nospawn: true // We need not to spawn so config can be changed dynamically.
},
},
});
return watchHandler;
};
+3 -6
View File
@@ -20,7 +20,6 @@ lib/editor/tinymce/plugins/spellchecker/rpc.php
lib/editor/tinymce/tiny_mce/
lib/mlbackend/php/phpml/
lib/adodb/
lib/behat/axe/
lib/bennu/
lib/evalmath/
lib/phpspreadsheet/
@@ -68,9 +67,6 @@ lib/babel-polyfill/
lib/polyfills/
lib/emoji-data/
lib/plist/
lib/zipstream/
lib/php-enum/
lib/http-message/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
@@ -84,6 +80,7 @@ theme/boost/amd/src/bootstrap/button.js
theme/boost/amd/src/bootstrap/carousel.js
theme/boost/amd/src/bootstrap/collapse.js
theme/boost/amd/src/bootstrap/dropdown.js
theme/boost/amd/src/bootstrap/index.js
theme/boost/amd/src/bootstrap/modal.js
theme/boost/amd/src/bootstrap/popover.js
theme/boost/amd/src/bootstrap/tools/sanitizer.js
@@ -92,5 +89,5 @@ theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/amd/src/index.js
theme/boost/scss/fontawesome/
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
+14 -21
View File
@@ -19,12 +19,6 @@ services:
addons:
postgresql: "9.6"
branches:
except:
- master
- /MOODLE_[0-9]+_STABLE/
- /^v[0-9]+\.[0-9]+\.[0-9]+.*/
jobs:
# Enable fast finish.
# This will fail the build if a single job fails (except those in allow_failures).
@@ -32,34 +26,34 @@ jobs:
fast_finish: true
include:
# First all the lowest php ones (7.3)
- php: 7.3
# First all the lowest php ones (7.2)
- php: 7.2
env: DB=none TASK=CITEST
- php: 7.3
- php: 7.2
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
- if: env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present
php: 7.3
php: 7.2
env: DB=pgsql TASK=PHPUNIT
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
php: 7.3
php: 7.2
env: DB=mysqli TASK=PHPUNIT
# Then, conditionally, all the highest php ones (8.0)
# Then, conditionally, all the highest php ones (7.4)
- if: env(MOODLE_PHP) = "all"
php: 8.0
php: 7.4
env: DB=none TASK=CITEST
- if: env(MOODLE_PHP) = "all"
php: 8.0
php: 7.4
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present)
php: 8.0
php: 7.4
env: DB=pgsql TASK=PHPUNIT
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
php: 8.0
php: 7.4
env: DB=mysqli TASK=PHPUNIT
cache:
@@ -118,8 +112,6 @@ install:
fi
before_script:
- if [[ ${TRAVIS_PHP_VERSION:0:1} -gt 7 ]]; then pecl install xmlrpc-beta; fi
- echo 'max_input_vars=5000' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
- phpenv config-rm xdebug.ini
- >
if [ "$TASK" = 'PHPUNIT' ];
@@ -189,9 +181,10 @@ before_script:
sed -i \
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
config.php ;
# Redis session tests
# Redis session tests, but not for PHP 7.2 and up. See MDL-60978 for more info.
redissession="define('TEST_SESSION_REDIS_HOST', '127.0.0.1');"
sed -i \
-e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
-e "/require_once/i \\${redissession}" \
config.php ;
# Initialise PHPUnit for Moodle.
@@ -221,7 +214,7 @@ before_script:
# We need the official upstream for comparison
git remote add upstream https://github.com/moodle/moodle.git;
git fetch upstream MOODLE_311_STABLE;
git fetch upstream MOODLE_39_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`
+762 -165
View File
@@ -16,129 +16,147 @@
/* eslint-env node */
/**
* Grunt configuration for Moodle.
*
* @copyright 2014 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/* eslint-env node */
/**
* Setup the Grunt Moodle environment.
* Calculate the cwd, taking into consideration the `root` option (for Windows).
*
* @param {Grunt} grunt
* @returns {Object}
* @param {Object} grunt
* @returns {String} The current directory as best we can determine
*/
const setupMoodleEnvironment = grunt => {
const getCwd = grunt => {
const fs = require('fs');
const path = require('path');
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
const getAmdConfiguration = () => {
// If the cwd is the amd directory in the current component then it will be empty.
// If the cwd is a child of the component's AMD directory, the relative directory will not start with ..
let inAMD = !path.relative(`${componentDirectory}/amd`, cwd).startsWith('..');
let cwd = fs.realpathSync(process.env.PWD || process.cwd());
// Globbing pattern for matching all AMD JS source files.
let amdSrc = [];
if (inComponent) {
amdSrc.push(
componentDirectory + "/amd/src/*.js",
componentDirectory + "/amd/src/**/*.js"
);
// Windows users can't run grunt in a subdirectory, so allow them to set
// the root by passing --root=path/to/dir.
if (grunt.option('root')) {
const root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) {
cwd = fs.realpathSync(path.join(__dirname, root));
grunt.log.ok('Setting root to ' + cwd);
} else {
amdSrc = ComponentList.getAmdSrcGlobList();
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
return cwd;
};
/**
* Register any stylelint tasks.
*
* @param {Object} grunt
* @param {Array} files
* @param {String} fullRunDir
*/
const registerStyleLintTasks = (grunt, files, fullRunDir) => {
const getCssConfigForFiles = files => {
return {
inAMD,
amdSrc,
stylelint: {
css: {
// Use a fully-qualified path.
src: files,
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
}
}
}
},
},
};
};
const getYuiConfiguration = () => {
let yuiSrc = [];
if (inComponent) {
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
const getScssConfigForFiles = files => {
return {
stylelint: {
scss: {
options: {syntax: 'scss'},
src: files,
},
},
};
};
let hasCss = true;
let hasScss = true;
if (files) {
// Specific files were passed. Just set them up.
grunt.config.merge(getCssConfigForFiles(files));
grunt.config.merge(getScssConfigForFiles(files));
} else {
// The stylelint system does not handle the case where there was no file to lint.
// Check whether there are any files to lint in the current directory.
const glob = require('glob');
const scssSrc = [];
glob.sync(`${fullRunDir}/**/*.scss`).forEach(path => scssSrc.push(path));
if (scssSrc.length) {
grunt.config.merge(getScssConfigForFiles(scssSrc));
} else {
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
hasScss = false;
}
return {
yuiSrc,
};
};
const cssSrc = [];
glob.sync(`${fullRunDir}/**/*.css`).forEach(path => cssSrc.push(path));
const getStyleConfiguration = () => {
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
// Build the cssSrc and scssSrc.
// Valid paths are:
// [component]/styles.css; and either
// [theme/[themename]]/scss/**/*.scss; or
// [theme/[themename]]/style/*.css.
//
// If a theme has scss, then it is assumed that the style directory contains generated content.
let cssSrc = [];
let scssSrc = [];
const checkComponentDirectory = componentDirectory => {
const isTheme = componentDirectory.startsWith('theme/');
if (isTheme) {
const scssDirectory = `${componentDirectory}/scss`;
if (fs.existsSync(scssDirectory)) {
// This theme has an SCSS directory.
// Include all scss files within it recursively, but do not check for css files.
scssSrc.push(`${scssDirectory}/*.scss`);
scssSrc.push(`${scssDirectory}/**/*.scss`);
} else {
// This theme has no SCSS directory.
// Only hte CSS files in the top-level directory are checked.
cssSrc.push(`${componentDirectory}/style/*.css`);
}
} else {
// This is not a theme.
// All other plugin types are restricted to a single styles.css in their top level.
cssSrc.push(`${componentDirectory}/styles.css`);
}
};
if (inComponent) {
checkComponentDirectory(componentDirectory);
if (cssSrc.length) {
grunt.config.merge(getCssConfigForFiles(cssSrc));
} else {
ComponentList.getComponentPaths(`${gruntFilePath}/`).forEach(componentPath => {
checkComponentDirectory(componentPath);
});
hasCss = false;
}
}
return {
cssSrc,
scssSrc,
};
};
const scssTasks = ['sass'];
if (hasScss) {
scssTasks.unshift('stylelint:scss');
}
grunt.registerTask('scss', scssTasks);
/**
* Calculate the cwd, taking into consideration the `root` option (for Windows).
*
* @param {Object} grunt
* @returns {String} The current directory as best we can determine
*/
const getCwd = grunt => {
let cwd = fs.realpathSync(process.env.PWD || process.cwd());
const cssTasks = [];
if (hasCss) {
cssTasks.push('stylelint:css');
}
grunt.registerTask('rawcss', cssTasks);
// Windows users can't run grunt in a subdirectory, so allow them to set
// the root by passing --root=path/to/dir.
if (grunt.option('root')) {
const root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) {
cwd = fs.realpathSync(path.join(__dirname, root));
grunt.log.ok('Setting root to ' + cwd);
} else {
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
grunt.registerTask('css', ['scss', 'rawcss']);
};
return cwd;
};
/**
* Grunt configuration.
*
* @param {Object} grunt
*/
module.exports = function(grunt) {
const path = require('path');
const tasks = {};
const async = require('async');
const DOMParser = require('xmldom').DOMParser;
const xpath = require('xpath');
const semver = require('semver');
const watchman = require('fb-watchman');
const watchmanClient = new watchman.Client();
const fs = require('fs');
const ComponentList = require(path.resolve('GruntfileComponents.js'));
const sass = require('node-sass');
// Verify the node version is new enough.
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
var actual = semver.valid(process.version);
if (!semver.satisfies(actual, expected)) {
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
}
// Detect directories:
// * gruntFilePath The real path on disk to this Gruntfile.js
@@ -153,19 +171,8 @@ const setupMoodleEnvironment = grunt => {
const relativeCwd = path.relative(gruntFilePath, cwd);
const componentDirectory = ComponentList.getOwningComponentDirectory(relativeCwd);
const inComponent = !!componentDirectory;
const inTheme = !!componentDirectory && componentDirectory.startsWith('theme/');
const runDir = inComponent ? componentDirectory : relativeCwd;
const fullRunDir = fs.realpathSync(gruntFilePath + path.sep + runDir);
const {inAMD, amdSrc} = getAmdConfiguration();
const {yuiSrc} = getYuiConfiguration();
const {cssSrc, scssSrc} = getStyleConfiguration();
let files = null;
if (grunt.option('files')) {
// Accept a comma separated list of files to process.
files = grunt.option('files').split(',');
}
grunt.log.debug('============================================================================');
grunt.log.debug(`= Node version: ${process.versions.node}`);
grunt.log.debug(`= grunt version: ${grunt.package.version}`);
@@ -185,77 +192,667 @@ const setupMoodleEnvironment = grunt => {
grunt.log.ok(`Running tasks for component directory ${componentDirectory}`);
}
return {
amdSrc,
componentDirectory,
cwd,
cssSrc,
files,
fullRunDir,
gruntFilePath,
inAMD,
inComponent,
inTheme,
relativeCwd,
runDir,
scssSrc,
yuiSrc,
};
};
/**
* Verify tha tthe current NodeJS version matches the required version in package.json.
*
* @param {Grunt} grunt
*/
const verifyNodeVersion = grunt => {
const semver = require('semver');
// Verify the node version is new enough.
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
var actual = semver.valid(process.version);
if (!semver.satisfies(actual, expected)) {
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
let files = null;
if (grunt.option('files')) {
// Accept a comma separated list of files to process.
files = grunt.option('files').split(',');
}
};
/**
* Grunt configuration.
*
* @param {Grunt} grunt
*/
module.exports = function(grunt) {
// Verify that the Node version meets our requirements.
verifyNodeVersion(grunt);
// If the cwd is the amd directory in the current component then it will be empty.
// If the cwd is a child of the component's AMD directory, the relative directory will not start with ..
const inAMD = !path.relative(`${componentDirectory}/amd`, cwd).startsWith('..');
// Setup the Moodle environemnt within the Grunt object.
grunt.moodleEnv = setupMoodleEnvironment(grunt);
// Globbing pattern for matching all AMD JS source files.
let amdSrc = [];
if (inComponent) {
amdSrc.push(componentDirectory + "/amd/src/*.js");
amdSrc.push(componentDirectory + "/amd/src/**/*.js");
} else {
amdSrc = ComponentList.getAmdSrcGlobList();
}
let yuiSrc = [];
if (inComponent) {
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
} else {
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
}
/**
* Add the named task.
* Function to generate the destination for the uglify task
* (e.g. build/file.min.js). This function will be passed to
* the rename property of files array when building dynamically:
* http://gruntjs.com/configuring-tasks#building-the-files-object-dynamically
*
* @param {string} name
* @param {Grunt} grunt
* @param {String} destPath the current destination
* @param {String} srcPath the matched src path
* @return {String} The rewritten destination path.
*/
const addTask = (name, grunt) => {
const path = require('path');
const taskPath = path.resolve(`./.grunt/tasks/${name}.js`);
grunt.log.debug(`Including tasks for ${name} from ${taskPath}`);
require(path.resolve(`./.grunt/tasks/${name}.js`))(grunt);
var babelRename = function(destPath, srcPath) {
destPath = srcPath.replace('src', 'build');
destPath = destPath.replace('.js', '.min.js');
return destPath;
};
/**
* Find thirdpartylibs.xml and generate an array of paths contained within
* them (used to generate ignore files and so on).
*
* @return {array} The list of thirdparty paths.
*/
var getThirdPartyPathsFromXML = function() {
const thirdpartyfiles = ComponentList.getThirdPartyLibsList(gruntFilePath + '/');
const libs = ['node_modules/', 'vendor/'];
// Add Moodle task configuration.
addTask('gherkinlint', grunt);
addTask('ignorefiles', grunt);
thirdpartyfiles.forEach(function(file) {
const dirname = path.dirname(file);
addTask('javascript', grunt);
addTask('style', grunt);
const doc = new DOMParser().parseFromString(grunt.file.read(file));
const nodes = xpath.select("/libraries/library/location/text()", doc);
addTask('watch', grunt);
addTask('startup', grunt);
nodes.forEach(function(node) {
let lib = path.posix.join(dirname, node.toString());
if (grunt.file.isDir(lib)) {
// Ensure trailing slash on dirs.
lib = lib.replace(/\/?$/, '/');
}
// Look for duplicate paths before adding to array.
if (libs.indexOf(lib) === -1) {
libs.push(lib);
}
});
});
return libs;
};
/**
* Get the list of feature files to pass to the gherkin linter.
*
* @returns {Array}
*/
const getGherkinLintTargets = () => {
if (files) {
// Specific files were requested. Only check these.
return files;
}
if (inComponent) {
return [`${runDir}/tests/behat/*.feature`];
}
return ['**/tests/behat/*.feature'];
};
// Project configuration.
grunt.initConfig({
eslint: {
// Even though warnings dont stop the build we don't display warnings by default because
// at this moment we've got too many core warnings.
// To display warnings call: grunt eslint --show-lint-warnings
// To fail on warnings call: grunt eslint --max-lint-warnings=0
// Also --max-lint-warnings=-1 can be used to display warnings but not fail.
options: {
quiet: (!grunt.option('show-lint-warnings')) && (typeof grunt.option('max-lint-warnings') === 'undefined'),
maxWarnings: ((typeof grunt.option('max-lint-warnings') !== 'undefined') ? grunt.option('max-lint-warnings') : -1)
},
amd: {src: files ? files : amdSrc},
// Check YUI module source files.
yui: {src: files ? files : yuiSrc},
},
babel: {
options: {
sourceMaps: true,
comments: false,
plugins: [
'transform-es2015-modules-amd-lazy',
'system-import-transformer',
// This plugin modifies the Babel transpiling for "export default"
// so that if it's used then only the exported value is returned
// by the generated AMD module.
//
// It also adds the Moodle plugin name to the AMD module definition
// so that it can be imported as expected in other modules.
path.resolve('babel-plugin-add-module-to-define.js'),
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-syntax-import-meta',
['@babel/plugin-proposal-class-properties', {'loose': false}],
'@babel/plugin-proposal-json-strings'
],
presets: [
['minify', {
// This minification plugin needs to be disabled because it breaks the
// source map generation and causes invalid source maps to be output.
simplify: false,
builtIns: false
}],
['@babel/preset-env', {
targets: {
browsers: [
">0.25%",
"last 2 versions",
"not ie <= 10",
"not op_mini all",
"not Opera > 0",
"not dead"
]
},
modules: false,
useBuiltIns: false
}]
]
},
dist: {
files: [{
expand: true,
src: files ? files : amdSrc,
rename: babelRename
}]
}
},
sass: {
dist: {
files: {
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss",
"theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss"
}
},
options: {
implementation: sass,
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
}
},
watch: {
options: {
nospawn: true // We need not to spawn so config can be changed dynamically.
},
amd: {
files: inComponent
? ['amd/src/*.js', 'amd/src/**/*.js']
: ['**/amd/src/**/*.js'],
tasks: ['amd']
},
boost: {
files: [inComponent ? 'scss/**/*.scss' : 'theme/boost/scss/**/*.scss'],
tasks: ['scss']
},
rawcss: {
files: [
'**/*.css',
],
excludes: [
'**/moodle.css',
'**/editor.css',
],
tasks: ['rawcss']
},
yui: {
files: inComponent
? ['yui/src/*.json', 'yui/src/**/*.js']
: ['**/yui/src/**/*.js'],
tasks: ['yui']
},
gherkinlint: {
files: [inComponent ? 'tests/behat/*.feature' : '**/tests/behat/*.feature'],
tasks: ['gherkinlint']
}
},
shifter: {
options: {
recursive: true,
// Shifter takes a relative path.
paths: files ? files : [runDir]
}
},
gherkinlint: {
options: {
files: getGherkinLintTargets(),
}
},
});
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
tasks.ignorefiles = function() {
// An array of paths to third party directories.
const thirdPartyPaths = getThirdPartyPathsFromXML();
// Generate .eslintignore.
const eslintIgnores = [
'# Generated by "grunt ignorefiles"',
'*/**/yui/src/*/meta/',
'*/**/build/',
].concat(thirdPartyPaths);
grunt.file.write('.eslintignore', eslintIgnores.join('\n'));
// Generate .stylelintignore.
const stylelintIgnores = [
'# Generated by "grunt ignorefiles"',
'**/yui/build/*',
'theme/boost/style/moodle.css',
'theme/classic/style/moodle.css',
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
};
/**
* Shifter task. Is configured with a path to a specific file or a directory,
* in the case of a specific file it will work out the right module to be built.
*
* Note that this task runs the invidiaul shifter jobs async (becase it spawns
* so be careful to to call done().
*/
tasks.shifter = function() {
var done = this.async(),
options = grunt.config('shifter.options');
// Run the shifter processes one at a time to avoid confusing output.
async.eachSeries(options.paths, function(src, filedone) {
var args = [];
args.push(path.normalize(__dirname + '/node_modules/shifter/bin/shifter'));
// Always ignore the node_modules directory.
args.push('--excludes', 'node_modules');
// Determine the most appropriate options to run with based upon the current location.
if (grunt.file.isMatch('**/yui/**/*.js', src)) {
// When passed a JS file, build our containing module (this happen with
// watch).
grunt.log.debug('Shifter passed a specific JS file');
src = path.dirname(path.dirname(src));
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src', src)) {
// When in a src directory --walk all modules.
grunt.log.debug('In a src directory');
args.push('--walk');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*', src)) {
// When in module, only build our module.
grunt.log.debug('In a module directory');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*/js', src)) {
// When in module src, only build our module.
grunt.log.debug('In a source directory');
src = path.dirname(src);
options.recursive = false;
}
if (grunt.option('watch')) {
grunt.fail.fatal('The --watch option has been removed, please use `grunt watch` instead');
}
// Add the stderr option if appropriate
if (grunt.option('verbose')) {
args.push('--lint-stderr');
}
if (grunt.option('no-color')) {
args.push('--color=false');
}
var execShifter = function() {
grunt.log.ok("Running shifter on " + src);
grunt.util.spawn({
cmd: "node",
args: args,
opts: {cwd: src, stdio: 'inherit', env: process.env}
}, function(error, result, code) {
if (code) {
grunt.fail.fatal('Shifter failed with code: ' + code);
} else {
grunt.log.ok('Shifter build complete.');
filedone();
}
});
};
// Actually run shifter.
if (!options.recursive) {
execShifter();
} else {
// Check that there are yui modules otherwise shifter ends with exit code 1.
if (grunt.file.expand({cwd: src}, '**/yui/src/**/*.js').length > 0) {
args.push('--recursive');
execShifter();
} else {
grunt.log.ok('No YUI modules to build.');
filedone();
}
}
}, done);
};
tasks.gherkinlint = function() {
const done = this.async();
const options = grunt.config('gherkinlint.options');
// Grab the gherkin-lint linter and required scaffolding.
const linter = require('gherkin-lint/dist/linter.js');
const featureFinder = require('gherkin-lint/dist/feature-finder.js');
const configParser = require('gherkin-lint/dist/config-parser.js');
const formatter = require('gherkin-lint/dist/formatters/stylish.js');
// Run the linter.
return linter.lint(
featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
configParser.getConfiguration(configParser.defaultConfigFileName)
)
.then(results => {
// Print the results out uncondtionally.
formatter.printResults(results);
return results;
})
.then(results => {
// Report on the results.
// The done function takes a bool whereby a falsey statement causes the task to fail.
return results.every(result => result.errors.length === 0);
})
.then(done); // eslint-disable-line promise/no-callback-in-promise
};
tasks.startup = function() {
// Are we in a YUI directory?
if (path.basename(path.resolve(cwd, '../../')) == 'yui') {
grunt.task.run('yui');
// Are we in an AMD directory?
} else if (inAMD) {
grunt.task.run('amd');
} else {
// Run them all!.
grunt.task.run('css');
grunt.task.run('js');
grunt.task.run('gherkinlint');
}
};
/**
* This is a wrapper task to handle the grunt watch command. It attempts to use
* Watchman to monitor for file changes, if it's installed, because it's much faster.
*
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
* watcher for backwards compatibility.
*/
tasks.watch = function() {
var watchTaskDone = this.async();
var watchInitialised = false;
var watchTaskQueue = {};
var processingQueue = false;
// Grab the tasks and files that have been queued up and execute them.
var processWatchTaskQueue = function() {
if (!Object.keys(watchTaskQueue).length || processingQueue) {
// If there is nothing in the queue or we're already processing then wait.
return;
}
processingQueue = true;
// Grab all tasks currently in the queue.
var queueToProcess = watchTaskQueue;
// Reset the queue.
watchTaskQueue = {};
async.forEachSeries(
Object.keys(queueToProcess),
function(task, next) {
var files = queueToProcess[task];
var filesOption = '--files=' + files.join(',');
grunt.log.ok('Running task ' + task + ' for files ' + filesOption);
// Spawn the task in a child process so that it doesn't kill this one
// if it failed.
grunt.util.spawn(
{
// Spawn with the grunt bin.
grunt: true,
// Run from current working dir and inherit stdio from process.
opts: {
cwd: fullRunDir,
stdio: 'inherit'
},
args: [task, filesOption]
},
function(err, res, code) {
if (code !== 0) {
// The grunt task failed.
grunt.log.error(err);
}
// Move on to the next task.
next();
}
);
},
function() {
// No longer processing.
processingQueue = false;
// Once all of the tasks are done then recurse just in case more tasks
// were queued while we were processing.
processWatchTaskQueue();
}
);
};
const originalWatchConfig = grunt.config.get(['watch']);
const watchConfig = Object.keys(originalWatchConfig).reduce(function(carry, key) {
if (key == 'options') {
return carry;
}
const value = originalWatchConfig[key];
const taskNames = value.tasks;
const files = value.files;
let excludes = [];
if (value.excludes) {
excludes = value.excludes;
}
taskNames.forEach(function(taskName) {
carry[taskName] = {
files,
excludes,
};
});
return carry;
}, {});
watchmanClient.on('error', function(error) {
// We have to add an error handler here and parse the error string because the
// example way from the docs to check if Watchman is installed doesn't actually work!!
// See: https://github.com/facebook/watchman/issues/509
if (error.message.match('Watchman was not found')) {
// If watchman isn't installed then we should fallback to the other watch task.
grunt.log.ok('It is recommended that you install Watchman for better performance using the "watch" command.');
// Fallback to the old grunt-contrib-watch task.
grunt.renameTask('watch-grunt', 'watch');
grunt.task.run(['watch']);
// This task is finished.
watchTaskDone(0);
} else {
grunt.log.error(error);
// Fatal error.
watchTaskDone(1);
}
});
watchmanClient.on('subscription', function(resp) {
if (resp.subscription !== 'grunt-watch') {
return;
}
resp.files.forEach(function(file) {
grunt.log.ok('File changed: ' + file.name);
var fullPath = fullRunDir + '/' + file.name;
Object.keys(watchConfig).forEach(function(task) {
const fileGlobs = watchConfig[task].files;
var match = fileGlobs.some(function(fileGlob) {
return grunt.file.isMatch(`**/${fileGlob}`, fullPath);
});
if (match) {
// If we are watching a subdirectory then the file.name will be relative
// to that directory. However the grunt tasks expect the file paths to be
// relative to the Gruntfile.js location so let's normalise them before
// adding them to the queue.
var relativePath = fullPath.replace(gruntFilePath + '/', '');
if (task in watchTaskQueue) {
if (!watchTaskQueue[task].includes(relativePath)) {
watchTaskQueue[task] = watchTaskQueue[task].concat(relativePath);
}
} else {
watchTaskQueue[task] = [relativePath];
}
}
});
});
processWatchTaskQueue();
});
process.on('SIGINT', function() {
// Let the user know that they may need to manually stop the Watchman daemon if they
// no longer want it running.
if (watchInitialised) {
grunt.log.ok('The Watchman daemon may still be running and may need to be stopped manually.');
}
process.exit();
});
// Initiate the watch on the current directory.
watchmanClient.command(['watch-project', fullRunDir], function(watchError, watchResponse) {
if (watchError) {
grunt.log.error('Error initiating watch:', watchError);
watchTaskDone(1);
return;
}
if ('warning' in watchResponse) {
grunt.log.error('warning: ', watchResponse.warning);
}
var watch = watchResponse.watch;
var relativePath = watchResponse.relative_path;
watchInitialised = true;
watchmanClient.command(['clock', watch], function(clockError, clockResponse) {
if (clockError) {
grunt.log.error('Failed to query clock:', clockError);
watchTaskDone(1);
return;
}
// Generate the expression query used by watchman.
// Documentation is limited, but see https://facebook.github.io/watchman/docs/expr/allof.html for examples.
// We generate an expression to match any value in the files list of all of our tasks, but excluding
// all value in the excludes list of that task.
//
// [anyof, [
// [allof, [
// [anyof, [
// ['match', validPath, 'wholename'],
// ['match', validPath, 'wholename'],
// ],
// [not,
// [anyof, [
// ['match', invalidPath, 'wholename'],
// ['match', invalidPath, 'wholename'],
// ],
// ],
// ],
var matchWholeName = fileGlob => ['match', fileGlob, 'wholename'];
var matches = Object.keys(watchConfig).map(function(task) {
const matchAll = [];
matchAll.push(['anyof'].concat(watchConfig[task].files.map(matchWholeName)));
if (watchConfig[task].excludes.length) {
matchAll.push(['not', ['anyof'].concat(watchConfig[task].excludes.map(matchWholeName))]);
}
return ['allof'].concat(matchAll);
});
matches = ['anyof'].concat(matches);
var sub = {
expression: matches,
// Which fields we're interested in.
fields: ["name", "size", "type"],
// Add our time constraint.
since: clockResponse.clock
};
if (relativePath) {
/* eslint-disable camelcase */
sub.relative_root = relativePath;
}
watchmanClient.command(['subscribe', watch, 'grunt-watch', sub], function(subscribeError) {
if (subscribeError) {
// Probably an error in the subscription criteria.
grunt.log.error('failed to subscribe: ', subscribeError);
watchTaskDone(1);
return;
}
grunt.log.ok('Listening for changes to files in ' + fullRunDir);
});
});
});
};
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
var files = Object.keys(changedFiles);
grunt.config('eslint.amd.src', files);
grunt.config('eslint.yui.src', files);
grunt.config('shifter.options.paths', files);
grunt.config('gherkinlint.options.files', files);
grunt.config('babel.dist.files', [{expand: true, src: files, rename: babelRename}]);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
// Register NPM tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-stylelint');
grunt.loadNpmTasks('grunt-babel');
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
grunt.renameTask('watch', 'watch-grunt');
// Register JS tasks.
grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter);
grunt.registerTask('gherkinlint', 'Run gherkinlint against the current directory', tasks.gherkinlint);
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles);
grunt.registerTask('watch', 'Run tasks on file changes', tasks.watch);
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
grunt.registerTask('amd', ['eslint:amd', 'babel']);
grunt.registerTask('js', ['amd', 'yui']);
// Register CSS tasks.
registerStyleLintTasks(grunt, files, fullRunDir);
// Register the startup task.
grunt.registerTask('startup', 'Run the correct tasks for the current directory', tasks.startup);
// Register the default task.
grunt.registerTask('default', ['startup']);
@@ -92,16 +92,6 @@ const fetchComponentData = () => {
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.
*
@@ -150,49 +140,6 @@ const getThirdPartyLibsList = relativeTo => {
.sort();
};
/**
* Get the list of thirdparty library paths.
*
* @returns {array}
*/
const getThirdPartyPaths = () => {
const DOMParser = require('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.
*
@@ -235,9 +182,7 @@ const getOwningComponentDirectory = checkPath => {
module.exports = {
getAmdSrcGlobList,
getComponentFromPath,
getComponentPaths,
getOwningComponentDirectory,
getYuiSrcGlobList,
getThirdPartyLibsList,
getThirdPartyPaths,
};
+1 -1
View File
@@ -2,7 +2,7 @@ MOODLE TRADEMARKS POLICY
========================
The word "Moodle" is trademarked in many countries around the world. The word
was originally coined as an acronym: Modular Object-Oriented Dynamic Learning
was originally an acronym: Modular Object-Oriented Dynamic Learning
Environment. The trademark is owned by Martin Dougiamas, Founder and Director
of Moodle.
@@ -15,41 +15,34 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Clientside filter base.
* Admin settings search form
*
* @package tool_usertours
* @copyright 2020 The Open University
* @package admin
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\clientside_filter;
defined('MOODLE_INTERNAL') || die();
use stdClass;
use tool_usertours\local\filter\base;
use tool_usertours\tour;
require_once $CFG->libdir.'/formslib.php';
/**
* Clientside filter base.
* Admin settings search form
*
* @copyright 2020 The Open University
* @package admin
* @copyright 2016 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class clientside_filter extends base {
/**
* Returns the filter values needed for client side filtering.
*
* @param tour $tour The tour to find the filter values for
* @return stdClass
*/
public static function get_client_side_values(tour $tour): stdClass {
$data = (object) [];
class admin_settings_search_form extends moodleform {
function definition () {
$mform = $this->_form;
if (is_a(static::class, clientside_filter::class, true)) {
$data->filterdata = $tour->get_filter_values(static::get_filter_name());
}
return $data;
//$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));
}
}
}
+4 -13
View File
@@ -44,9 +44,7 @@ switch ($action) {
$key = array_search($auth, $authsenabled);
if ($key !== false) {
unset($authsenabled[$key]);
$value = implode(',', $authsenabled);
add_to_config_log('auth', $CFG->auth, $value, 'core');
set_config('auth', $value);
set_config('auth', implode(',', $authsenabled));
}
if ($auth == $CFG->registerauth) {
@@ -61,11 +59,8 @@ switch ($action) {
if (!in_array($auth, $authsenabled)) {
$authsenabled[] = $auth;
$authsenabled = array_unique($authsenabled);
$value = implode(',', $authsenabled);
add_to_config_log('auth', $CFG->auth, $value, 'core');
set_config('auth', $value);
set_config('auth', implode(',', $authsenabled));
}
\core\session\manager::gc(); // Remove stale sessions.
core_plugin_manager::reset_caches();
break;
@@ -81,9 +76,7 @@ switch ($action) {
$fsave = $authsenabled[$key];
$authsenabled[$key] = $authsenabled[$key + 1];
$authsenabled[$key + 1] = $fsave;
$value = implode(',', $authsenabled);
add_to_config_log('auth', $CFG->auth, $value, 'core');
set_config('auth', $value);
set_config('auth', implode(',', $authsenabled));
}
break;
@@ -98,9 +91,7 @@ switch ($action) {
$fsave = $authsenabled[$key];
$authsenabled[$key] = $authsenabled[$key - 1];
$authsenabled[$key - 1] = $fsave;
$value = implode(',', $authsenabled);
add_to_config_log('auth', $CFG->auth, $value, 'core');
set_config('auth', $value);
set_config('auth', implode(',', $authsenabled));
}
break;
+2
View File
@@ -171,6 +171,8 @@ function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts,
// limit for the setting name is 100.
continue;
}
} elseif ($fieldname == 'url') {
$fieldname = get_string('webpage');
} else {
$fieldname = get_string($fieldname);
}
@@ -43,7 +43,7 @@ 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');
@@ -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);
}
}
@@ -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);
}
}
+2 -6
View File
@@ -57,8 +57,6 @@ class task_log_table extends \table_sql {
'userid' => get_string('user', 'admin'),
'timestart' => get_string('task_starttime', 'admin'),
'duration' => get_string('task_duration', 'admin'),
'hostname' => get_string('hostname', 'tool_task'),
'pid' => get_string('pid', 'tool_task'),
'db' => get_string('task_dbstats', 'admin'),
'result' => get_string('task_result', 'admin'),
'actions' => '',
@@ -124,9 +122,8 @@ class task_log_table extends \table_sql {
$sort = "ORDER BY $sort";
}
// TODO Does not support custom user profile fields (MDL-70456).
$userfieldsapi = \core_user\fields::for_identity(\context_system::instance(), false)->with_userpic();
$userfields = $userfieldsapi->get_sql('u', false, 'user', 'userid2', false)->selects;
$extrafields = get_extra_user_fields(\context_system::instance());
$userfields = \user_picture::fields('u', $extrafields, 'userid2', 'user');
$where = '';
if (!empty($this->sql->where)) {
@@ -135,7 +132,6 @@ class task_log_table extends \table_sql {
$sql = "SELECT
tl.id, tl.type, tl.component, tl.classname, tl.userid, tl.timestart, tl.timeend,
tl.hostname, tl.pid,
tl.dbreads, tl.dbwrites, tl.result,
tl.dbreads + tl.dbwrites AS db,
tl.timeend - tl.timestart AS duration,
-9
View File
@@ -37,13 +37,11 @@ list($options, $unrecognized) = cli_get_params(
'showsql' => false,
'showdebugging' => false,
'ignorelimits' => false,
'force' => false,
], [
'h' => 'help',
'e' => 'execute',
'k' => 'keep-alive',
'i' => 'ignorelimits',
'f' => 'force',
]
);
@@ -63,7 +61,6 @@ Options:
-e, --execute Run all queued adhoc tasks
-k, --keep-alive=N Keep this script alive for N seconds and poll for new adhoc tasks
-i --ignorelimits Ignore task_adhoc_concurrency_limit and task_adhoc_max_runtime limits
-f, --force Run even if cron is disabled
Example:
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
@@ -95,12 +92,6 @@ if (moodle_needs_upgrading()) {
if (empty($options['execute'])) {
exit(0);
}
if (!get_config('core', 'cron_enabled') && !$options['force']) {
mtrace('Cron is disabled. Use --force to override.');
exit(1);
}
if (empty($options['keep-alive'])) {
$options['keep-alive'] = 0;
}
+6 -105
View File
@@ -36,23 +36,14 @@ require_once($CFG->libdir.'/cronlib.php');
// now get cli options
list($options, $unrecognized) = cli_get_params(
[
array(
'help' => false,
'stop' => false,
'list' => false,
'force' => false,
'enable' => false,
'disable' => false,
'disable-wait' => false,
], [
),
array(
'h' => 'help',
's' => 'stop',
'l' => 'list',
'f' => 'force',
'e' => 'enable',
'd' => 'disable',
'w' => 'disable-wait',
]
)
);
if ($unrecognized) {
@@ -65,13 +56,8 @@ if ($options['help']) {
"Execute periodic cron actions.
Options:
-h, --help Print out this help
-s, --stop Notify all other running cron processes to stop after the current task
-l, --list Show the list of currently running tasks and how long they have been running
-f, --force Execute task even if cron is disabled
-e, --enable Enable cron
-d, --disable Disable cron
-w, --disable-wait=600 Disable cron and wait until all tasks finished or fail after N seconds (optional param)
-h, --help Print out this help
-s, --stop Notify all other running cron processes to stop after the current task
Example:
\$sudo -u www-data /usr/bin/php admin/cli/cron.php
@@ -88,91 +74,6 @@ if ($options['stop']) {
die;
}
if ($options['enable']) {
set_config('cron_enabled', 1);
mtrace('Cron has been enabled for the site.');
exit(0);
}
if ($options['disable']) {
set_config('cron_enabled', 0);
\core\task\manager::clear_static_caches();
mtrace('Cron has been disabled for the site.');
exit(0);
}
if ($options['list']) {
$tasks = \core\task\manager::get_running_tasks();
mtrace('The list of currently running tasks:');
$format = "%7s %-12s %-9s %-20s %-52s\n";
printf ($format,
'PID',
'HOST',
'TYPE',
'TIME',
'CLASSNAME'
);
foreach ($tasks as $task) {
printf ($format,
$task->pid,
substr($task->hostname, 0, 12),
$task->type,
format_time(time() - $task->timestarted),
substr($task->classname, 0, 52)
);
}
exit(0);
}
if ($wait = $options['disable-wait']) {
$started = time();
if (true === $wait) {
// Default waiting time.
$waitsec = 600;
} else {
$waitsec = $wait;
$wait = true;
}
set_config('cron_enabled', 0);
\core\task\manager::clear_static_caches();
mtrace('Cron has been disabled for the site.');
mtrace('Allocating '. format_time($waitsec) . ' for the tasks to finish.');
$lastcount = 0;
while ($wait) {
$tasks = \core\task\manager::get_running_tasks();
if (count($tasks) == 0) {
mtrace('');
mtrace('All scheduled and adhoc tasks finished.');
exit(0);
}
if (time() - $started >= $waitsec) {
mtrace('');
mtrace('Wait time ('. format_time($waitsec) . ') elapsed, but ' . count($tasks) . ' task(s) still running.');
mtrace('Exiting with code 1.');
exit(1);
}
if (count($tasks) !== $lastcount) {
mtrace('');
mtrace(count($tasks) . " tasks currently running.", '');
$lastcount = count($tasks);
} else {
mtrace('.', '');
}
sleep(1);
}
}
if (!get_config('core', 'cron_enabled') && !$options['force']) {
mtrace('Cron is disabled. Use --force to override.');
exit(1);
}
\core\local\cli\shutdown::script_supports_graceful_exit();
cron_run();
-65
View File
@@ -1,65 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI script to reset dashboards.
*
* @package core
* @subpackage cli
* @copyright 2021 Brendan Heywood (brendan@catalyst-au.net)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require_once($CFG->libdir.'/clilib.php');
require_once($CFG->dirroot.'/my/lib.php');
list($options, $unrecognized) = cli_get_params([
'help' => false,
'execute' => false,
], [
'h' => 'help',
'e' => 'execute',
]);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2);
}
if (!$options['execute']) {
$help = <<<EOF
Resets Moodle dashboards for all users
Options:
-h, --help Print out this help
-e, --execute Actually run the reset
Example:
\$ sudo -u www-data /usr/bin/php admin/cli/dashboard_reset.php -e
EOF;
echo $help;
exit(0);
}
$progressbar = new progress_bar();
$progressbar->create();
my_reset_page_for_all_users(MY_PAGE_PRIVATE, 'my-index', $progressbar);
-138
View File
@@ -1,138 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Fix orphaned calendar events that were broken by MDL-67494.
*
* This script will look for all the calendar events which userids
* where broken by a wrong upgrade step, affecting to Moodle 3.9.5
* and up.
*
* It performs checks to both:
* a) Detect if the site was affected (ran the wrong upgrade step).
* b) Look for orphaned calendar events, categorising them as:
* - standard: site / category / course / group / user events
* - subscription: events created via subscriptions.
* - action: normal action events, created to show common important dates.
* - override: user and group override events, particular, that some activities support.
* - custom: other events, not being any of the above, common or particular.
* By specifying it (--fix) try to recover as many broken events (missing userid) as
* possible. Standard, subscription, action, override events in core are fully supported but
* override or custom events should be fixed by each plugin as far as there isn't any standard
* API (plugin-wise) to launch a rebuild of the calendar events.
*
* @package core
* @copyright 2021 onwards Simey Lameze <simey@moodle.com>
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require_once(__DIR__ . '/../../config.php');
require_once($CFG->libdir . "/clilib.php");
require_once($CFG->libdir . '/db/upgradelib.php');
// Supported options.
$long = ['fix' => false, 'help' => false];
$short = ['f' => 'fix', 'h' => 'help'];
// CLI options.
[$options, $unrecognized] = cli_get_params($long, $short);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
$help = <<<EOT
Fix orphaned calendar events.
This script detects calendar events that have had their
userid lost. By default it will perform various checks
and report them, showing the site status in an easy way.
Also, optionally (--fix), it wil try to recover as many
lost userids as possible from different sources. Note that
this script aims to process well-know events in core,
leaving custom events in 3rd part plugins mostly unmodified
because there isn't any consistent way to regenerate them.
For more details: https://tracker.moodle.org/browse/MDL-71156
Options:
-h, --help Print out this help.
-f, --fix Fix the orphaned calendar events in the DB.
If not specified only check and report problems to STDERR.
Usage:
- Only report: \$ sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_calendar_events.php
- Report and fix: \$ sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_calendar_events.php -f
EOT;
cli_writeln($help);
die;
}
// Check various usual pre-requisites.
if (empty($CFG->version)) {
cli_error('Database is not yet installed.');
}
$admin = get_admin();
if (!$admin) {
cli_error('Error: No admin account was found.');
}
if (moodle_needs_upgrading()) {
cli_error('Moodle upgrade pending, script execution suspended.');
}
// Do everything as admin by default.
\core\session\manager::set_user($admin);
// Report current site status.
cli_heading('Checking the site status');
$needsfix = upgrade_calendar_site_status();
// Report current calendar events status.
cli_heading('Checking the calendar events status');
$info = upgrade_calendar_events_status();
$hasbadevents = $info['total']->bad > 0 || $info['total']->bad != $info['other']->bad;
$needsfix = $needsfix || $hasbadevents;
// If, selected, fix as many calendar events as possible.
if ($options['fix']) {
// If the report has told us that the fix was not needed... ask for confirmation!
if (!$needsfix) {
cli_writeln("This site DOES NOT NEED to run the calendar events fix.");
$input = cli_input('Are you completely sure that you want to run the fix? (y/N)', 'N', ['y', 'Y', 'n', 'N']);
if (strtolower($input) != 'y') {
exit(0);
}
cli_writeln("");
}
cli_heading('Fixing as many as possible calendar events');
upgrade_calendar_events_fix_remaining($info);
// Report current (after fix) calendar events status.
cli_heading('Checking the calendar events status (after fix)');
upgrade_calendar_events_status();
} else if ($needsfix) {
// Fix option was not provided but problem events have been found. Notify the user and provide info how to fix these events.
cli_writeln("This site NEEDS to run the calendar events fix!");
cli_writeln("To fix the calendar events, re-run this script with the --fix option.");
}
-79
View File
@@ -1,79 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Generates a secure key for the current server (presuming it does not already exist).
*
* @package core_admin
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use \core\encryption;
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/clilib.php');
// Get cli options.
[$options, $unrecognized] = cli_get_params(
['help' => false, 'method' => null],
['h' => 'help']);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
// TODO: MDL-71421 - Remove the openssl alternative once sodium becomes a requirement in Moodle 4.2.
if ($options['help']) {
echo "Generate secure key
This script manually creates a secure key within the secret data root folder (configured in
config.php as \$CFG->secretdataroot). You must run it using an account with access to write
to that folder.
In normal use Moodle automatically creates the key; this script is intended when setting up
a new Moodle system, for cases where the secure folder is not on shared storage and the key
may be manually installed on multiple servers.
Options:
-h, --help Print out this help
--method <method> Generate key for specified encryption method instead of default.
* sodium
* openssl-aes-256-ctr
Example:
php admin/cli/generate_key.php
";
exit;
}
$method = $options['method'];
if (encryption::key_exists($method)) {
echo 'Key already exists: ' . encryption::get_key_file($method) . "\n";
exit;
}
// Creates key with default permissions (no chmod).
echo "Generating key...\n";
encryption::create_key($method, false);
echo "\nKey created: " . encryption::get_key_file($method) . "\n\n";
echo "If the key folder is not shared storage, then key files should be copied to all servers.\n";
-7
View File
@@ -56,7 +56,6 @@ Options:
--agree-license Indicates agreement with software license.
--fullname=STRING Name of the site
--shortname=STRING Name of the site
--summary=STRING The summary to be displayed on the front page
-h, --help Print out this help
Example:
@@ -97,7 +96,6 @@ list($options, $unrecognized) = cli_get_params(
'adminemail' => '',
'fullname' => '',
'shortname' => '',
'summary' => '',
'agree-license' => false,
'help' => false
),
@@ -106,11 +104,6 @@ list($options, $unrecognized) = cli_get_params(
)
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
// We show help text even if tables are installed.
if ($options['help']) {
echo $help;
+8 -8
View File
@@ -119,7 +119,7 @@ if (!empty($options['collation'])) {
if ($dbcollation->value !== $collation || $dbcharset->value !== $charset) {
// Try to convert the DB.
echo "Converting database to '$collation' for $CFG->wwwroot:\n";
$sql = "ALTER DATABASE `$CFG->dbname` DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
$sql = "ALTER DATABASE $CFG->dbname DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
try {
$DB->change_database_structure($sql);
} catch (exception $e) {
@@ -146,7 +146,7 @@ if (!empty($options['collation'])) {
} else {
try {
$DB->change_database_structure("ALTER TABLE `$table->name` CONVERT TO CHARACTER SET $charset COLLATE $collation");
$DB->change_database_structure("ALTER TABLE $table->name CONVERT TO CHARACTER SET $charset COLLATE $collation");
echo "CONVERTED\n";
$converted++;
} catch (ddl_exception $e) {
@@ -163,7 +163,7 @@ if (!empty($options['collation'])) {
}
}
$sql = "SHOW FULL COLUMNS FROM `$table->name` WHERE collation IS NOT NULL";
$sql = "SHOW FULL COLUMNS FROM $table->name WHERE collation IS NOT NULL";
$rs2 = $DB->get_recordset_sql($sql);
foreach ($rs2 as $column) {
$column = (object)array_change_key_case((array)$column, CASE_LOWER);
@@ -181,7 +181,7 @@ if (!empty($options['collation'])) {
$notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
$default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
// primary, unique and inc are not supported for texts
$sql = "ALTER TABLE `$table->name`
$sql = "ALTER TABLE $table->name
MODIFY COLUMN $column->field $column->type
CHARACTER SET $charset
COLLATE $collation $notnull $default";
@@ -192,11 +192,11 @@ if (!empty($options['collation'])) {
$default = !is_null($column->default) ? "DEFAULT '$column->default'" : '';
if ($rowformat != '') {
$sql = "ALTER TABLE `$table->name` $rowformat";
$sql = "ALTER TABLE $table->name $rowformat";
$DB->change_database_structure($sql);
}
$sql = "ALTER TABLE `$table->name`
$sql = "ALTER TABLE $table->name
MODIFY COLUMN $column->field $column->type
CHARACTER SET $charset
COLLATE $collation $notnull $default";
@@ -315,8 +315,8 @@ function mysql_set_row_format($tablename, $charset, $collation, $engine) {
if ($rs->row_format == 'Compact' || $rs->row_format == 'Redundant') {
$rowformat = $DB->get_row_format_sql($engine, $collation);
// Try to convert to compressed format and then try updating the collation again.
$DB->change_database_structure("ALTER TABLE `$tablename` $rowformat");
$DB->change_database_structure("ALTER TABLE `$tablename` CONVERT TO CHARACTER SET $charset COLLATE $collation");
$DB->change_database_structure("ALTER TABLE $tablename $rowformat");
$DB->change_database_structure("ALTER TABLE $tablename CONVERT TO CHARACTER SET $charset COLLATE $collation");
} else {
// Row format may not be the problem. Can not diagnose problem. Send fail reply.
return false;
+2 -2
View File
@@ -158,7 +158,7 @@ if (!empty($options['info'])) {
}
foreach ($fixtables as $table) {
$DB->change_database_structure("ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed");
$DB->change_database_structure("ALTER TABLE {$prefix}$table ROW_FORMAT=Compressed");
echo str_pad($prefix . $table, 32, ' ', STR_PAD_RIGHT) . " ... Compressed\n";
}
@@ -189,7 +189,7 @@ if (!empty($options['info'])) {
echo "SET GLOBAL innodb_file_per_table=1;\n";
echo "SET GLOBAL innodb_file_format=Barracuda;\n";
foreach ($fixtables as $table) {
echo "ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed;\n";
echo "ALTER TABLE {$prefix}$table ROW_FORMAT=Compressed;\n";
}
echo "\n";
exit(0);
-109
View File
@@ -1,109 +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/>.
/**
* This script allows to restore a course from CLI.
*
* @package core
* @subpackage cli
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', 1);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/clilib.php');
require_once($CFG->dirroot . "/backup/util/includes/restore_includes.php");
list($options, $unrecognized) = cli_get_params([
'file' => '',
'categoryid' => '',
'showdebugging' => false,
'help' => false,
], [
'f' => 'file',
'c' => 'categoryid',
's' => 'showdebugging',
'h' => 'help',
]);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help'] || !($options['file']) || !($options['categoryid'])) {
$help = <<<EOL
Restore backup into provided category.
Options:
-f, --file=STRING Path to the backup file.
-c, --categoryid=INT ID of the category to restore too.
-s, --showdebugging Show developer level debugging information
-h, --help Print out this help.
Example:
\$sudo -u www-data /usr/bin/php admin/cli/restore_backup.php --file=/path/to/backup/file.mbz --categoryid=1\n
EOL;
echo $help;
exit(0);
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if (!$admin = get_admin()) {
print_error('noadmins');
}
if (!file_exists($options['file'])) {
print_error('filenotfound');
}
if (!$category = $DB->get_record('course_categories', ['id' => $options['categoryid']], 'id')) {
print_error('invalidcategoryid');
}
$backupdir = "restore_" . uniqid();
$path = $CFG->tempdir . DIRECTORY_SEPARATOR . "backup" . DIRECTORY_SEPARATOR . $backupdir;
cli_heading(get_string('extractingbackupfileto', 'backup', $path));
$fp = get_file_packer('application/vnd.moodle.backup');
$fp->extract_to_pathname($options['file'], $path);
cli_heading(get_string('preprocessingbackupfile'));
try {
list($fullname, $shortname) = restore_dbops::calculate_course_names(0, get_string('restoringcourse', 'backup'),
get_string('restoringcourseshortname', 'backup'));
$courseid = restore_dbops::create_new_course($fullname, $shortname, $category->id);
$rc = new restore_controller($backupdir, $courseid, backup::INTERACTIVE_NO,
backup::MODE_GENERAL, $admin->id, backup::TARGET_NEW_COURSE);
$rc->execute_precheck();
$rc->execute_plan();
$rc->destroy();
} catch (Exception $e) {
cli_heading(get_string('cleaningtempdata'));
fulldelete($path);
print_error('generalexceptionmessage', 'error', '', $e->getMessage());
}
cli_heading(get_string('restoredcourseid', 'backup', $courseid));
exit(0);
+2 -19
View File
@@ -30,17 +30,8 @@ require_once("$CFG->libdir/clilib.php");
require_once("$CFG->libdir/cronlib.php");
list($options, $unrecognized) = cli_get_params(
[
'help' => false,
'list' => false,
'execute' => false,
'showsql' => false,
'showdebugging' => false,
'force' => false,
], [
'h' => 'help',
'f' => 'force',
]
array('help' => false, 'list' => false, 'execute' => false, 'showsql' => false, 'showdebugging' => false),
array('h' => 'help')
);
if ($unrecognized) {
@@ -58,7 +49,6 @@ if ($options['help'] or (!$options['list'] and !$options['execute'])) {
--showsql Show sql queries before they are executed
--showdebugging Show developer level debugging information
-h, --help Print out this help
-f, --force Execute task even if cron is disabled
Example:
\$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
@@ -131,13 +121,6 @@ if ($execute = $options['execute']) {
exit(1);
}
if (!get_config('core', 'cron_enabled') && !$options['force']) {
mtrace('Cron is disabled. Use --force to override.');
exit(1);
}
\core\task\manager::scheduled_task_starting($task);
// Increase memory limit.
raise_memory_limit(MEMORY_EXTRA);
+7 -7
View File
@@ -38,17 +38,17 @@ if ($unrecognized) {
}
// If necessary add files that should be ignored - such as in 3rd party plugins.
$ignorelist = array();
$blacklist = array();
$path = $options['path'];
if (!file_exists($path)) {
cli_error("Invalid path $path");
}
if ($options['ie9fix']) {
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $ignorelist);
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $blacklist);
} else if ($options['noaspectratio']) {
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $ignorelist);
core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $blacklist);
} else {
$help =
@@ -153,9 +153,9 @@ function core_admin_svgtool_noaspectratio($file) {
* @param string $base
* @param string $sub
* @param string $filecallback
* @param array $ignorelist List of files to be ignored and skipped.
* @param array $blacklist
*/
function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
function core_admin_recurse_svgs($base, $sub, $filecallback, $blacklist) {
if (is_dir("$base/$sub")) {
$items = new DirectoryIterator("$base/$sub");
foreach ($items as $item) {
@@ -163,7 +163,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
continue;
}
$file = $item->getFilename();
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $ignorelist);
core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $blacklist);
}
unset($item);
unset($items);
@@ -174,7 +174,7 @@ function core_admin_recurse_svgs($base, $sub, $filecallback, $ignorelist) {
return;
}
$file = realpath("$base/$sub");
if (in_array($file, $ignorelist)) {
if (in_array($file, $blacklist)) {
return;
}
$filecallback($file);
-12
View File
@@ -39,8 +39,6 @@ Options:
--purge-missing Uninstall all missing from disk plugins.
--plugins=<plugin name> A comma separated list of plugins to be uninstalled. E.g. mod_assign,mod_forum
--run Execute uninstall. If this option is not set, then the script will be run in a dry mode.
--showsql Show sql queries before they are executed.
--showdebugging Show developer level debugging information.
Examples:
@@ -74,8 +72,6 @@ list($options, $unrecognised) = cli_get_params([
'purge-missing' => false,
'plugins' => false,
'run' => false,
'showsql' => false,
'showdebugging' => false,
], [
'h' => 'help'
]);
@@ -90,14 +86,6 @@ if ($options['help']) {
exit(0);
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql']) {
$DB->set_debug(true);
}
$pluginman = core_plugin_manager::instance();
$plugininfo = $pluginman->get_plugins();
-9
View File
@@ -135,15 +135,6 @@ if (!$envstatus) {
exit(1);
}
// Make sure there are no files left over from previous versions.
if (upgrade_stale_php_files_present()) {
cli_problem(get_string('upgradestalefiles', 'admin'));
// Stale file info contains HTML elements which aren't suitable for CLI.
$upgradestalefilesinfo = get_string('upgradestalefilesinfo', 'admin', get_docs_url('Upgrading'));
cli_error(strip_tags($upgradestalefilesinfo));
}
// Test plugin dependencies.
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
+1 -6
View File
@@ -2815,7 +2815,6 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.1.0" level="required">
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
@@ -2997,7 +2996,6 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.2.0" level="required">
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
@@ -3179,7 +3177,6 @@
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.2.0" level="required">
<RESTRICT function="restrict_php_version_80" message="unsupportedphpversion80" />
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
@@ -3447,7 +3444,7 @@
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="optional"/>
<PHP_EXTENSION name="sodium" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
@@ -3527,8 +3524,6 @@
<ON_CHECK message="sixtyfourbitswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_max_input_vars" level="optional">
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
-9
View File
@@ -119,19 +119,10 @@ if (($form = data_submitted()) && confirm_sesskey()) {
// Save processors enabled/disabled status.
foreach ($allprocessors as $processor) {
$enabled = isset($form->{$processor->name});
if ($enabled != $processor->enabled) {
add_to_config_log($processor->name, $processor->enabled, $enabled, 'core');
}
\core_message\api::update_processor_status($processor, $enabled);
}
foreach ($newpreferences as $name => $value) {
$old = isset($preferences->$name) ? $preferences->$name : '';
if ($old != $value) {
add_to_config_log($name, $old, $value, 'core');
}
set_config($name, $value, 'message');
}
$transaction->allow_commit();
+4 -6
View File
@@ -34,12 +34,11 @@ $error = optional_param('error', '', PARAM_RAW);
if ($error) {
$message = optional_param('error_description', '', PARAM_RAW);
if ($message) {
$SESSION->loginerrormsg = $message;
redirect(new moodle_url(get_login_url()));
print_error($message);
} else {
$SESSION->loginerrormsg = $error;
redirect(new moodle_url(get_login_url()));
print_error($error);
}
die();
}
// The authorization code generated by the authorization server.
@@ -54,6 +53,5 @@ if (isset($params['sesskey']) and confirm_sesskey($params['sesskey'])) {
$redirecturl->param('oauth2code', $code);
redirect($redirecturl);
} else {
$SESSION->loginerrormsg = get_string('invalidsesskey', 'error');
redirect(new moodle_url(get_login_url()));
print_error('invalidsesskey');
}
+1 -7
View File
@@ -52,14 +52,8 @@ if ($data = $form->get_data()) {
$message = get_string('purgecachesfinished', 'admin');
}
// Redirect and/or show notification message confirming cache(s) were purged.
if (isset($message)) {
if (!$PAGE->url->compare($returnurl, URL_MATCH_BASE)) {
redirect($returnurl, $message);
}
// We are already on the purge caches page, add the notification.
\core\notification::add($message, \core\output\notification::NOTIFY_INFO);
redirect($returnurl, $message);
}
// Otherwise, show a form to actually purge the caches.
+1 -2
View File
@@ -271,8 +271,7 @@ if ($roleid) {
foreach ($assignableroles as $roleid => $notused) {
$roleusers = '';
if (0 < $assigncounts[$roleid] && $assigncounts[$roleid] <= MAX_USERS_TO_LIST_PER_ROLE) {
$userfieldsapi = \core_user\fields::for_name();
$userfields = 'u.id, u.username' . $userfieldsapi->get_sql('u')->selects;
$userfields = 'u.id, u.username, ' . get_all_user_name_fields(true, 'u');
$roleusers = get_role_users($roleid, $context, false, $userfields);
if (!empty($roleusers)) {
$strroleusers = array();
+7 -7
View File
@@ -536,7 +536,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user1->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist2->get_userids());
$this->assertEquals($expected, $userlist2->get_userids(), '', 0.0, 10, true);
// The user list for coursecontext1 should user1, user2 and admin (role creator).
$userlist3 = new \core_privacy\local\request\userlist($coursecontext1, $component);
@@ -547,7 +547,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user2->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist3->get_userids());
$this->assertEquals($expected, $userlist3->get_userids(), '', 0.0, 10, true);
// The user list for coursecatcontext should user2 and admin (role creator).
$userlist4 = new \core_privacy\local\request\userlist($coursecatcontext, $component);
@@ -557,7 +557,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user2->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist4->get_userids());
$this->assertEquals($expected, $userlist4->get_userids(), '', 0.0, 10, true);
// The user list for systemcontext should user1 and admin (role creator).
$userlist6 = new \core_privacy\local\request\userlist($systemcontext, $component);
@@ -567,7 +567,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user1->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist6->get_userids());
$this->assertEquals($expected, $userlist6->get_userids(), '', 0.0, 10, true);
// The user list for cmcontext should user1, user2 and admin (role creator).
$userlist7 = new \core_privacy\local\request\userlist($cmcontext, $component);
@@ -578,7 +578,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user2->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist7->get_userids());
$this->assertEquals($expected, $userlist7->get_userids(), '', 0.0, 10, true);
// The user list for blockcontext should user1 and admin (role creator).
$userlist8 = new \core_privacy\local\request\userlist($blockcontext, $component);
@@ -588,7 +588,7 @@ class core_role_privacy_testcase extends provider_testcase {
$user1->id,
$admin->id
];
$this->assertEqualsCanonicalizing($expected, $userlist8->get_userids());
$this->assertEquals($expected, $userlist8->get_userids(), '', 0.0, 10, true);
}
/**
@@ -744,4 +744,4 @@ class core_role_privacy_testcase extends provider_testcase {
}
return $rolesnames;
}
}
}
+3 -10
View File
@@ -68,16 +68,9 @@ if ($errormsg !== '') {
$showsettingslinks = true;
if ($hassiteconfig) {
$data = [
'action' => new moodle_url('/admin/search.php'),
'btnclass' => 'btn-primary',
'inputname' => 'query',
'searchstring' => get_string('search'),
'query' => $query,
'extraclasses' => 'd-flex justify-content-center'
];
echo $OUTPUT->render_from_template('core/search_input', $data);
require_once("admin_settings_search_form.php");
$form = new admin_settings_search_form();
$form->display();
echo '<hr>';
if ($query) {
echo admin_search_settings_html($query);
-15
View File
@@ -144,20 +144,5 @@ if ($hassiteconfig && \core_analytics\manager::is_analytics_enabled()) {
$settings->add(new admin_setting_configduration('analytics/modeltimelimit', new lang_string('modeltimelimit', 'analytics'),
new lang_string('modeltimelimitinfo', 'analytics'), 20 * MINSECS));
$options = array(
0 => new lang_string('neverdelete', 'analytics'),
1000 => new lang_string('numdays', '', 1000),
365 => new lang_string('numdays', '', 365),
180 => new lang_string('numdays', '', 180),
150 => new lang_string('numdays', '', 150),
120 => new lang_string('numdays', '', 120),
90 => new lang_string('numdays', '', 90),
60 => new lang_string('numdays', '', 60),
35 => new lang_string('numdays', '', 35));
$settings->add(new admin_setting_configselect('analytics/calclifetime',
new lang_string('calclifetime', 'analytics'),
new lang_string('configlcalclifetime', 'analytics'), 35, $options));
}
}
+1
View File
@@ -269,6 +269,7 @@ preferences,moodle|/user/preferences.php|t/preferences',
$setting = new admin_setting_configcheckbox('cachejs', new lang_string('cachejs', 'admin'), new lang_string('cachejs_help', 'admin'), 1);
$setting->set_updatedcallback('js_reset_all_caches');
$temp->add($setting);
$temp->add(new admin_setting_configcheckbox('modchooserdefault', new lang_string('modchooserdefault', 'admin'), new lang_string('configmodchooserdefault', 'admin'), 1));
$ADMIN->add('appearance', $temp);
// Link to tag management interface.
+23 -4
View File
@@ -57,14 +57,20 @@ if (($hassiteconfig || has_any_capability(array(
new lang_string('badgesalt_desc', 'badges'),
'badges' . $SITE->timecreated, PARAM_ALPHANUM));
$backpacks = badges_get_site_backpacks();
$choices = array();
$defaultchoice = 0;
foreach ($backpacks as $backpack) {
$choices[$backpack->id] = $backpack->backpackweburl;
if ($backpack->backpackweburl == BADGRIO_BACKPACKWEBURL) {
$defaultchoice = $backpack->id;
}
}
$globalsettings->add(new admin_setting_configcheckbox('badges_allowcoursebadges',
new lang_string('allowcoursebadges', 'badges'),
new lang_string('allowcoursebadges_desc', 'badges'), 1));
$globalsettings->add(new admin_setting_configcheckbox('badges_allowexternalbackpack',
new lang_string('allowexternalbackpack', 'badges'),
new lang_string('allowexternalbackpack_desc', 'badges'), 1));
$ADMIN->add('badges', $globalsettings);
$ADMIN->add('badges',
@@ -91,6 +97,19 @@ if (($hassiteconfig || has_any_capability(array(
array('moodle/badges:createbadge'), empty($CFG->enablebadges)
)
);
$backpacksettings = new admin_settingpage('backpacksettings', new lang_string('backpacksettings', 'badges'),
array('moodle/badges:manageglobalsettings'), empty($CFG->enablebadges));
$backpacksettings->add(new admin_setting_configcheckbox('badges_allowexternalbackpack',
new lang_string('allowexternalbackpack', 'badges'),
new lang_string('allowexternalbackpack_desc', 'badges'), 1));
$backpacksettings->add(new admin_setting_configselect('badges_site_backpack',
new lang_string('sitebackpack', 'badges'),
new lang_string('sitebackpack_help', 'badges'),
$defaultchoice, $choices));
$ADMIN->add('badges', $backpacksettings);
$ADMIN->add('badges',
new admin_externalpage('managebackpacks',
-91
View File
@@ -22,8 +22,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use core_admin\local\settings\filesize;
$capabilities = array(
'moodle/backup:backupcourse',
'moodle/category:manage',
@@ -77,17 +75,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configselect('moodlecourse/visible', new lang_string('visible'), new lang_string('visible_help'),
1, $choices));
// Enable/disable download course content.
$choices = [
DOWNLOAD_COURSE_CONTENT_DISABLED => new lang_string('no'),
DOWNLOAD_COURSE_CONTENT_ENABLED => new lang_string('yes'),
];
$downloadcontentsitedefault = new admin_setting_configselect('moodlecourse/downloadcontentsitedefault',
new lang_string('enabledownloadcoursecontent', 'course'),
new lang_string('downloadcoursecontent_help', 'course'), 0, $choices);
$downloadcontentsitedefault->add_dependent_on('downloadcoursecontentallowed');
$temp->add($downloadcontentsitedefault);
// Course format.
$temp->add(new admin_setting_heading('courseformathdr', new lang_string('type_format', 'plugin'), ''));
@@ -139,13 +126,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
new lang_string('coursehelpshowgrades'), 1, array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
$temp->add(new admin_setting_configselect('moodlecourse/showreports', new lang_string('showreports'), '', 0,
array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
$temp->add(new admin_setting_configselect('moodlecourse/showactivitydates',
new lang_string('showactivitydates'),
new lang_string('showactivitydates_help'), 1, [
0 => new lang_string('no'),
1 => new lang_string('yes')
]
));
// Files and uploads.
$temp->add(new admin_setting_heading('filesanduploadshdr', new lang_string('filesanduploads'), ''));
@@ -170,15 +150,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configselect('moodlecourse/enablecompletion', new lang_string('completion', 'completion'),
new lang_string('enablecompletion_help', 'completion'), 1, array(0 => new lang_string('no'), 1 => new lang_string('yes'))));
// Display completion conditions.
$temp->add(new admin_setting_configselect('moodlecourse/showcompletionconditions',
new lang_string('showcompletionconditions', 'completion'),
new lang_string('showcompletionconditions_help', 'completion'), 1, [
0 => new lang_string('no'),
1 => new lang_string('yes')
]
));
// Groups.
$temp->add(new admin_setting_heading('groups', new lang_string('groups', 'group'), ''));
$choices = array();
@@ -190,21 +161,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$ADMIN->add('courses', $temp);
// Download course content.
$downloadcoursedefaulturl = new moodle_url('/admin/settings.php', ['section' => 'coursesettings']);
$temp = new admin_settingpage('downloadcoursecontent', new lang_string('downloadcoursecontent', 'course'));
$temp->add(new admin_setting_configcheckbox('downloadcoursecontentallowed',
new lang_string('downloadcoursecontentallowed', 'admin'),
new lang_string('downloadcoursecontentallowed_desc', 'admin', $downloadcoursedefaulturl->out()), 0));
// 50MB default maximum size per file when downloading course content.
$defaultmaxdownloadsize = 50 * filesize::UNIT_MB;
$temp->add(new filesize('maxsizeperdownloadcoursefile', new lang_string('maxsizeperdownloadcoursefile', 'admin'),
new lang_string('maxsizeperdownloadcoursefile_desc', 'admin'), $defaultmaxdownloadsize, filesize::UNIT_MB));
$temp->hide_if('maxsizeperdownloadcoursefile', 'downloadcoursecontentallowed');
$ADMIN->add('courses', $temp);
// "courserequests" settingpage.
$temp = new admin_settingpage('courserequest', new lang_string('courserequest'));
$temp->add(new admin_setting_configcheckbox('enablecourserequests',
@@ -228,7 +184,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
// Add a category for the Activity Chooser.
$ADMIN->add('courses', new admin_category('activitychooser', new lang_string('activitychoosercategory', 'course')));
$temp = new admin_settingpage('activitychoosersettings', new lang_string('activitychoosersettings', 'course'));
// Tab mode for the activity chooser.
$temp->add(
new admin_setting_configselect(
'activitychoosertabmode',
@@ -242,31 +197,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
]
)
);
// Build a list of plugins that use the footer callback.
$pluginswithfunction = get_plugins_with_function('custom_chooser_footer', 'lib.php');
$pluginsoptions = [];
$pluginsoptions[COURSE_CHOOSER_FOOTER_NONE] = get_string('activitychooserhidefooter', 'course');
if ($pluginswithfunction) {
foreach ($pluginswithfunction as $plugintype => $plugins) {
foreach ($plugins as $pluginname => $pluginfunction) {
$plugin = $plugintype.'_'.$pluginname;
$pluginsoptions[$plugin] = get_string('pluginname', $plugin);
}
}
}
// Select what plugin to show in the footer.
$temp->add(
new admin_setting_configselect(
'activitychooseractivefooter',
new lang_string('activitychooseractivefooter', 'course'),
new lang_string('activitychooseractivefooter_desc', 'course'),
COURSE_CHOOSER_FOOTER_NONE,
$pluginsoptions
)
);
$ADMIN->add('activitychooser', $temp);
$ADMIN->add('activitychooser',
new admin_externalpage('activitychooserrecommended', new lang_string('activitychooserrecommendations', 'course'),
@@ -329,9 +259,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
['value' => 1, 'locked' => 0])
);
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_legacyfiles',
new lang_string('generallegacyfiles', 'backup'),
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
$ADMIN->add('backups', $temp);
// Create a page for general import configuration and defaults.
@@ -343,11 +270,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
// Import defaults section.
$temp->add(new admin_setting_heading('importsettings', new lang_string('importsettings', 'backup'), ''));
$temp->add(new admin_setting_configcheckbox_with_lock(
'backup/backup_import_permissions',
new lang_string('generalpermissions', 'backup'),
new lang_string('configgeneralpermissions', 'backup'),
array('value' => 0, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_activities', new lang_string('generalactivities','backup'), new lang_string('configgeneralactivities','backup'), array('value'=>1, 'locked'=>0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_blocks', new lang_string('generalblocks','backup'), new lang_string('configgeneralblocks','backup'), array('value'=>1, 'locked'=>0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_filters', new lang_string('generalfilters','backup'), new lang_string('configgeneralfilters','backup'), array('value'=>1, 'locked'=>0)));
@@ -363,9 +285,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
new lang_string('configgeneralcontentbankcontent', 'backup'),
['value' => 1, 'locked' => 0])
);
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_legacyfiles',
new lang_string('generallegacyfiles', 'backup'),
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
$ADMIN->add('backups', $temp);
@@ -492,10 +411,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
1)
);
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_legacyfiles',
new lang_string('generallegacyfiles', 'backup'),
new lang_string('configlegacyfiles', 'backup'), 1));
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_messages', new lang_string('messages', 'message'), new lang_string('backupmessageshelp','message'), 0));
//$temp->add(new admin_setting_configcheckbox('backup/backup_auto_blogs', new lang_string('blogs', 'blog'), new lang_string('backupblogshelp','blog'), 0));
@@ -522,9 +437,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_role_assignments',
new lang_string('generalroleassignments', 'backup'),
new lang_string('configrestoreroleassignments', 'backup'), array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_permissions',
new lang_string('generalpermissions', 'backup'),
new lang_string('configrestorepermissions', 'backup'), array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_activities',
new lang_string('generalactivities', 'backup'),
new lang_string('configrestoreactivities', 'backup'), array('value' => 1, 'locked' => 0)));
@@ -561,9 +473,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_contentbankcontent',
new lang_string('generalcontentbankcontent', 'backup'),
new lang_string('configrestorecontentbankcontent', 'backup'), array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_legacyfiles',
new lang_string('generallegacyfiles', 'backup'),
new lang_string('configlegacyfiles', 'backup'), array('value' => 1, 'locked' => 0)));
// Restore defaults when merging into another course.
$temp->add(new admin_setting_heading('mergerestoredefaults', new lang_string('mergerestoredefaults', 'backup'), ''));
-7
View File
@@ -41,13 +41,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp->add(new admin_setting_configcheckbox('debugdisplay', new lang_string('debugdisplay', 'admin'), new lang_string('configdebugdisplay', 'admin'), ini_get_bool('display_errors')));
$temp->add(new admin_setting_configcheckbox('perfdebug', new lang_string('perfdebug', 'admin'), new lang_string('configperfdebug', 'admin'), '7', '15', '7'));
$temp->add(new admin_setting_configcheckbox('debugstringids', new lang_string('debugstringids', 'admin'), new lang_string('debugstringids_desc', 'admin'), 0));
$temp->add(new admin_setting_configselect('debugsqltrace',
new lang_string('debugsqltrace', 'admin'),
new lang_string('debugsqltrace_desc', 'admin'), 0, array(
0 => new lang_string('disabled', 'admin'),
1 => new lang_string('debugsqltrace1', 'admin'),
2 => new lang_string('debugsqltrace2', 'admin'),
100 => new lang_string('debugsqltrace100', 'admin'))));
$temp->add(new admin_setting_configcheckbox('debugvalidators', new lang_string('debugvalidators', 'admin'), new lang_string('configdebugvalidators', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('debugpageinfo', new lang_string('debugpageinfo', 'admin'), new lang_string('configdebugpageinfo', 'admin'), 0));
$ADMIN->add('development', $temp);
-2
View File
@@ -8,8 +8,6 @@ if ($hassiteconfig) {
$temp = new admin_settingpage('langsettings', new lang_string('languagesettings', 'admin'));
$temp->add(new admin_setting_configcheckbox('autolang', new lang_string('autolang', 'admin'), new lang_string('configautolang', 'admin'), 1));
$temp->add(new admin_setting_configselect('lang', new lang_string('lang', 'admin'), new lang_string('configlang', 'admin'), current_language(), get_string_manager()->get_list_of_translations())); // $CFG->lang might be set in installer already, default en is in setup.php
$temp->add(new admin_setting_configcheckbox('autolangusercreation', new lang_string('autolangusercreation', 'admin'),
new lang_string('configautolangusercreation', 'admin'), 1));
$temp->add(new admin_setting_configcheckbox('langmenu', new lang_string('langmenu', 'admin'), new lang_string('configlangmenu', 'admin'), 1));
$temp->add(new admin_setting_langlist());
$temp->add(new admin_setting_configcheckbox('langcache', new lang_string('langcache', 'admin'), new lang_string('langcache_desc', 'admin'), 1));
-29
View File
@@ -1,29 +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/>.
/**
* Adds payments links to the admin tree
*
* @package core
* @copyright 2020 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$ADMIN->add('payment', new admin_externalpage(
'paymentaccounts',
new lang_string('paymentaccounts', 'payment'),
new moodle_url("/payment/accounts.php"),
['moodle/payment:manageaccounts', 'moodle/payment:viewpayments']));
+51 -105
View File
@@ -167,42 +167,6 @@ if ($hassiteconfig) {
$ADMIN->add('modules', new admin_category('antivirussettings', new lang_string('antiviruses', 'antivirus')));
$temp = new admin_settingpage('manageantiviruses', new lang_string('antivirussettings', 'antivirus'));
$temp->add(new admin_setting_manageantiviruses());
// Common settings.
$temp->add(new admin_setting_heading('antiviruscommonsettings', new lang_string('antiviruscommonsettings', 'antivirus'), ''));
// Alert email.
$temp->add(
new admin_setting_configtext(
'antivirus/notifyemail',
new lang_string('notifyemail', 'antivirus'),
new lang_string('notifyemail_help', 'antivirus'),
'',
PARAM_EMAIL
)
);
// Enable quarantine.
$temp->add(
new admin_setting_configcheckbox(
'antivirus/enablequarantine',
new lang_string('enablequarantine', 'antivirus'),
new lang_string('enablequarantine_help', 'antivirus',
\core\antivirus\quarantine::DEFAULT_QUARANTINE_FOLDER),
0
)
);
// Quarantine time.
$temp->add(
new admin_setting_configduration(
'antivirus/quarantinetime',
new lang_string('quarantinetime', 'antivirus'),
new lang_string('quarantinetime_desc', 'antivirus'),
\core\antivirus\quarantine::DEFAULT_QUARANTINE_TIME
)
);
$ADMIN->add('antivirussettings', $temp);
$plugins = core_plugin_manager::instance()->get_plugins_of_type('antivirus');
core_collator::asort_objects_by_property($plugins, 'displayname');
@@ -280,25 +244,6 @@ if ($hassiteconfig) {
$plugin->load_settings($ADMIN, 'mediaplayers', $hassiteconfig);
}
// Payment gateway plugins.
$ADMIN->add('modules', new admin_category('paymentgateways', new lang_string('type_paygw_plural', 'plugin')));
$temp = new admin_settingpage('managepaymentgateways', new lang_string('type_paygwmanage', 'plugin'));
$temp->add(new \core_admin\local\settings\manage_payment_gateway_plugins());
$temp->add(new admin_setting_description(
'managepaymentgatewayspostfix',
'',
new lang_string('gotopaymentaccounts', 'payment',
html_writer::link(new moodle_url('/payment/accounts.php'), get_string('paymentaccounts', 'payment')))
));
$ADMIN->add('paymentgateways', $temp);
$plugins = core_plugin_manager::instance()->get_plugins_of_type('paygw');
core_collator::asort_objects_by_property($plugins, 'displayname');
foreach ($plugins as $plugin) {
/** @var \core\plugininfo\paygw $plugin */
$plugin->load_settings($ADMIN, 'paymentgateways', $hassiteconfig);
}
// Data format settings.
$ADMIN->add('modules', new admin_category('dataformatsettings', new lang_string('dataformats')));
$temp = new admin_settingpage('managedataformats', new lang_string('managedataformats'));
@@ -401,6 +346,55 @@ if ($hassiteconfig) {
/** @var \core\plugininfo\repository $plugin */
$plugin->load_settings($ADMIN, 'repositorysettings', $hassiteconfig);
}
/// Web services
$ADMIN->add('modules', new admin_category('webservicesettings', new lang_string('webservices', 'webservice')));
/// overview page
$temp = new admin_settingpage('webservicesoverview', new lang_string('webservicesoverview', 'webservice'));
$temp->add(new admin_setting_webservicesoverview());
$ADMIN->add('webservicesettings', $temp);
//API documentation
$ADMIN->add('webservicesettings', new admin_externalpage('webservicedocumentation', new lang_string('wsdocapi', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/documentation.php", 'moodle/site:config', false));
/// manage service
$temp = new admin_settingpage('externalservices', new lang_string('externalservices', 'webservice'));
$temp->add(new admin_setting_heading('manageserviceshelpexplaination', new lang_string('information', 'webservice'), new lang_string('servicehelpexplanation', 'webservice')));
$temp->add(new admin_setting_manageexternalservices());
$ADMIN->add('webservicesettings', $temp);
$ADMIN->add('webservicesettings', new admin_externalpage('externalservice', new lang_string('editaservice', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/service.php", 'moodle/site:config', true));
$ADMIN->add('webservicesettings', new admin_externalpage('externalservicefunctions', new lang_string('externalservicefunctions', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/service_functions.php", 'moodle/site:config', true));
$ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusers', new lang_string('externalserviceusers', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/service_users.php", 'moodle/site:config', true));
$ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusersettings', new lang_string('serviceusersettings', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/service_user_settings.php", 'moodle/site:config', true));
/// manage protocol page link
$temp = new admin_settingpage('webserviceprotocols', new lang_string('manageprotocols', 'webservice'));
$temp->add(new admin_setting_managewebserviceprotocols());
if (empty($CFG->enablewebservices)) {
$temp->add(new admin_setting_heading('webservicesaredisabled', '', new lang_string('disabledwarning', 'webservice')));
}
// We cannot use $OUTPUT this early, doing so means that we lose the ability
// to set the page layout on all admin pages.
// $wsdoclink = $OUTPUT->doc_link('How_to_get_a_security_key');
$url = new moodle_url(get_docs_url('How_to_get_a_security_key'));
$wsdoclink = html_writer::tag('a', new lang_string('supplyinfo', 'webservice'), array('href'=>$url));
$temp->add(new admin_setting_configcheckbox('enablewsdocumentation', new lang_string('enablewsdocumentation',
'admin'), new lang_string('configenablewsdocumentation', 'admin', $wsdoclink), false));
$ADMIN->add('webservicesettings', $temp);
/// links to protocol pages
$plugins = core_plugin_manager::instance()->get_plugins_of_type('webservice');
core_collator::asort_objects_by_property($plugins, 'displayname');
foreach ($plugins as $plugin) {
/** @var \core\plugininfo\webservice $plugin */
$plugin->load_settings($ADMIN, 'webservicesettings', $hassiteconfig);
}
/// manage token page link
$ADMIN->add('webservicesettings', new admin_externalpage('addwebservicetoken', new lang_string('managetokens', 'webservice'), "$CFG->wwwroot/$CFG->admin/webservice/tokens.php", 'moodle/site:config', true));
$temp = new admin_settingpage('webservicetokens', new lang_string('managetokens', 'webservice'));
$temp->add(new admin_setting_managewebservicetokens());
if (empty($CFG->enablewebservices)) {
$temp->add(new admin_setting_heading('webservicesaredisabled', '', new lang_string('disabledwarning', 'webservice')));
}
$ADMIN->add('webservicesettings', $temp);
}
// Question type settings
@@ -555,19 +549,8 @@ if ($hassiteconfig) {
// Search engine selection.
$temp->add(new admin_setting_heading('searchengineheading', new lang_string('searchengine', 'admin'), ''));
$searchengineselect = new admin_setting_configselect('searchengine',
new lang_string('selectsearchengine', 'admin'), '', 'simpledb', $engines);
$searchengineselect->set_validate_function(function(string $value): string {
global $CFG;
// Check nobody's setting the indexing and query-only server to the same one.
if (isset($CFG->searchenginequeryonly) && $CFG->searchenginequeryonly === $value) {
return get_string('searchenginequeryonlysame', 'admin');
} else {
return '';
}
});
$temp->add($searchengineselect);
$temp->add(new admin_setting_configselect('searchengine',
new lang_string('selectsearchengine', 'admin'), '', 'simpledb', $engines));
$temp->add(new admin_setting_heading('searchoptionsheading', new lang_string('searchoptions', 'admin'), ''));
$temp->add(new admin_setting_configcheckbox('searchindexwhendisabled',
new lang_string('searchindexwhendisabled', 'admin'), new lang_string('searchindexwhendisabled_desc', 'admin'),
@@ -607,43 +590,6 @@ if ($hassiteconfig) {
new lang_string('searchhideallcategory_desc', 'admin'),
0));
$temp->add(new admin_setting_heading('searchmanagement', new lang_string('searchmanagement', 'admin'),
new lang_string('searchmanagement_desc', 'admin')));
// Get list of search engines including those with alternate settings.
$searchenginequeryonlyselect = new admin_setting_configselect('searchenginequeryonly',
new lang_string('searchenginequeryonly', 'admin'),
new lang_string('searchenginequeryonly_desc', 'admin'), '', function() use($engines) {
$options = ['' => new lang_string('searchenginequeryonly_none', 'admin')];
foreach ($engines as $name => $display) {
$options[$name] = $display;
$classname = '\search_' . $name . '\engine';
$engine = new $classname;
if ($engine->has_alternate_configuration()) {
$options[$name . '-alternate'] =
new lang_string('searchenginealternatesettings', 'admin', $display);
}
}
return $options;
});
$searchenginequeryonlyselect->set_validate_function(function(string $value): string {
global $CFG;
// Check nobody's setting the indexing and query-only server to the same one.
if (isset($CFG->searchengine) && $CFG->searchengine === $value) {
return get_string('searchenginequeryonlysame', 'admin');
} else {
return '';
}
});
$temp->add($searchenginequeryonlyselect);
$temp->add(new admin_setting_configcheckbox('searchbannerenable',
new lang_string('searchbannerenable', 'admin'), new lang_string('searchbannerenable_desc', 'admin'),
0));
$temp->add(new admin_setting_confightmleditor('searchbanner',
new lang_string('searchbanner', 'admin'), '', ''));
$ADMIN->add('searchplugins', $temp);
$ADMIN->add('searchplugins', new admin_externalpage('searchareas', new lang_string('searchareas', 'admin'),
new moodle_url('/admin/searchareas.php')));
-17
View File
@@ -160,23 +160,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp->add(new admin_setting_configportlist('curlsecurityallowedport',
new lang_string('curlsecurityallowedport', 'admin'),
new lang_string('curlsecurityallowedportsyntax', 'admin'), ""));
// HTTP Header referrer policy settings.
$referreroptions = [
'default' => get_string('referrernone', 'admin'),
'no-referrer' => 'no-referrer',
'no-referrer-when-downgrade' => 'no-referrer-when-downgrade',
'origin' => 'origin',
'origin-when-cross-origin' => 'origin-when-cross-origin',
'same-origin' => 'same-origin',
'strict-origin' => 'strict-origin',
'strict-origin-when-cross-origin' => 'strict-origin-when-cross-origin',
'unsafe-url' => 'unsafe-url',
];
$temp->add(new admin_setting_configselect('referrerpolicy',
new lang_string('referrerpolicy', 'admin'),
new lang_string('referrerpolicydesc', 'admin'), 'default', $referreroptions));
$ADMIN->add('security', $temp);
// "notifications" settingpage
+313 -536
View File
@@ -1,243 +1,162 @@
<?php
// This file is part of Moodle - https://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Defines settingpages and externalpages under the "server" category.
*
* @package core
* @category admin
* @copyright 2006 Martin Dougiamas
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This file defines settingpages and externalpages under the "server" category
defined('MOODLE_INTERNAL') || die();
if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
if ($hassiteconfig) {
// System paths.
$temp = new admin_settingpage('systempaths', new lang_string('systempaths', 'admin'));
$temp->add(new admin_setting_configexecutable('pathtophp', new lang_string('pathtophp', 'admin'),
new lang_string('configpathtophp', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'),
new lang_string('configpathtodu', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'),
new lang_string('edhelpaspellpath'), ''));
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'),
new lang_string('pathtodot_help', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtogs', new lang_string('pathtogs', 'admin'),
new lang_string('pathtogs_help', 'admin'), '/usr/bin/gs'));
$temp->add(new admin_setting_configexecutable('pathtopdftoppm', new lang_string('pathtopdftoppm', 'admin'),
new lang_string('pathtopdftoppm_help', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtopython', new lang_string('pathtopython', 'admin'),
new lang_string('pathtopythondesc', 'admin'), ''));
$ADMIN->add('server', $temp);
// "systempaths" settingpage
$temp = new admin_settingpage('systempaths', new lang_string('systempaths','admin'));
$temp->add(new admin_setting_configexecutable('pathtophp', new lang_string('pathtophp', 'admin'),
new lang_string('configpathtophp', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'), new lang_string('configpathtodu', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'), new lang_string('edhelpaspellpath'), ''));
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'), new lang_string('pathtodot_help', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtogs', new lang_string('pathtogs', 'admin'), new lang_string('pathtogs_help', 'admin'), '/usr/bin/gs'));
$temp->add(new admin_setting_configexecutable('pathtopython', new lang_string('pathtopython', 'admin'),
new lang_string('pathtopythondesc', 'admin'), ''));
$ADMIN->add('server', $temp);
// Support contact.
$temp = new admin_settingpage('supportcontact', new lang_string('supportcontact', 'admin'));
$primaryadmin = get_admin();
if ($primaryadmin) {
$primaryadminemail = $primaryadmin->email;
$primaryadminname = fullname($primaryadmin, true);
} else {
// No defaults during installation - admin user must be created first.
$primaryadminemail = null;
$primaryadminname = null;
}
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'),
new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
$setting = new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'),
new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_EMAIL);
$setting->set_force_ltr(true);
$temp->add($setting);
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'),
new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
$ADMIN->add('server', $temp);
// Session handling.
$temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandling', 'admin'));
if (empty($CFG->session_handler_class) and $DB->session_lock_supported()) {
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'),
new lang_string('configdbsessions', 'admin'), 0));
}
$temp->add(new admin_setting_configduration('sessiontimeout', new lang_string('sessiontimeout', 'admin'),
new lang_string('configsessiontimeout', 'admin'), 8 * 60 * 60));
// "supportcontact" settingpage
$temp = new admin_settingpage('supportcontact', new lang_string('supportcontact','admin'));
$primaryadmin = get_admin();
if ($primaryadmin) {
$primaryadminemail = $primaryadmin->email;
$primaryadminname = fullname($primaryadmin, true);
} else {
// no defaults during installation - admin user must be created first
$primaryadminemail = NULL;
$primaryadminname = NULL;
}
$temp->add(new admin_setting_configtext('supportname', new lang_string('supportname', 'admin'),
new lang_string('configsupportname', 'admin'), $primaryadminname, PARAM_NOTAGS));
$setting = new admin_setting_configtext('supportemail', new lang_string('supportemail', 'admin'),
new lang_string('configsupportemail', 'admin'), $primaryadminemail, PARAM_EMAIL);
$setting->set_force_ltr(true);
$temp->add($setting);
$temp->add(new admin_setting_configtext('supportpage', new lang_string('supportpage', 'admin'), new lang_string('configsupportpage', 'admin'), '', PARAM_URL));
$ADMIN->add('server', $temp);
$sessiontimeoutwarning = new admin_setting_configduration('sessiontimeoutwarning',
new lang_string('sessiontimeoutwarning', 'admin'),
new lang_string('configsessiontimeoutwarning', 'admin'), 20 * 60);
$sessiontimeoutwarning->set_validate_function(function(int $value): string {
global $CFG;
// Check sessiontimeoutwarning is less than sessiontimeout.
if ($CFG->sessiontimeout <= $value) {
return get_string('configsessiontimeoutwarningcheck', 'admin');
} else {
return '';
}
});
// "sessionhandling" settingpage
$temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandling', 'admin'));
if (empty($CFG->session_handler_class) and $DB->session_lock_supported()) {
$temp->add(new admin_setting_configcheckbox('dbsessions', new lang_string('dbsessions', 'admin'), new lang_string('configdbsessions', 'admin'), 0));
}
$temp->add($sessiontimeoutwarning);
$temp->add(new admin_setting_configduration('sessiontimeout', new lang_string('sessiontimeout', 'admin'),
new lang_string('configsessiontimeout', 'admin'), 8 * 60 * 60));
$temp->add(new admin_setting_configtext('sessioncookie', new lang_string('sessioncookie', 'admin'),
new lang_string('configsessioncookie', 'admin'), '', PARAM_ALPHANUM));
$temp->add(new admin_setting_configtext('sessioncookiepath', new lang_string('sessioncookiepath', 'admin'),
new lang_string('configsessioncookiepath', 'admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtext('sessioncookiedomain', new lang_string('sessioncookiedomain', 'admin'),
new lang_string('configsessioncookiedomain', 'admin'), '', PARAM_RAW, 50));
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_configtext('sessioncookie', new lang_string('sessioncookie', 'admin'), new lang_string('configsessioncookie', 'admin'), '', PARAM_ALPHANUM));
$temp->add(new admin_setting_configtext('sessioncookiepath', new lang_string('sessioncookiepath', 'admin'), new lang_string('configsessioncookiepath', 'admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtext('sessioncookiedomain', new lang_string('sessioncookiedomain', 'admin'), new lang_string('configsessioncookiedomain', 'admin'), '', PARAM_RAW, 50));
$ADMIN->add('server', $temp);
// Statistics.
$temp = new admin_settingpage('stats', new lang_string('stats'), 'moodle/site:config', empty($CFG->enablestats));
$temp->add(new admin_setting_configselect('statsfirstrun', new lang_string('statsfirstrun', 'admin'),
new lang_string('configstatsfirstrun', 'admin'), 'none',
[
'none' => new lang_string('none'),
60 * 60 * 24 * 7 => new lang_string('numweeks', 'moodle', 1),
60 * 60 * 24 * 14 => new lang_string('numweeks', 'moodle', 2),
60 * 60 * 24 * 21 => new lang_string('numweeks', 'moodle', 3),
60 * 60 * 24 * 28 => new lang_string('nummonths', 'moodle', 1),
60 * 60 * 24 * 56 => new lang_string('nummonths', 'moodle', 2),
60 * 60 * 24 * 84 => new lang_string('nummonths', 'moodle', 3),
60 * 60 * 24 * 112 => new lang_string('nummonths', 'moodle', 4),
60 * 60 * 24 * 140 => new lang_string('nummonths', 'moodle', 5),
60 * 60 * 24 * 168 => new lang_string('nummonths', 'moodle', 6),
'all' => new lang_string('all')
]
));
$temp->add(new admin_setting_configselect('statsmaxruntime', new lang_string('statsmaxruntime', 'admin'),
new lang_string('configstatsmaxruntime3', 'admin'), 0,
[
0 => new lang_string('untilcomplete'),
60 * 30 => '10 ' . new lang_string('minutes'),
60 * 30 => '30 ' . new lang_string('minutes'),
60 * 60 => '1 ' . new lang_string('hour'),
60 * 60 * 2 => '2 ' . new lang_string('hours'),
60 * 60 * 3 => '3 ' . new lang_string('hours'),
60 * 60 * 4 => '4 ' . new lang_string('hours'),
60 * 60 * 5 => '5 ' . new lang_string('hours'),
60 * 60 * 6 => '6 ' . new lang_string('hours'),
60 * 60 * 7 => '7 ' . new lang_string('hours'),
60 * 60 * 8 => '8 ' . new lang_string('hours'),
]
));
$temp->add(new admin_setting_configtext('statsruntimedays', new lang_string('statsruntimedays', 'admin'),
new lang_string('configstatsruntimedays', 'admin'), 31, PARAM_INT));
$temp->add(new admin_setting_configtext('statsuserthreshold', new lang_string('statsuserthreshold', 'admin'),
new lang_string('configstatsuserthreshold', 'admin'), 0, PARAM_INT));
$ADMIN->add('server', $temp);
// HTTP.
$temp = new admin_settingpage('http', new lang_string('http', 'admin'));
$temp->add(new admin_setting_configcheckbox('slasharguments', new lang_string('slasharguments', 'admin'),
new lang_string('configslasharguments', 'admin'), 1));
$temp->add(new admin_setting_heading('reverseproxy', new lang_string('reverseproxy', 'admin'), '', ''));
$options = [
0 => 'HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR => 'HTTP_CLIENT, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR | GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'REMOTE_ADDR'
];
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'),
new lang_string('configgetremoteaddrconf', 'admin'),
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR | GETREMOTEADDR_SKIP_HTTP_CLIENT_IP, $options));
$temp->add(new admin_setting_configtext('reverseproxyignore', new lang_string('reverseproxyignore', 'admin'),
new lang_string('configreverseproxyignore', 'admin'), ''));
// "stats" settingpage
$temp = new admin_settingpage('stats', new lang_string('stats'), 'moodle/site:config', empty($CFG->enablestats));
$temp->add(new admin_setting_configselect('statsfirstrun', new lang_string('statsfirstrun', 'admin'), new lang_string('configstatsfirstrun', 'admin'), 'none', array('none' => new lang_string('none'),
60*60*24*7 => new lang_string('numweeks','moodle',1),
60*60*24*14 => new lang_string('numweeks','moodle',2),
60*60*24*21 => new lang_string('numweeks','moodle',3),
60*60*24*28 => new lang_string('nummonths','moodle',1),
60*60*24*56 => new lang_string('nummonths','moodle',2),
60*60*24*84 => new lang_string('nummonths','moodle',3),
60*60*24*112 => new lang_string('nummonths','moodle',4),
60*60*24*140 => new lang_string('nummonths','moodle',5),
60*60*24*168 => new lang_string('nummonths','moodle',6),
'all' => new lang_string('all') )));
$temp->add(new admin_setting_configselect('statsmaxruntime', new lang_string('statsmaxruntime', 'admin'), new lang_string('configstatsmaxruntime3', 'admin'), 0, array(0 => new lang_string('untilcomplete'),
60*30 => '10 '.new lang_string('minutes'),
60*30 => '30 '.new lang_string('minutes'),
60*60 => '1 '.new lang_string('hour'),
60*60*2 => '2 '.new lang_string('hours'),
60*60*3 => '3 '.new lang_string('hours'),
60*60*4 => '4 '.new lang_string('hours'),
60*60*5 => '5 '.new lang_string('hours'),
60*60*6 => '6 '.new lang_string('hours'),
60*60*7 => '7 '.new lang_string('hours'),
60*60*8 => '8 '.new lang_string('hours') )));
$temp->add(new admin_setting_configtext('statsruntimedays', new lang_string('statsruntimedays', 'admin'), new lang_string('configstatsruntimedays', 'admin'), 31, PARAM_INT));
$temp->add(new admin_setting_configtext('statsuserthreshold', new lang_string('statsuserthreshold', 'admin'), new lang_string('configstatsuserthreshold', 'admin'), 0, PARAM_INT));
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_heading('webproxy', new lang_string('webproxy', 'admin'),
new lang_string('webproxyinfo', 'admin')));
$temp->add(new admin_setting_configtext('proxyhost', new lang_string('proxyhost', 'admin'),
new lang_string('configproxyhost', 'admin'), '', PARAM_HOST));
$temp->add(new admin_setting_configtext('proxyport', new lang_string('proxyport', 'admin'),
new lang_string('configproxyport', 'admin'), 0, PARAM_INT));
$options = ['HTTP' => 'HTTP'];
if (defined('CURLPROXY_SOCKS5')) {
$options['SOCKS5'] = 'SOCKS5';
}
$temp->add(new admin_setting_configselect('proxytype', new lang_string('proxytype', 'admin'),
new lang_string('configproxytype', 'admin'), 'HTTP', $options));
$temp->add(new admin_setting_configtext('proxyuser', new lang_string('proxyuser', 'admin'),
new lang_string('configproxyuser', 'admin'), ''));
$temp->add(new admin_setting_configpasswordunmask('proxypassword', new lang_string('proxypassword', 'admin'),
new lang_string('configproxypassword', 'admin'), ''));
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'),
new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
$ADMIN->add('server', $temp);
$temp = new admin_settingpage('maintenancemode', new lang_string('sitemaintenancemode', 'admin'));
$options = [0 => new lang_string('disable'), 1 => new lang_string('enable')];
$temp->add(new admin_setting_configselect('maintenance_enabled', new lang_string('sitemaintenancemode', 'admin'),
new lang_string('helpsitemaintenance', 'admin'), 0, $options));
$temp->add(new admin_setting_confightmleditor('maintenance_message', new lang_string('optionalmaintenancemessage', 'admin'),
'', ''));
$ADMIN->add('server', $temp);
// "http" settingpage
$temp = new admin_settingpage('http', new lang_string('http', 'admin'));
$temp->add(new admin_setting_configcheckbox('slasharguments', new lang_string('slasharguments', 'admin'), new lang_string('configslasharguments', 'admin'), 1));
$temp->add(new admin_setting_heading('reverseproxy', new lang_string('reverseproxy', 'admin'), '', ''));
$options = array(
0 => 'HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'HTTP_X_FORWARDED_FOR, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR => 'HTTP_CLIENT, REMOTE_ADDR',
GETREMOTEADDR_SKIP_HTTP_X_FORWARDED_FOR|GETREMOTEADDR_SKIP_HTTP_CLIENT_IP => 'REMOTE_ADDR');
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'),
new lang_string('configgetremoteaddrconf', 'admin'),
GETREMOTEADDR_SKIP_DEFAULT, $options));
$temp->add(new admin_setting_configtext('reverseproxyignore', new lang_string('reverseproxyignore', 'admin'), new lang_string('configreverseproxyignore', 'admin'), ''));
// Cleanup.
$temp = new admin_settingpage('cleanup', new lang_string('cleanup', 'admin'));
$temp->add(new admin_setting_configselect('deleteunconfirmed', new lang_string('deleteunconfirmed', 'admin'),
new lang_string('configdeleteunconfirmed', 'admin'), 168,
[
0 => new lang_string('never'),
168 => new lang_string('numdays', '', 7),
144 => new lang_string('numdays', '', 6),
120 => new lang_string('numdays', '', 5),
96 => new lang_string('numdays', '', 4),
72 => new lang_string('numdays', '', 3),
48 => new lang_string('numdays', '', 2),
24 => new lang_string('numdays', '', 1),
12 => new lang_string('numhours', '', 12),
6 => new lang_string('numhours', '', 6),
1 => new lang_string('numhours', '', 1),
]
));
$temp->add(new admin_setting_heading('webproxy', new lang_string('webproxy', 'admin'), new lang_string('webproxyinfo', 'admin')));
$temp->add(new admin_setting_configtext('proxyhost', new lang_string('proxyhost', 'admin'), new lang_string('configproxyhost', 'admin'), '', PARAM_HOST));
$temp->add(new admin_setting_configtext('proxyport', new lang_string('proxyport', 'admin'), new lang_string('configproxyport', 'admin'), 0, PARAM_INT));
$options = array('HTTP'=>'HTTP');
if (defined('CURLPROXY_SOCKS5')) {
$options['SOCKS5'] = 'SOCKS5';
}
$temp->add(new admin_setting_configselect('proxytype', new lang_string('proxytype', 'admin'), new lang_string('configproxytype','admin'), 'HTTP', $options));
$temp->add(new admin_setting_configtext('proxyuser', new lang_string('proxyuser', 'admin'), new lang_string('configproxyuser', 'admin'), ''));
$temp->add(new admin_setting_configpasswordunmask('proxypassword', new lang_string('proxypassword', 'admin'), new lang_string('configproxypassword', 'admin'), ''));
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'), new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_configselect('deleteincompleteusers', new lang_string('deleteincompleteusers', 'admin'),
new lang_string('configdeleteincompleteusers', 'admin'), 0,
[
0 => new lang_string('never'),
168 => new lang_string('numdays', '', 7),
144 => new lang_string('numdays', '', 6),
120 => new lang_string('numdays', '', 5),
96 => new lang_string('numdays', '', 4),
72 => new lang_string('numdays', '', 3),
48 => new lang_string('numdays', '', 2),
24 => new lang_string('numdays', '', 1),
]
));
$temp = new admin_settingpage('maintenancemode', new lang_string('sitemaintenancemode', 'admin'));
$options = array(0=>new lang_string('disable'), 1=>new lang_string('enable'));
$temp->add(new admin_setting_configselect('maintenance_enabled', new lang_string('sitemaintenancemode', 'admin'),
new lang_string('helpsitemaintenance', 'admin'), 0, $options));
$temp->add(new admin_setting_confightmleditor('maintenance_message', new lang_string('optionalmaintenancemessage', 'admin'),
'', ''));
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_configcheckbox('disablegradehistory', new lang_string('disablegradehistory', 'grades'),
new lang_string('disablegradehistory_help', 'grades'), 0));
$temp = new admin_settingpage('cleanup', new lang_string('cleanup', 'admin'));
$temp->add(new admin_setting_configselect('deleteunconfirmed', new lang_string('deleteunconfirmed', 'admin'), new lang_string('configdeleteunconfirmed', 'admin'), 168, array(0 => new lang_string('never'),
168 => new lang_string('numdays', '', 7),
144 => new lang_string('numdays', '', 6),
120 => new lang_string('numdays', '', 5),
96 => new lang_string('numdays', '', 4),
72 => new lang_string('numdays', '', 3),
48 => new lang_string('numdays', '', 2),
24 => new lang_string('numdays', '', 1),
12 => new lang_string('numhours', '', 12),
6 => new lang_string('numhours', '', 6),
1 => new lang_string('numhours', '', 1))));
$temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_string('gradehistorylifetime', 'grades'),
new lang_string('gradehistorylifetime_help', 'grades'), 0,
[
0 => new lang_string('neverdeletehistory', 'grades'),
1000 => new lang_string('numdays', '', 1000),
365 => new lang_string('numdays', '', 365),
180 => new lang_string('numdays', '', 180),
150 => new lang_string('numdays', '', 150),
120 => new lang_string('numdays', '', 120),
90 => new lang_string('numdays', '', 90),
60 => new lang_string('numdays', '', 60),
30 => new lang_string('numdays', '', 30),
]
));
$temp->add(new admin_setting_configselect('deleteincompleteusers', new lang_string('deleteincompleteusers', 'admin'), new lang_string('configdeleteincompleteusers', 'admin'), 0, array(0 => new lang_string('never'),
168 => new lang_string('numdays', '', 7),
144 => new lang_string('numdays', '', 6),
120 => new lang_string('numdays', '', 5),
96 => new lang_string('numdays', '', 4),
72 => new lang_string('numdays', '', 3),
48 => new lang_string('numdays', '', 2),
24 => new lang_string('numdays', '', 1))));
$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'),
new lang_string('configtempdatafoldercleanup', 'admin'), 168,
[
$temp->add(new admin_setting_configcheckbox('disablegradehistory', new lang_string('disablegradehistory', 'grades'),
new lang_string('disablegradehistory_help', 'grades'), 0));
$temp->add(new admin_setting_configselect('gradehistorylifetime', new lang_string('gradehistorylifetime', 'grades'),
new lang_string('gradehistorylifetime_help', 'grades'), 0, array(0 => new lang_string('neverdeletehistory', 'grades'),
1000 => new lang_string('numdays', '', 1000),
365 => new lang_string('numdays', '', 365),
180 => new lang_string('numdays', '', 180),
150 => new lang_string('numdays', '', 150),
120 => new lang_string('numdays', '', 120),
90 => new lang_string('numdays', '', 90),
60 => new lang_string('numdays', '', 60),
30 => new lang_string('numdays', '', 30))));
$temp->add(new admin_setting_configselect('tempdatafoldercleanup', new lang_string('tempdatafoldercleanup', 'admin'),
new lang_string('configtempdatafoldercleanup', 'admin'), 168, array(
1 => new lang_string('numhours', '', 1),
3 => new lang_string('numhours', '', 3),
6 => new lang_string('numhours', '', 6),
@@ -247,366 +166,224 @@ if ($hassiteconfig) {
24 => new lang_string('numhours', '', 24),
48 => new lang_string('numdays', '', 2),
168 => new lang_string('numdays', '', 7),
]
));
)));
$ADMIN->add('server', $temp);
$ADMIN->add('server', $temp);
$temp->add(new admin_setting_configduration('filescleanupperiod',
new lang_string('filescleanupperiod', 'admin'),
new lang_string('filescleanupperiod_help', 'admin'),
86400));
// Environment.
$ADMIN->add('server', new admin_externalpage('environment', new lang_string('environment', 'admin'),
"{$CFG->wwwroot}/{$CFG->admin}/environment.php"));
$ADMIN->add('server', new admin_externalpage('environment', new lang_string('environment','admin'), "$CFG->wwwroot/$CFG->admin/environment.php"));
$ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo'), "$CFG->wwwroot/$CFG->admin/phpinfo.php"));
$ADMIN->add('server', new admin_externalpage('testoutgoingmailconf', new lang_string('testoutgoingmailconf', 'admin'),
new moodle_url("$CFG->wwwroot/$CFG->admin/testoutgoingmailconf.php"), 'moodle/site:config', true));
// PHP info.
$ADMIN->add('server', new admin_externalpage('phpinfo', new lang_string('phpinfo'),
"{$CFG->wwwroot}/{$CFG->admin}/phpinfo.php"));
// Test outgoing mail configuration (hidden, accessed via direct link from the settings page).
$ADMIN->add('server', new admin_externalpage('testoutgoingmailconf', new lang_string('testoutgoingmailconf', 'admin'),
new moodle_url('/admin/testoutgoingmailconf.php'), 'moodle/site:config', true));
// "performance" settingpage
$temp = new admin_settingpage('performance', new lang_string('performance', 'admin'));
// Performance.
$temp = new admin_settingpage('performance', new lang_string('performance', 'admin'));
// Memory limit options for large administration tasks.
$memoryoptions = array(
'64M' => '64M',
'128M' => '128M',
'256M' => '256M',
'512M' => '512M',
'1024M' => '1024M',
'2048M' => '2048M');
// Memory limit options for large administration tasks.
$memoryoptions = [
'64M' => '64M',
'128M' => '128M',
'256M' => '256M',
'512M' => '512M',
'1024M' => '1024M',
'2048M' => '2048M',
];
// Allow larger memory usage for 64-bit sites only.
if (PHP_INT_SIZE === 8) {
$memoryoptions['3072M'] = '3072M';
$memoryoptions['4096M'] = '4096M';
}
// Allow larger memory usage for 64-bit sites only.
if (PHP_INT_SIZE === 8) {
$memoryoptions['3072M'] = '3072M';
$memoryoptions['4096M'] = '4096M';
}
$temp->add(new admin_setting_configselect('extramemorylimit', new lang_string('extramemorylimit', 'admin'),
new lang_string('configextramemorylimit', 'admin'), '512M', $memoryoptions));
$temp->add(new admin_setting_configtext('maxtimelimit', new lang_string('maxtimelimit', 'admin'),
$temp->add(new admin_setting_configselect('extramemorylimit', new lang_string('extramemorylimit', 'admin'),
new lang_string('configextramemorylimit', 'admin'), '512M',
$memoryoptions));
$temp->add(new admin_setting_configtext('maxtimelimit', new lang_string('maxtimelimit', 'admin'),
new lang_string('maxtimelimit_desc', 'admin'), 0, PARAM_INT));
$temp->add(new admin_setting_configtext('curlcache', new lang_string('curlcache', 'admin'),
new lang_string('configcurlcache', 'admin'), 120, PARAM_INT));
$temp->add(new admin_setting_configtext('curlcache', new lang_string('curlcache', 'admin'),
new lang_string('configcurlcache', 'admin'), 120, PARAM_INT));
$temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('curltimeoutkbitrate', 'admin'),
new lang_string('curltimeoutkbitrate_help', 'admin'), 56, PARAM_INT));
$temp->add(new admin_setting_configtext('curltimeoutkbitrate', new lang_string('curltimeoutkbitrate', 'admin'),
new lang_string('curltimeoutkbitrate_help', 'admin'), 56, PARAM_INT));
$ADMIN->add('server', $temp);
$ADMIN->add('server', $temp);
// Tasks.
$ADMIN->add('server', new admin_category('taskconfig', new lang_string('taskadmintitle', 'admin')));
// Task processing.
$temp = new admin_settingpage('taskprocessing', new lang_string('taskprocessing', 'admin'));
$ADMIN->add('server', new admin_category('taskconfig', new lang_string('taskadmintitle', 'admin')));
$temp = new admin_settingpage('taskprocessing', new lang_string('taskprocessing','admin'));
$temp->add(
new admin_setting_configtext(
'task_scheduled_concurrency_limit',
new lang_string('task_scheduled_concurrency_limit', 'admin'),
new lang_string('task_scheduled_concurrency_limit_desc', 'admin'),
3,
PARAM_INT
)
);
$setting = new admin_setting_configcheckbox(
'cron_enabled',
new lang_string('cron_enabled', 'admin'),
new lang_string('cron_enabled_desc', 'admin'),
$temp->add(
new admin_setting_configduration(
'task_scheduled_max_runtime',
new lang_string('task_scheduled_max_runtime', 'admin'),
new lang_string('task_scheduled_max_runtime_desc', 'admin'),
30 * MINSECS
)
);
$temp->add(
new admin_setting_configtext(
'task_adhoc_concurrency_limit',
new lang_string('task_adhoc_concurrency_limit', 'admin'),
new lang_string('task_adhoc_concurrency_limit_desc', 'admin'),
3,
PARAM_INT
)
);
$temp->add(
new admin_setting_configduration(
'task_adhoc_max_runtime',
new lang_string('task_adhoc_max_runtime', 'admin'),
new lang_string('task_adhoc_max_runtime_desc', 'admin'),
30 * MINSECS
)
);
$ADMIN->add('taskconfig', $temp);
$temp = new admin_settingpage('tasklogging', new lang_string('tasklogging','admin'));
$temp->add(
new admin_setting_configselect(
'task_logmode',
new lang_string('task_logmode', 'admin'),
new lang_string('task_logmode_desc', 'admin'),
\core\task\logmanager::MODE_ALL,
[
\core\task\logmanager::MODE_ALL => new lang_string('task_logmode_all', 'admin'),
\core\task\logmanager::MODE_FAILONLY => new lang_string('task_logmode_failonly', 'admin'),
\core\task\logmanager::MODE_NONE => new lang_string('task_logmode_none', 'admin'),
]
)
);
$temp->add(
new admin_setting_configcheckbox(
'task_logtostdout',
new lang_string('task_logtostdout', 'admin'),
new lang_string('task_logtostdout_desc', 'admin'),
1
);
$setting->set_updatedcallback('theme_reset_static_caches');
$temp->add($setting);
$temp->add(
new admin_setting_configtext(
'task_scheduled_concurrency_limit',
new lang_string('task_scheduled_concurrency_limit', 'admin'),
new lang_string('task_scheduled_concurrency_limit_desc', 'admin'),
3,
PARAM_INT
)
);
)
);
if (\core\task\logmanager::uses_standard_settings()) {
$temp->add(
new admin_setting_configduration(
'task_scheduled_max_runtime',
new lang_string('task_scheduled_max_runtime', 'admin'),
new lang_string('task_scheduled_max_runtime_desc', 'admin'),
30 * MINSECS
'task_logretention',
new \lang_string('task_logretention', 'admin'),
new \lang_string('task_logretention_desc', 'admin'),
28 * DAYSECS
)
);
$temp->add(
new admin_setting_configtext(
'task_adhoc_concurrency_limit',
new lang_string('task_adhoc_concurrency_limit', 'admin'),
new lang_string('task_adhoc_concurrency_limit_desc', 'admin'),
3,
'task_logretainruns',
new \lang_string('task_logretainruns', 'admin'),
new \lang_string('task_logretainruns_desc', 'admin'),
20,
PARAM_INT
)
);
}
$ADMIN->add('taskconfig', $temp);
$temp->add(
new admin_setting_configduration(
'task_adhoc_max_runtime',
new lang_string('task_adhoc_max_runtime', 'admin'),
new lang_string('task_adhoc_max_runtime_desc', 'admin'),
30 * MINSECS
)
);
$ADMIN->add('taskconfig', $temp);
if (\core\task\logmanager::uses_standard_settings()) {
$ADMIN->add('taskconfig', new admin_externalpage(
'tasklogs',
new lang_string('tasklogs','admin'),
"{$CFG->wwwroot}/{$CFG->admin}/tasklogs.php"
));
}
// Task log configuration.
$temp = new admin_settingpage('tasklogging', new lang_string('tasklogging', 'admin'));
$temp->add(
new admin_setting_configselect(
'task_logmode',
new lang_string('task_logmode', 'admin'),
new lang_string('task_logmode_desc', 'admin'),
\core\task\logmanager::MODE_ALL,
[
\core\task\logmanager::MODE_ALL => new lang_string('task_logmode_all', 'admin'),
\core\task\logmanager::MODE_FAILONLY => new lang_string('task_logmode_failonly', 'admin'),
\core\task\logmanager::MODE_NONE => new lang_string('task_logmode_none', 'admin'),
]
)
);
$temp->add(
new admin_setting_configcheckbox(
'task_logtostdout',
new lang_string('task_logtostdout', 'admin'),
new lang_string('task_logtostdout_desc', 'admin'),
1
)
);
// E-mail settings.
$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
if (\core\task\logmanager::uses_standard_settings()) {
$temp->add(
new admin_setting_configduration(
'task_logretention',
new \lang_string('task_logretention', 'admin'),
new \lang_string('task_logretention_desc', 'admin'),
28 * DAYSECS
)
);
$temp = new admin_settingpage('outgoingmailconfig', new lang_string('outgoingmailconfig', 'admin'));
$temp->add(
new admin_setting_configtext(
'task_logretainruns',
new \lang_string('task_logretainruns', 'admin'),
new \lang_string('task_logretainruns_desc', 'admin'),
20,
PARAM_INT
)
);
}
$ADMIN->add('taskconfig', $temp);
// Task logs.
if (\core\task\logmanager::uses_standard_settings()) {
$ADMIN->add('taskconfig', new admin_externalpage(
'tasklogs',
new lang_string('tasklogs', 'admin'),
"{$CFG->wwwroot}/{$CFG->admin}/tasklogs.php"
));
}
// Email.
$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
// Outgoing mail configuration.
$temp = new admin_settingpage('outgoingmailconfig', new lang_string('outgoingmailconfig', 'admin'));
$temp->add(new admin_setting_heading('smtpheading', new lang_string('smtp', 'admin'),
new lang_string('smtpdetail', 'admin')));
$temp->add(new admin_setting_configtext('smtphosts', new lang_string('smtphosts', 'admin'),
new lang_string('configsmtphosts', 'admin'), '', PARAM_RAW));
$options = [
'' => new lang_string('none', 'admin'),
'ssl' => 'SSL',
'tls' => 'TLS',
];
$temp->add(new admin_setting_configselect('smtpsecure', new lang_string('smtpsecure', 'admin'),
new lang_string('configsmtpsecure', 'admin'), '', $options));
$authtypeoptions = [
'LOGIN' => 'LOGIN',
'PLAIN' => 'PLAIN',
'NTLM' => 'NTLM',
'CRAM-MD5' => 'CRAM-MD5',
];
$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));
$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));
$temp->add(new admin_setting_configpasswordunmask('smtppass', new lang_string('smtppass', 'admin'),
new lang_string('configsmtpuser', 'admin'), ''));
$temp->add(new admin_setting_configtext('smtpmaxbulk', new lang_string('smtpmaxbulk', 'admin'),
new lang_string('configsmtpmaxbulk', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_heading('noreplydomainheading', new lang_string('noreplydomain', 'admin'),
$temp->add(new admin_setting_heading('smtpheading', new lang_string('smtp', 'admin'),
new lang_string('smtpdetail', 'admin')));
$temp->add(new admin_setting_configtext('smtphosts', new lang_string('smtphosts', 'admin'),
new lang_string('configsmtphosts', 'admin'), '', PARAM_RAW));
$options = array('' => new lang_string('none', 'admin'), 'ssl' => 'SSL', 'tls' => 'TLS');
$temp->add(new admin_setting_configselect('smtpsecure', new lang_string('smtpsecure', 'admin'),
new lang_string('configsmtpsecure', 'admin'), '', $options));
$authtypeoptions = array('LOGIN' => 'LOGIN', 'PLAIN' => 'PLAIN', 'NTLM' => 'NTLM', 'CRAM-MD5' => 'CRAM-MD5');
$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));
$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));
$temp->add(new admin_setting_configpasswordunmask('smtppass', new lang_string('smtppass', 'admin'),
new lang_string('configsmtpuser', 'admin'), ''));
$temp->add(new admin_setting_configtext('smtpmaxbulk', new lang_string('smtpmaxbulk', 'admin'),
new lang_string('configsmtpmaxbulk', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_heading('noreplydomainheading', new lang_string('noreplydomain', 'admin'),
new lang_string('noreplydomaindetail', 'admin')));
$temp->add(new admin_setting_configtext('noreplyaddress', new lang_string('noreplyaddress', 'admin'),
new lang_string('confignoreplyaddress', 'admin'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_EMAIL));
$temp->add(new admin_setting_configtextarea('allowedemaildomains',
$temp->add(new admin_setting_configtext('noreplyaddress', new lang_string('noreplyaddress', 'admin'),
new lang_string('confignoreplyaddress', 'admin'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_EMAIL));
$temp->add(new admin_setting_configtextarea('allowedemaildomains',
new lang_string('allowedemaildomains', 'admin'),
new lang_string('configallowedemaildomains', 'admin'),
''));
$temp->add(new admin_setting_heading('divertallemailsheading', new lang_string('divertallemails', 'admin'),
new lang_string('divertallemailsdetail', 'admin')));
$temp->add(new admin_setting_configtext('divertallemailsto',
new lang_string('divertallemailsto', 'admin'),
new lang_string('divertallemailsto_desc', 'admin'),
''));
$temp->add(new admin_setting_configtextarea('divertallemailsexcept',
new lang_string('divertallemailsexcept', 'admin'),
new lang_string('divertallemailsexcept_desc', 'admin'),
'', PARAM_RAW, '50', '4'));
$noreplyaddress = isset($CFG->noreplyaddress) ? $CFG->noreplyaddress : 'noreply@example.com';
$dkimdomain = substr(strrchr($noreplyaddress, "@"), 1);
$dkimselector = empty($CFG->emaildkimselector) ? '[selector]' : $CFG->emaildkimselector;
$pempath = "\$CFG->dataroot/dkim/{$dkimdomain}/{$dkimselector}.private";
$temp->add(new admin_setting_heading('emaildkim', new lang_string('emaildkim', 'admin'),
new lang_string('emaildkiminfo', 'admin', ['path' => $pempath, 'docs' => \get_docs_url('Mail_configuration#DKIM')])));
$temp->add(new admin_setting_configtext('emaildkimselector', new lang_string('emaildkimselector', 'admin'),
new lang_string('configemaildkimselector', 'admin'), '', PARAM_FILE));
$url = new moodle_url('/admin/testoutgoingmailconf.php');
$link = html_writer::link($url, get_string('testoutgoingmailconf', 'admin'));
$temp->add(new admin_setting_heading('testoutgoinmailc', new lang_string('testoutgoingmailconf', 'admin'),
$url = new moodle_url('/admin/testoutgoingmailconf.php');
$link = html_writer::link($url, get_string('testoutgoingmailconf', 'admin'));
$temp->add(new admin_setting_heading('testoutgoinmailc', new lang_string('testoutgoingmailconf', 'admin'),
new lang_string('testoutgoingmaildetail', 'admin', $link)));
$temp->add(new admin_setting_heading('emaildoesnotfit', new lang_string('doesnotfit', 'admin'),
$temp->add(new admin_setting_heading('emaildoesnotfit', new lang_string('doesnotfit', 'admin'),
new lang_string('doesnotfitdetail', 'admin')));
$charsets = get_list_of_charsets();
unset($charsets['UTF-8']); // Not needed here.
$options = array();
$options['0'] = 'UTF-8';
$options = array_merge($options, $charsets);
$temp->add(new admin_setting_configselect('sitemailcharset', new lang_string('sitemailcharset', 'admin'),
new lang_string('configsitemailcharset','admin'), '0', $options));
$temp->add(new admin_setting_configcheckbox('allowusermailcharset', new lang_string('allowusermailcharset', 'admin'),
new lang_string('configallowusermailcharset', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('allowattachments', new lang_string('allowattachments', 'admin'),
new lang_string('configallowattachments', 'admin'), 1));
$options = array('LF' => 'LF', 'CRLF' => 'CRLF');
$temp->add(new admin_setting_configselect('mailnewline', new lang_string('mailnewline', 'admin'),
new lang_string('configmailnewline', 'admin'), 'LF', $options));
$charsets = get_list_of_charsets();
unset($charsets['UTF-8']);
$options = [
'0' => 'UTF-8',
];
$options = array_merge($options, $charsets);
$temp->add(new admin_setting_configselect('sitemailcharset', new lang_string('sitemailcharset', 'admin'),
new lang_string('configsitemailcharset', 'admin'), '0', $options));
$temp->add(new admin_setting_configcheckbox('allowusermailcharset', new lang_string('allowusermailcharset', 'admin'),
new lang_string('configallowusermailcharset', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('allowattachments', new lang_string('allowattachments', 'admin'),
new lang_string('configallowattachments', 'admin'), 1));
$options = [
'LF' => 'LF',
'CRLF' => 'CRLF',
];
$temp->add(new admin_setting_configselect('mailnewline', new lang_string('mailnewline', 'admin'),
new lang_string('configmailnewline', 'admin'), 'LF', $options));
$choices = [
new lang_string('never', 'admin'),
new lang_string('always', 'admin'),
new lang_string('onlynoreply', 'admin'),
];
$temp->add(new admin_setting_configselect('emailfromvia', new lang_string('emailfromvia', 'admin'),
new lang_string('configemailfromvia', 'admin'), 1, $choices));
$choices = array(new lang_string('never', 'admin'),
new lang_string('always', 'admin'),
new lang_string('onlynoreply', 'admin'));
$temp->add(new admin_setting_configselect('emailfromvia', new lang_string('emailfromvia', 'admin'),
new lang_string('configemailfromvia', 'admin'), 1, $choices));
$temp->add(new admin_setting_configtext('emailsubjectprefix', new lang_string('emailsubjectprefix', 'admin'),
new lang_string('configemailsubjectprefix', 'admin'), '', PARAM_RAW));
$temp->add(new admin_setting_configtextarea('emailheaders', new lang_string('emailheaders', 'admin'),
new lang_string('configemailheaders', 'admin'), '', PARAM_RAW, '50', '3'));
$ADMIN->add('email', $temp);
$ADMIN->add('email', $temp);
// Update notifications.
if (empty($CFG->disableupdatenotifications)) {
$temp = new admin_settingpage('updatenotifications', new lang_string('updatenotifications', 'core_admin'));
$temp->add(new admin_setting_configcheckbox('updateautocheck', new lang_string('updateautocheck', 'core_admin'),
new lang_string('updateautocheck_desc', 'core_admin'), 1));
$temp->add(new admin_setting_configselect('updateminmaturity', new lang_string('updateminmaturity', 'core_admin'),
new lang_string('updateminmaturity_desc', 'core_admin'), MATURITY_STABLE,
[
MATURITY_ALPHA => new lang_string('maturity'.MATURITY_ALPHA, 'core_admin'),
MATURITY_BETA => new lang_string('maturity'.MATURITY_BETA, 'core_admin'),
MATURITY_RC => new lang_string('maturity'.MATURITY_RC, 'core_admin'),
MATURITY_STABLE => new lang_string('maturity'.MATURITY_STABLE, 'core_admin'),
]
));
$temp->add(new admin_setting_configcheckbox('updatenotifybuilds', new lang_string('updatenotifybuilds', 'core_admin'),
new lang_string('updatenotifybuilds_desc', 'core_admin'), 0));
$ADMIN->add('server', $temp);
}
// Web services.
$ADMIN->add('server', new admin_category('webservicesettings', new lang_string('webservices', 'webservice')));
// Web services > Overview.
$temp = new admin_settingpage('webservicesoverview', new lang_string('webservicesoverview', 'webservice'));
$temp->add(new admin_setting_webservicesoverview());
$ADMIN->add('webservicesettings', $temp);
// Web services > API documentation.
$ADMIN->add('webservicesettings', new admin_externalpage('webservicedocumentation', new lang_string('wsdocapi', 'webservice'),
"{$CFG->wwwroot}/{$CFG->admin}/webservice/documentation.php", 'moodle/site:config', false));
// Web services > External services.
$temp = new admin_settingpage('externalservices', new lang_string('externalservices', 'webservice'));
$temp->add(new admin_setting_heading('manageserviceshelpexplaination', new lang_string('information', 'webservice'),
new lang_string('servicehelpexplanation', 'webservice')));
$temp->add(new admin_setting_manageexternalservices());
$ADMIN->add('webservicesettings', $temp);
$ADMIN->add('webservicesettings', new admin_externalpage('externalservice', new lang_string('editaservice', 'webservice'),
"{$CFG->wwwroot}/{$CFG->admin}/webservice/service.php", 'moodle/site:config', true));
$ADMIN->add('webservicesettings', new admin_externalpage('externalservicefunctions',
new lang_string('externalservicefunctions', 'webservice'), "{$CFG->wwwroot}/{$CFG->admin}/webservice/service_functions.php",
'moodle/site:config', true));
$ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusers',
new lang_string('externalserviceusers', 'webservice'), "{$CFG->wwwroot}/{$CFG->admin}/webservice/service_users.php",
'moodle/site:config', true));
$ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusersettings',
new lang_string('serviceusersettings', 'webservice'), "{$CFG->wwwroot}/{$CFG->admin}/webservice/service_user_settings.php",
'moodle/site:config', true));
// Web services > Manage protocols.
$temp = new admin_settingpage('webserviceprotocols', new lang_string('manageprotocols', 'webservice'));
$temp->add(new admin_setting_managewebserviceprotocols());
if (empty($CFG->enablewebservices)) {
$temp->add(new admin_setting_heading('webservicesaredisabled', '', new lang_string('disabledwarning', 'webservice')));
}
// We cannot use $OUTPUT->doc_link() this early, we would lose the ability to set the page layout on all admin pages.
$url = new moodle_url(get_docs_url('How_to_get_a_security_key'));
$wsdoclink = html_writer::link($url, new lang_string('supplyinfo', 'webservice'), ['target' => '_blank']);
$temp->add(new admin_setting_configcheckbox('enablewsdocumentation', new lang_string('enablewsdocumentation', 'admin'),
new lang_string('configenablewsdocumentation', 'admin', $wsdoclink), false));
$ADMIN->add('webservicesettings', $temp);
$plugins = core_plugin_manager::instance()->get_plugins_of_type('webservice');
core_collator::asort_objects_by_property($plugins, 'displayname');
foreach ($plugins as $plugin) {
/** @var \core\plugininfo\webservice $plugin */
$plugin->load_settings($ADMIN, 'webservicesettings', $hassiteconfig);
}
// Web services > Manage tokens.
$ADMIN->add('webservicesettings', new admin_externalpage('webservicetokens', new lang_string('managetokens', 'webservice'),
new moodle_url('/admin/webservice/tokens.php')));
// "update notifications" settingpage
if (empty($CFG->disableupdatenotifications)) {
$temp = new admin_settingpage('updatenotifications', new lang_string('updatenotifications', 'core_admin'));
$temp->add(new admin_setting_configcheckbox('updateautocheck', new lang_string('updateautocheck', 'core_admin'),
new lang_string('updateautocheck_desc', 'core_admin'), 1));
$temp->add(new admin_setting_configselect('updateminmaturity', new lang_string('updateminmaturity', 'core_admin'),
new lang_string('updateminmaturity_desc', 'core_admin'), MATURITY_STABLE,
array(
MATURITY_ALPHA => new lang_string('maturity'.MATURITY_ALPHA, 'core_admin'),
MATURITY_BETA => new lang_string('maturity'.MATURITY_BETA, 'core_admin'),
MATURITY_RC => new lang_string('maturity'.MATURITY_RC, 'core_admin'),
MATURITY_STABLE => new lang_string('maturity'.MATURITY_STABLE, 'core_admin'),
)));
$temp->add(new admin_setting_configcheckbox('updatenotifybuilds', new lang_string('updatenotifybuilds', 'core_admin'),
new lang_string('updatenotifybuilds_desc', 'core_admin'), 0));
$ADMIN->add('server', $temp);
}
} // end of speedup
-1
View File
@@ -39,7 +39,6 @@ $ADMIN->add('root', new admin_category('license', new lang_string('license')));
$ADMIN->add('root', new admin_category('location', new lang_string('location','admin')));
$ADMIN->add('root', new admin_category('language', new lang_string('language')));
$ADMIN->add('root', new admin_category('messaging', new lang_string('messagingcategory', 'admin')));
$ADMIN->add('root', new admin_category('payment', new lang_string('payments', 'payment')));
$ADMIN->add('root', new admin_category('modules', new lang_string('plugins', 'admin')));
$ADMIN->add('root', new admin_category('security', new lang_string('security','admin')));
$ADMIN->add('root', new admin_category('appearance', new lang_string('appearance','admin')));
+19 -39
View File
@@ -87,14 +87,6 @@ if ($hassiteconfig
$choices['1'] = new lang_string('trackforumsyes');
$temp->add(new admin_setting_configselect('defaultpreference_trackforums', new lang_string('trackforums'),
'', 0, $choices));
$choices = [];
$choices[\core_contentbank\content::VISIBILITY_PUBLIC] = new lang_string('visibilitychoicepublic', 'core_contentbank');
$choices[\core_contentbank\content::VISIBILITY_UNLISTED] = new lang_string('visibilitychoiceunlisted', 'core_contentbank');
$temp->add(new admin_setting_configselect('defaultpreference_core_contentbank_visibility',
new lang_string('visibilitypref', 'core_contentbank'),
new lang_string('visibilitypref_help', 'core_contentbank'),
\core_contentbank\content::VISIBILITY_PUBLIC, $choices));
}
$ADMIN->add('accounts', $temp);
@@ -196,6 +188,12 @@ if ($hassiteconfig
'country' => new lang_string('country'),
'moodlenetprofile' => new lang_string('moodlenetprofile', 'user'),
'timezone' => new lang_string('timezone'),
'webpage' => new lang_string('webpage'),
'icqnumber' => new lang_string('icqnumber'),
'skypeid' => new lang_string('skypeid'),
'yahooid' => new lang_string('yahooid'),
'aimid' => new lang_string('aimid'),
'msnid' => new lang_string('msnid'),
'firstaccess' => new lang_string('firstaccess'),
'lastaccess' => new lang_string('lastaccess'),
'lastip' => new lang_string('lastip'),
@@ -208,39 +206,21 @@ if ($hassiteconfig
// with moodle/site:viewuseridentity).
// Options include fields from the user table that might be helpful to
// distinguish when adding or listing users ('I want to add the John
// Smith from Science faculty') and any custom profile fields.
// Smith from Science faculty').
// Custom user profile fields are not currently supported.
$temp->add(new admin_setting_configmulticheckbox('showuseridentity',
new lang_string('showuseridentity', 'admin'),
new lang_string('showuseridentity_desc', 'admin'), ['email' => 1],
function() {
global $CFG;
require_once($CFG->dirroot.'/user/profile/lib.php');
// Basic fields available in user table.
$fields = [
'username' => new lang_string('username'),
'idnumber' => new lang_string('idnumber'),
'email' => new lang_string('email'),
'phone1' => new lang_string('phone1'),
'phone2' => new lang_string('phone2'),
'department' => new lang_string('department'),
'institution' => new lang_string('institution'),
'city' => new lang_string('city'),
'country' => new lang_string('country'),
];
// Custom profile fields.
$profilefields = profile_get_custom_fields();
foreach ($profilefields as $field) {
// Only reasonable-length text fields can be used as identity fields.
if ($field->param2 > 255 || $field->datatype != 'text') {
continue;
}
$fields['profile_field_' . $field->shortname] = $field->name . ' *';
}
return $fields;
}));
new lang_string('showuseridentity_desc', 'admin'), array('email' => 1), array(
'username' => new lang_string('username'),
'idnumber' => new lang_string('idnumber'),
'email' => new lang_string('email'),
'phone1' => new lang_string('phone1'),
'phone2' => new lang_string('phone2'),
'department' => new lang_string('department'),
'institution' => new lang_string('institution'),
'city' => new lang_string('city'),
'country' => new lang_string('country'),
)));
$setting = new admin_setting_configtext('fullnamedisplay', new lang_string('fullnamedisplay', 'admin'),
new lang_string('configfullnamedisplay', 'admin'), 'language', PARAM_TEXT, 50);
$setting->set_force_ltr(true);
@@ -1,87 +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/>.
}}
{{!
@template core_admin\local\settings\autocomplete
Admin setting auto complete.
Context variables required for this template:
* name - element name
* id - element id
* options - choices
* multiple - is multiple choices?
* manageurl - url to manage choices
* managetext - string to display manage url
* tags - Should we allow typing new entries to the field?
* ajax - Name of an AMD module to send/process ajax requests
* placeholder - Placeholder text for an empty list
* casesensitive - Whether the search has to be case-sensitive
* showsuggestions - Show suggestions by default - but this can be turned off
* noselectionstring - String that is shown when there are no selections
Example context (json):
{
"name": "name0",
"id": "id0",
"options": [{
"value": "1",
"text": "option 1",
"selected": true,
"disabled": false
}],
"multiple": true,
"manageurl": "",
"managetext": "",
"tags": false,
"ajax": "",
"placeholder": "",
"casesensitive": false,
"showsuggestions": true,
"noselectionstring": ""
}
}}
{{!
Setting autocomplete.
}}
<div class="form-select defaultsnext">
<input type="hidden" name="{{name}}[xxxxx]" value="_qf__force_multiselect_submission">
<select class="custom-select" name="{{name}}[]"
id="{{id}}"
{{#multiple}}multiple{{/multiple}}>
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{{text}}}</option>
{{/options}}
</select>
{{#manageurl}}
<a href="{{manageurl}}">{{managetext}}</a>
{{/manageurl}}
</div>
<br/>
{{#js}}
require(['core/form-autocomplete'], function(module) {
module.enhance({{#quote}}#{{id}}{{/quote}},
{{tags}},
{{#quote}}{{ajax}}{{/quote}},
{{#quote}}{{placeholder}}{{/quote}},
{{casesensitive}},
{{showsuggestions}},
{{#quote}}{{noselectionstring}}{{/quote}});
});
{{/js}}
@@ -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/>.
}}
{{!
@template core_admin/admin_setting_encryptedpassword
Admin encrypted password template.
Context variables required for this template:
* name - form element name
* set - whether it is set or empty
* id - element id
Example context (json):
{
"name": "test",
"id": "test0",
"set": true
}
}}
<div class="core_admin_encryptedpassword" data-encryptedpasswordid="{{ id }}"
{{#novalue}}data-novalue="y"{{/novalue}}>
{{#set}}
<span>{{# str }} encryptedpassword_set, admin {{/ str }}</span>
{{/set}}
{{^set}}
<a href="#" title="{{# str }} encryptedpassword_edit, admin {{/ str }}">
<span>{{# str }} novalueclicktoset, form {{/ str }}</span>
{{# pix }} t/passwordunmask-edit, core, {{# str }} passwordunmaskedithint, form {{/ str }}{{/ pix }}
</a>
{{/set}}
<input style="display: none" type="password" name="{{name}}" disabled>
{{!
Using buttons instead of links here allows them to be connected to the label, so the button
works if you click the label.
}}
{{#set}}
<button type="button" id="{{id}}" title="{{# str }} encryptedpassword_edit, admin {{/ str }}" class="btn btn-link" data-editbutton>
{{# pix }} t/passwordunmask-edit, core, {{/ pix }}
</button>
{{/set}}
<button type="button" style="display: none" title="{{# str }} cancel {{/ str }}" class="btn btn-link" data-cancelbutton>
<i class="icon fa fa-times"></i>
</button>
</div>
{{#js}}
require(['core_form/encryptedpassword'], function(encryptedpassword) {
new encryptedpassword.EncryptedPassword("{{ id }}");
});
{{/js}}
+2 -11
View File
@@ -56,7 +56,7 @@ class behat_admin extends behat_base {
$this->execute('behat_navigation::i_select_from_flat_navigation_drawer', [get_string('administrationsite')]);
// Search by label.
$this->execute('behat_forms::i_set_the_field_to', [get_string('search'), $label]);
$this->execute('behat_forms::i_set_the_field_to', [get_string('query', 'admin'), $label]);
$this->execute("behat_forms::press_button", get_string('search', 'admin'));
// Admin settings does not use the same DOM structure than other moodle forms
@@ -89,7 +89,7 @@ class behat_admin extends behat_base {
}
/**
* Sets the specified site settings. A table with | config | value | (optional)plugin | (optional)encrypted | is expected.
* Sets the specified site settings. A table with | config | value | (optional)plugin | is expected.
*
* @Given /^the following config values are set as admin:$/
* @param TableNode $table
@@ -103,20 +103,11 @@ class behat_admin extends behat_base {
foreach ($data as $config => $value) {
// Default plugin value is null.
$plugin = null;
$encrypted = false;
if (is_array($value)) {
$plugin = $value[1];
if (array_key_exists(2, $value)) {
$encrypted = $value[2] === 'encrypted';
}
$value = $value[0];
}
if ($encrypted) {
$value = \core\encryption::encrypt($value);
}
set_config($config, $value, $plugin);
}
}
-50
View File
@@ -1,50 +0,0 @@
@core @core_admin
Feature: An administrator can browse user accounts
In order to find the user accounts I am looking for
As an admin
I can browse users and see their basic information
Background:
Given the following "custom profile fields" exist:
| datatype | shortname | name |
| text | frog | Favourite frog |
And the following "users" exist:
| username | firstname | lastname | email | department | profile_field_frog | firstnamephonetic |
| user1 | User | One | one@example.com | Attack | Kermit | Yewzer |
| user2 | User | Two | two@example.com | Defence | Tree | Yoozare |
And I log in as "admin"
Scenario: User accounts display default fields
When I navigate to "Users > Accounts > Browse list of users" in site administration
# Name field always present, email field is default for showidentity.
Then the following should exist in the "users" table:
| First name / Surname | Email address |
| User One | one@example.com |
| User Two | two@example.com |
# Should not see other identity fields or non-default name fields.
And I should not see "Department" in the "table" "css_element"
And I should not see "Attack"
And I should not see "Favourite frog" in the "table" "css_element"
And I should not see "Kermit"
And I should not see "First name - phonetic" in the "table" "css_element"
And I should not see "Yoozare"
Scenario: User accounts with extra name fields
Given the following config values are set as admin:
| alternativefullnameformat | firstnamephonetic lastname |
When I navigate to "Users > Accounts > Browse list of users" in site administration
Then the following should exist in the "users" table:
| First name - phonetic / Surname | Email address |
| Yewzer One | one@example.com |
| Yoozare Two | two@example.com |
Scenario: User accounts with specified identity fields
Given the following config values are set as admin:
| showuseridentity | department,profile_field_frog |
When I navigate to "Users > Accounts > Browse list of users" in site administration
Then the following should exist in the "users" table:
| First name / Surname | Favourite frog | Department |
| User One | Kermit | Attack |
| User Two | Tree | Defence |
And I should not see "Email address" in the "table" "css_element"
And I should not see "one@example.com"
+6 -27
View File
@@ -5,16 +5,12 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
I need to filter the users account list using different filter
Background:
Given the following "custom profile fields" exist:
| datatype | shortname | name |
| text | frog | Favourite frog |
| text | undead | Type of undead |
And the following "users" exist:
| username | firstname | lastname | email | auth | confirmed | lastip | institution | department | profile_field_frog | profile_field_undead |
| user1 | User | One | one@example.com | manual | 0 | 127.0.1.1 | moodle | red | Kermit | |
| user2 | User | Two | two@example.com | ldap | 1 | 0.0.0.0 | moodle | blue | Mr Toad | Zombie |
| user3 | User | Three | three@example.com | manual | 1 | 0.0.0.0 | | | | |
| user4 | User | Four | four@example.com | ldap | 0 | 127.0.1.2 | | | | |
Given the following "users" exist:
| username | firstname | lastname | email | auth | confirmed | lastip | institution | department |
| user1 | User | One | one@example.com | manual | 0 | 127.0.1.1 | moodle | red |
| user2 | User | Two | two@example.com | ldap | 1 | 0.0.0.0 | moodle | blue |
| user3 | User | Three | three@example.com | manual | 1 | 0.0.0.0 | | |
| user4 | User | Four | four@example.com | ldap | 0 | 127.0.1.2 | | |
And the following "cohorts" exist:
| name | idnumber |
| Cohort 1 | CH1 |
@@ -120,20 +116,3 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
And I press "Add filter"
And I should see "User One"
And I should not see "User Two"
Scenario: Filter users by custom profile field (specific or any)
When I set the field "id_profile_fld" to "Favourite frog"
And I set the field "id_profile" to "Kermit"
And I press "Add filter"
Then I should see "User One"
And I should not see "User Two"
And I should not see "User Three"
And I should not see "User Four"
And I press "Remove all filters"
And I set the field "id_profile_fld" to "any field"
And I set the field "id_profile" to "Zombie"
And I press "Add filter"
And I should see "User Two"
And I should not see "User One"
And I should not see "User Three"
And I should not see "User Four"
+16 -65
View File
@@ -1,76 +1,27 @@
@core @core_admin
Feature: Manage external services tokens
In order to manage external service usage
Feature: Manage tokens
In order to manage webservice usage
As an admin
I need to be able to create, filter and delete tokens
I need to be able to create and delete tokens
Background:
Given the following "users" exist:
| username | password | firstname | lastname |
| user1 | user1 | Firstname1 | Lastname1 |
| user2 | user2 | Firstname2 | Lastname2 |
| user3 | user3 | Firstname3 | Lastname3 |
| user4 | user4 | Firstname4 | Lastname4 |
| username | password | firstname | lastname |
| testuser | testuser | Joe | Bloggs |
| testuser2 | testuser2 | TestFirstname | TestLastname |
And I change window size to "small"
And I log in as "admin"
And I am on site homepage
@javascript
Scenario: Add a token to user identified by name and then delete that token
Given I log in as "admin"
And I am on site homepage
And I navigate to "Server > Web services > Manage tokens" in site administration
And I press "Create token"
And I set the field "User" to "Firstname1 Lastname1"
And I set the field "Service" to "Moodle mobile web service"
Scenario: Add & delete a token
Given I navigate to "Plugins > Web services > Manage tokens" in site administration
And I follow "Add"
And I set the field "User" to "Joe Bloggs"
And I set the field "IP restriction" to "127.0.0.1"
When I press "Save changes"
Then I should see "Moodle mobile web service" in the "Firstname1 Lastname1" "table_row"
And I should see "127.0.0.1" in the "Firstname1 Lastname1" "table_row"
And I click on "Delete" "link" in the "Firstname1 Lastname1" "table_row"
And I should see "Do you really want to delete this web service token for Firstname1 Lastname1 on the service Moodle mobile web service?"
Then I should see "Joe Bloggs"
And I should see "127.0.0.1"
And I follow "Delete"
And I press "Delete"
And "Firstname1 Lastname1" "table_row" should not exist
@javascript
Scenario: Tokens can be filtered by user and by service
Given the following "core_webservice > Service" exists:
| name | Site information |
| shortname | siteinfo |
| enabled | 1 |
And the following "core_webservice > Service function" exists:
| service | siteinfo |
| functions | core_webservice_get_site_info |
And the following "core_webservice > Tokens" exist:
| user | service |
| user2 | siteinfo |
| user3 | moodle_mobile_app |
| user4 | siteinfo |
When I log in as "admin"
And I navigate to "Server > Web services > Manage tokens" in site administration
# All created tokens are shown by default.
And "Firstname1 Lastname1" "table_row" should not exist
And I should see "Site information" in the "Firstname2 Lastname2" "table_row"
And I should see "Moodle mobile web service" in the "Firstname3 Lastname3" "table_row"
And I should see "Site information" in the "Firstname4 Lastname4" "table_row"
# Filter tokens by user (note we can select the user by the identity field here).
When I click on "Tokens filter" "link"
And I set the field "User" to "user2@example.com"
And I press "Show only matching tokens"
Then "Firstname3 Lastname3" "table_row" should not exist
And "Firstname4 Lastname4" "table_row" should not exist
And I should see "Site information" in the "Firstname2 Lastname2" "table_row"
# Reset the filter.
And I press "Show all tokens"
And I should see "Site information" in the "Firstname2 Lastname2" "table_row"
And I should see "Moodle mobile web service" in the "Firstname3 Lastname3" "table_row"
And I should see "Site information" in the "Firstname4 Lastname4" "table_row"
# Filter tokens by service.
And I click on "Tokens filter" "link"
And I set the field "Service" to "Site information"
And I press "Show only matching tokens"
And I should see "Site information" in the "Firstname2 Lastname2" "table_row"
And I should see "Site information" in the "Firstname4 Lastname4" "table_row"
And "Firstname3 Lastname3" "table_row" should not exist
And I should not see "Joe Bloggs"
@@ -1,31 +0,0 @@
@core @core_admin
Feature: Web service user settings
In order to configure authorised users for a web service
As an admin
I need to use the page that lets you do that
Background:
# Include a custom profile field so we can check it gets displayed
Given the following "custom profile fields" exist:
| datatype | shortname | name | param2 |
| text | frog | Favourite frog | 100 |
And the following config values are set as admin:
| showuseridentity | email,profile_field_frog |
And the following "users" exist:
| username | firstname | lastname | email | profile_field_frog |
| user1 | User | One | 1@example.org | Kermit |
And the following "core_webservice > Service" exists:
| name | Silly service |
| shortname | silly |
| restrictedusers | 1 |
| enabled | 1 |
Scenario: Add a user to a web service
When I log in as "admin"
And I navigate to "Server > Web services > External services" in site administration
And I click on "Authorised users" "link" in the "Silly service" "table_row"
And I set the field "Not authorised users" to "User One"
And I press "Add"
Then I should see "User One" in the ".alloweduserlist" "css_element"
And I should see "1@example.org" in the ".alloweduserlist" "css_element"
And I should see "Kermit" in the ".alloweduserlist" "css_element"
@@ -64,7 +64,7 @@ class models_list implements \renderable, \templatable {
$data = new \stdClass();
$newmodelmenu = new \action_menu();
$newmodelmenu->set_menu_trigger(get_string('newmodel', 'tool_analytics'), 'btn btn-secondary');
$newmodelmenu->set_menu_trigger(get_string('newmodel', 'tool_analytics'), 'btn btn-default');
$newmodelmenu->set_alignment(\action_menu::TL, \action_menu::BL);
$newmodelmenu->add(new \action_menu_link(
@@ -57,10 +57,10 @@
{{/trainedexternally}}
{{! Hidden by default if #trainedexternally as the default option is trainedmodel in this case.}}
<div id="id-evaluation-timesplitting-container" class="mt-3 {{#trainedexternally}}hidden{{/trainedexternally}}">
<div id="id-evaluation-timesplitting-container" class="m-t-1 {{#trainedexternally}}hidden{{/trainedexternally}}">
{{#str}} selecttimesplittingforevaluation, tool_analytics {{/str}}
<div>
<select id="id-evaluation-timesplitting" name="timesplitting" class="custom-select mt-3">
<select id="id-evaluation-timesplitting" name="timesplitting" class="custom-select m-t-1">
{{#timesplittingmethods}}
<option value="{{id}}">{{text}}</option>
{{/timesplittingmethods}}
@@ -39,7 +39,7 @@
<input class="custom-control-input" type="radio" name="exportoption" id="id-mode-exportmodel" value="exportmodel" checked>
<label class="custom-control-label" for="id-mode-exportmodel">{{#str}} exportmodel, tool_analytics {{/str}}</label>
</div>
<div class="custom-control custom-checkbox ml-5" id="id-includeweights-container">
<div class="custom-control custom-checkbox m-l-2" id="id-includeweights-container">
<input class="custom-control-input" type="checkbox" id="id-includeweights" value="1" checked>
<label class="custom-control-label" for="id-includeweights">{{#str}} exportincludeweights, tool_analytics {{/str}}</label>
</div>
+2 -1
View File
@@ -66,6 +66,8 @@ class tool_analytics_external_testcase extends externallib_advanced_testcase {
/**
* test_potential_contexts description
*
* @expectedException required_capability_exception
*/
public function test_potential_contexts_no_manager() {
$this->resetAfterTest();
@@ -73,7 +75,6 @@ class tool_analytics_external_testcase extends externallib_advanced_testcase {
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$this->expectException(required_capability_exception::class);
$this->assertCount(2, \tool_analytics\external::potential_contexts());
}
}
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2021051700; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2021051100; // Requires this Moodle version.
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2020060900; // Requires this Moodle version.
$plugin->component = 'tool_analytics'; // Full name of the plugin (used for diagnostics).
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2021051700;
$plugin->requires = 2021051100;
$plugin->version = 2020061500;
$plugin->requires = 2020060900;
$plugin->component = 'tool_availabilityconditions';
+11 -43
View File
@@ -49,10 +49,6 @@ list($options, $unrecognized) = cli_get_params(
'torun' => 0,
'optimize-runs' => '',
'add-core-features-to-theme' => false,
'axe' => false,
'disable-composer' => false,
'composer-upgrade' => true,
'composer-self-update' => true,
),
array(
'j' => 'parallel',
@@ -68,36 +64,18 @@ $help = "
Behat utilities to initialise behat tests
Usage:
php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]]
[--axe] [-o | --optimize-runs] [-a | --add-core-features-to-theme]
[--no-composer-self-update] [--no-composer-upgrade]
[--disable-composer]
[--help]
php init.php [--parallel=value [--maxruns=value] [--fromrun=value --torun=value]] [--help]
Options:
-j, --parallel Number of parallel behat run to initialise
-m, --maxruns Max parallel processes to be executed at one time
--fromrun Execute run starting from (Used for parallel runs on different vms)
--torun Execute run till (Used for parallel runs on different vms)
--axe Include axe accessibility tests
-j, --parallel Number of parallel behat run to initialise
-m, --maxruns Max parallel processes to be executed at one time.
--fromrun Execute run starting from (Used for parallel runs on different vms)
--torun Execute run till (Used for parallel runs on different vms)
-o, --optimize-runs
Split features with specified tags in all parallel runs.
-o, --optimize-runs Split features with specified tags in all parallel runs.
-a, --add-core-features-to-theme Add all core features to specified theme's
-a, --add-core-features-to-theme
Add all core features to specified theme's
--no-composer-self-update
Prevent upgrade of the composer utility using its self-update command
--no-composer-upgrade
Prevent update development dependencies using composer
--disable-composer
A shortcut to disable composer self-update and dependency update
Note: Installation of composer and/or dependencies will still happen as required
-h, --help Print out this help
-h, --help Print out this help
Example from Moodle root directory:
\$ php admin/tool/behat/cli/init.php --parallel=2
@@ -124,10 +102,7 @@ if ($options['parallel'] && $options['parallel'] > 1) {
}
} else {
// Only sanitize options for single run.
$cmdoptionsforsinglerun = [
'add-core-features-to-theme',
'axe',
];
$cmdoptionsforsinglerun = array('add-core-features-to-theme');
foreach ($cmdoptionsforsinglerun as $option) {
if (!empty($options[$option])) {
@@ -140,15 +115,8 @@ if ($options['parallel'] && $options['parallel'] > 1) {
$cwd = getcwd();
$output = null;
if ($options['disable-composer']) {
// Disable self-update and upgrade easily.
// Note: Installation will still occur regardless of this setting.
$options['composer-self-update'] = false;
$options['composer-upgrade'] = false;
}
// Install and update composer and dependencies as required.
testing_update_composer_dependencies($options['composer-self-update'], $options['composer-upgrade']);
// If behat dependencies not downloaded then do it first, else symfony/process can't be used.
testing_update_composer_dependencies();
// Check whether the behat test environment needs to be updated.
chdir(__DIR__);
+4 -5
View File
@@ -45,7 +45,7 @@ list($options, $unrecognised) = cli_get_params(
array(
'stop-on-failure' => 0,
'verbose' => false,
'replace' => '',
'replace' => false,
'help' => false,
'tags' => '',
'profile' => '',
@@ -70,7 +70,7 @@ $help = "
Behat utilities to run behat tests in parallel
Usage:
php run.php [--BEHAT_OPTION=\"value\"] [--feature=\"value\"] [--replace=\"{run}\"] [--fromrun=value --torun=value] [--help]
php run.php [--BEHAT_OPTION=\"value\"] [--feature=\"value\"] [--replace] [--fromrun=value --torun=value] [--help]
Options:
--BEHAT_OPTION Any combination of behat option specified in http://behat.readthedocs.org/en/v2.5/guides/6.cli.html
@@ -144,10 +144,9 @@ $extraopts = $unrecognised;
if ($options['profile']) {
$profile = $options['profile'];
// If profile passed is not set, then exit (note we skip if the 'replace' option is found within the 'profile' value).
// If profile passed is not set, then exit.
if (!isset($CFG->behat_config[$profile]) && !isset($CFG->behat_profiles[$profile]) &&
!($options['replace'] && (strpos($profile, (string) $options['replace']) !== false))) {
!(isset($options['replace']) && (strpos($options['profile'], $options['replace']) >= 0 ))) {
echo "Invalid profile passed: " . $profile . PHP_EOL;
exit(1);
}
+1 -3
View File
@@ -54,7 +54,6 @@ list($options, $unrecognized) = cli_get_params(
'torun' => 0,
'optimize-runs' => '',
'add-core-features-to-theme' => false,
'axe' => false,
),
array(
'h' => 'help',
@@ -70,7 +69,7 @@ $help = "
Behat utilities to manage the test environment
Usage:
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--axe|--help] [--parallel=value [--maxruns=value]]
php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--help] [--parallel=value [--maxruns=value]]
Options:
--install Installs the test environment for acceptance tests
@@ -79,7 +78,6 @@ Options:
--disable Disables test environment
--diag Get behat test environment status code
--updatesteps Update feature step file.
--axe Include axe accessibility tests
-j, --parallel Number of parallel behat run operation
-m, --maxruns Max parallel processes to be executed at one time.
+1 -9
View File
@@ -49,7 +49,6 @@ list($options, $unrecognized) = cli_get_params(
'updatesteps' => false,
'optimize-runs' => '',
'add-core-features-to-theme' => false,
'axe' => false,
),
array(
'h' => 'help',
@@ -76,7 +75,6 @@ Options:
--disable Disables test environment
--diag Get behat test environment status code
--updatesteps Update feature step file.
--axe Include axe accessibility tests
-o, --optimize-runs Split features with specified tags in all parallel runs.
-a, --add-core-features-to-theme Add all core features to specified theme's
@@ -183,17 +181,11 @@ if ($options['install']) {
behat_config_manager::set_behat_run_config_value('behatsiteenabled', 1);
}
// Define whether to run Behat with axe tests.
behat_config_manager::set_behat_run_config_value('axe', $options['axe']);
// Enable test mode.
$timestart = microtime(true);
mtrace('Creating Behat configuration ...', '');
behat_util::start_test_mode($options['add-core-features-to-theme'], $options['optimize-runs'], $parallel, $run);
mtrace(' done in ' . round(microtime(true) - $timestart, 2) . ' seconds.');
// Themes are only built in the 'enable' command.
behat_util::build_themes(true);
behat_util::build_themes();
mtrace("Testing environment themes built");
// This is only displayed once for parallel install.
-1
View File
@@ -46,7 +46,6 @@ $string['stepsdefinitionstype'] = 'Type';
$string['theninfo'] = 'Then. Checkings to ensure the outcomes are the expected ones';
$string['unknownexceptioninfo'] = 'There was a problem with Selenium or your browser. Please ensure you are using the latest version of Selenium. Error:';
$string['viewsteps'] = 'Filter';
$string['warndirrootconfigfound'] = 'A configuration file was found at {$a}. This file is not automatically updated and may become stale. We recommend removing this file.';
$string['wheninfo'] = 'When. Action that provokes an event';
$string['wrongbehatsetup'] = 'Something is wrong with the behat setup and so step definitions cannot be listed: <b>{$a->errormsg}</b><br/><br/>Please check:<ul>
<li>$CFG->behat_dataroot, $CFG->behat_prefix and $CFG->behat_wwwroot are set in config.php with different values from $CFG->dataroot, $CFG->prefix and $CFG->wwwroot.</li>
@@ -156,7 +156,7 @@ Feature: Set up contextual data for tests
And I log in as "user5"
And I should see "You are logged in as"
And I am on "Course 1" course homepage
And I should see "You cannot enrol yourself in this course."
And I should see "You can not enrol yourself in this course."
Scenario: Add modules
Given the following "courses" exist:
@@ -21,5 +21,5 @@ Feature: Transform date time string arguments
And I log in as "teacher1"
And I am on "Course 1" course homepage
And I follow "Test assignment name"
And I should see "##yesterday##%d %B %Y##"
And I should see "##yesterday##l, j F Y##"
And I log out
@@ -49,14 +49,10 @@ Feature: Edit capabilities
Scenario: Module capabilities overrides
Given I log in as "teacher1"
And the following "activity" exists:
| activity | forum |
| course | C1 |
| idnumber | 00001 |
| name | I'm the name |
| intro | I'm the introduction |
| section | 1 |
And I am on "Course 1" course homepage with editing mode on
And I add a "Forum" to section "1" and I fill the form with:
| Forum name | I'm the name |
| Description | I'm the introduction |
And I follow "I'm the name"
And I navigate to "Permissions" in current page administration
And I override the system permissions of "Student" role with:
@@ -79,9 +75,9 @@ Feature: Edit capabilities
| Your word for 'Student' | Studier & 'learner' |
And I press "Save and display"
And I navigate to course participants
Then I should see "Teacher >= editing (Teacher)" in the "Teacher 1" "table_row"
And I should see "Teacher < \"editing\" (Non-editing teacher)" in the "Teaching Assistant" "table_row"
And I should see "Studier & 'learner' (Student)" in the "Student One" "table_row"
Then I should see "Teacher >= editing" in the "Teacher 1" "table_row"
And I should see "Teacher < \"editing\"" in the "Teaching Assistant" "table_row"
And I should see "Studier & 'learner'" in the "Student One" "table_row"
And I navigate to "Users > Permissions" in current page administration
And I should see "Teacher >= editing" in the "mod/forum:replypost" "table_row"
And I should see "Teacher < \"editing\"" in the "mod/forum:replypost" "table_row"
@@ -115,24 +115,15 @@ Feature: Verify that all form fields values can be get and set
| Wiki name | Test this one baby |
| Default format | HTML |
And I press "Cancel"
And I am on "Course 1" course homepage
# Radio - Checking "I set the field" and "the field matches value".
And the following "activity" exists:
| activity | choice |
| course | C1 |
| idnumber | choice1 |
| intro | Test choice description |
| name | Test choice name |
| choice1 | Option 1, Option 2, Option 3 |
| section | 1 |
| allowupdate | 1 |
And I am on "Course 1" course homepage
And I follow "Test choice name"
And I navigate to "Edit settings" in current page administration
And I set the field "Option 1" to "one"
And I set the field "Option 2" to "two"
And I set the field "Option 3" to "three"
And I press "Save and return to course"
And I am on "Course 1" course homepage
And I add a "Choice" to section "1" and I fill the form with:
| Choice name | Test choice name |
| Description | Test choice description |
| Allow choice to be updated | Yes |
| Option 1 | one |
| Option 2 | two |
| Option 3 | three |
And I follow "Test choice name"
And I set the field "one" to "1"
And I press "Save my choice"
@@ -14,6 +14,8 @@ Feature: Forms manipulation
Then the field "First name" matches value "Field value"
And the "Select a country" select box should contain "Japan"
And the field "New password" matches value "TestPass"
And I take focus off "Update profile" "button"
And I press "Update profile"
@javascript
Scenario: Expand all fieldsets and advanced elements
+22 -22
View File
@@ -87,7 +87,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
/**
* Setup test.
*/
public function setUp(): void {
public function setup() {
global $CFG;
$this->resetAfterTest();
@@ -149,7 +149,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
public function test_get_config_file_contents_with_single_run() {
$mockbuilder = $this->getMockBuilder('behat_config_util');
$mockbuilder->onlyMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$behatconfigutil = $mockbuilder->getMock();
@@ -165,7 +165,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -188,7 +188,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
public function test_get_config_file_contents_with_single_run_no_theme() {
$mockbuilder = $this->getMockBuilder('behat_config_util');
$mockbuilder->onlyMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$behatconfigutil = $mockbuilder->getMock();
@@ -219,7 +219,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -242,7 +242,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
public function test_get_config_file_contents_with_parallel_run() {
$mockbuilder = $this->getMockBuilder('behat_config_util');
$mockbuilder->onlyMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$behatconfigutil = $mockbuilder->getMock();
@@ -264,7 +264,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -295,7 +295,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -324,7 +324,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -345,7 +345,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
public function test_get_config_file_contents_with_parallel_run_optimize_tags() {
$mockbuilder = $this->getMockBuilder('behat_config_util');
$mockbuilder->onlyMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$behatconfigutil = $mockbuilder->getMock();
@@ -368,7 +368,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -399,7 +399,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -428,7 +428,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -489,7 +489,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
public function test_get_config_file_contents_with_blacklisted_tags() {
$mockbuilder = $this->getMockBuilder('behat_config_util');
$mockbuilder->onlyMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_blacklisted_tests_for_theme',
$mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_blacklisted_tests_for_theme',
'get_default_theme', 'get_theme_config'));
$behatconfigutil = $mockbuilder->getMock();
@@ -532,7 +532,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -553,7 +553,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
public function test_get_config_file_contents_with_blacklisted_features_contexts() {
$mockbuilder = $this->getMockBuilder('behat_config_util');
$mockbuilder->onlyMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_blacklisted_tests_for_theme',
$mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_blacklisted_tests_for_theme',
'get_default_theme', 'get_theme_config'));
$behatconfigutil = $mockbuilder->getMock();
@@ -611,7 +611,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
// Check contexts.
@@ -632,7 +632,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
public function test_core_features_to_include_in_specified_theme() {
$mockbuilder = $this->getMockBuilder('behat_config_util');
$mockbuilder->onlyMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$mockbuilder->setMethods(array('get_theme_test_directory', 'get_list_of_themes', 'get_default_theme', 'get_theme_config'));
$behatconfigutil = $mockbuilder->getMock();
@@ -646,7 +646,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -662,7 +662,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -678,7 +678,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
@@ -693,7 +693,7 @@ class tool_behat_manager_util_testcase extends advanced_testcase {
$this->assertCount(count($paths), $suites[$themename]['paths']);
foreach ($paths as $key => $feature) {
$this->assertStringContainsString($feature, $suites[$themename]['paths'][$key]);
$this->assertContains($feature, $suites[$themename]['paths'][$key]);
}
}
}
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2021051700; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2021051100; // Requires this Moodle version.
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2020060900; // Requires this Moodle version
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
-219
View File
@@ -1,219 +0,0 @@
PLEASE NOTE:
There are included libraries in the directory quail/common/services which might have different (but compatible) licenses than the one covered in this file. Current licenses include:
*The current BSD:
*services/readability/php-text-statistics
*The MIT License:
*common/css.php The function parseSelector is from the PHPQuery project:
*http://code.google.com/p/phpquery
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for software and other kinds of works.
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.
Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS
0. Definitions.
ÒThis LicenseÓ refers to version 3 of the GNU General Public License.
ÒCopyrightÓ also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
ÒThe ProgramÓ refers to any copyrightable work licensed under this License. Each licensee is addressed as ÒyouÓ. ÒLicenseesÓ and ÒrecipientsÓ may be individuals or organizations.
To ÒmodifyÓ a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a Òmodified versionÓ of the earlier work or a work Òbased onÓ the earlier work.
A Òcovered workÓ means either the unmodified Program or a work based on the Program.
To ÒpropagateÓ a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
To ÒconveyÓ a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays ÒAppropriate Legal NoticesÓ to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
1. Source Code.
The Òsource codeÓ for a work means the preferred form of the work for making modifications to it. ÒObject codeÓ means any non-source form of a work.
A ÒStandard InterfaceÓ means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
The ÒSystem LibrariesÓ of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A ÒMajor ComponentÓ, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
The ÒCorresponding SourceÓ for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
* a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
* b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to Òkeep intact all noticesÓ.
* c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
* d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an ÒaggregateÓ if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
* a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
* b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
* c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
* d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
* e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
A ÒUser ProductÓ is either (1) a Òconsumer productÓ, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, Ònormally usedÓ refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
ÒInstallation InformationÓ for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
7. Additional Terms.
ÒAdditional permissionsÓ are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
* a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
* b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
* c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
* d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
* e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
* f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
All other non-permissive additional terms are considered Òfurther restrictionsÓ within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
An Òentity transactionÓ is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
11. Patents.
A ÒcontributorÓ is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's Òcontributor versionÓ.
A contributor's Òessential patent claimsÓ are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, ÒcontrolÓ includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
In the following three paragraphs, a Òpatent licenseÓ is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To ÒgrantÓ such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. ÒKnowingly relyingÓ means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
A patent license is ÒdiscriminatoryÓ if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License Òor any later versionÓ applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ÒAS ISÓ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS FOR QUAIL LIBRARY
THE FOLLOWING LICENSE COVERS PORTIONS OF THE FILE LOCATED AT common/css.php, NAMELY THE FUNCTION parseSelector:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-23
View File
@@ -1,23 +0,0 @@
# Brickfield accessibility tool plugin #
Copyright (C) 2021 [Brickfield Education Labs](https://www.brickfield.ie/)
The Accessibility admin tool plugin provides a simple means of checking content for any accessibility issues.
Created by an enthusiastic team from Brickfield Education Labs, including:
* Karen Holland
* Gavin Henrick
* Mike Churchward
* Renée Mackey
* Laia Joana Canet
* Jay Churchward
* Paul Ffrench
* Holly Lynn
* Michael Pound
* Max Larkin
with a little help from our friends.
Portions of the htmlchecker files were derived from the ["Quail PHP Accessibility Library"](https://code.google.com/archive/p/quail-lib/).
The Quail library (Copyright (C) 2009 Kevin Miller) is licensed under [GNU GPL v3](http://www.gnu.org/licenses/gpl.html).
See the LICENSE_QUAIL.txt file in this directory for original Quail license information.
@@ -1,576 +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 tool_brickfield;
use context_system;
use moodle_exception;
use moodle_url;
use stdClass;
use tool_brickfield\local\tool\filter;
/**
* Provides the Brickfield Accessibility toolkit API.
*
* @package tool_brickfield
* @copyright 2020 onward Brickfield Education Labs Ltd, https://www.brickfield.ie
* @author Mike Churchward (mike@brickfieldlabs.ie)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class accessibility {
/** @var string The component sub path */
private static $pluginpath = 'tool/brickfield';
/** @var string Supported format of topics */
const TOOL_BRICKFIELD_FORMAT_TOPIC = 'topics';
/** @var string Supported format of weeks */
const TOOL_BRICKFIELD_FORMAT_WEEKLY = 'weeks';
/**
* Return the state of the site enable condition.
* @return bool
*/
public static function is_accessibility_enabled(): bool {
global $CFG;
if (isset($CFG->enableaccessibilitytools)) {
return $CFG->enableaccessibilitytools;
}
// Enabled by default.
return true;
}
/**
* Throw an error if the toolkit is not enabled.
* @return bool
* @throws moodle_exception
*/
public static function require_accessibility_enabled(): bool {
if (!static::is_accessibility_enabled()) {
throw new moodle_exception('accessibilitydisabled', manager::PLUGINNAME);
}
return true;
}
/**
* Get a URL for a page within the plugin.
*
* This takes into account the value of the admin config value.
*
* @param string $url The URL within the plugin
* @return moodle_url
*/
public static function get_plugin_url(string $url = ''): moodle_url {
$url = ($url == '') ? 'index.php' : $url;
$pluginpath = self::$pluginpath;
return new moodle_url("/admin/{$pluginpath}/{$url}");
}
/**
* Get a file path for a file within the plugin.
*
* This takes into account the value of the admin config value.
*
* @param string $path The path within the plugin
* @return string
*/
public static function get_file_path(string $path): string {
global $CFG;
return implode(DIRECTORY_SEPARATOR, [$CFG->dirroot, $CFG->admin, self::$pluginpath, $path, ]);
}
/**
* Get the canonicalised name of a capability.
*
* @param string $capability
* @return string
*/
public static function get_capability_name(string $capability): string {
return self::$pluginpath . ':' . $capability;
}
/**
* Get the relevant title.
* @param filter $filter
* @param int $countdata
* @return string
* @throws \coding_exception
* @throws \dml_exception
* @throws \moodle_exception
*/
public static function get_title(filter $filter, int $countdata): string {
global $DB;
$tmp = new \stdClass();
$tmp->count = $countdata;
$langstr = 'title' . $filter->tab . 'partial';
if ($filter->courseid != 0) {
$thiscourse = get_fast_modinfo($filter->courseid)->get_course();
$tmp->name = $thiscourse->fullname;
} else {
$langstr = 'title' . $filter->tab . 'all';
}
return get_string($langstr, manager::PLUGINNAME, $tmp);
}
/**
* Function to be run periodically according to the scheduled task.
* Return true if a process was completed. False if no process executed.
* Finds all unprocessed courses for bulk batch processing and completes them.
* @param int $batch
* @return bool
* @throws \ReflectionException
* @throws \coding_exception
* @throws \ddl_exception
* @throws \ddl_table_missing_exception
* @throws \dml_exception
*/
public static function bulk_process_courses_cron(int $batch = 0): bool {
global $PAGE;
// Run a registration check.
if (!(new registration())->validate()) {
return false;
}
if (analysis::is_enabled()) {
$PAGE->set_context(context_system::instance());
mtrace("Starting cron for bulk_process_courses");
// Do regular processing. True if full deployment type isn't selected as well.
static::bulk_processing($batch);
mtrace("Ending cron for bulk_process_courses");
return true;
} else {
mtrace('Content analysis is currently disabled in settings.');
return false;
}
}
/**
* Bulk processing.
* @param int $batch
* @return bool
*/
protected static function bulk_processing(int $batch = 0): bool {
manager::check_course_updates();
mtrace("check_course_updates completed at " . time());
$recordsprocessed = manager::check_scheduled_areas($batch);
mtrace("check_scheduled_areas completed at " . time());
manager::check_scheduled_deletions();
mtrace("check_scheduled_deletions completed at " . time());
manager::delete_historical_data();
mtrace("delete_historical_data completed at " . time());
return $recordsprocessed;
}
/**
* Function to be run periodically according to the scheduled task.
* Finds all unprocessed courses for cache processing and completes them.
*/
public static function bulk_process_caches_cron() {
global $DB;
// Run a registration check.
if (!(new registration())->validate()) {
return;
}
if (analysis::is_enabled()) {
mtrace("Starting cron for bulk_process_caches");
// Monitor ongoing caching requests.
$fields = 'DISTINCT courseid';
$reruns = $DB->get_records(manager::DB_PROCESS, ['item' => 'cache'], '', $fields);
foreach ($reruns as $rerun) {
mtrace("Running rerun caching for Courseid " . $rerun->courseid);
manager::store_result_summary($rerun->courseid);
mtrace("rerun cache completed at " . time());
$DB->delete_records(manager::DB_PROCESS, ['courseid' => $rerun->courseid, 'item' => 'cache']);
}
mtrace("Ending cron for bulk_process_caches at " . time());
} else {
mtrace('Content analysis is currently disabled in settings.');
}
}
/**
* This function runs the checks on the html item
*
* @param string $html The html string to be analysed; might be NULL.
* @param int $contentid The content area ID
* @param int $processingtime
* @param int $resultstime
*/
public static function run_check(string $html, int $contentid, int &$processingtime, int &$resultstime) {
global $DB;
// Change the limit if 10,000 is not appropriate.
$bulkrecordlimit = manager::BULKRECORDLIMIT;
$bulkrecordcount = 0;
$checkids = static::checkids();
$checknameids = array_flip($checkids);
$testname = 'brickfield';
$stime = time();
// Swapping in new library.
$htmlchecker = new local\htmlchecker\brickfield_accessibility($html, $testname, 'string');
$htmlchecker->run_check();
$tests = $htmlchecker->guideline->get_tests();
$report = $htmlchecker->get_report();
$processingtime += (time() - $stime);
$records = [];
foreach ($tests as $test) {
$records[$test]['count'] = 0;
$records[$test]['errors'] = [];
}
foreach ($report['report'] as $a) {
if (!isset($a['type'])) {
continue;
}
$type = $a['type'];
$records[$type]['errors'][] = $a;
if (!isset($records[$type]['count'])) {
$records[$type]['count'] = 0;
}
$records[$type]['count']++;
}
$stime = time();
$returnchecks = [];
$errors = [];
// Build up records for inserting.
foreach ($records as $key => $rec) {
$recordres = new stdClass();
// Handling if checkid is unknown.
$checkid = (isset($checknameids[$key])) ? $checknameids[$key] : 0;
$recordres->contentid = $contentid;
$recordres->checkid = $checkid;
$recordres->errorcount = $rec['count'];
// Build error inserts if needed.
if ($rec['count'] > 0) {
foreach ($rec['errors'] as $tmp) {
$error = new stdClass();
$error->resultid = 0;
$error->linenumber = $tmp['lineNo'];
$error->htmlcode = $tmp['html'];
$error->errordescription = $tmp['title'];
// Add contentid and checkid so that we can query for the results record id later.
$error->contentid = $contentid;
$error->checkid = $checkid;
$errors[] = $error;
}
}
$returnchecks[] = $recordres;
$bulkrecordcount++;
// If we've hit the bulk limit, write the results records and reset.
if ($bulkrecordcount > $bulkrecordlimit) {
$DB->insert_records(manager::DB_RESULTS, $returnchecks);
$bulkrecordcount = 0;
$returnchecks = [];
// Get the results id value for each error record and write the errors.
foreach ($errors as $key2 => $error) {
$errors[$key2]->resultid = $DB->get_field(manager::DB_RESULTS, 'id',
['contentid' => $error->contentid, 'checkid' => $error->checkid]);
unset($errors[$key2]->contentid);
unset($errors[$key2]->checkid);
}
$DB->insert_records(manager::DB_ERRORS, $errors);
$errors = [];
}
}
// Write any leftover records.
if ($bulkrecordcount > 0) {
$DB->insert_records(manager::DB_RESULTS, $returnchecks);
// Get the results id value for each error record and write the errors.
foreach ($errors as $key => $error) {
$errors[$key]->resultid = $DB->get_field(manager::DB_RESULTS, 'id',
['contentid' => $error->contentid, 'checkid' => $error->checkid]);
unset($errors[$key]->contentid);
unset($errors[$key]->checkid);
}
$DB->insert_records(manager::DB_ERRORS, $errors);
}
$resultstime += (time() - $stime);
}
/**
* This function runs one specified check on the html item
*
* @param string $html The html string to be analysed; might be NULL.
* @param int $contentid The content area ID
* @param int $errid The error ID
* @param string $check The check name to run
* @param int $processingtime
* @param int $resultstime
* @throws \coding_exception
* @throws \dml_exception
*/
public static function run_one_check(
string $html = null,
int $contentid,
int $errid,
string $check,
int &$processingtime,
int &$resultstime
) {
global $DB;
$stime = time();
$checkdata = $DB->get_record(manager::DB_CHECKS, ['shortname' => $check], 'id,shortname,severity');
$testname = 'brickfield';
// Swapping in new library.
$htmlchecker = new local\htmlchecker\brickfield_accessibility($html, $testname, 'string');
$htmlchecker->run_check();
$report = $htmlchecker->get_test($check);
$processingtime += (time() - $stime);
$record = [];
$record['count'] = 0;
$record['errors'] = [];
foreach ($report as $a) {
$a->html = $a->get_html();
$record['errors'][] = $a;
$record['count']++;
}
// Build up record for inserting.
$recordres = new stdClass();
// Handling if checkid is unknown.
$checkid = (isset($checkdata->id)) ? $checkdata->id : 0;
$recordres->contentid = $contentid;
$recordres->checkid = $checkid;
$recordres->errorcount = $record['count'];
if ($exists = $DB->get_record(manager::DB_RESULTS, ['contentid' => $contentid, 'checkid' => $checkid])) {
$resultid = $exists->id;
$DB->set_field(manager::DB_RESULTS, 'errorcount', $record['count'], ['id' => $resultid]);
// Remove old error records for specific resultid, if existing.
$DB->delete_records(manager::DB_ERRORS, ['id' => $errid]);
} else {
$resultid = $DB->insert_record(manager::DB_RESULTS, $recordres);
}
$errors = [];
// Build error inserts if needed.
if ($record['count'] > 0) {
// Reporting all found errors for this check, so need to ignore existing other error records.
foreach ($record['errors'] as $tmp) {
// Confirm if error is reported separately.
if ($DB->record_exists_select(manager::DB_ERRORS,
'resultid = ? AND ' . $DB->sql_compare_text('htmlcode', 255) . ' = ' . $DB->sql_compare_text('?', 255),
[$resultid, html_entity_decode($tmp->html)])) {
continue;
}
$error = new stdClass();
$error->resultid = $resultid;
$error->linenumber = $tmp->line;
$error->htmlcode = html_entity_decode($tmp->html);
$errors[] = $error;
}
$DB->insert_records(manager::DB_ERRORS, $errors);
}
$resultstime += (time() - $stime);
}
/**
* Returns all of the id's and shortnames of all of the checks.
* @param int $status
* @return array
* @throws \dml_exception
*/
public static function checkids(int $status = 1): array {
global $DB;
$checks = $DB->get_records_menu(manager::DB_CHECKS, ['status' => $status], 'id ASC', 'id,shortname');
return $checks;
}
/**
* Returns an array of translations from htmlchecker of all of the checks, and their descriptions.
* @return array
* @throws \dml_exception
*/
public static function get_translations(): array {
global $DB;
$htmlchecker = new local\htmlchecker\brickfield_accessibility('test', 'brickfield', 'string');
$htmlchecker->run_check();
ksort($htmlchecker->guideline->translations);
// Need to limit to active checks.
$activechecks = $DB->get_fieldset_select(manager::DB_CHECKS, 'shortname', 'status = :status', ['status' => 1]);
$translations = [];
foreach ($htmlchecker->guideline->translations as $key => $trans) {
if (in_array($key, $activechecks)) {
$translations[$key] = $trans;
}
}
return $translations;
}
/**
* Returns an array of all of the course id's for a given category.
* @param int $categoryid
* @return array|null
* @throws \dml_exception
*/
public static function get_category_courseids(int $categoryid): ?array {
global $DB;
if (!$DB->record_exists('course_categories', ['id' => $categoryid])) {
return null;
}
$sql = "SELECT {course}.id
FROM {course}, {course_categories}
WHERE {course}.category = {course_categories}.id
AND (
" . $DB->sql_like('path', ':categoryid1') . "
OR " . $DB->sql_like('path', ':categoryid2') . "
)";
$params = ['categoryid1' => "%/$categoryid/%", 'categoryid2' => "%/$categoryid"];
$courseids = $DB->get_fieldset_sql($sql, $params);
return $courseids;
}
/**
* Get summary data for this site.
* @param int $id
* @return \stdClass
* @throws \dml_exception
*/
public static function get_summary_data(int $id): \stdClass {
global $CFG, $DB;
$components = $DB->get_records(manager::DB_AREAS);
$summarydata = new \stdClass();
$summarydata->siteurl = (substr($CFG->wwwroot, -1) !== '/') ? $CFG->wwwroot . '/' : $CFG->wwwroot;
$summarydata->moodlerelease = (preg_match('/^(\d+\.\d.*?)[. ]/', $CFG->release, $matches)) ? $matches[1] : $CFG->release;
$summarydata->numcourses = $DB->count_records('course') - 1;
$summarydata->numusers = $DB->count_records('user', array('deleted' => 0));
$summarydata->numfiles = $DB->count_records('files');
$summarydata->numfactivities = $DB->count_records('course_modules');
$summarydata->mobileservice = (int)$CFG->enablemobilewebservice === 1 ? true : false;
$summarydata->usersmobileregistered = $DB->count_records('user_devices');
$summarydata->contenttyperesults = static::get_contenttyperesults($id, $components);
$summarydata->contenttypeerrors = static::get_contenttypeerrors();
$summarydata->percheckerrors = static::get_percheckerrors();
return $summarydata;
}
/**
* Get content type results.
* @param int $id
* @param array $components
* @return \stdClass
*/
private static function get_contenttyperesults(int $id, array $components): \stdClass {
$contenttyperesults = new \stdClass();
$contenttyperesults->id = $id;
$datacomponents = array();
foreach ($components as $component) {
$datacomponents[$component->component][] = $component;
}
$contenttyperesults->contenttype = new \stdClass();
foreach ($datacomponents as $key => $component) {
$contenttyperesults->contenttype->$key = count($component);
}
$contenttyperesults->summarydatastorage = static::get_summary_data_storage();
$contenttyperesults->datachecked = time(); // Correct??
return $contenttyperesults;
}
/**
* Get per check errors.
* @return stdClass
* @throws dml_exception
*/
private static function get_percheckerrors(): stdClass {
global $DB;
$sql = 'SELECT ' . $DB->sql_concat_join("'_'", ['courseid', 'checkid']) . ' as tmpid,
ca.courseid, ca.status, ca.checkid, ch.shortname, ca.checkcount, ca.errorcount
FROM {' . manager::DB_CACHECHECK . '} ca
INNER JOIN {' . manager::DB_CHECKS . '} ch on ch.id = ca.checkid
ORDER BY courseid, checkid ASC';
$combo = $DB->get_records_sql($sql);
return (object) [
'percheckerrors' => $combo,
];
}
/**
* Get content type errors.
* @return stdClass
* @throws dml_exception
*/
private static function get_contenttypeerrors(): stdClass {
global $DB;
$fields = 'courseid, status, activities, activitiespassed, activitiesfailed,
errorschecktype1, errorschecktype2, errorschecktype3, errorschecktype4,
errorschecktype5, errorschecktype6, errorschecktype7,
failedchecktype1, failedchecktype2, failedchecktype3, failedchecktype4,
failedchecktype5, failedchecktype6, failedchecktype7,
percentchecktype1, percentchecktype2, percentchecktype3, percentchecktype4,
percentchecktype5, percentchecktype6, percentchecktype7';
$combo = $DB->get_records(manager::DB_SUMMARY, null, 'courseid ASC', $fields);
return (object) [
'typeerrors' => $combo,
];
}
/**
* Get summary data storage.
* @return array
* @throws dml_exception
*/
private static function get_summary_data_storage(): array {
global $DB;
$fields = $DB->sql_concat_join("''", ['component', 'courseid']) . ' as tmpid,
courseid, component, errorcount, totalactivities, failedactivities, passedactivities';
$combo = $DB->get_records(manager::DB_CACHEACTS, null, 'courseid, component ASC', $fields);
return $combo;
}
}
@@ -1,95 +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 tool_brickfield;
use tool_brickfield\task\process_analysis_requests;
/**
* Analysis and deployment class.
*
* @package tool_brickfield
* @copyright 2020 Brickfield Education Labs https://www.brickfield.ie
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class analysis {
/**
* Indicates that analysis of content has been enabled.
*/
const ANALYSISDISABLED = '0';
/**
* Indicates that analysis is enabled and using request method.
*/
const ANALYSISBYREQUEST = '1';
/**
* Return the type of analysis being used (currently only request).
*
* @return false|mixed|object|string|null
* @throws \dml_exception
*/
public static function get_type() {
// Moodle caches these calls, so it's not expensive.
return get_config(manager::PLUGINNAME, 'analysistype');
}
/**
* Return true is analysis has been enabled.
*
* @return bool
* @throws \dml_exception
*/
public static function is_enabled(): bool {
$analysistype = static::get_type();
return ($analysistype !== false) && ($analysistype !== self::ANALYSISDISABLED);
}
/**
* Return true if analysis is by request method.
*
* @return bool
* @throws \dml_exception
*/
public static function type_is_byrequest(): bool {
return static::get_type() === self::ANALYSISBYREQUEST;
}
/**
* Return true if the course has been analyzed.
*
* @param int $courseid
* @return bool
* @throws \dml_exception
*/
public static function is_course_analyzed(int $courseid): bool {
return scheduler::is_course_analyzed($courseid);
}
/**
* Return a redirect message with the earliest time expected for analysis to complete.
* @return \lang_string|string
* @throws \coding_exception
*/
public static function redirect_message() {
$epoch = new process_analysis_requests;
$time = userdate($epoch->get_next_scheduled_time(), get_string('strftimetime', 'core_langconfig'));
$message = get_string('confirmationmessage', manager::PLUGINNAME, $time);
return $message;
}
}
-219
View File
@@ -1,219 +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 tool_brickfield;
/**
* Area base class.
*
* @package tool_brickfield
* @copyright 2020 Brickfield Education Labs https://www.brickfield.ie
*/
abstract class area_base {
/**
* Defines the unknown for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_UNKNOWN = 0;
/**
* Defines the form for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_FORM = 1;
/**
* Defines the image for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_IMAGE = 2;
/**
* Defines the layout for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_LAYOUT = 3;
/**
* Defines the link for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_LINK = 4;
/**
* Defines the media for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_MEDIA = 5;
/**
* Defines the table for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_TABLE = 6;
/**
* Defines the text for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_TEXT = 7;
/** @var string[] Array for quick access of string names for 'checkgroups'. */
const CHECKGROUP_NAMES = [
self::CHECKGROUP_UNKNOWN => 'unknown',
self::CHECKGROUP_FORM => 'form',
self::CHECKGROUP_IMAGE => 'image',
self::CHECKGROUP_LAYOUT => 'layout',
self::CHECKGROUP_LINK => 'link',
self::CHECKGROUP_MEDIA => 'media',
self::CHECKGROUP_TABLE => 'table',
self::CHECKGROUP_TEXT => 'text'
];
/**
* Defines field value.
*/
const TYPE_FIELD = 0;
/**
* Defines file value.
*/
const TYPE_FILE = 1;
/**
* Return the name for the specified checkgroup value, or 'unknown' if no valid name for the value. Preferably, use this rather
* than direct access to CHECKGROUP_NAMES, since it checks value boundaries.
* @param int $checkgroupvalue
* @return string
*/
final public static function checkgroup_name(int $checkgroupvalue): string {
if (($checkgroupvalue < 0) || ($checkgroupvalue >= count(self::CHECKGROUP_NAMES))) {
return self::CHECKGROUP_NAMES[self::CHECKGROUP_UNKNOWN];
} else {
return self::CHECKGROUP_NAMES[$checkgroupvalue];
}
}
/**
* Return the value for the specified checkgroup name, or the unknown value if no valid value for the name.
* @param string $checkgroupname
* @return int
*/
final public static function checkgroup_value(string $checkgroupname): int {
$value = array_search($checkgroupname, self::CHECKGROUP_NAMES);
return ($value !== false) ? $value : self::CHECKGROUP_UNKNOWN;
}
/**
* Return the defined content type.
* @return int
*/
protected function get_type(): int {
return self::TYPE_FIELD;
}
/**
* Return the component from the full class name.
* @return mixed|string
*/
public function get_component(): string {
$parts = preg_split('|\\\\|', get_class($this));
return $parts[3];
}
/**
* Check if the system plugin is avaliable.
* @return bool
*/
public function is_available(): bool {
list($type, $plugin) = \core_component::normalize_component($this->get_component());
if ($type === 'core') {
// We assume that all core components are defined corretly.
return true;
}
// Some contrib plugins may not be installed.
return ($dir = \core_component::get_component_directory($this->get_component()))
&& file_exists($dir . '/version.php');
}
/**
* Return the name of the database table where information is stored
* @return string
*/
abstract public function get_tablename(): string;
/**
* Return the name of the reference data table name.
* @return string
*/
public function get_ref_tablename(): string {
return '';
}
/**
* Return the name of the field in the table that has the content
* @return string
*/
abstract public function get_fieldname(): string;
/**
* Return a recordset of the relevant areas for the component/module.
* @param \core\event\base $event
* @return \moodle_recordset|null
*/
abstract public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset;
/**
* Return a recordset of the course areas for the course id.
* @param int $courseid
* @return \moodle_recordset|null
*/
abstract public function find_course_areas(int $courseid): ?\moodle_recordset;
/**
* Return an array of area objects that contain content at the site and system levels only. Override this where necessary.
* @return \moodle_recordset|null
*/
public function find_system_areas(): ?\moodle_recordset {
return null;
}
/**
* The standard Moodle parameter DML parameter substitution doesn't work on all versions of MySQL or Postgres, so we need to use
* inline function substitution to ensure that the left side is a string.
* @return string
*/
public function get_standard_area_fields_sql(): string {
return '\'' . $this->get_component() . '\' AS component,
\'' . $this->get_tablename() . '\' AS tablename,
\'' . $this->get_fieldname() . '\' AS fieldorarea, ';
}
/**
* The standard Moodle parameter DML parameter substitution doesn't work on all versions of MySQL or Postgres, so we need to use
* inline function substitution to ensure that the left side is a string.
* @return string
*/
public function get_reftable_field_sql(): string {
return '\'' . $this->get_ref_tablename() . '\' AS reftable, ';
}
/**
* Processes any sql filtering data. Implement in extensions.
*
* @return null
* @throws \coding_exception
* @throws \dml_exception
*/
public function get_courseid_filtering() {
$this->filter = '';
$this->filterparams = [];
return null;
}
}
@@ -1,258 +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 tool_brickfield;
defined('MOODLE_INTERNAL') || die;
// The curl class is in filelib.
global $CFG;
require_once("{$CFG->libdir}/filelib.php");
use curl;
use moodle_url;
/**
* Class brickfieldconnect. Contains all function to connect to Brickfield external services.
*
* @package tool_brickfield
* @author 2020 Onwards Mike Churchward <mike@brickfieldlabs.ie>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class brickfieldconnect extends curl {
/** @var string The base api uri. */
private static $baseapiuri = 'https://api.mybrickfield.ie/moodle/';
/** @var array Endpoint details for setting and checking a site registration */
const ACTION_CHECK_REGISTRATION = [
'endpoint' => 'checkRegister',
'method' => 'get',
];
/** @var array Endpoint details for sending site summary data */
const ACTION_SEND_SUMMARY = [
'endpoint' => 'summary',
'method' => 'post',
];
/**
* Object method to test whether site is already registered.
* @return bool
*/
public function is_registered(): bool {
return !empty($this->get_registration_id_for_credentials());
}
/**
* Update registration of this site.
* @param string $apikey The API key to use for the registration attempt
* @param string $secretkey The secret key to use
* @return bool
*/
public function update_registration(string $apikey, string $secretkey): bool {
$registrationid = $this->get_registration_id_for_credentials($apikey, $secretkey);
if (empty($registrationid)) {
return false;
}
(new registration())->set_siteid($registrationid);
return true;
}
/**
* Send the summary data to Brickfield.
* @return bool
* @throws \dml_exception
*/
public function send_summary(): bool {
// Run a registration check.
if (!(new registration())->validate()) {
return false;
}
$headers = $this->get_common_headers();
// Sanity-check $headers 'id' value.
if (!isset($headers['id'])) {
return false;
}
$this->set_headers($headers);
$summary = accessibility::get_summary_data($headers['id']);
$body = json_encode($summary, JSON_UNESCAPED_SLASHES);
$result = json_decode($this->call(self::ACTION_SEND_SUMMARY, $body));
if (is_object($result) && ((int)$result->statusCode === 200)) {
return true;
} else {
return false;
}
}
/**
* Get the URL required for the command.
*
* @param array $command The command to call, for example see self::ACTION_REGISTER
* @return string The complete URL
*/
protected function get_url_for_command(array $command): string {
return $this->get_baseapiuri() . $command['endpoint'];
}
/**
* Call the specified command.
*
* @param array $command The command to call, for example see self::ACTION_REGISTER
* @param array|string $params The params provided to the call
* @return string The response body
*/
protected function call(array $command, $params = ''): string {
$url = $this->get_url_for_command($command);
if ($command['method'] === 'get') {
return $this->get($url, $params);
}
if ($command['method'] === 'post') {
return $this->post($url, $params);
}
return '';
}
/**
* Get the common headers used for all calls to the Brickfields endpoints.
*
* @return array
*/
protected function get_common_headers(): array {
$headers = [
'Cache-Control' => 'no-cache',
'Content-Type' => 'application/json',
'siteurl' => static::get_siteurl(),
];
if (static::has_registration_key()) {
$registration = new registration();
$headers['secret'] = $registration->get_api_key();
$headers['userhash'] = $registration->get_secret_key();
$headers['id'] = $registration->get_siteid();
}
return $headers;
}
/**
* Set headers on the request from the specified list of headers.
*
* @param array $headers An array of header name => value
*/
protected function set_headers(array $headers) {
foreach ($headers as $key => $value) {
$this->setHeader("{$key}: {$value}");
}
}
/**
* Whether the site currently has a registration key stored.
*
* @return bool
*/
protected function has_registration_key(): bool {
$registration = new registration();
$localkey = $registration->get_api_key();
$localhash = $registration->get_secret_key();
$localid = $registration->get_siteid();
if (!$localhash || !$localkey || !$localid) {
return false;
}
return true;
}
/**
* Get a normalised URL for the site.
*
* @return string
*/
protected function get_siteurl(): string {
return (new moodle_url('/'))->out(false);
}
/**
* Get the registration ID for the given set of credentials.
* @param null|string $apikey The API key to use for the registration attempt
* @param null|string $secretkey The secret key to use
* @return null|string The registration ID if registration was successful, or null if not
*/
protected function get_registration_id_for_credentials(string $apikey = null, string $secretkey = null): string {
$headers = $this->get_common_headers();
if ($apikey || $secretkey) {
$headers['secret'] = $apikey;
$headers['userhash'] = $secretkey;
} else if (!$this->has_registration_key()) {
return '';
}
$this->set_headers($headers);
$response = $this->call(self::ACTION_CHECK_REGISTRATION);
if ((int)$this->info['http_code'] !== 200) {
// The response was unsuccessful.
return '';
}
$result = json_decode($response);
if (!$result) {
// The response could not be decoded.
return '';
}
if ((int)$result->statusCode !== 200) {
// The data from the response suggests a failure.
return '';
}
// Decode the actual result.
$registrationdata = json_decode($result->body);
if (empty($registrationdata) || !is_array($registrationdata)) {
// Unable to decode the body of the response.
return '';
}
if (!property_exists($registrationdata[0], 'id') || !property_exists($registrationdata[0]->id, 'N')) {
// Unable to find a valid id in the response.
return '';
}
return $registrationdata[0]->id->N;
}
/**
* Get the check registration API URI.
* @return string
* @throws dml_exception
*/
protected function get_baseapiuri(): string {
$baseapiuri = get_config(manager::PLUGINNAME, 'baseapiuri');
if (!empty($baseapiuri)) {
return $baseapiuri;
} else {
set_config('baseapiuri', self::$baseapiuri, manager::PLUGINNAME);
return self::$baseapiuri;
}
}
}
@@ -1,54 +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 tool_brickfield\event;
use tool_brickfield\manager;
/**
* Class analysis_requested
*
* @package tool_brickfield
* @copyright 2020 onward Brickfield Education Labs, https://www.brickfield.ie
* @author Mike Churchward <mike@brickfieldlabs.ie>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class analysis_requested extends \core\event\base {
/**
* Init function.
*/
protected function init() {
$this->data['crud'] = 'c';
$this->data['edulevel'] = self::LEVEL_OTHER;
}
/**
* Get name.
* @return \lang_string|string
*/
public static function get_name() {
return get_string('eventanalysis_requested', manager::PLUGINNAME);
}
/**
* Get description.
* @return \lang_string|string|null
*/
public function get_description() {
return get_string('eventanalysis_requesteddesc', manager::PLUGINNAME, $this->other['course']);
}
}
@@ -1,54 +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 tool_brickfield\event;
use tool_brickfield\manager;
/**
* Class report_downloaded
*
* @package tool_brickfield
* @copyright 2020 onward Brickfield Education Labs, https://www.brickfield.ie
* @author Mike Churchward <mike@brickfieldlabs.ie>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class report_downloaded extends \core\event\base {
/**
* Init function.
*/
protected function init() {
$this->data['crud'] = 'r';
$this->data['edulevel'] = self::LEVEL_OTHER;
}
/**
* Get name.
* @return \lang_string|string
*/
public static function get_name() {
return get_string('eventreport_downloaded', manager::PLUGINNAME);
}
/**
* Get description.
* @return \lang_string|string|null
*/
public function get_description() {
return get_string('eventreport_downloadeddesc', manager::PLUGINNAME, $this->courseid);
}
}
@@ -1,54 +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 tool_brickfield\event;
use tool_brickfield\manager;
/**
* Class report_viewed
*
* @package tool_brickfield
* @copyright 2020 onward Brickfield Education Labs, https://www.brickfield.ie
* @author Mike Churchward <mike@brickfieldlabs.ie>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class report_viewed extends \core\event\base {
/**
* Init function.
*/
protected function init() {
$this->data['crud'] = 'r';
$this->data['edulevel'] = self::LEVEL_OTHER;
}
/**
* Get name.
* @return \lang_string|string
*/
public static function get_name() {
return get_string('eventreport_viewed', manager::PLUGINNAME);
}
/**
* Get description.
* @return \lang_string|string|null
*/
public function get_description() {
return get_string('eventreport_vieweddesc', manager::PLUGINNAME, (object)$this->other);
}
}
@@ -1,438 +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 tool_brickfield;
use core\event\base;
use stdClass;
/**
* Observer class containing methods monitoring various events.
*
* @package tool_brickfield
* @copyright 2020 Brickfield Education Labs https://www.brickfield.ie
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*
*/
class eventobservers {
/**
* For course events to be handled, the accessibility tool needs to be enabled, and if a courseid is specified, the course
* has to have been added to the scheduler.
* @param int $courseid
* @return bool
* @throws \dml_exception
*/
private static function course_event_should_be_handled(int $courseid): bool {
return accessibility::is_accessibility_enabled() && analysis::is_enabled() &&
(empty($courseid) || (isset($courseid) && scheduler::is_course_in_schedule($courseid)));
}
/**
* Content area altered event observer.
* @param base $event The area altered event.
* @throws \ReflectionException
* @throws \dml_exception
*/
private static function area_altered(base $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
manager::find_new_or_updated_areas($event);
}
}
/**
* Course event observers.
* These observer monitors course created / restored / updated events,
* then its HTML content is processed with accessibility checking.
*/
/**
* Course created event observer.
* @param \core\event\course_created $event The course created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_created(\core\event\course_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
// Need to trigger rerun check for automatically created forum...
$data = new stdClass();
$data->courseid = $event->courseid;
$data->item = 'coursererun';
static::observer_insert($data);
static::course_altered($event);
}
}
/**
* Course deleted event observer.
* @param \core\event\course_deleted $event The course deleted event.
* @throws \dml_exception
*/
public static function course_deleted(\core\event\course_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->item = 'core_course';
static::observer_insert($data);
}
}
/**
* Course restored event observer.
* @param \core\event\course_restored $event The course restored event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_restored(\core\event\course_restored $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->item = 'coursererun';
static::observer_insert($data);
static::course_altered($event);
}
}
/**
* Course update event observer.
* @param \core\event\course_updated $event The course updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_updated(\core\event\course_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::course_altered($event);
}
}
/**
* Course update event observer. This is called on both course_created and course_updated, so use the base class as a type hint.
* @param base $event The course updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_altered(base $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
// Need to rerun caching of allowed courseid, from category white/blacklist.
$data = new stdClass();
$data->courseid = $data->contextid = $event->courseid;
$data->contextid = -1;
$data->item = 'category';
static::observer_insert($data);
static::area_altered($event);
}
}
/**
* Course section created event observer.
* @param \core\event\course_section_created $event The course section created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_section_created(\core\event\course_section_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* Course section deleted event observer.
* @param \core\event\course_section_deleted $event The course section deleted event.
* @throws \dml_exception
*/
public static function course_section_deleted(\core\event\course_section_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->objectid;
$data->item = 'course_sections';
static::observer_insert($data);
}
}
/**
* Course section update event observer.
* @param \core\event\course_section_updated $event The course section updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_section_updated(\core\event\course_section_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* Course module event observers.
* These observer monitors course module created / restored / updated events,
* then its HTML content is processed with accessibility checking.
*/
/**
* Course module created event observer.
* @param \core\event\course_module_created $event The course module created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_module_created(\core\event\course_module_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* Course module deleted event observer.
* @param \core\event\course_module_deleted $event The course module deleted event.
* @throws \dml_exception
*/
public static function course_module_deleted(\core\event\course_module_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->other['instanceid'];
$data->item = 'mod_' . $event->other['modulename'];
static::observer_insert($data);
}
}
/**
* Course module restored event observer.
* @param \core\event\course_module_restored $event The course module restored event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_module_restored(\core\event\course_module_restored $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* Course module updated event observer.
* @param \core\event\course_module_updated $event The course module updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_module_updated(\core\event\course_module_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* course_category created event observer.
* @param \core\event\course_category_created $event The course_category created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_category_created(\core\event\course_category_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* course_category deleted event observer.
* @param \core\event\course_category_deleted $event The course_category deleted event.
* @throws \dml_exception
*/
public static function course_category_deleted(\core\event\course_category_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->contextid = $data->courseid = -1;
$data->innercontextid = $event->objectid;
$data->item = 'course_categories';
static::observer_insert($data);
}
}
/**
* course_category update event observer.
* @param \core\event\course_category_updated $event The course_category updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_category_updated(\core\event\course_category_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* mod_lesson_page created event observer.
* @param \mod_lesson\event\page_created $event The mod_lesson page created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function mod_lesson_page_created(\mod_lesson\event\page_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* mod_lesson_page deleted event observer.
* @param \mod_lesson\event\page_deleted $event The mod_lesson page deleted event.
* @throws \dml_exception
*/
public static function mod_lesson_page_deleted(\mod_lesson\event\page_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->objectid;
$data->item = 'lesson_pages';
static::observer_insert($data);
}
}
/**
* mod_lesson_page updated event observer.
* @param \mod_lesson\event\page_updated $event The mod_lesson page updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function mod_lesson_page_updated(\mod_lesson\event\page_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* core_question created observer
* @param \core\event\question_created $event The core_question created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function core_question_created(\core\event\question_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
manager::find_new_or_updated_areas($event);
}
}
/**
* core_question updated observer
* @param \core\event\question_updated $event The core_question created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function core_question_updated(\core\event\question_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
manager::find_new_or_updated_areas($event);
}
}
/**
* core_question deleted observer
* @param \core\event\question_deleted $event The core_question deleted event.
* @throws \dml_exception
*/
public static function core_question_deleted(\core\event\question_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->objectid;
$data->item = $event->objecttable;
static::observer_insert($data);
}
}
/**
* Book chapter created event observer.
* @param \mod_book\event\chapter_created $event The book chapter created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function book_chapter_created(\mod_book\event\chapter_created $event) {
// If this feature has been disabled, do nothing.
if (accessibility::is_accessibility_enabled()) {
static::area_altered($event);
}
}
/**
* Book chapter deleted event observer.
* @param \mod_book\event\chapter_deleted $event The book chapter deleted event.
* @throws \dml_exception
*/
public static function book_chapter_deleted(\mod_book\event\chapter_deleted $event) {
// If this feature has been disabled, do nothing.
if (accessibility::is_accessibility_enabled()) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->objectid;
$data->item = 'book_chapters';
static::observer_insert($data);
}
}
/**
* Book chapter update event observer.
* @param \mod_book\event\chapter_updated $event The book chapter updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function book_chapter_updated(\mod_book\event\chapter_updated $event) {
// If this feature has been disabled, do nothing.
if (accessibility::is_accessibility_enabled()) {
static::area_altered($event);
}
}
/**
* Add an observer record if appropriate.
* @param stdClass $data
* @throws \dml_exception
*/
private static function observer_insert(stdClass $data) {
global $DB;
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($data->courseid)) {
$data->timecreated = time();
$data->timecompleted = 0;
$DB->insert_record(manager::DB_PROCESS, $data);
}
}
}
@@ -1,149 +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/>.
/**
* Class registration_form
*
* @package tool_brickfield
* @copyright 2021 Brickfield Education Labs https://www.brickfield.ie
* @author 2020 JM Tomas <jmtomas@tresipunt.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
namespace tool_brickfield\form;
defined('MOODLE_INTERNAL') || die();
use coding_exception;
use dml_exception;
use html_writer;
use moodle_exception;
use moodleform;
use stdClass;
use tool_brickfield\manager;
use tool_brickfield\registration;
global $CFG;
require_once($CFG->libdir . '/formslib.php');
/**
* Class registration_form
*
* @package tool_brickfield
* @author 2020 JM Tomas <jmtomas@tresipunt.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class registration_form extends moodleform {
/**
* Form definition.
* @throws moodle_exception
*/
public function definition() {
$mform = & $this->_form;
$required = get_string('required');
$info = $this->get_defaultinfo();
$registration = new registration();
$key = $registration->get_api_key();
$hash = $registration->get_secret_key();
$mform->addElement('header', 'activationheader', get_string('activationheader', manager::PLUGINNAME));
$mform->addElement('text', 'key', get_string('secretkey', manager::PLUGINNAME));
$mform->setType('key', PARAM_TEXT);
$mform->setDefault('key', !empty($key) ? $key : '');
$mform->addHelpButton('key', 'secretkey', manager::PLUGINNAME);
$mform->addElement('text', 'hash', get_string('sitehash', manager::PLUGINNAME));
$mform->setType('hash', PARAM_TEXT);
$mform->setDefault('hash', !empty($hash) ? $hash : '');
$mform->addHelpButton('hash', 'sitehash', manager::PLUGINNAME);
$mform->addElement('header', 'moreinfo', get_string('moreinfo', manager::PLUGINNAME));
$mform->addElement('static', 'siteinfosummary', '',
get_string('sendfollowinginfo', manager::PLUGINNAME, $info->moreinfostring));
$mform->addElement('hidden', 'lang', $info->languagecode);
$mform->setType('lang', PARAM_TEXT);
$mform->addElement('hidden', 'countrycode', $info->country);
$mform->setType('countrycode', PARAM_TEXT);
$mform->addElement('hidden', 'url', $info->url);
$mform->setType('url', PARAM_URL);
$this->add_action_buttons(false, get_string('activate', manager::PLUGINNAME, '#'));
}
/**
* Get default data for registration form
*
* @throws moodle_exception
* @return stdClass
*/
protected function get_defaultinfo(): stdClass {
global $CFG;
$admin = get_admin();
$site = get_site();
$data = new stdClass();
$data->name = $site->fullname;
$data->url = $CFG->wwwroot;
$data->language = get_string('thislanguage', 'langconfig');
$data->languagecode = $admin->lang ?: $CFG->lang;
$data->country = $admin->country ?: $CFG->country;
$data->email = $admin->email;
$data->moreinfo = self::get_moreinfo();
$data->moreinfostring = self::get_moreinfostring($data->moreinfo);
return $data;
}
/**
* Get more information.
* @return array
* @throws dml_exception
*/
private static function get_moreinfo(): array {
global $CFG, $DB;
$moreinfo = array();
$moodlerelease = $CFG->release;
if (preg_match('/^(\d+\.\d.*?)[. ]/', $moodlerelease, $matches)) {
$moodlerelease = $matches[1];
}
$moreinfo['release'] = $moodlerelease;
$moreinfo['numcourses'] = $DB->count_records('course') - 1;
$moreinfo['numusers'] = $DB->count_records('user', array('deleted' => 0));
$moreinfo['numfiles'] = $DB->count_records('files');
$moreinfo['numfactivities'] = $DB->count_records('course_modules');
$moreinfo['mobileservice'] = empty($CFG->enablemobilewebservice) ? 0 : $CFG->enablemobilewebservice;
$moreinfo['usersmobileregistered'] = $DB->count_records('user_devices');
$moreinfo['contentyperesults'] = '';
$moreinfo['contenttypeerrors'] = '';
$moreinfo['percheckerrors'] = '';
return $moreinfo;
}
/**
* Get HTML list for more information.
*
* @param array $moreinfo
* @return string
* @throws coding_exception
*/
private static function get_moreinfostring(array $moreinfo): string {
$html = html_writer::start_tag('ul');
foreach ($moreinfo as $key => $value) {
$html .= html_writer::tag('li', get_string($key, manager::PLUGINNAME, $value));
}
$html .= html_writer::end_tag('ul');
return $html;
}
}
@@ -1,118 +0,0 @@
<?php
// This file is part of the Query submission plugin
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\core_course;
use core\event\course_created;
use core\event\course_updated;
use core\event\course_restored;
use tool_brickfield\area_base;
/**
* Base class for various course-related areas
*
* This is an abstract class so it will be skipped by manager when it finds all areas
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class base extends area_base {
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event instanceof course_created) {
return $this->find_fields_in_course_table(['courseid' => $event->courseid]);
} else if ($event instanceof course_restored) {
return $this->find_fields_in_course_table(['courseid' => $event->courseid]);
} else if ($event instanceof course_updated) {
return $this->find_fields_in_course_table(['courseid' => $event->courseid]);
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_fields_in_course_table(['courseid' => $courseid]);
}
/**
* Return an array of area objects that contain content at the site and system levels only.
* @return mixed
*/
public function find_system_areas(): ?\moodle_recordset {
return null;
}
/**
* Helper method that can be used by the classes that define a field in the 'course' table
*
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_fields_in_course_table(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['courseid'])) {
$where[] = 't.id = :courseid';
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
t.id AS itemid,
t.id AS courseid,
t.'.$this->get_fieldname().' AS content
FROM {'.$this->get_tablename().'} t
JOIN {context} ctx ON ctx.instanceid = t.id AND ctx.contextlevel = :pctxlevelcourse '.
($where ? 'WHERE ' . join(' AND ', $where) : '') . '
ORDER BY t.id',
['pctxlevelcourse' => CONTEXT_COURSE] + $params);
return $rs;
}
/**
* Returns the moodle_url of the page to edit the error.
* @param \stdClass $componentinfo
* @return \moodle_url
*/
public static function get_edit_url(\stdClass $componentinfo): \moodle_url {
if ($componentinfo->tablename == 'course_sections') {
return new \moodle_url('/course/editsection.php', ['id' => $componentinfo->itemid, 'sr' => '']);
} else if ($componentinfo->tablename == 'course_categories') {
return new \moodle_url('/course/editcategory.php', ['id' => $componentinfo->itemid]);
} else {
return new \moodle_url('/course/edit.php', ['id' => $componentinfo->courseid]);
}
}
}
@@ -1,92 +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 tool_brickfield\local\areas\core_course;
use core\event\course_category_created;
use core\event\course_category_updated;
use tool_brickfield\area_base;
/**
* Base class for all areas that represent a field from the course_categories table (such as 'intro' or 'name')
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class category_base extends area_base {
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event instanceof course_category_updated || $event instanceof course_category_created) {
return $this->find_fields_in_course_categories_table(['itemid' => $event->objectid]);
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset|null
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return null;
}
/**
* Return an array of area objects that contain content at the site and system levels only. All category content is considered
* system level.
* @return mixed
*/
public function find_system_areas(): ?\moodle_recordset {
return $this->find_fields_in_course_categories_table();
}
/**
* Helper method that can be used by the classes that define a field in the respective module table
*
* @param array $params
* @return \moodle_recordset
* @throws \dml_exception
*/
protected function find_fields_in_course_categories_table(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['itemid'])) {
$where[] = 't.id = :itemid';
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
t.id AS itemid,
t.id AS categoryid,
t.'.$this->get_fieldname().' AS content
FROM {'.$this->get_tablename().'} t
JOIN {context} ctx ON ctx.instanceid = t.id AND ctx.contextlevel = :pctxlevelcategory '.
($where ? 'WHERE ' . join(' AND ', $where) : '') . '
ORDER BY t.id',
['pctxlevelcategory' => CONTEXT_COURSECAT] + $params);
return $rs;
}
}
@@ -1,43 +0,0 @@
<?php
// This file is part of the Query submission plugin
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\core_course;
/**
* Category description observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class category_description extends category_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course_categories';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'description';
}
}
@@ -1,43 +0,0 @@
<?php
// This file is part of the Query submission plugin
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\core_course;
/**
* Category name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class category_name extends category_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course_categories';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -1,43 +0,0 @@
<?php
// This file is part of the Query submission plugin
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\core_course;
/**
* Course full name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class fullname extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'fullname';
}
}

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