Compare commits

..

225 Commits

Author SHA1 Message Date
Andrew Nicols 77be1e3fe3 Moodle release 3.8.1 2020-01-10 13:03:44 +08:00
Andrew Nicols de7b3e37b3 Merge branch 'install_38_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_38_STABLE 2020-01-10 13:03:42 +08:00
AMOS bot ffd8dfcf27 Automatically generated installer lang files 2020-01-10 00:12:13 +00:00
Sara Arjona 8a82f51043 weekly release 3.8+ 2020-01-09 15:42:53 +01:00
Jun Pataleta 68cab31dba Merge branch 'MDL-67544-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-01-09 15:22:35 +08:00
Andrew Nicols 3f50c24fc3 MDL-67544f= mod_forum: Correct "for" attribute on private checkbox 2020-01-09 14:55:52 +08:00
Andrew Nicols 9973646ca7 MDL-67544 mod_forum: Ensure post actions menu id is unique 2020-01-09 14:09:21 +08:00
Andrew Nicols f14420c739 Merge branch 'MOODLE_38_MDL-67485' of https://github.com/golenkovm/moodle into MOODLE_38_STABLE 2020-01-09 12:40:19 +08:00
Mikhail Golenkov 70868d8648 MDL-67485 task: Release the task runner lock before throwing exception. 2020-01-09 14:49:38 +11:00
Andrew Nicols 8f45c9b6a5 Merge branch 'MDL-67596-cron-ramp-up-MOODLE_38_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_38_STABLE 2020-01-09 09:32:49 +08:00
Brendan Heywood 1f5c6c6b7a MDL-67596 cron: Allow runners to ramp up instantly 2020-01-09 11:07:19 +11:00
Eloy Lafuente (stronk7) 26999dda23 Merge branch 'MDL-67544-38' of git://github.com/andrewnicols/moodle into MOODLE_38_STABLE 2020-01-08 16:35:32 +01:00
Eloy Lafuente (stronk7) 022206f2fe Merge branch 'MDL-67533-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-08 16:31:18 +01:00
Jake Dallimore f9e0f61467 MDL-67637 core_message: only preview lastmessage text if safe to do so
If any html/script tags are found in the text() value, don't display it.
2020-01-08 12:31:17 +01:00
Jun Pataleta c07bc83480 MDL-67533 mod_forum: Remove duplicate Re in experimental view subject 2020-01-08 16:29:43 +08:00
Sara Arjona 7d7d3520a7 Merge branch 'MDL-67417-38' of https://github.com/KietChan/moodle into MOODLE_38_STABLE 2020-01-08 08:26:44 +01:00
Andrew Nicols f34f8131ba MDL-67544 mod_forum: Ensure that private reply checkbox has unique id 2020-01-08 15:26:03 +08:00
Sara Arjona 85ba5d1d88 Merge branch 'MDL-67510-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-08 08:11:01 +01:00
Andrew Nicols e0b8a3b17a Merge branch 'MDL-64764-38' of git://github.com/paulholden/moodle into MOODLE_38_STABLE 2020-01-08 08:30:33 +08:00
Eloy Lafuente (stronk7) 5577e472e5 Merge branch 'MDL-67469-38' of git://github.com/junpataleta/moodle into MOODLE_38_STABLE 2020-01-07 22:59:51 +01:00
Marina Glancy 571f508d4e MDL-64764 core_admin: allow to submit empty list of allowed roles.
Co-authored-by: Paul Holden <paulh@moodle.com>
2020-01-07 10:01:33 +00:00
Andrew Nicols 764ec8d7fb Merge branch 'MDL-65849-38' of git://github.com/rezaies/moodle into MOODLE_38_STABLE 2020-01-07 13:26:56 +08:00
Andrew Nicols eb04dc8792 Merge branch 'MDL-66938-38' of https://github.com/grabs/moodle into MOODLE_38_STABLE 2020-01-07 12:49:42 +08:00
Andrew Nicols 6fefb88819 MDL-67114 mod_wiki: Whitespace fix 2020-01-07 11:05:02 +08:00
Andrew Nicols 1b2a8dad89 Merge branch 'MDL-67114_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2020-01-07 11:04:55 +08:00
Andrew Nicols ec63d3eab4 Merge branch 'MDL-66871-38-v2' of git://github.com/lameze/moodle into MOODLE_38_STABLE 2020-01-07 08:54:44 +08:00
Andrew Nicols 5f4250dc43 MDL-67544 form: Ensure that form errors have a unique id 2020-01-06 15:01:07 +08:00
Andrew Nicols b024306e5c MDL-67544 mod_forum: Add missing label for discussion move 2020-01-06 15:01:07 +08:00
Andrew Nicols 0d285e9334 MDL-67544 mod_forum: Add missing menuitem roles 2020-01-06 15:01:07 +08:00
Andrew Nicols bed212f61b MDL-67544 mod_forum: Correct aria-labelledby node 2020-01-06 15:01:07 +08:00
Andrew Nicols 14d58697a3 MDL-67544 mod_forum: Correct aria-controls to point to valid node 2020-01-06 15:01:07 +08:00
Andrew Nicols e98103354d MDL-67544 mod_forum: Add missing aria label for grade search 2020-01-06 15:01:07 +08:00
Andrew Nicols d8dfb98417 MDL-67544 core: Ensure unique IDs for YUI dialogues 2020-01-06 15:01:07 +08:00
Andrew Nicols 3684d9e03c MDL-67544 theme: Ensure that search box is in valid li 2020-01-06 15:01:06 +08:00
Andrew Nicols 629ef7772f MDL-67544 mod_forum: Add default role for favourite toggle 2020-01-06 15:01:06 +08:00
Andrew Nicols 9e57c09d7b MDL-67544 mod_forum: Add missing aria label for discussion actions 2020-01-06 15:01:06 +08:00
Andrew Nicols 949d3f1c02 MDL-67544 mod_forum: Correct aria-role => aria-live 2020-01-06 15:01:06 +08:00
Andrew Nicols 11524653b0 MDL-67544 mod_forum: Correct aria-role => role 2020-01-06 15:01:06 +08:00
Jun Pataleta f9b2f6634d MDL-67510 tool_dataprivacy: Fix the reply-to name of the privacy officer 2020-01-06 11:36:49 +08:00
Simey Lameze dafe4c5a78 MDL-66871 calendar: fix deprecated parameter in the phpDoc 2020-01-06 10:42:22 +08:00
Simey Lameze 550c4e1c42 MDL-66871 calendar: add unit test coverage for ics importing 2020-01-06 10:42:22 +08:00
Simey Lameze 0287928c4b MDL-66871 calendar: fix ics importing logic 2020-01-06 10:42:22 +08:00
Jake Dallimore 701d27e5d9 Merge branch 'MDL-67336-38' of https://github.com/roland04/moodle into MOODLE_38_STABLE 2020-01-06 09:36:53 +08:00
Andreas Grabs 13d5d3edb1 MDL-66938 mod_feedback: Export includes unwanted html in field names 2020-01-05 19:33:27 +01:00
Eloy Lafuente (stronk7) abc8f149ce MDL-67114 core: php74 fix. Fix use of scalar as array in core
There are various places where it's not guaranteed that the
variable being used is array, and instead, can be null, bool, int...

We need to check that because php74 warns about it.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

So we have decided to, instead of upgrade, apply the needed php74 fixes.
2019-11-20 10:01:02 +08:00
sam marshall 7d05f78363 MDL-67274 Tasks: Log display fails with memory errors 2019-11-19 10:51:22 +08:00
Jun Pataleta d0a9211f51 MDL-67148 tool_mobile: Set auth_cas|auth_name config value in unit test
Thanks to Renaat Debleu for the fix suggestion!
2019-11-18 18:50:11 +01:00
Marina Glancy e2a0a42003 MDL-67073 core_course: fix capability context 2019-11-18 16:02:46 +08:00
Jake Dallimore 7e24491f2c Merge branch 'MDL-67284_38' of https://github.com/stronk7/moodle into MOODLE_38_STABLE 2019-11-18 11:29:29 +08:00
Eloy Lafuente (stronk7) 4619c8a7e3 MDL-67284 mod_feedback: Add missing file phpdoc block 2019-11-17 12:47:05 +01:00
Eloy Lafuente (stronk7) 2aff0046c1 MDL-67284 upgrade: add 3.8.0 separation line to all upgrade scripts 2019-11-17 11:43:41 +01:00
5270 changed files with 92292 additions and 271819 deletions
+16 -18
View File
@@ -9,8 +9,6 @@ cache/stores/mongodb/MongoDB/
enrol/lti/ims-blti/
filter/algebra/AlgParser.pm
filter/tex/mimetex.*
h5p/h5plib/v124/joubel/core/
h5p/h5plib/v124/joubel/editor/
lib/editor/atto/plugins/html/yui/src/codemirror/
lib/editor/atto/plugins/html/yui/src/beautify/
lib/editor/atto/yui/src/rangy/js/*.*
@@ -63,9 +61,9 @@ lib/amd/src/popper.js
lib/geopattern-php/
lib/php-jwt/
lib/babel-polyfill/
lib/polyfills/
lib/mdn-polyfills/
lib/emoji-data/
lib/plist/
lib/h5p/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
@@ -74,19 +72,19 @@ media/player/videojs/videojs/video-js.swf
mod/assign/feedback/editpdf/fpdi/
repository/s3/S3.php
theme/boost/scss/bootstrap/
theme/boost/amd/src/bootstrap/alert.js
theme/boost/amd/src/bootstrap/button.js
theme/boost/amd/src/bootstrap/carousel.js
theme/boost/amd/src/bootstrap/collapse.js
theme/boost/amd/src/bootstrap/dropdown.js
theme/boost/amd/src/bootstrap/index.js
theme/boost/amd/src/bootstrap/modal.js
theme/boost/amd/src/bootstrap/popover.js
theme/boost/amd/src/bootstrap/tools/sanitizer.js
theme/boost/amd/src/bootstrap/scrollspy.js
theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/amd/src/alert.js
theme/boost/amd/src/button.js
theme/boost/amd/src/carousel.js
theme/boost/amd/src/collapse.js
theme/boost/amd/src/dropdown.js
theme/boost/amd/src/index.js
theme/boost/amd/src/modal.js
theme/boost/amd/src/popover.js
theme/boost/amd/src/sanitizer.js
theme/boost/amd/src/scrollspy.js
theme/boost/amd/src/tab.js
theme/boost/amd/src/toast.js
theme/boost/amd/src/tooltip.js
theme/boost/amd/src/util.js
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
+3 -7
View File
@@ -3,8 +3,6 @@
"Feature": 0,
"Background": 2,
"Scenario": 2,
"Examples": 4,
"example": 6,
"Step": 4,
"given": 4,
"and": 4
@@ -16,9 +14,7 @@
"no-multiple-empty-lines": "on",
"no-partially-commented-tag-lines": "on",
"no-trailing-spaces": "on",
"no-unnamed-features": "on",
"no-unnamed-scenarios": "on",
"no-scenario-outlines-without-examples": "on",
"no-examples-in-scenarios": "on",
"new-line-at-eof": ["on", "yes"]
"no-unamed-features": "on",
"no-unamed-scenarios": "on",
"no-scenario-outlines-without-examples": "on"
}
-2
View File
@@ -1,2 +0,0 @@
# Primary donations pages.
custom: ["https://moodle.com/donations/", moodle.org]
-71
View File
@@ -1,71 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Template configuraton file for github actions CI/CD.
*
* @package core
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com}
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This cannot be used out from a github actions workflow, so just exit.
getenv('GITHUB_WORKFLOW') || die; // phpcs:ignore moodle.Files.MoodleInternal.MoodleInternalGlobalState
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->dbtype = getenv('dbtype');
$CFG->dblibrary = 'native';
$CFG->dbhost = '127.0.0.1';
$CFG->dbname = 'test';
$CFG->dbuser = 'test';
$CFG->dbpass = 'test';
$CFG->prefix = 'm_';
$CFG->dboptions = ['dbcollation' => 'utf8mb4_bin'];
$host = 'localhost';
$CFG->wwwroot = "http://{$host}";
$CFG->dataroot = realpath(dirname(__DIR__)) . '/moodledata';
$CFG->admin = 'admin';
$CFG->directorypermissions = 0777;
// Debug options - possible to be controlled by flag in future.
$CFG->debug = (E_ALL | E_STRICT); // DEBUG_DEVELOPER.
$CFG->debugdisplay = 1;
$CFG->debugstringids = 1; // Add strings=1 to url to get string ids.
$CFG->perfdebug = 15;
$CFG->debugpageinfo = 1;
$CFG->allowthemechangeonurl = 1;
$CFG->passwordpolicy = 0;
$CFG->cronclionly = 0;
$CFG->pathtophp = getenv('pathtophp');
$CFG->phpunit_dataroot = realpath(dirname(__DIR__)) . '/phpunitdata';
$CFG->phpunit_prefix = 't_';
define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://localhost:8080');
define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://localhost:8080');
define('TEST_SESSION_REDIS_HOST', 'localhost');
define('TEST_CACHESTORE_REDIS_TESTSERVERS', 'localhost');
// TODO: add others (solr, mongodb, memcached, ldap...).
// Too much for now: define('PHPUNIT_LONGTEST', true); // Only leaves a few tests out and they are run later by CI.
require_once(__DIR__ . '/lib/setup.php');
-103
View File
@@ -1,103 +0,0 @@
name: Core
on: [push]
env:
php: 7.4
jobs:
Grunt:
runs-on: ubuntu-18.04
steps:
- name: Checking out code
uses: actions/checkout@v2
- name: Configuring node & npm
shell: bash -l {0}
run: nvm install
- name: Installing node stuff
run: npm install
- name: Running grunt
run: npx grunt
- name: Looking for uncommitted changes
# Add all files to the git index and then run diff --cached to see all changes.
# This ensures that we get the status of all files, including new files.
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
run: |
git add .
git reset -- npm-shrinkwrap.json
git diff --cached --exit-code
PHPUnit:
runs-on: ${{ matrix.os }}
services:
exttests:
image: moodlehq/moodle-exttests
ports:
- 8080:80
redis:
image: redis
ports:
- 6379:6379
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
php: 7.2
db: mysqli
- os: ubuntu-18.04
php: 7.4
db: pgsql
steps:
- name: Setting up DB mysql
if: ${{ matrix.db == 'mysqli' }}
uses: johanmeiring/mysql-action@tmpfs-patch
with:
collation server: utf8mb4_bin
mysql version: 5.7
mysql database: test
mysql user: test
mysql password: test
use tmpfs: true
- name: Setting up DB pgsql
if: ${{ matrix.db == 'pgsql' }}
uses: m4nu56/postgresql-action@v1
with:
postgresql version: 9.6
postgresql db: test
postgresql user: test
postgresql password: test
- name: Configuring git vars
uses: rlespinasse/github-slug-action@v3.x
- name: Setting up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
uses: actions/checkout@v2
- name: Setting up PHPUnit
env:
dbtype: ${{ matrix.db }}
run: |
echo "pathtophp=$(which php)" >> $GITHUB_ENV # Inject installed pathtophp to env. The template config needs it.
cp .github/workflows/config-template.php config.php
mkdir ../moodledata
sudo locale-gen en_AU.UTF-8
php admin/tool/phpunit/cli/init.php --no-composer-self-update
- name: Running PHPUnit tests
env:
dbtype: ${{ matrix.db }}
run: vendor/bin/phpunit -v
+1 -1
View File
@@ -1 +1 @@
v14.15.0
v8.16.1
+16 -18
View File
@@ -10,8 +10,6 @@ cache/stores/mongodb/MongoDB/
enrol/lti/ims-blti/
filter/algebra/AlgParser.pm
filter/tex/mimetex.*
h5p/h5plib/v124/joubel/core/
h5p/h5plib/v124/joubel/editor/
lib/editor/atto/plugins/html/yui/src/codemirror/
lib/editor/atto/plugins/html/yui/src/beautify/
lib/editor/atto/yui/src/rangy/js/*.*
@@ -64,9 +62,9 @@ lib/amd/src/popper.js
lib/geopattern-php/
lib/php-jwt/
lib/babel-polyfill/
lib/polyfills/
lib/mdn-polyfills/
lib/emoji-data/
lib/plist/
lib/h5p/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
@@ -75,19 +73,19 @@ media/player/videojs/videojs/video-js.swf
mod/assign/feedback/editpdf/fpdi/
repository/s3/S3.php
theme/boost/scss/bootstrap/
theme/boost/amd/src/bootstrap/alert.js
theme/boost/amd/src/bootstrap/button.js
theme/boost/amd/src/bootstrap/carousel.js
theme/boost/amd/src/bootstrap/collapse.js
theme/boost/amd/src/bootstrap/dropdown.js
theme/boost/amd/src/bootstrap/index.js
theme/boost/amd/src/bootstrap/modal.js
theme/boost/amd/src/bootstrap/popover.js
theme/boost/amd/src/bootstrap/tools/sanitizer.js
theme/boost/amd/src/bootstrap/scrollspy.js
theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/amd/src/alert.js
theme/boost/amd/src/button.js
theme/boost/amd/src/carousel.js
theme/boost/amd/src/collapse.js
theme/boost/amd/src/dropdown.js
theme/boost/amd/src/index.js
theme/boost/amd/src/modal.js
theme/boost/amd/src/popover.js
theme/boost/amd/src/sanitizer.js
theme/boost/amd/src/scrollspy.js
theme/boost/amd/src/tab.js
theme/boost/amd/src/toast.js
theme/boost/amd/src/tooltip.js
theme/boost/amd/src/util.js
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
+75 -48
View File
@@ -2,59 +2,58 @@
# process (which uses our internal CI system) this file is here for the benefit
# of community developers git clones - see MDL-51458.
sudo: required
# We currently disable Travis notifications entirely until https://github.com/travis-ci/travis-ci/issues/4976
# is fixed.
notifications:
email:
if: env(MOODLE_EMAIL) != no
email: false
language: php
os: linux
dist: xenial
services:
- mysql
- docker
php:
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
- 7.3
- 7.1.30 # Make this sticky because current default version (7.1.11) has a bug with redis-extension output (MDL-66062)
addons:
postgresql: "9.6"
jobs:
env:
# Although we want to run these jobs and see failures as quickly as possible, we also want to get the slowest job to
# start first so that the total run time is not too high.
#
# We only run MySQL on PHP 7.2, so run that first.
# CI Tests should be second-highest in priority as these only take <= 60 seconds to run under normal circumstances.
# Postgres is significantly is pretty reasonable in its run-time.
# Run CI Tests without running PHPUnit.
- DB=none TASK=CITEST
# Run unit tests on Postgres
- DB=pgsql TASK=PHPUNIT
# Perform an upgrade test too.
- DB=pgsql TASK=UPGRADE
matrix:
# Enable fast finish.
# This will fail the build if a single job fails (except those in allow_failures).
# It will not stop the jobs from running.
fast_finish: true
include:
# First all the lowest php ones (7.2)
- php: 7.2
env: DB=none TASK=CITEST
- 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.2
env: DB=pgsql TASK=PHPUNIT
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
php: 7.2
env: DB=mysqli TASK=PHPUNIT
# Then, conditionally, all the highest php ones (7.4)
- if: env(MOODLE_PHP) = "all"
php: 7.4
env: DB=none TASK=CITEST
- if: env(MOODLE_PHP) = "all"
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: 7.4
env: DB=pgsql TASK=PHPUNIT
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
php: 7.4
# Run mysql only on 7.3 - it's just too slow
- php: 7.3
env: DB=mysqli TASK=PHPUNIT
# Run grunt/npm install on highest version ('node' is an alias for the latest node.js version.)
- php: 7.2
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
cache:
directories:
@@ -62,9 +61,8 @@ cache:
- $HOME/.npm
before_install:
- docker run -d -p 127.0.0.1:8080:80 --name exttests moodlehq/moodle-exttests
# Avoid IPv6 default binding as service (causes redis not to start).
- sudo service redis-server start --bind 127.0.0.1
sudo service redis-server start --bind 127.0.0.1
install:
- >
@@ -114,7 +112,7 @@ install:
before_script:
- phpenv config-rm xdebug.ini
- >
if [ "$TASK" = 'PHPUNIT' ];
if [ "$TASK" = 'PHPUNIT' -o "$TASK" = 'UPGRADE' ];
then
# Copy generic configuration in place.
cp config-dist.php config.php ;
@@ -171,12 +169,6 @@ before_script:
-e "/require_once/i \\\$CFG->phpunit_dataroot = '\/home\/travis\/roots\/phpunit';" \
-e "/require_once/i \\\$CFG->phpunit_prefix = 'p_';" \
config.php ;
# Enable test external resources
sed -i \
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://127.0.0.1:8080');" \
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://127.0.0.1:8080');" \
config.php ;
# Redis cache store tests
sed -i \
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
@@ -214,7 +206,7 @@ before_script:
# We need the official upstream for comparison
git remote add upstream https://github.com/moodle/moodle.git;
git fetch upstream MOODLE_39_STABLE;
git fetch upstream MOODLE_38_STABLE;
export GIT_PREVIOUS_COMMIT="`git merge-base FETCH_HEAD $TRAVIS_COMMIT`";
export GIT_COMMIT="$TRAVIS_COMMIT";
export UPSTREAM_FETCH_HEAD=`git rev-parse FETCH_HEAD`
@@ -225,6 +217,32 @@ before_script:
export phpcmd=`which php`;
fi
########################################################################
# Upgrade test
########################################################################
- >
if [ "$TASK" = 'UPGRADE' ];
then
# We need the official upstream.
git remote add upstream https://github.com/moodle/moodle.git;
# Checkout 30 STABLE branch (the first version compatible with PHP 7.x)
git fetch upstream MOODLE_30_STABLE;
git checkout MOODLE_30_STABLE;
# Perform the upgrade
php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
# Return to the previous commit
git checkout -;
# Perform the upgrade
php admin/cli/upgrade.php --non-interactive --allow-unstable ;
# The local_ci repository can be used to check upgrade savepoints.
git clone https://github.com/moodlehq/moodle-local_ci.git local/ci ;
fi
script:
- >
if [ "$TASK" = 'PHPUNIT' ];
@@ -250,10 +268,19 @@ script:
git diff --cached --exit-code ;
fi
after_script:
########################################################################
# Upgrade test
########################################################################
- >
if [ "$TASK" = 'PHPUNIT' ];
if [ "$TASK" = 'UPGRADE' ];
then
EXTTESTS_HITS=$(docker logs exttests 2>&1 | grep -Fv -e 'AH00558' -e '[pid 1]' | wc -l)
echo -e "\nTest local resources number of hits: ${EXTTESTS_HITS}.\n"
cp local/ci/check_upgrade_savepoints/check_upgrade_savepoints.php ./check_upgrade_savepoints.php
result=`php check_upgrade_savepoints.php`;
# Check if there are problems
count=`echo "$result" | grep -P "ERROR|WARN" | wc -l` ;
if (($count > 0));
then
echo "$result"
exit 1 ;
fi
fi
+123 -335
View File
@@ -20,136 +20,22 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Grunt configuration
*/
/* eslint-env node */
/**
* 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 => {
const fs = require('fs');
const path = require('path');
let cwd = fs.realpathSync(process.env.PWD || process.cwd());
// Windows users can't run grunt in a subdirectory, so allow them to set
// the root by passing --root=path/to/dir.
if (grunt.option('root')) {
const root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) {
cwd = fs.realpathSync(path.join(__dirname, root));
grunt.log.ok('Setting root to ' + cwd);
} else {
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
return cwd;
};
/**
* Register any stylelint tasks.
*
* @param {Object} grunt
* @param {Array} files
* @param {String} fullRunDir
*/
const registerStyleLintTasks = (grunt, files, fullRunDir) => {
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,
},
},
};
};
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 {
hasScss = false;
}
const cssSrc = [];
glob.sync(`${fullRunDir}/**/*.css`).forEach(path => cssSrc.push(path));
if (cssSrc.length) {
grunt.config.merge(getCssConfigForFiles(cssSrc));
} else {
hasCss = false;
}
}
const scssTasks = ['sass'];
if (hasScss) {
scssTasks.unshift('stylelint:scss');
}
grunt.registerTask('scss', scssTasks);
const cssTasks = [];
if (hasCss) {
cssTasks.push('stylelint:css');
}
grunt.registerTask('rawcss', cssTasks);
grunt.registerTask('css', ['scss', 'rawcss']);
};
/**
* 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');
var path = require('path'),
tasks = {},
cwd = process.env.PWD || process.cwd(),
async = require('async'),
DOMParser = require('xmldom').DOMParser,
xpath = require('xpath'),
semver = require('semver'),
watchman = require('fb-watchman'),
watchmanClient = new watchman.Client(),
gruntFilePath = process.cwd();
// Verify the node version is new enough.
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
@@ -158,64 +44,34 @@ module.exports = function(grunt) {
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
}
// Detect directories:
// * gruntFilePath The real path on disk to this Gruntfile.js
// * cwd The current working directory, which can be overridden by the `root` option
// * relativeCwd The cwd, relative to the Gruntfile.js
// * componentDirectory The root directory of the component if the cwd is in a valid component
// * inComponent Whether the cwd is in a valid component
// * runDir The componentDirectory or cwd if not in a component, relative to Gruntfile.js
// * fullRunDir The full path to the runDir
const gruntFilePath = fs.realpathSync(process.cwd());
const cwd = getCwd(grunt);
const relativeCwd = path.relative(gruntFilePath, cwd);
const componentDirectory = ComponentList.getOwningComponentDirectory(relativeCwd);
const inComponent = !!componentDirectory;
const runDir = inComponent ? componentDirectory : relativeCwd;
const fullRunDir = fs.realpathSync(gruntFilePath + path.sep + runDir);
grunt.log.debug('============================================================================');
grunt.log.debug(`= Node version: ${process.versions.node}`);
grunt.log.debug(`= grunt version: ${grunt.package.version}`);
grunt.log.debug(`= process.cwd: '` + process.cwd() + `'`);
grunt.log.debug(`= process.env.PWD: '${process.env.PWD}'`);
grunt.log.debug(`= path.sep '${path.sep}'`);
grunt.log.debug('============================================================================');
grunt.log.debug(`= gruntFilePath: '${gruntFilePath}'`);
grunt.log.debug(`= relativeCwd: '${relativeCwd}'`);
grunt.log.debug(`= componentDirectory: '${componentDirectory}'`);
grunt.log.debug(`= inComponent: '${inComponent}'`);
grunt.log.debug(`= runDir: '${runDir}'`);
grunt.log.debug(`= fullRunDir: '${fullRunDir}'`);
grunt.log.debug('============================================================================');
if (inComponent) {
grunt.log.ok(`Running tasks for component directory ${componentDirectory}`);
// Windows users can't run grunt in a subdirectory, so allow them to set
// the root by passing --root=path/to/dir.
if (grunt.option('root')) {
var root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) {
cwd = path.join(__dirname, root);
grunt.log.ok('Setting root to ' + cwd);
} else {
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
let files = null;
var files = null;
if (grunt.option('files')) {
// Accept a comma separated list of files to process.
files = grunt.option('files').split(',');
}
// 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('..');
var inAMD = path.basename(cwd) == 'amd';
// 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");
var amdSrc = [];
if (inAMD) {
amdSrc.push(cwd + "/src/*.js");
amdSrc.push(cwd + "/src/**/*.js");
} else {
amdSrc = ComponentList.getAmdSrcGlobList();
}
let yuiSrc = [];
if (inComponent) {
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
} else {
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
amdSrc.push("**/amd/src/*.js");
amdSrc.push("**/amd/src/**/*.js");
}
/**
@@ -241,65 +97,40 @@ module.exports = function(grunt) {
* @return {array} The list of thirdparty paths.
*/
var getThirdPartyPathsFromXML = function() {
const thirdpartyfiles = ComponentList.getThirdPartyLibsList(gruntFilePath + '/');
const libs = ['node_modules/', 'vendor/'];
var thirdpartyfiles = grunt.file.expand('*/**/thirdpartylibs.xml');
var libs = ['node_modules/', 'vendor/'];
thirdpartyfiles.forEach(function(file) {
const dirname = path.dirname(file);
var dirname = path.dirname(file);
const doc = new DOMParser().parseFromString(grunt.file.read(file));
const nodes = xpath.select("/libraries/library/location/text()", doc);
var doc = new DOMParser().parseFromString(grunt.file.read(file));
var nodes = xpath.select("/libraries/library/location/text()", doc);
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(/\/?$/, '/');
}
nodes.forEach(function(node) {
var lib = path.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);
}
});
// 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)
},
options: {quiet: !grunt.option('show-lint-warnings')},
amd: {src: files ? files : amdSrc},
// Check YUI module source files.
yui: {src: files ? files : yuiSrc},
yui: {src: files ? files : ['**/yui/src/**/*.js', '!*/**/yui/src/*/meta/*.js']}
},
babel: {
options: {
@@ -359,7 +190,6 @@ module.exports = function(grunt) {
}
},
options: {
implementation: sass,
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
}
},
@@ -368,72 +198,73 @@ module.exports = function(grunt) {
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'],
files: ['**/amd/src/**/*.js'],
tasks: ['amd']
},
boost: {
files: [inComponent ? 'scss/**/*.scss' : 'theme/boost/scss/**/*.scss'],
files: ['**/theme/boost/scss/**/*.scss'],
tasks: ['scss']
},
rawcss: {
files: [
'**/*.css',
],
excludes: [
'**/moodle.css',
'**/editor.css',
],
files: ['**/*.css', '**/theme/**/!(moodle.css|editor.css)'],
tasks: ['rawcss']
},
yui: {
files: inComponent
? ['yui/src/*.json', 'yui/src/**/*.js']
: ['**/yui/src/**/*.js'],
files: ['**/yui/src/**/*.js'],
tasks: ['yui']
},
gherkinlint: {
files: [inComponent ? 'tests/behat/*.feature' : '**/tests/behat/*.feature'],
files: ['**/tests/behat/*.feature'],
tasks: ['gherkinlint']
}
},
shifter: {
options: {
recursive: true,
// Shifter takes a relative path.
paths: files ? files : [runDir]
paths: files ? files : [cwd]
}
},
gherkinlint: {
options: {
files: getGherkinLintTargets(),
files: files ? files : ['**/tests/behat/*.feature'],
}
},
stylelint: {
scss: {
options: {syntax: 'scss'},
src: files ? files : ['*/**/*.scss']
},
css: {
src: files ? files : ['*/**/*.css'],
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
}
}
}
}
}
});
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
tasks.ignorefiles = function() {
// An array of paths to third party directories.
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'));
// An array of paths to third party directories.
var thirdPartyPaths = getThirdPartyPathsFromXML();
// Generate .eslintignore.
var eslintIgnores = ['# Generated by "grunt ignorefiles"', '*/**/yui/src/*/meta/', '*/**/build/'].concat(thirdPartyPaths);
grunt.file.write('.eslintignore', eslintIgnores.join('\n'));
// Generate .stylelintignore.
var stylelintIgnores = [
'# Generated by "grunt ignorefiles"',
'**/yui/build/*',
'theme/boost/style/moodle.css',
'theme/classic/style/moodle.css',
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
};
/**
@@ -525,32 +356,19 @@ module.exports = function(grunt) {
};
tasks.gherkinlint = function() {
const done = this.async();
const options = grunt.config('gherkinlint.options');
var done = this.async(),
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
var args = grunt.file.expand(options.files);
args.unshift(path.normalize(__dirname + '/node_modules/.bin/gherkin-lint'));
grunt.util.spawn({
cmd: 'node',
args: args,
opts: {stdio: 'inherit', env: process.env}
}, function(error, result, code) {
// Propagate the exit code.
done(code === 0);
});
};
tasks.startup = function() {
@@ -610,7 +428,7 @@ module.exports = function(grunt) {
grunt: true,
// Run from current working dir and inherit stdio from process.
opts: {
cwd: fullRunDir,
cwd: cwd,
stdio: 'inherit'
},
args: [task, filesOption]
@@ -636,26 +454,18 @@ module.exports = function(grunt) {
);
};
const originalWatchConfig = grunt.config.get(['watch']);
const watchConfig = Object.keys(originalWatchConfig).reduce(function(carry, key) {
var watchConfig = grunt.config.get(['watch']);
watchConfig = Object.keys(watchConfig).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;
}
var value = watchConfig[key];
var fileGlobs = value.files;
var taskNames = value.tasks;
taskNames.forEach(function(taskName) {
carry[taskName] = {
files,
excludes,
};
carry[taskName] = fileGlobs;
});
return carry;
@@ -689,14 +499,12 @@ module.exports = function(grunt) {
resp.files.forEach(function(file) {
grunt.log.ok('File changed: ' + file.name);
var fullPath = fullRunDir + '/' + file.name;
var fullPath = cwd + '/' + 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);
var fileGlobs = watchConfig[task];
var match = fileGlobs.every(function(fileGlob) {
return grunt.file.isMatch(fileGlob, fullPath);
});
if (match) {
// If we are watching a subdirectory then the file.name will be relative
// to that directory. However the grunt tasks expect the file paths to be
@@ -728,7 +536,7 @@ module.exports = function(grunt) {
});
// Initiate the watch on the current directory.
watchmanClient.command(['watch-project', fullRunDir], function(watchError, watchResponse) {
watchmanClient.command(['watch-project', cwd], function(watchError, watchResponse) {
if (watchError) {
grunt.log.error('Error initiating watch:', watchError);
watchTaskDone(1);
@@ -750,40 +558,18 @@ module.exports = function(grunt) {
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'];
// Use the matching patterns specified in the watch config.
var matches = Object.keys(watchConfig).map(function(task) {
const matchAll = [];
matchAll.push(['anyof'].concat(watchConfig[task].files.map(matchWholeName)));
var fileGlobs = watchConfig[task];
var fileGlobMatches = fileGlobs.map(function(fileGlob) {
return ['match', fileGlob, 'wholename'];
});
if (watchConfig[task].excludes.length) {
matchAll.push(['not', ['anyof'].concat(watchConfig[task].excludes.map(matchWholeName))]);
}
return ['allof'].concat(matchAll);
return ['allof'].concat(fileGlobMatches);
});
matches = ['anyof'].concat(matches);
var sub = {
expression: matches,
expression: ["anyof"].concat(matches),
// Which fields we're interested in.
fields: ["name", "size", "type"],
// Add our time constraint.
@@ -803,7 +589,7 @@ module.exports = function(grunt) {
return;
}
grunt.log.ok('Listening for changes to files in ' + fullRunDir);
grunt.log.ok('Listening for changes to files in ' + cwd);
});
});
});
@@ -848,8 +634,10 @@ module.exports = function(grunt) {
grunt.registerTask('amd', ['eslint:amd', 'babel']);
grunt.registerTask('js', ['amd', 'yui']);
// Register CSS tasks.
registerStyleLintTasks(grunt, files, fullRunDir);
// Register CSS taks.
grunt.registerTask('css', ['stylelint:scss', 'sass', 'stylelint:css']);
grunt.registerTask('scss', ['stylelint:scss', 'sass']);
grunt.registerTask('rawcss', ['stylelint:css']);
// Register the startup task.
grunt.registerTask('startup', 'Run the correct tasks for the current directory', tasks.startup);
-188
View File
@@ -1,188 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Helper functions for working with Moodle component names, directories, and sources.
*
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
/* eslint-env node */
/** @var {Object} A list of subsystems in Moodle */
const componentData = {};
/**
* Load details of all moodle modules.
*
* @returns {object}
*/
const fetchComponentData = () => {
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const gruntFilePath = process.cwd();
if (!Object.entries(componentData).length) {
componentData.subsystems = {};
componentData.pathList = [];
// Fetch the component definiitions from the distributed JSON file.
const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`));
// Build the list of moodle subsystems.
componentData.subsystems.lib = 'core';
componentData.pathList.push(process.cwd() + path.sep + 'lib');
for (const [component, thisPath] of Object.entries(components.subsystems)) {
if (thisPath) {
// Prefix "core_" to the front of the subsystems.
componentData.subsystems[thisPath] = `core_${component}`;
componentData.pathList.push(process.cwd() + path.sep + thisPath);
}
}
// The list of components incldues the list of subsystems.
componentData.components = componentData.subsystems;
// Go through each of the plugintypes.
Object.entries(components.plugintypes).forEach(([pluginType, pluginTypePath]) => {
// We don't allow any code in this place..?
glob.sync(`${pluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${pluginType}_${componentName}`;
componentData.components[`${pluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
// Look for any subplugins.
const subPluginConfigurationFile = `${componentPath}/db/subplugins.json`;
if (fs.existsSync(subPluginConfigurationFile)) {
const subpluginList = JSON.parse(fs.readFileSync(fs.realpathSync(subPluginConfigurationFile)));
Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => {
glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${subpluginType}_${componentName}`;
componentData.components[`${subpluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
});
});
}
});
});
}
return componentData;
};
/**
* Get the list of paths to build AMD sources.
*
* @returns {Array}
*/
const getAmdSrcGlobList = () => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
globList.push(`${componentPath}/amd/src/*.js`);
globList.push(`${componentPath}/amd/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to build YUI sources.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getYuiSrcGlobList = relativeTo => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
const relativeComponentPath = componentPath.replace(relativeTo, '');
globList.push(`${relativeComponentPath}/yui/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to thirdpartylibs.xml.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getThirdPartyLibsList = relativeTo => {
const fs = require('fs');
const path = require('path');
return fetchComponentData().pathList
.map(componentPath => path.relative(relativeTo, componentPath) + '/thirdpartylibs.xml')
.map(componentPath => componentPath.replace(/\\/g, '/'))
.filter(path => fs.existsSync(path))
.sort();
};
/**
* Find the name of the component matching the specified path.
*
* @param {String} path
* @returns {String|null} Name of matching component.
*/
const getComponentFromPath = path => {
const componentList = fetchComponentData().components;
if (componentList.hasOwnProperty(path)) {
return componentList[path];
}
return null;
};
/**
* Check whether the supplied path, relative to the Gruntfile.js, is in a known component.
*
* @param {String} checkPath The path to check. This can be with either Windows, or Linux directory separators.
* @returns {String|null}
*/
const getOwningComponentDirectory = checkPath => {
const path = require('path');
// Fetch all components into a reverse sorted array.
// This ensures that components which are within the directory of another component match first.
const pathList = Object.keys(fetchComponentData().components).sort().reverse();
for (const componentPath of pathList) {
// If the componentPath is the directory being checked, it will be empty.
// If the componentPath is a parent of the directory being checked, the relative directory will not start with ..
if (!path.relative(componentPath, checkPath).startsWith('..')) {
return componentPath;
}
}
return null;
};
module.exports = {
getAmdSrcGlobList,
getComponentFromPath,
getOwningComponentDirectory,
getYuiSrcGlobList,
getThirdPartyLibsList,
};
+2 -4
View File
@@ -98,10 +98,8 @@ switch ($action) {
default:
break;
}
$new = implode(',', $activeantiviruses);
add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core');
set_config('antiviruses', $new);
set_config('antiviruses', implode(',', $activeantiviruses));
core_plugin_manager::reset_caches();
redirect ($returnurl);
redirect ($returnurl);
@@ -178,7 +178,6 @@ class filesize extends \admin_setting {
'id' => $this->get_id(),
'name' => $this->get_full_name(),
'value' => $data['v'],
'readonly' => $this->is_readonly(),
'options' => array_map(function($unit, $title) use ($data, $defaultunit) {
return [
'value' => $unit,
-122
View File
@@ -1,122 +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/>.
/**
* Task executor for adhoc tasks.
*
* @package core
* @subpackage cli
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @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->libdir}/cronlib.php");
list($options, $unrecognized) = cli_get_params(
[
'execute' => false,
'help' => false,
'keep-alive' => 0,
'showsql' => false,
'showdebugging' => false,
'ignorelimits' => false,
], [
'h' => 'help',
'e' => 'execute',
'k' => 'keep-alive',
'i' => 'ignorelimits',
]
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help'] or empty($options['execute'])) {
$help = <<<EOT
Ad hoc cron tasks.
Options:
-h, --help Print out this help
--showsql Show sql queries before they are executed
--showdebugging Show developer level debugging information
-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
Example:
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
EOT;
echo $help;
die;
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql']) {
$DB->set_debug(true);
}
if (CLI_MAINTENANCE) {
echo "CLI maintenance mode active, cron execution suspended.\n";
exit(1);
}
if (moodle_needs_upgrading()) {
echo "Moodle upgrade pending, cron execution suspended.\n";
exit(1);
}
if (empty($options['execute'])) {
exit(0);
}
if (empty($options['keep-alive'])) {
$options['keep-alive'] = 0;
}
if (!empty($CFG->showcronsql)) {
$DB->set_debug(true);
}
if (!empty($CFG->showcrondebugging)) {
set_debugging(DEBUG_DEVELOPER, true);
}
$checklimits = empty($options['ignorelimits']);
core_php_time_limit::raise();
// Increase memory limit.
raise_memory_limit(MEMORY_EXTRA);
// Emulate normal session - we use admin account by default.
cron_setup_user();
$humantimenow = date('r', time());
$keepalive = (int)$options['keep-alive'];
\core\local\cli\shutdown::script_supports_graceful_exit();
mtrace("Server Time: {$humantimenow}\n");
cron_run_adhoc_tasks(time(), $keepalive, $checklimits);
+1 -6
View File
@@ -124,12 +124,7 @@ if ($options['unset'] || $options['set'] !== null) {
cli_error('The configuration variable is hard-set in the config.php, unable to change.', 4);
}
$new = $options['set'];
$old = get_config($options['component'], $options['name']);
if ($new !== $old) {
set_config($options['name'], $options['set'], $options['component']);
add_to_config_log($options['name'], $old, $new, $options['component']);
}
set_config($options['name'], $options['set'], $options['component']);
exit(0);
}
-171
View File
@@ -1,171 +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 tool for system checks
*
* @package core
* @category check
* @copyright 2020 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');
use core\check\result;
list($options, $unrecognized) = cli_get_params([
'help' => false,
'filter' => '',
'type' => 'status',
'verbose' => false,
], [
'h' => 'help',
'f' => 'filter',
'v' => 'verbose',
't' => 'type',
]);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
$checks = \core\check\manager::get_checks($options['type']);
$types = join(', ', \core\check\manager::TYPES);
$help = "Run Moodle system checks
Options:
-h, --help Print out this help
-f, --filter Filter to a subset of checks
-t, --type Which set of checks? Defaults to 'status'
One of $types
-v, --verbose Show details of all checks, not just failed checks
Example:
sudo -u www-data php admin/cli/checks.php
sudo -u www-data php admin/cli/checks.php -v
sudo -u www-data php admin/cli/checks.php -v --filter=environment
";
if ($options['help']) {
echo $help;
die();
}
$filter = $options['filter'];
if ($filter) {
$checks = array_filter($checks, function($check, $key) use ($filter) {
$ref = $check->get_ref();
return (strpos($ref, $filter) !== false);
}, 1);
}
// These shell exit codes and labels align with the NRPE standard.
$exitcodes = [
result::NA => 0,
result::OK => 0,
result::INFO => 0,
result::UNKNOWN => 3,
result::WARNING => 1,
result::ERROR => 2,
result::CRITICAL => 2,
];
$exitlabel = [
result::NA => 'OK',
result::OK => 'OK',
result::INFO => 'OK',
result::UNKNOWN => 'UNKNOWN',
result::WARNING => 'WARNING',
result::ERROR => 'CRITICAL',
result::CRITICAL => 'CRITICAL',
];
$format = "% 10s| % -60s\n";
$spacer = "----------+--------------------------------------------------------------------\n";
$prefix = ' |';
$output = '';
$header = $exitlabel[result::OK] . ': ' . get_string('checksok', '', $options['type']) . "\n";
$exitcode = $exitcodes[result::OK];
foreach ($checks as $check) {
$ref = $check->get_ref();
$result = $check->get_result();
$status = $result->get_status();
$checkexitcode = $exitcodes[$status];
// Summary is treated as html.
$summary = $result->get_summary();
$summary = html_to_text($summary, 60, false);
if ($checkexitcode > $exitcode) {
$exitcode = $checkexitcode;
$header = $exitlabel[$status] . ': ' . $check->get_name() . " (" . $check->get_ref() . ")\n";
}
if (empty($messages[$status])) {
$messages[$status] = $result;
}
$len = strlen(get_string('status' . $status));
if ($options['verbose'] ||
$status == result::WARNING ||
$status == result::CRITICAL ||
$status == result::ERROR) {
$output .= sprintf(
$format,
$OUTPUT->check_result($result),
sprintf('%s (%s)', $check->get_name(), $ref)
);
$summary = str_replace("\n", "\n" . $prefix . ' ', $summary);
$output .= sprintf( $format, '', ' ' . $summary);
if ($options['verbose']) {
$actionlink = $check->get_action_link();
if ($actionlink) {
$output .= sprintf( $format, '', ' ' . $actionlink->url);
}
$output .= sprintf( $format, '', '');
}
}
}
// Print NRPE header.
print $header;
// Only show the table header if there is anything to show.
if ($output) {
print sprintf($format,
get_string('status'). ' ',
get_string('check')
) . $spacer;
print $output;
}
// NRPE shell exit code.
exit($exitcode);
+2 -20
View File
@@ -35,16 +35,8 @@ require_once($CFG->libdir.'/clilib.php'); // cli only functions
require_once($CFG->libdir.'/cronlib.php');
// now get cli options
list($options, $unrecognized) = cli_get_params(
array(
'help' => false,
'stop' => false,
),
array(
'h' => 'help',
's' => 'stop',
)
);
list($options, $unrecognized) = cli_get_params(array('help'=>false),
array('h'=>'help'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
@@ -57,7 +49,6 @@ if ($options['help']) {
Options:
-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
@@ -67,13 +58,4 @@ Example:
die;
}
if ($options['stop']) {
// By clearing the caches this signals to other running processes
// to exit after finishing the current task.
\core\task\manager::clear_static_caches();
die;
}
\core\local\cli\shutdown::script_supports_graceful_exit();
cron_run();
+97 -107
View File
@@ -215,7 +215,6 @@ define('SITEID', 1);
//Database types
$databases = array('mysqli' => moodle_database::get_driver_instance('mysqli', 'native'),
'auroramysql' => moodle_database::get_driver_instance('auroramysql', 'native'),
'mariadb'=> moodle_database::get_driver_instance('mariadb', 'native'),
'pgsql' => moodle_database::get_driver_instance('pgsql', 'native'),
'oci' => moodle_database::get_driver_instance('oci', 'native'),
@@ -267,7 +266,6 @@ list($options, $unrecognized) = cli_get_params(
);
$interactive = empty($options['non-interactive']);
$skipdatabase = $options['skip-database'];
// set up language
$lang = clean_param($options['lang'], PARAM_SAFEDIR);
@@ -639,100 +637,96 @@ do {
}
} while ($hintdatabase !== '');
// If --skip-database option is provided, we do not need to ask for site fullname, shortname, adminuser, adminpass, adminemail.
// These fields will be requested during the database install part.
if (!$skipdatabase) {
// Ask for fullname.
if ($interactive) {
cli_separator();
cli_heading(get_string('fullsitename', 'moodle'));
// ask for fullname
if ($interactive) {
cli_separator();
cli_heading(get_string('fullsitename', 'moodle'));
if ($options['fullname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['fullname'] = cli_input($prompt, $options['fullname']);
} while (empty($options['fullname']));
if ($options['fullname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
} else {
if (empty($options['fullname'])) {
$a = (object)['option' => 'fullname', 'value' => $options['fullname']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for shortname.
if ($interactive) {
cli_separator();
cli_heading(get_string('shortsitename', 'moodle'));
if ($options['shortname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['shortname'] = cli_input($prompt, $options['shortname']);
} while (empty($options['shortname']));
} else {
if (empty($options['shortname'])) {
$a = (object)['option' => 'shortname', 'value' => $options['shortname']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for admin user name.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminusername', 'install'));
if (!empty($options['adminuser'])) {
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
} else {
if ((empty($options['adminuser']) || $options['adminuser'] === 'guest')) {
$a = (object)['option' => 'adminuser', 'value' => $options['adminuser']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for admin user password.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminpassword', 'install'));
$prompt = get_string('clitypevalue', 'admin');
do {
$options['adminpass'] = cli_input($prompt);
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
} else {
if ((empty($options['adminpass']) or $options['adminpass'] === 'admin')) {
$a = (object)['option' => 'adminpass', 'value' => $options['adminpass']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for the admin email address.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
$options['adminemail'] = cli_input($prompt, $options['adminemail']);
}
// Validate that the address provided was an e-mail address.
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
$a = (object)['option' => 'adminemail', 'value' => $options['adminemail']];
do {
$options['fullname'] = cli_input($prompt, $options['fullname']);
} while (empty($options['fullname']));
} else {
if (empty($options['fullname'])) {
$a = (object)array('option'=>'fullname', 'value'=>$options['fullname']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// ask for shortname
if ($interactive) {
cli_separator();
cli_heading(get_string('shortsitename', 'moodle'));
if ($options['shortname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['shortname'] = cli_input($prompt, $options['shortname']);
} while (empty($options['shortname']));
} else {
if (empty($options['shortname'])) {
$a = (object)array('option'=>'shortname', 'value'=>$options['shortname']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// ask for admin user name
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminusername', 'install'));
if (!empty($options['adminuser'])) {
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
} else {
if (empty($options['adminuser']) or $options['adminuser'] === 'guest') {
$a = (object)array('option'=>'adminuser', 'value'=>$options['adminuser']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// ask for admin user password
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminpassword', 'install'));
$prompt = get_string('clitypevalue', 'admin');
do {
$options['adminpass'] = cli_input($prompt);
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
} else {
if (empty($options['adminpass']) or $options['adminpass'] === 'admin') {
$a = (object)array('option'=>'adminpass', 'value'=>$options['adminpass']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for the admin email address.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
$options['adminemail'] = cli_input($prompt, $options['adminemail']);
}
// Validate that the address provided was an e-mail address.
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
$a = (object) array('option' => 'adminemail', 'value' => $options['adminemail']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
// Ask for the upgrade key.
if ($interactive) {
cli_separator();
@@ -751,27 +745,23 @@ if ($options['upgradekey'] !== '') {
$CFG->upgradekey = $options['upgradekey'];
}
// The user does not also need to pass agree-license when --skip-database is provided as the user will need to accept
// the license again in the database install part.
if (!$skipdatabase) {
if ($interactive) {
if (!$options['agree-license']) {
cli_separator();
cli_heading(get_string('copyrightnotice'));
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
echo get_string('gpl3')."\n\n";
echo get_string('doyouagree')."\n";
$prompt = get_string('cliyesnoprompt', 'admin');
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
if ($input == get_string('clianswerno', 'admin')) {
exit(1);
}
}
} else {
if (!$options['agree-license'] && !$skipdatabase) {
cli_error(get_string('climustagreelicense', 'install'));
if ($interactive) {
if (!$options['agree-license']) {
cli_separator();
cli_heading(get_string('copyrightnotice'));
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
echo get_string('gpl3')."\n\n";
echo get_string('doyouagree')."\n";
$prompt = get_string('cliyesnoprompt', 'admin');
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
if ($input == get_string('clianswerno', 'admin')) {
exit(1);
}
}
} else {
if (!$options['agree-license']) {
cli_error(get_string('climustagreelicense', 'install'));
}
}
// Finally we have all info needed for config.php
@@ -819,7 +809,7 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
cli_error(get_string('pluginschecktodo', 'admin'));
}
if (!$skipdatabase) {
if (!$options['skip-database']) {
install_cli_database($options, $interactive);
// This needs to happen at the end to ensure it occurs after all caches
// have been purged for the last time.
-151
View File
@@ -1,151 +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 task execution.
*
* @package core
* @subpackage cli
* @copyright 2014 Petr Skoda
* @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->libdir/cronlib.php");
list($options, $unrecognized) = cli_get_params(
array('help' => false, 'list' => false, 'execute' => false, 'showsql' => false, 'showdebugging' => false),
array('h' => 'help')
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help'] or (!$options['list'] and !$options['execute'])) {
$help =
"Scheduled cron tasks.
Options:
--execute=\\some\\task Execute scheduled task manually
--list List all scheduled tasks
--showsql Show sql queries before they are executed
--showdebugging Show developer level debugging information
-h, --help Print out this help
Example:
\$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
";
echo $help;
die;
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql']) {
$DB->set_debug(true);
}
if ($options['list']) {
cli_heading("List of scheduled tasks ($CFG->wwwroot)");
$shorttime = get_string('strftimedatetimeshort');
$tasks = \core\task\manager::get_all_scheduled_tasks();
echo str_pad(get_string('scheduledtasks', 'tool_task'), 50, ' ') . ' ' . str_pad(get_string('runpattern', 'tool_task'), 17, ' ')
. ' ' . str_pad(get_string('lastruntime', 'tool_task'), 40, ' ') . get_string('nextruntime', 'tool_task') . "\n";
foreach ($tasks as $task) {
$class = '\\' . get_class($task);
$schedule = $task->get_minute() . ' '
. $task->get_hour() . ' '
. $task->get_day() . ' '
. $task->get_day_of_week() . ' '
. $task->get_month() . ' '
. $task->get_day_of_week();
$nextrun = $task->get_next_run_time();
$lastrun = $task->get_last_run_time();
$plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
$plugindisabled = $plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled();
if ($plugindisabled) {
$nextrun = get_string('plugindisabled', 'tool_task');
} else if ($task->get_disabled()) {
$nextrun = get_string('taskdisabled', 'tool_task');
} else if ($nextrun > time()) {
$nextrun = userdate($nextrun);
} else {
$nextrun = get_string('asap', 'tool_task');
}
if ($lastrun) {
$lastrun = userdate($lastrun);
} else {
$lastrun = get_string('never');
}
echo str_pad($class, 50, ' ') . ' ' . str_pad($schedule, 17, ' ') .
' ' . str_pad($lastrun, 40, ' ') . ' ' . $nextrun . "\n";
}
exit(0);
}
if ($execute = $options['execute']) {
if (!$task = \core\task\manager::get_scheduled_task($execute)) {
mtrace("Task '$execute' not found");
exit(1);
}
if (moodle_needs_upgrading()) {
mtrace("Moodle upgrade pending, cannot execute tasks.");
exit(1);
}
// Increase memory limit.
raise_memory_limit(MEMORY_EXTRA);
// Emulate normal session - we use admin account by default.
cron_setup_user();
// Execute the task.
\core\local\cli\shutdown::script_supports_graceful_exit();
$cronlockfactory = \core\lock\lock_config::get_lock_factory('cron');
if (!$cronlock = $cronlockfactory->get_lock('core_cron', 10)) {
mtrace('Cannot obtain cron lock');
exit(129);
}
if (!$lock = $cronlockfactory->get_lock('\\' . get_class($task), 10)) {
$cronlock->release();
mtrace('Cannot obtain task lock');
exit(130);
}
$task->set_lock($lock);
if (!$task->is_blocking()) {
$cronlock->release();
} else {
$task->set_cron_lock($cronlock);
}
cron_run_inner_scheduled_task($task);
}
+2 -10
View File
@@ -34,7 +34,6 @@ $help = "Command line tool to uninstall plugins.
Options:
-h --help Print this help.
--show-all Displays a list of all installed plugins.
--show-contrib Displays a list of all third-party installed plugins.
--show-missing Displays a list of plugins missing from disk.
--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
@@ -45,9 +44,6 @@ Examples:
# php uninstall_plugins.php --show-all
Prints tab-separated list of all installed plugins.
# php uninstall_plugins.php --show-contrib
Prints tab-separated list of all third-party installed plugins.
# php uninstall_plugins.php --show-missing
Prints tab-separated list of all missing from disk plugins.
@@ -67,7 +63,6 @@ Examples:
list($options, $unrecognised) = cli_get_params([
'help' => false,
'show-all' => false,
'show-contrib' => false,
'show-missing' => false,
'purge-missing' => false,
'plugins' => false,
@@ -89,15 +84,12 @@ if ($options['help']) {
$pluginman = core_plugin_manager::instance();
$plugininfo = $pluginman->get_plugins();
if ($options['show-all'] || $options['show-missing'] || $options['show-contrib']) {
if ($options['show-all'] || $options['show-missing']) {
foreach ($plugininfo as $type => $plugins) {
foreach ($plugins as $name => $plugin) {
if ($options['show-contrib'] && $plugin->is_standard()) {
continue;
}
$pluginstring = $plugin->component . "\t" . $plugin->displayname;
if ($options['show-all'] || $options['show-contrib']) {
if ($options['show-all']) {
cli_writeln($pluginstring);
} else {
if ($plugin->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
+1 -1
View File
@@ -137,7 +137,7 @@ if (!$envstatus) {
// Test plugin dependencies.
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
cli_error(get_string('pluginschecktodo', 'admin'));
}
-84
View File
@@ -1,84 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Content bank and its plugins settings.
*
* @package core
* @subpackage contentbank
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
$action = required_param('action', PARAM_ALPHANUMEXT);
$name = required_param('name', PARAM_PLUGIN);
$syscontext = context_system::instance();
$PAGE->set_url('/admin/contentbank.php');
$PAGE->set_context($syscontext);
require_admin();
require_sesskey();
$return = new moodle_url('/admin/settings.php', array('section' => 'managecontentbanktypes'));
$plugins = core_plugin_manager::instance()->get_plugins_of_type('contenttype');
$sortorder = array_flip(array_keys($plugins));
if (!isset($plugins[$name])) {
print_error('contenttypenotfound', 'error', $return, $name);
}
switch ($action) {
case 'disable':
if ($plugins[$name]->is_enabled()) {
set_config('disabled', 1, 'contentbank_'. $name);
}
break;
case 'enable':
if (!$plugins[$name]->is_enabled()) {
unset_config('disabled', 'contentbank_'. $name);
}
break;
case 'up':
if ($sortorder[$name]) {
$currentindex = $sortorder[$name];
$seq = array_keys($plugins);
$seq[$currentindex] = $seq[$currentindex - 1];
$seq[$currentindex - 1] = $name;
set_config('contentbank_plugins_sortorder', implode(',', $seq));
}
break;
case 'down':
if ($sortorder[$name] < count($sortorder) - 1) {
$currentindex = $sortorder[$name];
$seq = array_keys($plugins);
$seq[$currentindex] = $seq[$currentindex + 1];
$seq[$currentindex + 1] = $name;
set_config('contentbank_plugins_sortorder', implode(',', $seq));
}
break;
}
core_plugin_manager::reset_caches();
$cache = cache::make('core', 'contentbank_enabled_extensions');
$cache->purge();
$cache = cache::make('core', 'contentbank_context_extensions');
$cache->purge();
redirect($return);
-366
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>
@@ -3165,368 +3163,4 @@
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="3.10" requires="3.5">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.2.29" />
<VENDOR name="mysql" version="5.7" />
<VENDOR name="postgres" version="9.6" />
<VENDOR name="mssql" version="11.0" />
<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>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlrpc" level="optional">
<FEEDBACK>
<ON_CHECK message="xmlrpcrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="required">
<FEEDBACK>
<ON_ERROR message="intlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
<FEEDBACK>
<ON_CHECK message="sixtyfourbitswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
<MOODLE version="3.11" requires="3.6">
<UNICODE level="required">
<FEEDBACK>
<ON_ERROR message="unicoderequired" />
</FEEDBACK>
</UNICODE>
<DATABASE level="required">
<VENDOR name="mariadb" version="10.2.29" />
<VENDOR name="mysql" version="5.7" />
<VENDOR name="postgres" version="9.6" />
<VENDOR name="mssql" version="14.0" />
<VENDOR name="oracle" version="11.2" />
</DATABASE>
<PHP version="7.3.0" level="required">
</PHP>
<PCREUNICODE level="optional">
<FEEDBACK>
<ON_CHECK message="pcreunicodewarning" />
</FEEDBACK>
</PCREUNICODE>
<PHP_EXTENSIONS>
<PHP_EXTENSION name="iconv" level="required">
<FEEDBACK>
<ON_ERROR message="iconvrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="mbstring" level="required">
<FEEDBACK>
<ON_ERROR message="mbstringrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="curl" level="required">
<FEEDBACK>
<ON_ERROR message="curlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="openssl" level="required">
<FEEDBACK>
<ON_ERROR message="opensslrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="tokenizer" level="optional">
<FEEDBACK>
<ON_CHECK message="tokenizerrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlrpc" level="optional">
<FEEDBACK>
<ON_CHECK message="xmlrpcrecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="soap" level="optional">
<FEEDBACK>
<ON_CHECK message="soaprecommended" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="ctype" level="required">
<FEEDBACK>
<ON_ERROR message="ctyperequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zip" level="required">
<FEEDBACK>
<ON_ERROR message="ziprequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="zlib" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="gd" level="required">
<FEEDBACK>
<ON_ERROR message="gdrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="simplexml" level="required">
<FEEDBACK>
<ON_ERROR message="simplexmlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="spl" level="required">
<FEEDBACK>
<ON_ERROR message="splrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="pcre" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="dom" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xml" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="xmlreader" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="intl" level="required">
<FEEDBACK>
<ON_ERROR message="intlrequired" />
</FEEDBACK>
</PHP_EXTENSION>
<PHP_EXTENSION name="json" level="required">
</PHP_EXTENSION>
<PHP_EXTENSION name="hash" level="required"/>
<PHP_EXTENSION name="fileinfo" level="required"/>
<PHP_EXTENSION name="sodium" level="required"/>
</PHP_EXTENSIONS>
<PHP_SETTINGS>
<PHP_SETTING name="memory_limit" value="96M" level="required">
<FEEDBACK>
<ON_ERROR message="settingmemorylimit" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="file_uploads" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="settingfileuploads" />
</FEEDBACK>
</PHP_SETTING>
<PHP_SETTING name="opcache.enable" value="1" level="optional">
<FEEDBACK>
<ON_CHECK message="opcacherecommended" />
</FEEDBACK>
</PHP_SETTING>
</PHP_SETTINGS>
<CUSTOM_CHECKS>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbstorageengine" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
<FEEDBACK>
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
<FEEDBACK>
<ON_CHECK message="unoconvwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
<FEEDBACK>
<ON_CHECK message="libcurlwarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfileformat" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddbfilepertable" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
<FEEDBACK>
<ON_ERROR message="unsupporteddblargeprefix" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
<FEEDBACK>
<ON_CHECK message="ishttpswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
<FEEDBACK>
<ON_CHECK message="incompleteunicodesupport" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_sixtyfour_bits" level="optional">
<FEEDBACK>
<ON_CHECK message="sixtyfourbitswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
</CUSTOM_CHECKS>
</MOODLE>
</COMPATIBILITY_MATRIX>
+16 -43
View File
@@ -226,7 +226,7 @@ if (!core_tables_exist()) {
}
if (empty($confirmrelease)) {
require_once($CFG->libdir.'/environmentlib.php');
list($envstatus, $environmentresults) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
$strcurrentrelease = get_string('currentrelease');
$PAGE->navbar->add($strcurrentrelease);
@@ -235,13 +235,13 @@ if (!core_tables_exist()) {
$PAGE->set_cacheable(false);
$output = $PAGE->get_renderer('core', 'admin');
echo $output->install_environment_page($maturity, $envstatus, $environmentresults, $release);
echo $output->install_environment_page($maturity, $envstatus, $environment_results, $release);
die();
}
// check plugin dependencies
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
$PAGE->navbar->add(get_string('pluginscheck', 'admin'));
$PAGE->set_title($strinstallation);
$PAGE->set_heading($strinstallation . ' - Moodle ' . $CFG->target_release);
@@ -358,9 +358,9 @@ if (!$cache and $version > $CFG->version) { // upgrade
echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite);
die();
} else if (empty($confirmrelease)) {
} else if (empty($confirmrelease)){
require_once($CFG->libdir.'/environmentlib.php');
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
list($envstatus, $environment_results) = check_moodle_environment($release, ENV_SELECT_RELEASE);
$strcurrentrelease = get_string('currentrelease');
$PAGE->navbar->add($strcurrentrelease);
@@ -368,7 +368,7 @@ if (!$cache and $version > $CFG->version) { // upgrade
$PAGE->set_heading($strcurrentrelease);
$PAGE->set_cacheable(false);
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
echo $output->upgrade_environment_page($release, $envstatus, $environment_results);
die();
} else if (empty($confirmplugins)) {
@@ -508,9 +508,8 @@ if (!$cache and $version > $CFG->version) { // upgrade
} else {
// Always verify plugin dependencies!
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
array('confirmplugincheck' => 0)));
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
die();
}
unset($failed);
@@ -534,10 +533,7 @@ if (!$cache and $branch <> $CFG->branch) { // Update the branch
if (!$cache and moodle_needs_upgrading()) {
$PAGE->set_url(new moodle_url($PAGE->url, array(
'confirmrelease' => $confirmrelease,
'confirmplugincheck' => $confirmplugins,
)));
$PAGE->set_url(new moodle_url($PAGE->url, array('confirmplugincheck' => $confirmplugins)));
check_upgrade_key($upgradekeyhash);
@@ -547,21 +543,7 @@ if (!$cache and moodle_needs_upgrading()) {
$pluginman = core_plugin_manager::instance();
$output = $PAGE->get_renderer('core', 'admin');
if (empty($confirmrelease)) {
require_once($CFG->libdir . '/environmentlib.php');
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
$strcurrentrelease = get_string('currentrelease');
$PAGE->navbar->add($strcurrentrelease);
$PAGE->set_title($strcurrentrelease);
$PAGE->set_heading($strcurrentrelease);
$PAGE->set_cacheable(false);
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
die();
} else if (!$confirmplugins) {
if (!$confirmplugins) {
$strplugincheck = get_string('plugincheck');
$PAGE->navbar->add($strplugincheck);
@@ -700,10 +682,9 @@ if (!$cache and moodle_needs_upgrading()) {
// Make sure plugin dependencies are always checked.
$failed = array();
if (!$pluginman->all_plugins_ok($version, $failed, $CFG->branch)) {
if (!$pluginman->all_plugins_ok($version, $failed)) {
$output = $PAGE->get_renderer('core', 'admin');
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
array('confirmplugincheck' => 0)));
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
die();
}
unset($failed);
@@ -821,7 +802,7 @@ $SESSION->admin_critical_warning = ($insecuredataroot==INSECURE_DATAROOT_ERROR);
$adminroot = admin_get_root();
// Check if there are any new admin settings which have still yet to be set
if (any_new_admin_settings($adminroot)) {
if (any_new_admin_settings($adminroot)){
redirect('upgradesettings.php');
}
@@ -845,9 +826,8 @@ $errorsdisplayed = defined('WARN_DISPLAY_ERRORS_ENABLED');
$lastcron = get_config('tool_task', 'lastcronstart');
$cronoverdue = ($lastcron < time() - 3600 * 24);
$lastcroninterval = get_config('tool_task', 'lastcroninterval');
$expectedfrequency = $CFG->expectedcronfrequency ?? MINSECS;
$croninfrequent = !$cronoverdue && ($lastcroninterval > ($expectedfrequency + MINSECS) || $lastcron < time() - $expectedfrequency);
$expectedfrequency = $CFG->expectedcronfrequency ?? 200;
$croninfrequent = !$cronoverdue && ($lastcroninterval > $expectedfrequency || $lastcron < time() - $expectedfrequency);
$dbproblems = $DB->diagnose();
$maintenancemode = !empty($CFG->maintenance_enabled);
@@ -901,12 +881,6 @@ if (empty($CFG->disabledevlibdirscheck) && (is_dir($CFG->dirroot.'/vendor') || i
// Check if the site is being foced onto ssl.
$overridetossl = !empty($CFG->overridetossl);
// Check if moodle campaign content setting is enabled or not.
$showcampaigncontent = !isset($CFG->showcampaigncontent) || $CFG->showcampaigncontent;
// Encourage admins to enable the user feedback feature if it is not enabled already.
$showfeedbackencouragement = empty($CFG->enableuserfeedback);
admin_externalpage_setup('adminnotifications');
$output = $PAGE->get_renderer('core', 'admin');
@@ -914,5 +888,4 @@ $output = $PAGE->get_renderer('core', 'admin');
echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed, $cronoverdue, $dbproblems,
$maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
$registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir,
$mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent,
$showcampaigncontent, $showfeedbackencouragement);
$mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent);
@@ -1,4 +1,5 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@@ -15,32 +16,41 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* License manager page.
*
* @package tool_licensemanager
* @copyright 2019 Tom Dickman <tomdickman@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* Allows admin to configure licenses.
*/
require_once('../../../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/licenselib.php');
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/licenselib.php');
require_admin();
$returnurl = \tool_licensemanager\helper::get_licensemanager_url();
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=managelicenses";
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
$license = optional_param('license', '', PARAM_SAFEDIR);
////////////////////////////////////////////////////////////////////////////////
// process actions
if (!confirm_sesskey()) {
redirect($returnurl);
}
// Route via the manager.
$licensemanager = new \tool_licensemanager\manager();
$PAGE->set_context(context_system::instance());
$PAGE->set_url(\tool_licensemanager\helper::get_licensemanager_url());
$PAGE->set_title(get_string('licensemanager', 'tool_licensemanager'));
$return = true;
switch ($action) {
case 'disable':
license_manager::disable($license);
break;
$licensemanager->execute($action, $license);
case 'enable':
license_manager::enable($license);
break;
default:
break;
}
if ($return) {
redirect ($returnurl);
}
+1 -1
View File
@@ -83,7 +83,7 @@ if (($form = data_submitted()) && confirm_sesskey()) {
}
} else {
$newsettings = array();
if (property_exists($form, $componentprovidersetting)) {
if (array_key_exists($componentprovidersetting, $form)) {
// We must be processing loggedin or loggedoff checkboxes.
// Store defained comma-separated processors as setting value.
// Using array_filter eliminates elements set to 0 above.
+1 -1
View File
@@ -156,7 +156,7 @@ class mnet_review_host_form extends moodleform {
if ($mnet_peer && !empty($mnet_peer->deleted)) {
$radioarray = array();
$radioarray[] = $mform->createElement('static', 'deletedinfo', '',
$OUTPUT->container(get_string('deletedhostinfo', 'mnet'), 'alert alert-warning'));
$OUTPUT->container(get_string('deletedhostinfo', 'mnet'), 'deletedhostinfo'));
$radioarray[] = $mform->createElement('radio', 'deleted', '', get_string('yes'), 1);
$radioarray[] = $mform->createElement('radio', 'deleted', '', get_string('no'), 0);
$mform->addGroup($radioarray, 'radioar', get_string('deleted'), array(' ', ' '), false);
+2 -4
View File
@@ -49,7 +49,6 @@
array($module->id));
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
redirect(new moodle_url('/admin/modules.php'));
}
if (!empty($show) and confirm_sesskey()) {
@@ -67,7 +66,6 @@
array($module->id));
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
redirect(new moodle_url('/admin/modules.php'));
}
echo $OUTPUT->header();
@@ -123,8 +121,8 @@
$count = -1;
}
if ($count>0) {
$countlink = $OUTPUT->action_link(new moodle_url('/course/search.php', ['modulelist' => $module->name]),
$count, null, ['title' => $strshowmodulecourse]);
$countlink = "<a href=\"{$CFG->wwwroot}/course/search.php?modulelist=$module->name" .
"&amp;sesskey=".sesskey()."\" title=\"$strshowmodulecourse\">$count</a>";
} else if ($count < 0) {
$countlink = get_string('error');
} else {
+1 -1
View File
@@ -53,6 +53,7 @@ $pageurl = new moodle_url('/admin/plugins.php', $pageparams);
$pluginman = core_plugin_manager::instance();
if ($uninstall) {
require_sesskey();
if (!$confirmed) {
admin_externalpage_setup('pluginsoverview', '', $pageparams);
@@ -91,7 +92,6 @@ if ($uninstall) {
exit();
} else {
require_sesskey();
$SESSION->pluginuninstallreturn = $pluginfo->get_return_url_after_uninstall($return);
$progress = new progress_trace_buffer(new text_progress_trace(), false);
$pluginman->uninstall_plugin($pluginfo->component, $progress);
+1 -1
View File
@@ -170,7 +170,7 @@ foreach ($sortedbehaviours as $behaviour => $behaviourname) {
if ($version) {
$row[] = $version;
} else {
$row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'text-muted'));
$row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'disabled'));
}
// Other question types required by this one.
+1 -1
View File
@@ -172,7 +172,7 @@ foreach ($sortedqtypes as $qtypename => $localname) {
if ($version) {
$row[] = $version;
} else {
$row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'text-muted'));
$row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'disabled'));
}
// Other question types required by this one.
+1 -1
View File
@@ -45,7 +45,7 @@ $error = optional_param('error', '', PARAM_ALPHANUM);
admin_externalpage_setup('registrationmoodleorg');
if (parse_url($url, PHP_URL_HOST) !== parse_url(HUB_MOODLEORGHUBURL, PHP_URL_HOST)) {
if ($url !== HUB_MOODLEORGHUBURL) {
// Allow other plugins to confirm registration on custom hubs. Plugins implementing this
// callback need to redirect or exit. See https://docs.moodle.org/en/Hub_registration .
$callbacks = get_plugins_with_function('hub_registration');
+1 -1
View File
@@ -39,7 +39,7 @@ $token = optional_param('token', '', PARAM_TEXT);
admin_externalpage_setup('registrationmoodleorg');
if (parse_url($url, PHP_URL_HOST) !== parse_url(HUB_MOODLEORGHUBURL, PHP_URL_HOST)) {
if ($url !== HUB_MOODLEORGHUBURL) {
// Allow other plugins to renew registration on custom hubs. Plugins implementing this
// callback need to redirect or exit. See https://docs.moodle.org/en/Hub_registration .
$callbacks = get_plugins_with_function('hub_registration');
+79 -141
View File
@@ -253,7 +253,7 @@ class core_admin_renderer extends plugin_renderer_base {
$out .= $this->output->container(get_string('cancelinstallinfodir', 'core_plugin', $pluginfo->rootdir));
if ($repotype = $pluginman->plugin_external_source($pluginfo->component)) {
$out .= $this->output->container(get_string('uninstalldeleteconfirmexternal', 'core_plugin', $repotype),
'alert alert-warning mt-2');
'uninstalldeleteconfirmexternal');
}
}
@@ -282,8 +282,6 @@ class core_admin_renderer extends plugin_renderer_base {
* @param bool $overridetossl Whether or not ssl is being forced.
* @param bool $invalidforgottenpasswordurl Whether the forgotten password URL does not link to a valid URL.
* @param bool $croninfrequent If true, warn that cron hasn't run in the past few minutes
* @param bool $showcampaigncontent Whether the campaign content should be visible or not.
* @param bool $showfeedbackencouragement Whether the feedback encouragement content should be displayed or not.
*
* @return string HTML to output.
*/
@@ -291,9 +289,7 @@ class core_admin_renderer extends plugin_renderer_base {
$cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch,
$buggyiconvnomb, $registered, array $cachewarnings = array(), $eventshandlers = 0,
$themedesignermode = false, $devlibdir = false, $mobileconfigured = false,
$overridetossl = false, $invalidforgottenpasswordurl = false, $croninfrequent = false,
$showcampaigncontent = false, bool $showfeedbackencouragement = false) {
$overridetossl = false, $invalidforgottenpasswordurl = false, $croninfrequent = false) {
global $CFG;
$output = '';
@@ -316,8 +312,6 @@ class core_admin_renderer extends plugin_renderer_base {
$output .= $this->registration_warning($registered);
$output .= $this->mobile_configuration_warning($mobileconfigured);
$output .= $this->forgotten_password_url_warning($invalidforgottenpasswordurl);
$output .= $this->userfeedback_encouragement($showfeedbackencouragement);
$output .= $this->campaign_content($showcampaigncontent);
//////////////////////////////////////////////////////////////////////////////////////////////////
//// IT IS ILLEGAL AND A VIOLATION OF THE GPL TO HIDE, REMOVE OR MODIFY THIS COPYRIGHT NOTICE ///
@@ -367,15 +361,14 @@ class core_admin_renderer extends plugin_renderer_base {
$output = '';
if ($checker->enabled()) {
$output .= $this->container_start('checkforupdates mb-4');
$output .= $this->container_start('checkforupdates');
$output .= $this->single_button(
new moodle_url($reloadurl, array('fetchupdates' => 1)),
get_string('checkforupdates', 'core_plugin')
);
if ($timefetched = $checker->get_last_timefetched()) {
$timefetched = userdate($timefetched, get_string('strftimedatetime', 'core_langconfig'));
$output .= $this->container(get_string('checkforupdateslast', 'core_plugin', $timefetched),
'lasttimefetched small text-muted mt-1');
$output .= $this->container(get_string('checkforupdateslast', 'core_plugin', $timefetched), 'lasttimefetched');
}
$output .= $this->container_end();
}
@@ -439,7 +432,7 @@ class core_admin_renderer extends plugin_renderer_base {
if ($repotype = $pluginman->plugin_external_source($pluginfo->component)) {
$confirm .= $this->output->container(get_string('uninstalldeleteconfirmexternal', 'core_plugin', $repotype),
'alert alert-warning mt-2');
'uninstalldeleteconfirmexternal');
}
// After any uninstall we must execute full upgrade to finish the cleanup!
@@ -518,7 +511,7 @@ class core_admin_renderer extends plugin_renderer_base {
* @return string HTML to output.
*/
protected function warning($message, $type = 'warning') {
return $this->box($message, 'generalbox alert alert-' . $type);
return $this->box($message, 'generalbox admin' . $type);
}
/**
@@ -533,7 +526,7 @@ class core_admin_renderer extends plugin_renderer_base {
return $this->warning(get_string('datarootsecuritywarning', 'admin', $CFG->dataroot));
} else if ($insecuredataroot == INSECURE_DATAROOT_ERROR) {
return $this->warning(get_string('datarootsecurityerror', 'admin', $CFG->dataroot), 'danger');
return $this->warning(get_string('datarootsecurityerror', 'admin', $CFG->dataroot), 'error');
} else {
return '';
@@ -551,7 +544,7 @@ class core_admin_renderer extends plugin_renderer_base {
if ($devlibdir) {
$moreinfo = new moodle_url('/report/security/index.php');
$warning = get_string('devlibdirpresent', 'core_admin', ['moreinfourl' => $moreinfo->out()]);
return $this->warning($warning, 'danger');
return $this->warning($warning, 'error');
} else {
return '';
@@ -608,9 +601,19 @@ class core_admin_renderer extends plugin_renderer_base {
return '';
}
$check = new \tool_task\check\cronrunning();
$result = $check->get_result();
return $this->warning($result->get_summary() . '&nbsp;' . $this->help_icon('cron', 'admin'));
if (empty($CFG->cronclionly)) {
$url = new moodle_url('/admin/cron.php');
if (!empty($CFG->cronremotepassword)) {
$url = new moodle_url('/admin/cron.php', array('password' => $CFG->cronremotepassword));
}
return $this->warning(get_string('cronwarning', 'admin', $url->out()) . '&nbsp;' .
$this->help_icon('cron', 'admin'));
}
// $CFG->cronclionly is not empty: cron can run only from CLI.
return $this->warning(get_string('cronwarningcli', 'admin') . '&nbsp;' .
$this->help_icon('cron', 'admin'));
}
/**
@@ -626,9 +629,9 @@ class core_admin_renderer extends plugin_renderer_base {
return '';
}
$check = new \tool_task\check\cronrunning();
$result = $check->get_result();
return $this->warning($result->get_summary() . '&nbsp;' . $this->help_icon('cron', 'admin'));
$expectedfrequency = $CFG->expectedcronfrequency ?? 200;
return $this->warning(get_string('croninfrequent', 'admin', $expectedfrequency) . '&nbsp;' .
$this->help_icon('cron', 'admin'));
}
/**
@@ -718,7 +721,7 @@ class core_admin_renderer extends plugin_renderer_base {
return $this->warning(
$this->container(get_string('maturitycorewarning', 'admin', $maturitylevel)) .
$this->container($this->doc_link('admin/versions', get_string('morehelp'))),
'danger');
'error');
}
/*
@@ -734,7 +737,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
$warning = (get_string('testsiteupgradewarning', 'admin', $testsite));
return $this->warning($warning, 'danger');
return $this->warning($warning, 'error');
}
/**
@@ -769,7 +772,7 @@ class core_admin_renderer extends plugin_renderer_base {
$level = 'warning';
if ($maturity == MATURITY_ALPHA) {
$level = 'danger';
$level = 'error';
}
$maturitylevel = get_string('maturity' . $maturity, 'admin');
@@ -820,7 +823,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
}
$updateinfo .= $this->container_start('checkforupdates mt-1');
$updateinfo .= $this->container_start('checkforupdates');
$fetchurl = new moodle_url('/admin/index.php', array('fetchupdates' => 1, 'sesskey' => sesskey(), 'cache' => 0));
$updateinfo .= $this->single_button($fetchurl, get_string('checkforupdates', 'core_plugin'));
if ($fetch) {
@@ -884,20 +887,6 @@ class core_admin_renderer extends plugin_renderer_base {
return $output;
}
/**
* Display campaign content.
*
* @param bool $showcampaigncontent Whether the campaign content should be visible or not.
* @return string the campaign content raw html.
*/
protected function campaign_content(bool $showcampaigncontent): string {
if (!$showcampaigncontent) {
return '';
}
return $this->render_from_template('core/campaign_content', ['lang' => current_language()]);
}
/**
* Display a warning about the forgotten password URL not linking to a valid URL.
*
@@ -923,7 +912,7 @@ class core_admin_renderer extends plugin_renderer_base {
*/
protected function moodle_available_update_info(\core\update\info $updateinfo) {
$boxclasses = 'moodleupdateinfo mb-2';
$boxclasses = 'moodleupdateinfo';
$info = array();
if (isset($updateinfo->release)) {
@@ -943,8 +932,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
if (isset($updateinfo->download)) {
$info[] = html_writer::link($updateinfo->download, get_string('download'),
array('class' => 'info download btn btn-secondary'));
$info[] = html_writer::link($updateinfo->download, get_string('download'), array('class' => 'info download'));
}
if (isset($updateinfo->url)) {
@@ -952,9 +940,9 @@ class core_admin_renderer extends plugin_renderer_base {
array('class' => 'info more'));
}
$box = $this->output->container_start($boxclasses);
$box .= $this->output->container(implode(html_writer::tag('span', ' | ', array('class' => 'separator')), $info), '');
$box .= $this->output->container_end();
$box = $this->output->box_start($boxclasses);
$box .= $this->output->box(implode(html_writer::tag('span', ' ', array('class' => 'separator')), $info), '');
$box .= $this->output->box_end();
return $box;
}
@@ -966,7 +954,7 @@ class core_admin_renderer extends plugin_renderer_base {
protected function release_notes_link() {
$releasenoteslink = get_string('releasenoteslink', 'admin', 'http://docs.moodle.org/dev/Releases');
$releasenoteslink = str_replace('target="_blank"', 'onclick="this.target=\'_blank\'"', $releasenoteslink); // extremely ugly validation hack
return $this->box($releasenoteslink, 'generalbox alert alert-info');
return $this->box($releasenoteslink, 'generalbox releasenoteslink');
}
/**
@@ -995,7 +983,7 @@ class core_admin_renderer extends plugin_renderer_base {
* @return string HTML code
*/
public function plugins_check_table(core_plugin_manager $pluginman, $version, array $options = array()) {
global $CFG;
$plugininfo = $pluginman->get_plugins();
if (empty($plugininfo)) {
@@ -1066,7 +1054,7 @@ class core_admin_renderer extends plugin_renderer_base {
$displayname = new html_table_cell(
$icon.
html_writer::span($plugin->displayname, 'pluginname').
html_writer::div($plugin->get_dir(), 'plugindir text-muted small')
html_writer::div($plugin->get_dir(), 'plugindir')
);
$versiondb = new html_table_cell($plugin->versiondb);
@@ -1081,10 +1069,8 @@ class core_admin_renderer extends plugin_renderer_base {
}
$coredependency = $plugin->is_core_dependency_satisfied($version);
$incompatibledependency = $plugin->is_core_compatible_satisfied($CFG->branch);
$otherpluginsdependencies = $pluginman->are_dependencies_satisfied($plugin->get_other_required_plugins());
$dependenciesok = $coredependency && $otherpluginsdependencies && $incompatibledependency;
$dependenciesok = $coredependency && $otherpluginsdependencies;
$statuscode = $plugin->get_status();
$row->attributes['class'] .= ' status-' . $statuscode;
@@ -1103,17 +1089,17 @@ class core_admin_renderer extends plugin_renderer_base {
break;
case core_plugin_manager::PLUGIN_STATUS_NODB:
case core_plugin_manager::PLUGIN_STATUS_UPTODATE:
$statusclass .= $dependenciesok ? 'badge-light' : 'badge-warning';
$statusclass .= $dependenciesok ? '' : 'badge-warning';
break;
}
$status = html_writer::span(get_string('status_' . $statuscode, 'core_plugin'), $statusclass);
if (!empty($installabortable[$plugin->component])) {
$status .= $this->output->single_button(
new moodle_url($this->page->url, array('abortinstall' => $plugin->component, 'confirmplugincheck' => 0)),
new moodle_url($this->page->url, array('abortinstall' => $plugin->component)),
get_string('cancelinstallone', 'core_plugin'),
'post',
array('class' => 'actionbutton cancelinstallone d-block mt-1')
array('class' => 'actionbutton cancelinstallone')
);
}
@@ -1122,7 +1108,7 @@ class core_admin_renderer extends plugin_renderer_base {
new moodle_url($this->page->url, array('abortupgrade' => $plugin->component)),
get_string('cancelupgradeone', 'core_plugin'),
'post',
array('class' => 'actionbutton cancelupgradeone d-block mt-1')
array('class' => 'actionbutton cancelupgradeone')
);
}
@@ -1134,11 +1120,8 @@ class core_admin_renderer extends plugin_renderer_base {
}
$status = new html_table_cell($sourcelabel.' '.$status);
if ($plugin->pluginsupported != null) {
$requires = new html_table_cell($this->required_column($plugin, $pluginman, $version, $CFG->branch));
} else {
$requires = new html_table_cell($this->required_column($plugin, $pluginman, $version));
}
$requires = new html_table_cell($this->required_column($plugin, $pluginman, $version));
$statusisboring = in_array($statuscode, array(
core_plugin_manager::PLUGIN_STATUS_NODB, core_plugin_manager::PLUGIN_STATUS_UPTODATE));
@@ -1195,7 +1178,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
}
$out .= $this->output->container_start('actions mb-2');
$out .= $this->output->container_start('actions');
$installableupdates = $pluginman->filter_installable($pluginman->available_updates());
if ($installableupdates) {
@@ -1203,16 +1186,16 @@ class core_admin_renderer extends plugin_renderer_base {
new moodle_url($this->page->url, array('installupdatex' => 1)),
get_string('updateavailableinstallall', 'core_admin', count($installableupdates)),
'post',
array('class' => 'singlebutton updateavailableinstallall mr-1')
array('class' => 'singlebutton updateavailableinstallall')
);
}
if ($installabortable) {
$out .= $this->output->single_button(
new moodle_url($this->page->url, array('abortinstallx' => 1, 'confirmplugincheck' => 0)),
new moodle_url($this->page->url, array('abortinstallx' => 1)),
get_string('cancelinstallall', 'core_plugin', count($installabortable)),
'post',
array('class' => 'singlebutton cancelinstallall mr-1')
array('class' => 'singlebutton cancelinstallall')
);
}
@@ -1221,17 +1204,15 @@ class core_admin_renderer extends plugin_renderer_base {
new moodle_url($this->page->url, array('abortupgradex' => 1)),
get_string('cancelupgradeall', 'core_plugin', count($upgradeabortable)),
'post',
array('class' => 'singlebutton cancelupgradeall mr-1')
array('class' => 'singlebutton cancelupgradeall')
);
}
$out .= html_writer::div(html_writer::link(new moodle_url($this->page->url, array('showallplugins' => 0)),
get_string('plugincheckattention', 'core_plugin')).' '.html_writer::span($sumattention, 'badge badge-light'),
'btn btn-link mr-1');
get_string('plugincheckattention', 'core_plugin')).' '.html_writer::span($sumattention, 'badge'));
$out .= html_writer::div(html_writer::link(new moodle_url($this->page->url, array('showallplugins' => 1)),
get_string('plugincheckall', 'core_plugin')).' '.html_writer::span($sumtotal, 'badge badge-light'),
'btn btn-link mr-1');
get_string('plugincheckall', 'core_plugin')).' '.html_writer::span($sumtotal, 'badge'));
$out .= $this->output->container_end(); // End of .actions container.
$out .= $this->output->container_end(); // End of #plugins-check-info container.
@@ -1299,13 +1280,12 @@ class core_admin_renderer extends plugin_renderer_base {
}
}
$out = $this->output->container_start('plugins-check-dependencies mb-4');
$out = $this->output->container_start('plugins-check-dependencies');
if ($unavailable or $unknown) {
$out .= $this->output->heading(get_string('misdepsunavail', 'core_plugin'));
if ($unknown) {
$out .= $this->output->render((new \core\output\notification(get_string('misdepsunknownlist', 'core_plugin',
implode(', ', $unknown))))->set_show_closebutton(false));
$out .= $this->output->notification(get_string('misdepsunknownlist', 'core_plugin', implode($unknown, ', ')));
}
if ($unavailable) {
$unavailablelist = array();
@@ -1319,18 +1299,18 @@ class core_admin_renderer extends plugin_renderer_base {
}
$unavailablelist[] = $unavailablelistitem;
}
$out .= $this->output->render((new \core\output\notification(get_string('misdepsunavaillist', 'core_plugin',
implode(', ', $unavailablelist))))->set_show_closebutton(false));
$out .= $this->output->notification(get_string('misdepsunavaillist', 'core_plugin',
implode($unavailablelist, ', ')));
}
$out .= $this->output->container_start('plugins-check-dependencies-actions mb-4');
$out .= $this->output->container_start('plugins-check-dependencies-actions');
$out .= ' '.html_writer::link(new moodle_url('/admin/tool/installaddon/'),
get_string('dependencyuploadmissing', 'core_plugin'), array('class' => 'btn btn-secondary'));
get_string('dependencyuploadmissing', 'core_plugin'));
$out .= $this->output->container_end(); // End of .plugins-check-dependencies-actions container.
}
if ($available) {
$out .= $this->output->heading(get_string('misdepsavail', 'core_plugin'));
$out .= $this->output->container_start('plugins-check-dependencies-actions mb-2');
$out .= $this->output->container_start('plugins-check-dependencies-actions');
$installable = $pluginman->filter_installable($available);
if ($installable) {
@@ -1338,13 +1318,12 @@ class core_admin_renderer extends plugin_renderer_base {
new moodle_url($this->page->url, array('installdepx' => 1)),
get_string('dependencyinstallmissing', 'core_plugin', count($installable)),
'post',
array('class' => 'singlebutton dependencyinstallmissing d-inline-block mr-1')
array('class' => 'singlebutton dependencyinstallmissing')
);
}
$out .= html_writer::div(html_writer::link(new moodle_url('/admin/tool/installaddon/'),
get_string('dependencyuploadmissing', 'core_plugin'), array('class' => 'btn btn-link')),
'dependencyuploadmissing d-inline-block mr-1');
get_string('dependencyuploadmissing', 'core_plugin')), 'dependencyuploadmissing');
$out .= $this->output->container_end(); // End of .plugins-check-dependencies-actions container.
@@ -1385,7 +1364,7 @@ class core_admin_renderer extends plugin_renderer_base {
if ($CFG->branch == str_replace('.', '', $moodle->release)) {
$supportedmoodles[] = html_writer::span($moodle->release, 'badge badge-success');
} else {
$supportedmoodles[] = html_writer::span($moodle->release, 'badge badge-light');
$supportedmoodles[] = html_writer::span($moodle->release, 'label');
}
}
@@ -1399,7 +1378,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
$info = html_writer::div(
get_string('requiredby', 'core_plugin', implode(', ', $requriedby)),
'requiredby mb-1'
'requiredby'
);
} else {
$info = '';
@@ -1410,39 +1389,38 @@ class core_admin_renderer extends plugin_renderer_base {
$info .= html_writer::div(
html_writer::link('https://moodle.org/plugins/view.php?plugin='.$plugin->component,
get_string('misdepinfoplugin', 'core_plugin')),
'misdepinfoplugin d-inline-block mr-3 mb-1'
'misdepinfoplugin'
);
$info .= html_writer::div(
html_writer::link('https://moodle.org/plugins/pluginversion.php?id='.$plugin->version->id,
get_string('misdepinfoversion', 'core_plugin')),
'misdepinfoversion d-inline-block mr-3 mb-1'
'misdepinfoversion'
);
$info .= html_writer::div(html_writer::link($plugin->version->downloadurl, get_string('download')),
'misdepdownload d-inline-block mr-3 mb-1');
$info .= html_writer::div(html_writer::link($plugin->version->downloadurl, get_string('download')), 'misdepdownload');
if ($pluginman->is_remote_plugin_installable($plugin->component, $plugin->version->version, $reason)) {
$info .= $this->output->single_button(
new moodle_url($this->page->url, array('installdep' => $plugin->component)),
get_string('dependencyinstall', 'core_plugin'),
'post',
array('class' => 'singlebutton dependencyinstall mr-3 mb-1')
array('class' => 'singlebutton dependencyinstall')
);
} else {
$reasonhelp = $this->info_remote_plugin_not_installable($reason);
if ($reasonhelp) {
$info .= html_writer::div($reasonhelp, 'reasonhelp dependencyinstall d-inline-block mr-3 mb-1');
$info .= html_writer::div($reasonhelp, 'reasonhelp dependencyinstall');
}
}
$info .= $this->output->container_end(); // End of .actions container.
$table->data[] = array(
html_writer::div($plugin->name, 'name').' '.html_writer::div($plugin->component, 'component text-muted small'),
html_writer::div($plugin->name, 'name').' '.html_writer::div($plugin->component, 'component'),
$plugin->version->release,
$plugin->version->version,
implode(' ', $supportedmoodles),
implode($supportedmoodles, ' '),
$info
);
}
@@ -1474,38 +1452,24 @@ class core_admin_renderer extends plugin_renderer_base {
* @param \core\plugininfo\base $plugin the plugin we are rendering the row for.
* @param core_plugin_manager $pluginman provides data on all the plugins.
* @param string $version
* @param int $branch the current Moodle branch
* @return string HTML code
*/
protected function required_column(\core\plugininfo\base $plugin, core_plugin_manager $pluginman, $version, $branch = null) {
protected function required_column(\core\plugininfo\base $plugin, core_plugin_manager $pluginman, $version) {
$requires = array();
$displayuploadlink = false;
$displayupdateslink = false;
$requirements = $pluginman->resolve_requirements($plugin, $version, $branch);
foreach ($requirements as $reqname => $reqinfo) {
foreach ($pluginman->resolve_requirements($plugin, $version) as $reqname => $reqinfo) {
if ($reqname === 'core') {
if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_OK) {
$class = 'requires-ok text-muted';
$class = 'requires-ok';
$label = '';
} else {
$class = 'requires-failed';
$label = html_writer::span(get_string('dependencyfails', 'core_plugin'), 'badge badge-danger');
}
if ($branch != null && !$plugin->is_core_compatible_satisfied($branch)) {
$requires[] = html_writer::tag('li',
html_writer::span(get_string('incompatibleversion', 'core_plugin', $branch), 'dep dep-core').
' '.$label, array('class' => $class));
} else if ($branch != null && $plugin->pluginsupported != null) {
$requires[] = html_writer::tag('li',
html_writer::span(get_string('moodlebranch', 'core_plugin',
array('min' => $plugin->pluginsupported[0], 'max' => $plugin->pluginsupported[1])), 'dep dep-core').
' '.$label, array('class' => $class));
} else if ($reqinfo->reqver != ANY_VERSION) {
if ($reqinfo->reqver != ANY_VERSION) {
$requires[] = html_writer::tag('li',
html_writer::span(get_string('moodleversion', 'core_plugin', $plugin->versionrequires), 'dep dep-core').
' '.$label, array('class' => $class));
@@ -1516,7 +1480,7 @@ class core_admin_renderer extends plugin_renderer_base {
if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_OK) {
$label = '';
$class = 'requires-ok text-muted';
$class = 'requires-ok';
} else if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_MISSING) {
if ($reqinfo->availability == $pluginman::REQUIREMENT_AVAILABLE) {
@@ -1570,14 +1534,13 @@ class core_admin_renderer extends plugin_renderer_base {
return '';
}
$out = html_writer::tag('ul', implode("\n", $requires), array('class' => 'm-0'));
$out = html_writer::tag('ul', implode("\n", $requires));
if ($displayuploadlink) {
$out .= html_writer::div(
html_writer::link(
new moodle_url('/admin/tool/installaddon/'),
get_string('dependencyuploadmissing', 'core_plugin'),
array('class' => 'btn btn-secondary btn-sm m-1')
get_string('dependencyuploadmissing', 'core_plugin')
),
'dependencyuploadmissing'
);
@@ -1587,20 +1550,12 @@ class core_admin_renderer extends plugin_renderer_base {
$out .= html_writer::div(
html_writer::link(
new moodle_url($this->page->url, array('sesskey' => sesskey(), 'fetchupdates' => 1)),
get_string('checkforupdates', 'core_plugin'),
array('class' => 'btn btn-secondary btn-sm m-1')
get_string('checkforupdates', 'core_plugin')
),
'checkforupdates'
);
}
// Check if supports is present, and $branch is not in, only if $incompatible check was ok.
if ($plugin->pluginsupported != null && $class == 'requires-ok' && $branch != null) {
if ($pluginman->check_explicitly_supported($plugin, $branch) == $pluginman::VERSION_NOT_SUPPORTED) {
$out .= html_writer::div(get_string('notsupported', 'core_plugin', $branch));
}
}
return $out;
}
@@ -1947,7 +1902,7 @@ class core_admin_renderer extends plugin_renderer_base {
get_string('status'),
);
$servertable->colclasses = array('centeralign name', 'centeralign info', 'leftalign report', 'leftalign plugin', 'centeralign status');
$servertable->attributes['class'] = 'admintable environmenttable generaltable table-sm';
$servertable->attributes['class'] = 'admintable environmenttable generaltable';
$servertable->id = 'serverstatus';
$serverdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
@@ -1960,7 +1915,7 @@ class core_admin_renderer extends plugin_renderer_base {
get_string('status'),
);
$othertable->colclasses = array('aligncenter info', 'alignleft report', 'alignleft plugin', 'aligncenter status');
$othertable->attributes['class'] = 'admintable environmenttable generaltable table-sm';
$othertable->attributes['class'] = 'admintable environmenttable generaltable';
$othertable->id = 'otherserverstatus';
$otherdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
@@ -2056,7 +2011,7 @@ class core_admin_renderer extends plugin_renderer_base {
if (empty($CFG->docroot) or $environment_result->plugin) {
$report = get_string($stringtouse, 'admin', $rec);
} else {
$report = $this->doc_link(join('/', $linkparts), get_string($stringtouse, 'admin', $rec), true);
$report = $this->doc_link(join($linkparts, '/'), get_string($stringtouse, 'admin', $rec), true);
}
// Enclose report text in div so feedback text will be displayed underneath it.
$report = html_writer::div($report);
@@ -2180,21 +2135,4 @@ class core_admin_renderer extends plugin_renderer_base {
return $this->output->box($out);
}
/**
* Display message about benefits of enabling the user feedback feature.
*
* @param bool $showfeedbackencouragement Whether the encouragement content should be displayed or not
* @return string
*/
protected function userfeedback_encouragement(bool $showfeedbackencouragement): string {
$output = '';
if ($showfeedbackencouragement) {
$settingslink = new moodle_url('/admin/settings.php', ['section' => 'userfeedback']);
$output .= $this->warning(get_string('userfeedbackencouragement', 'admin', $settingslink->out()), 'info');
}
return $output;
}
}
@@ -43,7 +43,7 @@ abstract class core_role_capability_table_base {
protected $id;
/** Added to the class="" attribute on output. */
protected $classes = array('rolecap table-hover');
protected $classes = array('rolecap');
/** Default number of capabilities in the table for the search UI to be shown. */
const NUM_CAPS_FOR_SEARCH = 12;
@@ -50,7 +50,6 @@ class core_role_check_capability_table extends core_role_capability_table_base {
$this->contextname = $contextname;
$this->stryes = get_string('yes');
$this->strno = get_string('no');
$this->add_classes(['table-striped']);
}
protected function add_header_cells() {
@@ -55,7 +55,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
foreach ($levels as $level => $classname) {
$this->allcontextlevels[$level] = context_helper::get_level_name($level);
}
$this->add_classes(['table-striped']);
}
protected function load_current_permissions() {
@@ -66,9 +66,9 @@ class core_role_override_permissions_table_advanced extends core_role_capability
$rowattributes = parent::get_row_attributes($capability);
if ($this->permissions[$capability->name] !== 0) {
if (empty($rowattributes['class'])) {
$rowattributes['class'] = "overriddenpermission table-warning";
$rowattributes['class'] = "overriddenpermission";
} else {
$rowattributes['class'] .= " overriddenpermission table-warning";
$rowattributes['class'] .= " overriddenpermission";
}
}
return $rowattributes;
+8 -3
View File
@@ -131,10 +131,15 @@ if ($hassiteconfig && \core_analytics\manager::is_analytics_enabled()) {
$timesplittingdefaults, $timesplittingoptions)
);
// Predictions processor output dir - specify default in setting description (used if left blank).
$defaultmodeloutputdir = \core_analytics\model::default_output_dir();
// Predictions processor output dir.
$defaultmodeloutputdir = rtrim($CFG->dataroot, '/') . DIRECTORY_SEPARATOR . 'models';
if (empty(get_config('analytics', 'modeloutputdir')) && !file_exists($defaultmodeloutputdir) &&
is_writable($defaultmodeloutputdir)) {
// Automatically create the dir for them so users don't see the invalid value red cross.
mkdir($defaultmodeloutputdir, $CFG->directorypermissions, true);
}
$settings->add(new admin_setting_configdirectory('analytics/modeloutputdir', new lang_string('modeloutputdir', 'analytics'),
new lang_string('modeloutputdirwithdefaultinfo', 'analytics', $defaultmodeloutputdir), ''));
new lang_string('modeloutputdirinfo', 'analytics'), $defaultmodeloutputdir));
// Disable web interface evaluation and get predictions.
$settings->add(new admin_setting_configcheckbox('analytics/onlycli', new lang_string('onlycli', 'analytics'),
-6
View File
@@ -25,12 +25,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) { // sp
$temp->add(new admin_setting_configcheckbox('allowcohortthemes', new lang_string('allowcohortthemes', 'admin'), new lang_string('configallowcohortthemes', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('allowthemechangeonurl', new lang_string('allowthemechangeonurl', 'admin'), new lang_string('configallowthemechangeonurl', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('allowuserblockhiding', new lang_string('allowuserblockhiding', 'admin'), new lang_string('configallowuserblockhiding', 'admin'), 1));
$temp->add(new admin_setting_configcheckbox('langmenuinsecurelayout',
new lang_string('langmenuinsecurelayout', 'admin'),
new lang_string('langmenuinsecurelayout_desc', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('logininfoinsecurelayout',
new lang_string('logininfoinsecurelayout', 'admin'),
new lang_string('logininfoinsecurelayout_desc', 'admin'), 0));
$temp->add(new admin_setting_configtextarea('custommenuitems', new lang_string('custommenuitems', 'admin'),
new lang_string('configcustommenuitems', 'admin'), '', PARAM_RAW, '50', '10'));
$temp->add(new admin_setting_configtextarea(
+8 -5
View File
@@ -59,12 +59,8 @@ if (($hassiteconfig || has_any_capability(array(
$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',
@@ -107,7 +103,14 @@ if (($hassiteconfig || has_any_capability(array(
$backpacksettings->add(new admin_setting_configselect('badges_site_backpack',
new lang_string('sitebackpack', 'badges'),
new lang_string('sitebackpack_help', 'badges'),
$defaultchoice, $choices));
1, $choices));
$warning = badges_verify_site_backpack();
if (!empty($warning)) {
$backpacksettings->add(new admin_setting_description('badges_site_backpack_verify',
new lang_string('sitebackpackverify', 'badges'),
$warning));
}
$ADMIN->add('badges', $backpacksettings);
-46
View File
@@ -181,30 +181,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$CFG->wwwroot . '/course/pending.php', array('moodle/site:approvecourse')));
}
// 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'));
$temp->add(
new admin_setting_configselect(
'activitychoosertabmode',
new lang_string('activitychoosertabmode', 'course'),
new lang_string('activitychoosertabmode_desc', 'course'),
0,
[
0 => new lang_string('activitychoosertabmodeone', 'course'),
1 => new lang_string('activitychoosertabmodetwo', 'course'),
2 => new lang_string('activitychoosertabmodethree', 'course'),
]
)
);
$ADMIN->add('activitychooser', $temp);
$ADMIN->add('activitychooser',
new admin_externalpage('activitychooserrecommended', new lang_string('activitychooserrecommendations', 'course'),
new moodle_url('/course/recommendations.php'),
array('moodle/course:recommendactivity')
)
);
// Add a category for backups.
$ADMIN->add('courses', new admin_category('backups', new lang_string('backups','admin')));
@@ -253,11 +229,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
new lang_string('generalgroups', 'backup'), new lang_string('configgeneralgroups', 'backup'),
array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_competencies', new lang_string('generalcompetencies','backup'), new lang_string('configgeneralcompetencies','backup'), array('value'=>1, 'locked'=>0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_general_contentbankcontent',
new lang_string('generalcontentbankcontent', 'backup'),
new lang_string('configgeneralcontentbankcontent', 'backup'),
['value' => 1, 'locked' => 0])
);
$ADMIN->add('backups', $temp);
@@ -279,12 +250,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
new lang_string('generalgroups', 'backup'), new lang_string('configgeneralgroups', 'backup'),
array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('backup/backup_import_competencies', new lang_string('generalcompetencies','backup'), new lang_string('configgeneralcompetencies','backup'), array('value'=>1, 'locked'=>0)));
$temp->add(new admin_setting_configcheckbox_with_lock(
'backup/backup_import_contentbankcontent',
new lang_string('generalcontentbankcontent', 'backup'),
new lang_string('configgeneralcontentbankcontent', 'backup'),
['value' => 1, 'locked' => 0])
);
$ADMIN->add('backups', $temp);
@@ -311,8 +276,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$maxkeptoptions = array(
0 => new lang_string('all'), 1 => '1',
2 => '2',
3 => '3',
4 => '4',
5 => '5',
10 => '10',
20 => '20',
@@ -404,12 +367,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_groups', new lang_string('generalgroups', 'backup'),
new lang_string('configgeneralgroups', 'backup'), 1));
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_competencies', new lang_string('generalcompetencies','backup'), new lang_string('configgeneralcompetencies','backup'), 1));
$temp->add(new admin_setting_configcheckbox(
'backup/backup_auto_contentbankcontent',
new lang_string('generalcontentbankcontent', 'backup'),
new lang_string('configgeneralcontentbankcontent', '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));
@@ -470,9 +427,6 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_competencies',
new lang_string('generalcompetencies', 'backup'),
new lang_string('configrestorecompetencies', 'backup'), array('value' => 1, 'locked' => 0)));
$temp->add(new admin_setting_configcheckbox_with_lock('restore/restore_general_contentbankcontent',
new lang_string('generalcontentbankcontent', 'backup'),
new lang_string('configrestorecontentbankcontent', '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'), ''));
+1
View File
@@ -10,6 +10,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp = new admin_settingpage('experimentalsettings', new lang_string('experimentalsettings', 'admin'));
//TODO: Re-enable cc-import once re-implemented in 2.0.x
//$temp->add(new admin_setting_configcheckbox('enableimsccimport', new lang_string('enable_cc_import', 'imscc'), new lang_string('enable_cc_import_description', 'imscc'), 0));
$temp->add(new admin_setting_configcheckbox('enablesafebrowserintegration', new lang_string('enablesafebrowserintegration', 'admin'), new lang_string('configenablesafebrowserintegration', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('dndallowtextandlinks', new lang_string('dndallowtextandlinks', 'admin'), new lang_string('configdndallowtextandlinks', 'admin'), 0));
+2 -17
View File
@@ -24,21 +24,6 @@
defined('MOODLE_INTERNAL') || die();
// H5P overview.
$ADMIN->add('h5p', new admin_externalpage('h5poverview', get_string('h5poverview', 'core_h5p'),
new moodle_url('/h5p/overview.php'), ['moodle/site:config']));
// Manage H5P libraries page.
$ADMIN->add('h5p', new admin_externalpage('h5pmanagelibraries', get_string('h5pmanage', 'core_h5p'),
// Settings page.
$ADMIN->add('h5p', new admin_externalpage('h5psettings', get_string('h5pmanage', 'core_h5p'),
new moodle_url('/h5p/libraries.php'), ['moodle/site:config', 'moodle/h5p:updatelibraries']));
// H5P settings.
$defaulth5plib = \core_h5p\local\library\autoloader::get_default_handler_library();
if (!empty($defaulth5plib)) {
// As for now this page only has this setting, it will be hidden if there isn't any H5P libraries handler defined.
$settings = new admin_settingpage('h5psettings', new lang_string('h5psettings', 'core_h5p'));
$ADMIN->add('h5p', $settings);
$settings->add(new admin_settings_h5plib_handler_select('h5plibraryhandler', new lang_string('h5plibraryhandler', 'core_h5p'),
new lang_string('h5plibraryhandler_help', 'core_h5p'), $defaulth5plib));
}
-45
View File
@@ -1,45 +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 file defines the settings pages for licenses.
*
* @package core
* @copyright 2020 Tom Dickman <tomdickman@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/licenselib.php');
if ($hassiteconfig) {
$temp = new admin_settingpage('licensesettings', new lang_string('licensesettings', 'admin'));
$licenses = license_manager::get_active_licenses_as_array();
$temp->add(new admin_setting_configselect('sitedefaultlicense',
new lang_string('configsitedefaultlicense', 'admin'),
new lang_string('configsitedefaultlicensehelp', 'admin'),
'unknown',
$licenses));
$temp->add(new admin_setting_configcheckbox('rememberuserlicensepref',
new lang_string('rememberuserlicensepref', 'admin'),
new lang_string('rememberuserlicensepref_help', 'admin'),
1));
$ADMIN->add('license', $temp);
}
+14 -50
View File
@@ -1,57 +1,21 @@
<?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/>.
/**
* Define administration settings on the Location settings page.
*
* @package core
* @category admin
* @copyright 2006 Martin Dougiamas <martin@moodle.com>
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
defined('MOODLE_INTERNAL') || die();
// "locations" settingpage
$temp = new admin_settingpage('locationsettings', new lang_string('locationsettings', 'admin'));
$temp->add(new admin_setting_servertimezone());
$temp->add(new admin_setting_forcetimezone());
$temp->add(new admin_settings_country_select('country', new lang_string('country', 'admin'), new lang_string('configcountry', 'admin'), 0));
$temp->add(new admin_setting_configtext('defaultcity', new lang_string('defaultcity', 'admin'), new lang_string('defaultcity_help', 'admin'), ''));
if ($hassiteconfig) {
$temp = new admin_settingpage('locationsettings', new lang_string('locationsettings', 'core_admin'));
$temp->add(new admin_setting_heading('iplookup', new lang_string('iplookup', 'admin'), new lang_string('iplookupinfo', 'admin')));
$temp->add(new admin_setting_configfile('geoip2file', new lang_string('geoipfile', 'admin'),
new lang_string('configgeoipfile', 'admin', $CFG->dataroot.'/geoip/'), $CFG->dataroot.'/geoip/GeoLite2-City.mmdb'));
$temp->add(new admin_setting_configtext('googlemapkey3', new lang_string('googlemapkey3', 'admin'), new lang_string('googlemapkey3_help', 'admin'), '', PARAM_RAW, 60));
if ($ADMIN->fulltree) {
$temp->add(new admin_setting_servertimezone());
$temp->add(new admin_setting_forcetimezone());
$temp->add(new admin_settings_country_select('country', new lang_string('country', 'core_admin'),
new lang_string('configcountry', 'core_admin'), 0));
$temp->add(new admin_setting_configtext('defaultcity', new lang_string('defaultcity', 'core_admin'),
new lang_string('defaultcity_help', 'core_admin'), ''));
$temp->add(new admin_setting_heading('iplookup', new lang_string('iplookup', 'core_admin'),
new lang_string('iplookupinfo', 'core_admin')));
$temp->add(new admin_setting_configfile('geoip2file', new lang_string('geoipfile', 'core_admin'),
new lang_string('configgeoipfile', 'core_admin', $CFG->dataroot . '/geoip/'),
$CFG->dataroot . '/geoip/GeoLite2-City.mmdb'));
$temp->add(new admin_setting_configtext('googlemapkey3', new lang_string('googlemapkey3', 'core_admin'),
new lang_string('googlemapkey3_help', 'core_admin'), '', PARAM_RAW, 60));
$temp->add(new admin_setting_countrycodes('allcountrycodes', new lang_string('allcountrycodes', 'core_admin'),
new lang_string('configallcountrycodes', 'core_admin')));
}
$temp->add(new admin_setting_configtext('allcountrycodes', new lang_string('allcountrycodes', 'admin'), new lang_string('configallcountrycodes', 'admin'), '', '/^(?:\w+(?:,\w+)*)?$/'));
$ADMIN->add('location', $temp);
}
} // end of speedup
+14 -13
View File
@@ -182,6 +182,20 @@ if ($hassiteconfig) {
$plugin->load_settings($ADMIN, 'mlbackendsettings', $hassiteconfig);
}
/// License types
$ADMIN->add('modules', new admin_category('licensesettings', new lang_string('licenses')));
$temp = new admin_settingpage('managelicenses', new lang_string('managelicenses', 'admin'));
require_once($CFG->libdir . '/licenselib.php');
$licenses = array();
$array = explode(',', $CFG->licenses);
foreach ($array as $value) {
$licenses[$value] = new lang_string($value, 'license');
}
$temp->add(new admin_setting_configselect('sitedefaultlicense', new lang_string('configsitedefaultlicense','admin'), new lang_string('configsitedefaultlicensehelp','admin'), 'allrightsreserved', $licenses));
$temp->add(new admin_setting_managelicenses());
$ADMIN->add('licensesettings', $temp);
/// Filter plugins
$ADMIN->add('modules', new admin_category('filtersettings', new lang_string('managefilters')));
@@ -643,19 +657,6 @@ if ($hassiteconfig) {
}
}
// Content bank content types.
if ($hassiteconfig) {
$ADMIN->add('modules', new admin_category('contentbanksettings', new lang_string('contentbank')));
$temp = new admin_settingpage('managecontentbanktypes', new lang_string('managecontentbanktypes'));
$temp->add(new admin_setting_managecontentbankcontenttypes());
$ADMIN->add('contentbanksettings', $temp);
$plugins = core_plugin_manager::instance()->get_plugins_of_type('contenttype');
foreach ($plugins as $plugin) {
/** @var \core\plugininfo\contentbank $plugin */
$plugin->load_settings($ADMIN, 'contentbanksettings', $hassiteconfig);
}
}
/// Add all local plugins - must be always last!
if ($hassiteconfig) {
$ADMIN->add('modules', new admin_category('localplugins', new lang_string('localplugins')));
-3
View File
@@ -100,9 +100,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp->add(new admin_setting_configtext('minpasswordupper', new lang_string('minpasswordupper', 'admin'), new lang_string('configminpasswordupper', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_configtext('minpasswordnonalphanum', new lang_string('minpasswordnonalphanum', 'admin'), new lang_string('configminpasswordnonalphanum', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_configtext('maxconsecutiveidentchars', new lang_string('maxconsecutiveidentchars', 'admin'), new lang_string('configmaxconsecutiveidentchars', 'admin'), 0, PARAM_INT));
$temp->add(new admin_setting_configcheckbox('passwordpolicycheckonlogin',
new lang_string('passwordpolicycheckonlogin', 'admin'),
new lang_string('configpasswordpolicycheckonlogin', 'admin'), 0));
$temp->add(new admin_setting_configtext('passwordreuselimit',
new lang_string('passwordreuselimit', 'admin'),
+10 -8
View File
@@ -44,10 +44,15 @@ $temp = new admin_settingpage('sessionhandling', new lang_string('sessionhandlin
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));
$temp->add(new admin_setting_configselect('sessiontimeout', new lang_string('sessiontimeout', 'admin'), new lang_string('configsessiontimeout', 'admin'), 7200, array(14400 => new lang_string('numhours', '', 4),
10800 => new lang_string('numhours', '', 3),
7200 => new lang_string('numhours', '', 2),
5400 => new lang_string('numhours', '', '1.5'),
3600 => new lang_string('numminutes', '', 60),
2700 => new lang_string('numminutes', '', 45),
1800 => new lang_string('numminutes', '', 30),
900 => new lang_string('numminutes', '', 15),
300 => new lang_string('numminutes', '', 5))));
$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));
@@ -92,10 +97,7 @@ $options = array(
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'), ''));
$temp->add(new admin_setting_configselect('getremoteaddrconf', new lang_string('getremoteaddrconf', 'admin'), new lang_string('configgetremoteaddrconf', 'admin'), 0, $options));
$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));
-4
View File
@@ -20,9 +20,6 @@ $moodleservices = new admin_settingpage('moodleservices', new lang_string('moodl
'admin'));
$ADMIN->add('root', $moodleservices);
$userfeedback = new admin_settingpage('userfeedback', new lang_string('feedbacksettings', 'admin'));
$ADMIN->add('root', $userfeedback);
if ($hassiteconfig) {
$optionalsubsystems = new admin_settingpage('optionalsubsystems', new lang_string('advancedfeatures', 'admin'));
$ADMIN->add('root', $optionalsubsystems);
@@ -35,7 +32,6 @@ $ADMIN->add('root', new admin_category('analytics', new lang_string('analytics',
$ADMIN->add('root', new admin_category('competencies', new lang_string('competencies', 'core_competency')));
$ADMIN->add('root', new admin_category('badges', new lang_string('badges'), empty($CFG->enablebadges)));
$ADMIN->add('root', new admin_category('h5p', new lang_string('h5p', 'core_h5p')));
$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')));
-49
View File
@@ -1,49 +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 file contains call to feedback settings
*
* @package core
* @copyright 2020 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
if ($hassiteconfig) {
$userfeedback->add(new admin_setting_configcheckbox('enableuserfeedback',
new lang_string('enableuserfeedback', 'admin'),
new lang_string('enableuserfeedback_desc', 'admin'), 0, 1, 0));
$options = [
core_userfeedback::REMIND_AFTER_UPGRADE => new lang_string('userfeedbackafterupgrade', 'admin'),
core_userfeedback::REMIND_PERIODICALLY => new lang_string('userfeedbackperiodically', 'admin'),
core_userfeedback::REMIND_NEVER => new lang_string('never'),
];
$userfeedback->add(new admin_setting_configselect('userfeedback_nextreminder',
new lang_string('userfeedbacknextreminder', 'admin'),
new lang_string('userfeedbacknextreminder_desc', 'admin'), 1, $options));
$userfeedback->hide_if('userfeedback_nextreminder', 'enableuserfeedback');
$userfeedback->add(new admin_setting_configtext('userfeedback_remindafter',
new lang_string('userfeedbackremindafter', 'admin'),
new lang_string('userfeedbackremindafter_desc', 'admin'), 90, PARAM_INT));
$userfeedback->hide_if('userfeedback_remindafter', 'enableuserfeedback');
$userfeedback->hide_if('userfeedback_remindafter', 'userfeedback_nextreminder', 'eq', 3);
}
-19
View File
@@ -186,7 +186,6 @@ if ($hassiteconfig
'email' => new lang_string('email'),
'city' => new lang_string('city'),
'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'),
@@ -261,28 +260,10 @@ if ($hassiteconfig) {
$temp->add($setting);
// See {@link https://gdpr-info.eu/art-8-gdpr/}.
// See {@link https://www.betterinternetforkids.eu/web/portal/practice/awareness/detail?articleId=3017751}.
$ageofdigitalconsentmap = implode(PHP_EOL, [
'*, 16',
'AT, 14',
'BE, 13',
'BG, 14',
'CY, 14',
'CZ, 15',
'DK, 13',
'EE, 13',
'ES, 14',
'FI, 13',
'FR, 15',
'GB, 13',
'GR, 15',
'IT, 14',
'LT, 14',
'LV, 13',
'MT, 13',
'NO, 13',
'PT, 13',
'SE, 13',
'US, 13'
]);
$setting = new admin_setting_agedigitalconsentmap('agedigitalconsentmap',
+1 -5
View File
@@ -32,7 +32,6 @@ $result = optional_param('result', null, PARAM_INT);
$pageurl = new \moodle_url('/admin/tasklogs.php');
$pageurl->param('filter', $filter);
$pageurl->param('result', $result);
$PAGE->set_url($pageurl);
$PAGE->set_context(context_system::instance());
@@ -63,11 +62,9 @@ if (null !== $logid) {
$renderer = $PAGE->get_renderer('tool_task');
echo $OUTPUT->header();
// Output the search form.
echo $OUTPUT->render_from_template('core_admin/tasklogs', (object) [
'action' => $pageurl->out(),
'filter' => htmlentities($filter),
'filter' => $filter,
'resultfilteroptions' => [
(object) [
'value' => -1,
@@ -87,7 +84,6 @@ echo $OUTPUT->render_from_template('core_admin/tasklogs', (object) [
],
]);
// Output any matching logs.
$table = new \core_admin\task_log_table($filter, $result);
$table->baseurl = $pageurl;
$table->out(100, false);
+9 -35
View File
@@ -49,28 +49,15 @@
}}
<div class="form-item row" id="{{id}}">
<div class="form-label col-sm-3 text-sm-right">
{{#customcontrol}}
<p {{#labelfor}}id="{{labelfor}}_label"{{/labelfor}}>
{{{title}}}
{{#override}}
<div class="alert alert-info">{{override}}</div>
{{/override}}
{{#warning}}
<div class="alert alert-warning">{{warning}}</div>
{{/warning}}
</p>
{{/customcontrol}}
{{^customcontrol}}
<label {{#labelfor}}for="{{labelfor}}"{{/labelfor}}>
{{{title}}}
{{#override}}
<div class="alert alert-info">{{override}}</div>
{{/override}}
{{#warning}}
<div class="alert alert-warning">{{warning}}</div>
{{/warning}}
</label>
{{/customcontrol}}
<label {{#labelfor}}for="{{labelfor}}"{{/labelfor}}>
{{{title}}}
{{#override}}
<div class="form-overridden">{{override}}</div>
{{/override}}
{{#warning}}
<div class="form-warning">{{warning}}</div>
{{/warning}}
</label>
<span class="form-shortname d-block small text-muted">{{{name}}}</span>
</div>
<div class="form-setting col-sm-9">
@@ -85,16 +72,3 @@
{{#dependenton}}<div class="form-dependenton mb-4 text-muted">{{{.}}}</div>{{/dependenton}}
</div>
</div>
{{#customcontrol}}
{{#js}}
require(['jquery'], function($) {
$('#{{id}}_label').css('cursor', 'default');
$('#{{id}}_label').click(function() {
$('#{{id}}')
.find('button, a, input:not([type="hidden"]), select, textarea, [tabindex]')
.filter(':not([disabled]):not([tabindex="0"]):not([tabindex="-1"])')
.first().focus();
});
});
{{/js}}
{{/customcontrol}}
@@ -25,7 +25,6 @@
* value - yes value
* id - element id
* checked - boole
* readonly - bool
Example context (json):
{
@@ -33,11 +32,10 @@
"no": "False",
"value": "True",
"id": "test0",
"checked": "checked",
"readonly": false
"checked": "checked"
}
}}
<div class="form-checkbox defaultsnext">
<input type="hidden" name="{{name}}" value="{{no}}">
<input {{#readonly}}disabled{{/readonly}} type="checkbox" name="{{name}}" value="{{value}}" id="{{id}}" {{#checked}}checked{{/checked}}>
<input type="checkbox" name="{{name}}" value="{{value}}" id="{{id}}" {{#checked}}checked{{/checked}}>
</div>
@@ -25,7 +25,6 @@
* id - element id
* value - element value
* haspreviewconfig - show preview of selected color
* readonly - bool
Example context (json):
{
@@ -33,7 +32,6 @@
"name": "name0",
"id": "id0",
"value": "#555655",
"readonly": false,
"haspreviewconfig": false
}
}}
@@ -46,7 +44,7 @@
{{>core/pix_icon}}
{{/icon}}
</div>
<input type="text" name="{{name}}" id="{{id}}" value="{{value}}" size="12" class="form-control text-ltr" {{#readonly}}disabled{{/readonly}}>
<input type="text" name="{{name}}" id="{{id}}" value="{{value}}" size="12" class="form-control text-ltr">
{{#haspreviewconfig}}
<input type="button" id="{{id}}_preview" value={{#quote}}{{#str}}preview{{/str}}{{/quote}} class="admin_colourpicker_preview">
{{/haspreviewconfig}}
@@ -33,7 +33,7 @@
"name": "test",
"value": "/my-super-secret-path/",
"id": "test0",
"readonly": false,
"readonly": true,
"showvalidity": true,
"valid": false
}
@@ -23,7 +23,6 @@
* name - form element name
* options - list of options for units containing name, value, selected
* value - yes
* readonly - bool
* id - element id
Example context (json):
@@ -31,7 +30,6 @@
"name": "test",
"value": "5",
"id": "test0",
"readonly": false,
"options": [ { "name": "Minutes", "value": "mins", "selected": true } ]
}
}}
@@ -40,9 +38,9 @@
}}
<div class="form-duration defaultsnext">
<div class="form-inline">
<input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr" {{#readonly}}disabled{{/readonly}}>
<input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr">
<label class="sr-only" for="{{id}}u">{{#str}}durationunits, admin{{/str}}</label>
<select id="{{id}}u" name="{{name}}[u]" class="form-control custom-select" {{#readonly}}disabled{{/readonly}}>
<select id="{{id}}u" name="{{name}}[u]" class="form-control custom-select">
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -33,7 +33,7 @@
"name": "test",
"value": "/usr/bin/cowsay",
"id": "test0",
"readonly": false,
"readonly": true,
"showvalidity": true,
"valid": false
}
+1 -3
View File
@@ -26,7 +26,6 @@
* readonly - Make the field readonly
* value - value
* showvalidity - Show a green check if the path is readable
* readonly - bool
* valid - True if the path is readable
Example context (json):
@@ -34,9 +33,8 @@
"name": "test",
"value": "/my-super-secret-path/file",
"id": "test0",
"readonly": false,
"readonly": true,
"showvalidity": true,
"readonly": false,
"valid": false
}
}}
@@ -24,14 +24,12 @@
* options - list of options for units containing name, value, selected
* value - yes
* id - element id
* readonly - bool
Example context (json):
{
"name": "test",
"value": "5",
"id": "test0",
"readonly": false,
"options": [ { "name": "KB", "value": "1024", "selected": true } ]
}
}}
@@ -40,9 +38,9 @@
}}
<div class="form-filesize defaultsnext">
<div class="form-inline">
<input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr" {{#readonly}}disabled{{/readonly}}>
<input type="text" size="5" id="{{id}}v" name="{{name}}[v]" value="{{value}}" class="form-control text-ltr">
<label class="sr-only" for="{{id}}u">{{#str}}filesizeunits, admin{{/str}}</label>
<select id="{{id}}u" name="{{name}}[u]" class="form-control custom-select" {{#readonly}}disabled{{/readonly}}>
<select id="{{id}}u" name="{{name}}[u]" class="form-control custom-select">
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -24,13 +24,11 @@
* id - element id
* size - element size
* options - list of options containing name, value, selected
* readonly - bool
Example context (json):
{
"name": "test",
"id": "test0",
"readonly": false,
"size": "3",
"options": [ { "name": "Option 1", "value": "V", "selected": true },
{ "name": "Option 2", "value": "V", "selected": true } ]
@@ -41,7 +39,7 @@
}}
<div class="form-select">
<input type="hidden" name="{{name}}[xxxxx]" value="1">
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
<select id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -25,13 +25,11 @@
* size - element size
* options - list of options not grouped
* optgroups - list of options grouped containing the group label and for each option: name, value, selected
* readonly - bool
Example context (json):
{
"name": "test",
"id": "test0",
"readonly": false,
"size": "3",
"options": [
{ "name": "Option 1", "value": "V", "selected": false },
@@ -60,7 +58,7 @@
}}
<div class="form-select">
<input type="hidden" name="{{name}}[xxxxx]" value="1">
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
<select id="{{id}}" name="{{name}}[]" size="{{size}}" class="form-control" multiple>
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -24,30 +24,15 @@
* size - form element size
* value - form element value
* id - element id
* readonly - has value been defined in config.php
Example context (json):
{
"name": "test",
"id": "test0",
"size": "8",
"value": "secret",
"readonly": false
"value": "secret"
}
}}
{{#readonly}}
<div class="form-password">
<input type="text"
name = "{{ name }}"
id="{{ id }}"
value="********"
size="{{ size }}"
class="form-control"
disabled
>
</div>
{{/readonly}}
{{^readonly}}
<div class="form-password">
<span data-passwordunmask="wrapper" data-passwordunmaskid="{{ id }}">
<span data-passwordunmask="editor">
@@ -76,4 +61,3 @@ require(['core_form/passwordunmask'], function(PasswordUnmask) {
new PasswordUnmask("{{ id }}");
});
{{/js}}
{{/readonly}}
@@ -23,13 +23,11 @@
* name - form element name
* id - element id
* options - list of options containing name, value, selected
* readonly - bool
Example context (json):
{
"name": "test",
"id": "test0",
"readonly": false,
"options": [
{ "name": "Option 1", "value": "V", "selected": true },
{ "name": "Option 2", "value": "V", "selected": true }
@@ -40,7 +38,7 @@
Setting configselect.
}}
<div class="form-select defaultsnext">
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}" class="custom-select">
<select id="{{id}}" name="{{name}}" class="custom-select">
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
@@ -22,7 +22,6 @@
Context variables required for this template:
* name - form element name
* id - element id
* readonly - bool
* options - list of options (not grouped)
* optgroups - list of options grouped containing the group label and for each option: name, value, selected
@@ -30,7 +29,6 @@
{
"name": "test",
"id": "test0",
"readonly": false,
"options": [
{ "name": "Option 1", "value": "V", "selected": false },
{ "name": "Option 2", "value": "V", "selected": false }
@@ -57,7 +55,7 @@
Setting configselect with optgroup support.
}}
<div class="form-select defaultsnext">
<select {{#readonly}}disabled{{/readonly}} id="{{id}}" name="{{name}}" class="custom-select">
<select id="{{id}}" name="{{name}}" class="custom-select">
{{#options}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/options}}
+1 -3
View File
@@ -26,7 +26,6 @@
* size - element size
* forceltr - always display as ltr
* attributes - list of additional attributes containing name, value
* readonly - bool
Example context (json):
{
@@ -35,7 +34,6 @@
"value": "A tall, dark stranger will have more fun than you.",
"size": "21",
"forceltr": false,
"readonly": false,
"attributes": [ { "name": "readonly", "value": "readonly" } ]
}
}}
@@ -43,5 +41,5 @@
Setting configtext.
}}
<div class="form-text defaultsnext">
<input type="text" name="{{name}}" value="{{value}}" size="{{size}}" id="{{id}}" class="form-control {{#forceltr}}text-ltr{{/forceltr}}" {{#readonly}}disabled{{/readonly}}>
<input type="text" name="{{name}}" value="{{value}}" size="{{size}}" id="{{id}}" class="form-control {{#forceltr}}text-ltr{{/forceltr}}">
</div>
@@ -33,7 +33,6 @@
"cols": "30",
"rows": "3",
"value": "Excellent day for putting Slinkies on an escalator.",
"readonly": false,
"id": "test0"
}
}}
@@ -41,5 +40,5 @@
Setting configtextarea.
}}
<div class="form-textarea">
<textarea {{#readonly}}disabled{{/readonly}} rows="{{rows}}" cols="{{cols}}" id="{{id}}" name="{{name}}" spellcheck="true" class="form-control {{#forceltr}}text-ltr{{/forceltr}}">{{value}}</textarea>
<textarea rows="{{rows}}" cols="{{cols}}" id="{{id}}" name="{{name}}" spellcheck="true" class="form-control {{#forceltr}}text-ltr{{/forceltr}}">{{value}}</textarea>
</div>
+2 -4
View File
@@ -24,13 +24,11 @@
* id - element id
* hours - list of valid hour options containing name, value, selected
* minutes - list of valid minute options containing name, value, selected
* readonly - bool
Example context (json):
{
"name": "test",
"id": "test0",
"readonly": false,
"minutes": [
{ "name": "00", "value": "0", "selected": true },
{ "name": "01", "value": "1", "selected": false }
@@ -47,13 +45,13 @@
<div class="form-time defaultsnext">
<div class="form-inline text-ltr">
<label class="sr-only" for="{{id}}h">{{#str}}hours{{/str}}</label>
<select id="{{id}}h" name="{{name}}[h]" class="custom-select" {{#readonly}}disabled{{/readonly}}>
<select id="{{id}}h" name="{{name}}[h]" class="custom-select">
{{#hours}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/hours}}
</select>:
<label class="sr-only" for="{{id}}m">{{#str}}minutes{{/str}}</label>
<select id="{{id}}m" name="{{name}}[m]" class="custom-select" {{#readonly}}disabled{{/readonly}}>
<select id="{{id}}m" name="{{name}}[m]" class="custom-select">
{{#minutes}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/minutes}}
@@ -47,7 +47,7 @@
<h3 class="adminpagetitle"><a href="{{url}}">{{{title}}}</a></h3>
<ul class="adminpagepath" aria-label="{{#str}} pagepath, core {{/str}}">
{{#path}}
<li class="small text-muted">{{.}}</li>
<li>{{.}}</li>
{{/path}}
</ul>
<fieldset class="adminsettings">
+1 -1
View File
@@ -17,7 +17,7 @@
{{!
@template core_admin/tasklogs
This is the template for the search form which appears above the task logs report.
Task Logs template.
}}
<form class="form-inline" method="GET" action="{{{action}}}">
<label class="sr-only" for="tasklog-filter">{{#str}}filter{{/str}}</label>
+1 -2
View File
@@ -46,8 +46,7 @@ if ($data) {
$emailuser->email = $data->recipient;
$emailuser->id = -99;
$subject = get_string('testoutgoingmailconf_subject', 'admin',
format_string($SITE->fullname, true, ['context' => context_system::instance()]));
$subject = get_string('testoutgoingmailconf_subject', 'admin', $SITE->fullname);
$messagetext = get_string('testoutgoingmailconf_message', 'admin');
// Manage Moodle debugging options.
+5 -17
View File
@@ -6,11 +6,11 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
Background:
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 | | |
| username | firstname | lastname | email | auth | confirmed | lastip |
| user1 | User | One | one@example.com | manual | 0 | 127.0.1.1 |
| user2 | User | Two | two@example.com | ldap | 1 | 0.0.0.0 |
| 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 |
@@ -104,15 +104,3 @@ Feature: An administrator can filter user accounts by role, cohort and other pro
And I should see "User Two"
And I should see "User Three"
And I should see "User Four"
Scenario: Filter users by institution and department
When I set the field "id_institution" to "moodle"
And I press "Add filter"
Then I should see "User One"
And I should see "User Two"
And I should not see "User Three"
And I should not see "User Four"
And I set the field "id_department" to "red"
And I press "Add filter"
And I should see "User One"
And I should not see "User Two"
@@ -1,29 +0,0 @@
@core @core_admin
Feature: Administrator is warned and when trying to set invalid allcountrycodes value.
In order to avoid misconfiguration of the country selector fields
As an admin
I want to be warned when I try to set an invalid country code in the allcountrycodes field
Scenario: Attempting to set allcountrycodes field with valid country codes
Given I log in as "admin"
And I navigate to "Location > Location settings" in site administration
When I set the following administration settings values:
| All country codes | CZ,BE,GB,ES |
Then I should not see "Invalid country code"
Scenario: Attempting to set allcountrycodes field with invalid country code
Given I log in as "admin"
And I navigate to "Location > Location settings" in site administration
When I set the following administration settings values:
| All country codes | CZ,BE,FOOBAR,GB,ES |
Then I should see "Invalid country code: FOOBAR"
Scenario: Attempting to unset allcountrycodes field
Given I log in as "admin"
And I navigate to "Location > Location settings" in site administration
And I set the following administration settings values:
| All country codes | CZ,BE,GB,ES |
And I navigate to "Location > Location settings" in site administration
When I set the following administration settings values:
| All country codes | |
Then I should not see "Invalid country code"
@@ -1,34 +0,0 @@
@core @core_admin
Feature: Configure language settings for the site
In order to configure language settings for the site
As an admin
I want to set language settings relevant to my site users
Scenario: Set languages on language menu
Given I log in as "admin"
And I navigate to "Language > Language settings" in site administration
When I set the field "Languages on language menu" to "en"
And I press "Save changes"
Then I should not see "Invalid language code"
Scenario: Reset languages on language menu
Given I log in as "admin"
And I navigate to "Language > Language settings" in site administration
When I set the field "Languages on language menu" to ""
And I press "Save changes"
Then I should not see "Invalid language code"
Scenario Outline: Set languages on language menu with invalid language
Given I log in as "admin"
And I navigate to "Language > Language settings" in site administration
When I set the field "Languages on language menu" to "<fieldvalue>"
And I press "Save changes"
Then I should see "Invalid language code: <invalidlang>"
Examples:
| fieldvalue | invalidlang |
| xx | xx |
| xx\|Bad | xx |
| en,qq | qq |
| en,qq\|Bad | qq |
| en$$ | en$$ |
| en$$\|Bad | en$$ |
@@ -27,7 +27,8 @@ namespace tool_analytics\output;
defined('MOODLE_INTERNAL') || die();
use plugin_renderer_base;
use templatable;
use renderable;
/**
* Renderer class.
@@ -73,12 +74,14 @@ class renderer extends plugin_renderer_base {
* @return string HTML
*/
public function render_evaluate_results($results, $logs = array()) {
global $OUTPUT;
$output = '';
foreach ($results as $timesplittingid => $result) {
if (!CLI_SCRIPT) {
$output .= $this->output->box_start('generalbox mb-3');
$output .= $OUTPUT->box_start('generalbox mb-3');
}
// Check that the array key is a string, not all results depend on time splitting methods (e.g. general errors).
@@ -87,48 +90,47 @@ class renderer extends plugin_renderer_base {
$langstrdata = (object)array('name' => $timesplitting->get_name(), 'id' => $timesplittingid);
if (CLI_SCRIPT) {
$output .= $this->output->heading(get_string('scheduledanalysisresultscli', 'tool_analytics', $langstrdata), 3);
$output .= $OUTPUT->heading(get_string('scheduledanalysisresultscli', 'tool_analytics', $langstrdata), 3);
} else {
$output .= $this->output->heading(get_string('scheduledanalysisresults', 'tool_analytics', $langstrdata), 3);
$output .= $OUTPUT->heading(get_string('scheduledanalysisresults', 'tool_analytics', $langstrdata), 3);
}
}
if ($result->status == 0) {
$output .= $this->output->notification(get_string('goodmodel', 'tool_analytics'),
$output .= $OUTPUT->notification(get_string('goodmodel', 'tool_analytics'),
\core\output\notification::NOTIFY_SUCCESS);
} else if ($result->status === \core_analytics\model::NO_DATASET) {
$output .= $this->output->notification(get_string('nodatatoevaluate', 'tool_analytics'),
$output .= $OUTPUT->notification(get_string('nodatatoevaluate', 'tool_analytics'),
\core\output\notification::NOTIFY_WARNING);
}
if (isset($result->score)) {
// Score.
$output .= $this->output->heading(get_string('accuracy', 'tool_analytics') . ': ' .
$output .= $OUTPUT->heading(get_string('accuracy', 'tool_analytics') . ': ' .
round(floatval($result->score), 4) * 100 . '%', 4);
}
if (!empty($result->info)) {
foreach ($result->info as $message) {
$output .= $this->output->notification($message, \core\output\notification::NOTIFY_WARNING);
$output .= $OUTPUT->notification($message, \core\output\notification::NOTIFY_WARNING);
}
}
if (!CLI_SCRIPT) {
$output .= $this->output->box_end();
$output .= $OUTPUT->box_end();
}
}
// Info logged during evaluation.
if (!empty($logs) && debugging()) {
$output .= $this->output->heading(get_string('extrainfo', 'tool_analytics'), 3);
$output .= $OUTPUT->heading(get_string('extrainfo', 'tool_analytics'), 3);
foreach ($logs as $log) {
$output .= $this->output->notification($log, \core\output\notification::NOTIFY_WARNING);
$output .= $OUTPUT->notification($log, \core\output\notification::NOTIFY_WARNING);
}
}
if (!CLI_SCRIPT) {
$output .= $this->output->single_button(new \moodle_url('/admin/tool/analytics/index.php'),
get_string('continue'), 'get');
$output .= $OUTPUT->single_button(new \moodle_url('/admin/tool/analytics/index.php'), get_string('continue'), 'get');
}
return $output;
@@ -145,68 +147,62 @@ class renderer extends plugin_renderer_base {
* @return string HTML
*/
public function render_get_predictions_results($trainresults = false, $trainlogs = array(), $predictresults = false, $predictlogs = array()) {
global $OUTPUT;
$output = '';
if ($trainresults || (!empty($trainlogs) && debugging())) {
$output .= $this->output->heading(get_string('trainingresults', 'tool_analytics'), 3);
$output .= $OUTPUT->heading(get_string('trainingresults', 'tool_analytics'), 3);
}
if ($trainresults) {
if ($trainresults->status == 0) {
$output .= $this->output->notification(
get_string('trainingprocessfinished', 'tool_analytics'),
$output .= $OUTPUT->notification(get_string('trainingprocessfinished', 'tool_analytics'),
\core\output\notification::NOTIFY_SUCCESS);
} else if ($trainresults->status === \core_analytics\model::NO_DATASET ||
$trainresults->status === \core_analytics\model::NOT_ENOUGH_DATA) {
$output .= $this->output->notification(
get_string('nodatatotrain', 'tool_analytics'),
$output .= $OUTPUT->notification(get_string('nodatatotrain', 'tool_analytics'),
\core\output\notification::NOTIFY_WARNING);
} else {
$output .= $this->output->notification(
get_string('generalerror', 'tool_analytics', $trainresults->status),
$output .= $OUTPUT->notification(get_string('generalerror', 'tool_analytics', $trainresults->status),
\core\output\notification::NOTIFY_ERROR);
}
}
if (!empty($trainlogs) && debugging()) {
$output .= $this->output->heading(get_string('extrainfo', 'tool_analytics'), 4);
$output .= $OUTPUT->heading(get_string('extrainfo', 'tool_analytics'), 4);
foreach ($trainlogs as $log) {
$output .= $this->output->notification($log, \core\output\notification::NOTIFY_WARNING);
$output .= $OUTPUT->notification($log, \core\output\notification::NOTIFY_WARNING);
}
}
if ($predictresults || (!empty($predictlogs) && debugging())) {
$output .= $this->output->heading(
get_string('predictionresults', 'tool_analytics'), 3, 'main mt-3');
$output .= $OUTPUT->heading(get_string('predictionresults', 'tool_analytics'), 3, 'main mt-3');
}
if ($predictresults) {
if ($predictresults->status == 0) {
$output .= $this->output->notification(
get_string('predictionprocessfinished', 'tool_analytics'),
$output .= $OUTPUT->notification(get_string('predictionprocessfinished', 'tool_analytics'),
\core\output\notification::NOTIFY_SUCCESS);
} else if ($predictresults->status === \core_analytics\model::NO_DATASET ||
$predictresults->status === \core_analytics\model::NOT_ENOUGH_DATA) {
$output .= $this->output->notification(
get_string('nodatatopredict', 'tool_analytics'),
$output .= $OUTPUT->notification(get_string('nodatatopredict', 'tool_analytics'),
\core\output\notification::NOTIFY_WARNING);
} else {
$output .= $this->output->notification(
get_string('generalerror', 'tool_analytics', $predictresults->status),
$output .= $OUTPUT->notification(get_string('generalerror', 'tool_analytics', $predictresults->status),
\core\output\notification::NOTIFY_ERROR);
}
}
if (!empty($predictlogs) && debugging()) {
$output .= $this->output->heading(get_string('extrainfo', 'tool_analytics'), 4);
$output .= $OUTPUT->heading(get_string('extrainfo', 'tool_analytics'), 4);
foreach ($predictlogs as $log) {
$output .= $this->output->notification($log, \core\output\notification::NOTIFY_WARNING);
$output .= $OUTPUT->notification($log, \core\output\notification::NOTIFY_WARNING);
}
}
if (!CLI_SCRIPT) {
$output .= $this->output->single_button(new \moodle_url('/admin/tool/analytics/index.php'),
get_string('continue'), 'get');
$output .= $OUTPUT->single_button(new \moodle_url('/admin/tool/analytics/index.php'), get_string('continue'), 'get');
}
return $output;
@@ -240,18 +236,17 @@ class renderer extends plugin_renderer_base {
* @return string HTML
*/
public function render_analytics_disabled() {
global $FULLME;
global $OUTPUT, $PAGE, $FULLME;
$this->page->set_url($FULLME);
$this->page->set_title(get_string('pluginname', 'tool_analytics'));
$this->page->set_heading(get_string('pluginname', 'tool_analytics'));
$PAGE->set_url($FULLME);
$PAGE->set_title(get_string('pluginname', 'tool_analytics'));
$PAGE->set_heading(get_string('pluginname', 'tool_analytics'));
$output = $this->output->header();
$output .= $this->output->notification(get_string('analyticsdisabled', 'analytics'),
\core\output\notification::NOTIFY_INFO);
$output = $OUTPUT->header();
$output .= $OUTPUT->notification(get_string('analyticsdisabled', 'analytics'), \core\output\notification::NOTIFY_INFO);
$output .= \html_writer::tag('a', get_string('continue'), ['class' => 'btn btn-primary',
'href' => (new \moodle_url('/'))->out()]);
$output .= $this->output->footer();
$output .= $OUTPUT->footer();
return $output;
}
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2020060900; // Requires this Moodle version.
$plugin->version = 2019111800; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2019111200; // 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 = 2020061500;
$plugin->requires = 2020060900;
$plugin->version = 2019111800;
$plugin->requires = 2019111200;
$plugin->component = 'tool_availabilityconditions';
-6
View File
@@ -164,8 +164,6 @@ if ($options['install']) {
mtrace("Acceptance tests site installed");
}
// Note: Do not build the themes here. This is done during the 'enable' stage.
} else if ($options['drop']) {
// Ensure no tests are running.
test_lock::acquire('behat');
@@ -184,10 +182,6 @@ if ($options['install']) {
// Enable test mode.
behat_util::start_test_mode($options['add-core-features-to-theme'], $options['optimize-runs'], $parallel, $run);
// Themes are only built in the 'enable' command.
behat_util::build_themes();
mtrace("Testing environment themes built");
// This is only displayed once for parallel install.
if (empty($run)) {
// Notify user that 2.5 profile has been converted to 3.5.
+1 -1
View File
@@ -32,7 +32,7 @@ require_once($CFG->libdir . '/behat/classes/behat_config_manager.php');
// systems, but let's allow room for expansion.
core_php_time_limit::raise(300);
$filter = optional_param('filter', '', PARAM_NOTAGS);
$filter = optional_param('filter', '', PARAM_ALPHANUMEXT);
$type = optional_param('type', false, PARAM_ALPHAEXT);
$component = optional_param('component', '', PARAM_ALPHAEXT);
+1 -2
View File
@@ -24,7 +24,7 @@
$string['aim'] = 'This administration tool helps developers and test writers to create .feature files describing Moodle\'s functionalities and run them automatically. Step definitions available for use in .feature files are listed below.';
$string['allavailablesteps'] = 'All available step definitions';
$string['errorapproot'] = '$CFG->behat_ionic_dirroot is not pointing to a valid Moodle app developer install.';
$string['errorapproot'] = '$CFG->behat_ionic_dirroot is not pointing to a valid Moodle Mobile developer install.';
$string['errorbehatcommand'] = 'Error running behat CLI command. Try running "{$a} --help" manually from CLI to find out more about the problem.';
$string['errorcomposer'] = 'Composer dependencies are not installed.';
$string['errordataroot'] = '$CFG->behat_dataroot is not set or is invalid.';
@@ -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>
+2 -2
View File
@@ -55,13 +55,13 @@ class tool_behat {
// The loaded steps depends on the component specified.
behat_config_manager::update_config_file($component, false);
// The Moodle\BehatExtension\Definition\Printer\ConsoleDefinitionInformationPrinter will parse this search format.
// The Moodle\BehatExtension\HelpPrinter\MoodleDefinitionsPrinter will parse this search format.
if ($type) {
$filter .= '&&' . $type;
}
if ($filter) {
$filteroption = ' -d ' . escapeshellarg($filter);
$filteroption = ' -d "' . $filter . '"';
} else {
$filteroption = ' -di';
}
+17 -8
View File
@@ -44,9 +44,13 @@ class tool_behat_renderer extends plugin_renderer_base {
global $CFG;
require_once($CFG->libdir . '/behat/classes/behat_selectors.php');
$html = $this->output->header();
$html .= $this->output->heading(get_string('pluginname', 'tool_behat'));
$html .= $form->render();
$html = $this->generic_info();
// Form.
ob_start();
$form->display();
$html .= ob_get_contents();
ob_end_clean();
if (empty($stepsdefinitions)) {
$stepsdefinitions = get_string('nostepsdefinitions', 'tool_behat');
@@ -124,9 +128,7 @@ class tool_behat_renderer extends plugin_renderer_base {
*/
public function render_error($msg) {
$html = $this->output->header();
$html .= $this->output->heading(get_string('pluginname', 'tool_behat'));
$html .= $this->generic_info();
$html = $this->generic_info();
$a = new stdClass();
$a->errormsg = $msg;
@@ -151,7 +153,13 @@ class tool_behat_renderer extends plugin_renderer_base {
*
* @return string
*/
public function generic_info() {
protected function generic_info() {
$title = get_string('pluginname', 'tool_behat');
// Header.
$html = $this->output->header();
$html .= $this->output->heading($title);
// Info.
$installurl = behat_command::DOCS_URL;
@@ -167,7 +175,8 @@ class tool_behat_renderer extends plugin_renderer_base {
);
// List of steps.
$html = $this->output->box_start();
$html .= $this->output->box_start();
$html .= html_writer::tag('h3', get_string('infoheading', 'tool_behat'));
$html .= html_writer::tag('div', get_string('aim', 'tool_behat'));
$html .= html_writer::start_tag('div');
$html .= html_writer::start_tag('ul');
@@ -40,14 +40,8 @@ class steps_definitions_form extends moodleform {
* @return void
*/
public function definition() {
global $PAGE;
$mform = $this->_form;
$output = $PAGE->get_renderer('tool_behat');
$mform->addElement('header', 'info', get_string('infoheading', 'tool_behat'));
$mform->setExpanded('info', false);
$mform->addElement('html', $output->generic_info());
$mform->addElement('header', 'filters', get_string('stepsdefinitionsfilters', 'tool_behat'));
+14 -20
View File
@@ -1,31 +1,25 @@
#page-admin-tool-behat-index .steps-definitions {
margin: 1rem auto;
.steps-definitions {
border-style: solid;
border-width: 1px;
border-color: #bbb;
padding: 5px;
margin: auto;
width: 50%;
}
#page-admin-tool-behat-index .steps-definitions .step {
margin: 1rem 0 0 0;
border: 1px solid #eee;
padding: 1rem;
.steps-definitions .step {
margin: 10px 0 10px 0;
}
#page-admin-tool-behat-index .steps-definitions .stepdescription {
font-style: italic;
.steps-definitions .stepdescription {
color: #bf8c12;
}
#page-admin-tool-behat-index .steps-definitions .stepcontent {
margin: 1rem 0;
}
#page-admin-tool-behat-index .steps-definitions .steptype {
.steps-definitions .steptype {
color: #1467a6;
margin-right: 1ex;
margin-right: 5px;
}
#page-admin-tool-behat-index .steps-definitions .stepapipath {
font-family: monospace;
font-size: smaller;
}
#page-admin-tool-behat-index .steps-definitions .stepregex {
.steps-definitions .stepregex {
color: #060;
}
@@ -143,20 +143,20 @@ Feature: Set up contextual data for tests
And I log out
And I log in as "user2"
And I am on "Course 1" course homepage
And "Turn editing on" "button" should exist
And "Turn editing on" "link" should exist in current page administration
And I log out
And I log in as "user3"
And I am on "Course 1" course homepage
And "Turn editing on" "button" should exist
And "Turn editing on" "link" should exist in current page administration
And I log out
And I log in as "user4"
And I am on "Course 1" course homepage
And "Turn editing on" "button" should exist
And "Turn editing on" "link" should exist in current page administration
And I log out
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:
@@ -259,9 +259,9 @@ Feature: Set up contextual data for tests
Then the "groups" select box should contain "Group 1 (1)"
And the "groups" select box should contain "Group 2 (1)"
And I set the field "groups" to "Group 1 (1)"
And the "members" select box should contain "Student 1 (student1@example.com)"
And the "members" select box should contain "Student 1"
And I set the field "groups" to "Group 2 (1)"
And the "members" select box should contain "Student 2 (student2@example.com)"
And the "members" select box should contain "Student 2"
Scenario: Add cohorts and cohort members with data generator
Given the following "categories" exist:
@@ -6,18 +6,14 @@ Feature: Edit capabilities
Background:
Given the following "users" exist:
| username | firstname | lastname |
| teacher1 | Teacher | 1 |
| tutor | Teaching | Assistant |
| student | Student | One |
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| tutor | C1 | teacher |
| student | C1 | student |
| user | course | role |
| teacher1 | C1 | editingteacher |
Scenario: Default system capabilities modification
Given I log in as "admin"
@@ -64,25 +60,3 @@ Feature: Edit capabilities
Then "mod/forum:deleteanypost" capability has "Prohibit" permission
And "mod/forum:editanypost" capability has "Prevent" permission
And "mod/forum:addquestion" capability has "Allow" permission
@javascript
Scenario: Edit permissions escapes role names correctly
When I am on the "C1" "Course" page logged in as "admin"
And I navigate to "Edit settings" in current page administration
And I set the following fields to these values:
| Your word for 'Teacher' | Teacher >= editing |
| Your word for 'Non-editing teacher' | Teacher < "editing" |
| Your word for 'Student' | Studier & 'learner' |
And I press "Save and display"
And I navigate to course participants
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"
And I should see "Studier & 'learner'" in the "mod/forum:replypost" "table_row"
And I follow "Prohibit"
And "Teacher >= editing" "button" in the "Prohibit role" "dialogue" should be visible
And "Teacher < \"editing\"" "button" in the "Prohibit role" "dialogue" should be visible
And "Studier & 'learner'" "button" in the "Prohibit role" "dialogue" should be visible
@@ -147,13 +147,13 @@ Feature: Verify that all form fields values can be get and set
And I navigate to "Users > Groups" in current page administration
# Select (multi-select & AJAX) - Checking "I set the field" and "select box should contain".
And I set the field "groups" to "Group 2"
And the "members" select box should contain "Student 2 (s2@example.com)"
And the "members" select box should contain "Student 3 (s3@example.com)"
And the "members" select box should not contain "Student 1 (s1@example.com)"
And the "members" select box should contain "Student 2"
And the "members" select box should contain "Student 3"
And the "members" select box should not contain "Student 1"
And I set the field "groups" to "Group 1"
And the "members" select box should contain "Student 1 (s1@example.com)"
And the "members" select box should contain "Student 2 (s2@example.com)"
And the "members" select box should not contain "Student 3 (s3@example.com)"
And the "members" select box should contain "Student 1"
And the "members" select box should contain "Student 2"
And the "members" select box should not contain "Student 3"
# Checkbox (AJAX) - Checking "I set the field" and "I set the following fields to these values".
And I am on "Course 1" course homepage
And I add a "Lesson" to section "1"
@@ -1,30 +0,0 @@
@tool_behat
Feature: Verify that the inplace editable field works as expected
In order to use behat step definitions
As a test write
I need to ensure that the inplace editable works in forms
Background:
Given the following "course" exists:
| fullname | Course 1 |
| shortname | C1 |
And the following "activities" exist:
| activity | course | name | idnumber |
| forum | C1 | My first forum | forum1 |
| assign | C1 | My first assignment | assign1 |
| quiz | C1 | My first quiz | quiz1 |
And I log in as "admin"
And I am on "Course 1" course homepage with editing mode on
@javascript
Scenario: Using an inplace editable updates the name of an activity
When I set the field "Edit title" in the "My first assignment" "activity" to "Coursework submission"
Then I should see "Coursework submission"
And I should not see "My first assignment"
But I should see "My first forum"
And I should see "My first quiz"
And I set the field "Edit title" in the "Coursework submission" "activity" to "My first assignment"
And I should not see "Coursework submission"
But I should see "My first assignment"
And I should see "My first forum"
And I should see "My first quiz"
@@ -1,52 +0,0 @@
@tool_behat
Feature: Verify that keyboard steps work as expected
In order to use behat step definitions
As a test writer
I need to verify that the keyboard steps work as expected
@javascript
Scenario: Typing keys into a field causes them to be input
Given the following "users" exist:
| username | email | firstname | lastname | password |
| saffronr | saffron.rutledge@example.com | Saffron | Rutledge | flowerpower |
Given I click on "Log in" "link"
And I click on "Username" "field"
When I type "saffronr"
And I press the tab key
And I type "flowerpower"
And I press enter
Then I should see "You are logged in as Saffron Rutledge"
@javascript
Scenario: Using tab changes focus to the next or previous field
Given I click on "Log in" "link"
And I click on "Username" "field"
And the focused element is "Username" "field"
When I press the tab key
Then the focused element is "Password" "field"
And I press the shift tab key
And the focused element is "Username" "field"
@javascript
Scenario: Using the arrow keys allows me to navigate through menus
Given the following "users" exist:
| username | email | firstname | lastname |
| saffronr | saffron.rutledge@example.com | Saffron | Rutledge |
And I log in as "saffronr"
And I click on "Saffron Rutledge" "link" in the ".usermenu" "css_element"
When I press the up key
Then the focused element is "Log out" "link"
@javascript
Scenario: The escape key can be used to close a dialogue
Given the following "course" exists:
| fullname | C1|
| shortname | C1 |
And I log in as "admin"
And I am on "C1" course homepage
And I navigate to course participants
And I press "Enrol users"
And "Enrol users" "dialogue" should be visible
When I press the escape key
Then "Enrol users" "dialogue" should not be visible
@@ -26,11 +26,3 @@ Feature: List the system steps definitions
Given I set the field "Contains" to "homepage"
When I press "Filter"
Then I should see "Opens Moodle homepage."
@javascript
Scenario: Filtering by the multiple words pattern
Given I set the field "Contains" to "should exist"
When I press "Filter"
Then I should not see "There aren't steps definitions matching this filter"
And I should see "Checks the provided element and selector type exists in the current page."
And I should see "Checks that an element and selector type exists in another element and selector type on the current page."
@@ -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
+2 -2
View File
@@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2020061500; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2020060900; // Requires this Moodle version
$plugin->version = 2019111800; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2019111200; // Requires this Moodle version
$plugin->component = 'tool_behat'; // Full name of the plugin (used for diagnostics)
@@ -60,12 +60,7 @@ class tool_capability_settings_form extends moodleform {
$form->addElement('select', 'roles', get_string('roleslabel', 'tool_capability'), $roles, $attributes);
$form->setType('roles', PARAM_TEXT);
$filters = [];
$filters[] = $form->createElement('checkbox', 'onlydiff', get_string('onlydiff', 'tool_capability'));
$form->setType('onlydiff', PARAM_BOOL);
$form->addGroup($filters, 'filters', get_string('filters', 'tool_capability'), array('<br>'), false);
$form->addElement('submit', 'submitbutton', get_string('getreport', 'tool_capability'));
}
}
}
+2 -7
View File
@@ -66,7 +66,6 @@ $capabilities = array();
$rolestoshow = array();
$roleids = array('0');
$cleanedroleids = array();
$onlydiff = false;
if ($data = $form->get_data()) {
$roleids = array();
@@ -91,10 +90,6 @@ if ($data = $form->get_data()) {
}
}
}
if (isset($data->onlydiff)) {
$onlydiff = $data->onlydiff;
}
}
\tool_capability\event\report_viewed::create()->trigger();
@@ -108,7 +103,7 @@ $form->display();
// If we have a capability, generate the report.
if (count($capabilities) && count($rolestoshow)) {
/* @var tool_capability_renderer $renderer */
echo $renderer->capability_comparison_table($capabilities, $context->id, $rolestoshow, $onlydiff);
echo $renderer->capability_comparison_table($capabilities, $context->id, $rolestoshow);
}
// Footer.
@@ -143,7 +138,7 @@ function print_report_tree($contextid, $contexts, $allroles) {
// If there are any role overrides here, print them.
if (!empty($contexts[$contextid]->rolecapabilities)) {
$rowcounter = 0;
echo '<table class="generaltable table-striped"><tbody>';
echo '<table class="generaltable rolecaps"><tbody>';
foreach ($allroles as $role) {
if (isset($contexts[$contextid]->rolecapabilities[$role->id])) {
$permission = $contexts[$contextid]->rolecapabilities[$role->id];
@@ -22,18 +22,15 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['onlydiff'] = 'Show differences only';
$string['capabilitylabel'] = 'Capability:';
$string['capabilityreport'] = 'Capability overview';
$string['eventreportviewed'] = 'Report viewed';
$string['filters'] = 'Filter results';
$string['forroles'] = 'For roles {$a}';
$string['getreport'] = 'Get the overview';
$string['changeoverrides'] = 'Change overrides in this context';
$string['changeroles'] = 'Change role definitions';
$string['intro'] = 'This report shows, for a particular capability, what permission that capability has in the definition of every role (or a selection of roles), and everywhere in the site where that capability is overridden.';
$string['pluginname'] = 'Capability overview';
$string['nodifferences'] = 'There are no differences to show between selected roles in this context';
$string['reportforcapability'] = 'Report for capability \'{$a}\'';
$string['reportsettings'] = 'Report settings';
$string['roleslabel'] = 'Roles:';
+2 -11
View File
@@ -53,12 +53,7 @@ function tool_capability_calculate_role_data($capability, array $roles) {
$sql = 'SELECT DISTINCT con.path, 1
FROM {context} con
JOIN {role_capabilities} rc ON rc.contextid = con.id
WHERE capability = ? ' .
$sqlroletest .
// Context path should never be null, but can happen in old database with
// bad data (e.g. a course_module where the corresponding course no longer exists).
// We need to leave these out of the report to prevent errors.
' AND con.path IS NOT NULL';
WHERE capability = ? '.$sqlroletest;
$relevantpaths = $DB->get_records_sql_menu($sql, $params);
$requiredcontexts = array($systemcontext->id);
foreach ($relevantpaths as $path => $notused) {
@@ -93,10 +88,6 @@ function tool_capability_calculate_role_data($capability, array $roles) {
// Put the role capabilities into the context tree.
foreach ($rolecaps as $rolecap) {
if (!isset($contexts[$rolecap->contextid])) {
// Skip capabilities in orphaned contexts that are not in the tree.
continue;
}
$contexts[$rolecap->contextid]->rolecapabilities[$rolecap->roleid] = $rolecap->permission;
}
@@ -108,4 +99,4 @@ function tool_capability_calculate_role_data($capability, array $roles) {
}
return $contexts;
}
}
+8 -28
View File
@@ -72,11 +72,9 @@ class tool_capability_renderer extends plugin_renderer_base {
* @param array $capabilities An array of capabilities to show comparison for.
* @param int $contextid The context we are displaying for.
* @param array $roles An array of roles to show comparison for.
* @param bool $onlydiff show only different permissions
* @return string
*/
public function capability_comparison_table(array $capabilities, $contextid, array $roles, $onlydiff=false) {
static $capabilitycontexts = array();
public function capability_comparison_table(array $capabilities, $contextid, array $roles) {
$strpermissions = $this->get_permission_strings();
$permissionclasses = $this->get_permission_classes();
@@ -94,39 +92,25 @@ class tool_capability_renderer extends plugin_renderer_base {
}
$table->data = array();
$childcontextsids = [];
foreach ($capabilities as $capability) {
if (empty($capabilitycontexts[$capability])) {
$capabilitycontexts[$capability] = tool_capability_calculate_role_data($capability, $roles);
}
$contexts = $capabilitycontexts[$capability];
$contexts = tool_capability_calculate_role_data($capability, $roles);
$captitle = new html_table_cell(get_capability_string($capability) . html_writer::span($capability));
$captitle->header = true;
$row = new html_table_row(array($captitle));
$permissiontypes = array();
foreach ($roles as $role) {
if (isset($contexts[$contextid]->rolecapabilities[$role->id])) {
$permission = $contexts[$contextid]->rolecapabilities[$role->id];
} else {
$permission = CAP_INHERIT;
}
if (!in_array($permission, $permissiontypes)) {
$permissiontypes[] = $permission;
}
$cell = new html_table_cell($strpermissions[$permission]);
$cell->attributes['class'] = $permissionclasses[$permission];
$row->cells[] = $cell;
}
if (!$onlydiff || count($permissiontypes) > 1) {
$table->data[] = $row;
}
if (!empty($contexts[$contextid]->children)) {
$childcontextsids = array_merge($childcontextsids, $contexts[$contextid]->children);
$childcontextsids = array_unique($childcontextsids);
}
$table->data[] = $row;
}
// Start the list item, and print the context name as a link to the place to make changes.
@@ -141,15 +125,11 @@ class tool_capability_renderer extends plugin_renderer_base {
$title = get_string('permissionsincontext', 'core_role', $context->get_context_name());
$html = $this->output->heading(html_writer::link($url, $title), 3);
if (!empty($table->data)) {
$html .= html_writer::table($table);
} else {
$html .= html_writer::tag('p', get_string('nodifferences', 'tool_capability'));
}
$html .= html_writer::table($table);
// If there are any child contexts, print them recursively.
if (!empty($childcontextsids)) {
foreach ($childcontextsids as $childcontextid) {
$html .= $this->capability_comparison_table($capabilities, $childcontextid, $roles, $onlydiff);
if (!empty($contexts[$contextid]->children)) {
foreach ($contexts[$contextid]->children as $childcontextid) {
$html .= $this->capability_comparison_table($capabilities, $childcontextid, $roles, true);
}
}
return $html;
@@ -1,104 +0,0 @@
@tool @tool_capability
Feature: show capabilities for selected roles
In order to check roles capabilities
As an admin
I need to be able to customize capabilities report viewing only specific roles and capabilities
Background:
Given the following "roles" exist:
| shortname | name | archetype |
| studenteq | Studenteq | student |
| studentdf | Studentdf | student |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/course:changefullname | Allow | studentdf | System | |
| moodle/course:changeshortname | Prohibit | studentdf | System | |
| moodle/course:changeidnumber | Prevent | studentdf | System | |
And I log in as "admin"
And I navigate to "Users > Permissions > Capability overview" in site administration
Scenario: visualize capabilities table with a limited number of capabilities
When I set the following fields to these values:
| Capability: | moodle/course:changefullname, moodle/course:changeshortname |
| Roles: | Studentdf |
And I click on "Get the overview" "button"
Then I should see "moodle/course:changefullname" in the "comparisontable" "table"
And I should see "moodle/course:changeshortname" in the "comparisontable" "table"
And I should not see "moodle/course:changecategory" in the "comparisontable" "table"
Scenario: visualize an allow capability
When I set the following fields to these values:
| Capability: | moodle/course:changefullname |
| Roles: | Studentdf |
And I click on "Get the overview" "button"
Then I should see "Allow" in the "comparisontable" "table"
And I should not see "Prevent" in the "comparisontable" "table"
And I should not see "Prohibit" in the "comparisontable" "table"
And I should not see "Not set" in the "comparisontable" "table"
Scenario: visualize a prohibit capability
When I set the following fields to these values:
| Capability: | moodle/course:changeshortname |
| Roles: | Studentdf |
And I click on "Get the overview" "button"
Then I should not see "Allow" in the "comparisontable" "table"
And I should not see "Prevent" in the "comparisontable" "table"
And I should see "Prohibit" in the "comparisontable" "table"
And I should not see "Not set" in the "comparisontable" "table"
Scenario: visualize a not set capability
When I set the following fields to these values:
| Capability: | moodle/course:changecategory |
| Roles: | Studentdf |
And I click on "Get the overview" "button"
Then I should not see "Allow" in the "comparisontable" "table"
And I should not see "Prevent" in the "comparisontable" "table"
And I should not see "Prohibit" in the "comparisontable" "table"
And I should see "Not set" in the "comparisontable" "table"
Scenario: visualize more than one role
When I set the following fields to these values:
| Capability: | moodle/course:changecategory |
| Roles: | Student, Studentdf |
And I click on "Get the overview" "button"
Then I should see "Student" in the "comparisontable" "table"
And I should see "Studentdf" in the "comparisontable" "table"
And I should not see "Teacher" in the "comparisontable" "table"
Scenario: visualize all roles without selecting any role
When I set the following fields to these values:
| Capability: | moodle/course:changecategory |
And I click on "Get the overview" "button"
Then I should see "Student" in the "comparisontable" "table"
And I should see "Studentdf" in the "comparisontable" "table"
And I should see "Teacher" in the "comparisontable" "table"
Scenario: visualize all roles by selecting All option
When I set the following fields to these values:
| Capability: | moodle/course:changecategory |
| Roles: | All |
And I click on "Get the overview" "button"
Then I should see "Student" in the "comparisontable" "table"
And I should see "Studentdf" in the "comparisontable" "table"
And I should see "Teacher" in the "comparisontable" "table"
@javascript
Scenario: filter capability list using javascript
Given I should see "moodle/site:config" in the "Capability" "field"
And I should see "moodle/course:change" in the "Capability" "field"
When I wait until the page is ready
And I set the field "capabilitysearch" to "moodle/course:change"
Then I should see "moodle/course:change" in the "Capability" "field"
And I should not see "moodle/site:config" in the "Capability" "field"
@javascript
Scenario: selecting capabilities using filters
Given I should see "moodle/course:change" in the "Capability" "field"
When I wait until the page is ready
And I set the field "capabilitysearch" to "moodle/course:change"
When I set the following fields to these values:
| Capability: | moodle/course:changecategory |
| Roles: | Student |
And I set the field "capabilitysearch" to ""
And I click on "Get the overview" "button"
Then I should see "moodle/course:changecategory" in the "comparisontable" "table"
@@ -1,133 +0,0 @@
@tool @tool_capability
Feature: Show capabilities for multiple contexts
In order to check roles capabilities
As an admin
I need to be able to see capability overrides on several contexts
Background:
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
| Course 2 | C2 | 0 |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| enrol/category:config | Allow | student | Course | C1 |
| enrol/cohort:unenrol | Allow | student | Course | C2 |
And I log in as "admin"
And I navigate to "Users > Permissions > Capability overview" in site administration
Scenario: Show capabilities table with one capability with overrides
When I set the following fields to these values:
| Capability: | enrol/category:config |
| Roles: | Student |
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should see "Permissions in Category: Miscellaneous"
And I should see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
Scenario: Show capabilities table with one capability without overrides
When I set the following fields to these values:
| Capability: | enrol/cohort:config |
| Roles: | Student |
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should not see "Permissions in Category: Miscellaneous"
And I should not see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
Scenario: Show capabilities table with two capabilities, 1st without overrides and 2nd with
When I set the following fields to these values:
| Capability: | enrol/category:synchronised, enrol/category:config |
| Roles: | Student |
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should see "Permissions in Category: Miscellaneous"
And I should see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
Scenario: Show capabilities table with two capabilities, 1st with overrides and 2nd without
When I set the following fields to these values:
| Capability: | enrol/category:config, enrol/cohort:config |
| Roles: | Student |
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should see "Permissions in Category: Miscellaneous"
And I should see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
Scenario: Show capabilities table with two capabilities, none with overrides
When I set the following fields to these values:
| Capability: | enrol/category:synchronised, enrol/cohort:config |
| Roles: | Student |
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should not see "Permissions in Category: Miscellaneous"
And I should not see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
Scenario: Show capabilities table with capability with override and no role selected
When I set the following fields to these values:
| Capability: | enrol/category:config |
| Roles: | |
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should see "Permissions in Category: Miscellaneous"
And I should see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
Scenario: Show capabilities table with capability without override and no role selected
When I set the following fields to these values:
| Capability: | enrol/cohort:config |
| Roles: | |
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should not see "Permissions in Category: Miscellaneous"
And I should not see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
Scenario: Show capabilities table with capability with two overrides on different contexts
When I set the following fields to these values:
| Capability: | enrol/category:config, enrol/cohort:unenrol |
| Roles: | |
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should see "Permissions in Category: Miscellaneous"
And I should see "Permissions in Course: Course 1"
And I should see "Permissions in Course: Course 2"
Scenario: Show capabilities table with capability with override and only diff
When I set the following fields to these values:
| Capability: | enrol/category:config |
| Roles: | Student, Teacher |
And I set the field "Show differences only" to "1"
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should see "Permissions in Category: Miscellaneous"
And I should see "There are no differences to show between selected roles in this context"
And I should see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
Scenario: Show capabilities table with capability without override and only diff and same capability
When I set the following fields to these values:
| Capability: | enrol/category:synchronised |
| Roles: | Student, Teacher |
And I set the field "Show differences only" to "1"
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should see "There are no differences to show between selected roles in this context"
And I should not see "Permissions in Category: Miscellaneous"
And I should not see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
Scenario: Show capabilities table with two capabilities only one override and only diff checked
When I set the following fields to these values:
| Capability: | enrol/category:config, enrol/cohort:config |
| Roles: | Student, Teacher |
And I set the field "Show differences only" to "1"
And I click on "Get the overview" "button"
Then I should see "Permissions in System"
And I should see "Permissions in Category: Miscellaneous"
And I should see "There are no differences to show between selected roles in this context"
And I should see "Permissions in Course: Course 1"
And I should not see "Permissions in Course: Course 2"
@@ -1,67 +0,0 @@
@tool @tool_capability
Feature: show only differences between roles for selected capabilities
In order to check roles capabilities
As an admin
I need to be able to filter capabilities report viewing only role differences
Background:
Given the following "roles" exist:
| shortname | name | archetype |
| studenteq | Studenteq | student |
| studentdf | Studentdf | student |
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/course:changefullname | Allow | studentdf | System | |
| moodle/course:changeshortname | Prohibit | studentdf | System | |
And I log in as "admin"
And I navigate to "Users > Permissions > Capability overview" in site administration
Scenario: Compare identical roles
When I set the following fields to these values:
| Capability: | moodle/course:changefullname, moodle/course:changeshortname, moodle/course:changeidnumber, moodle/course:changesummary |
| Roles: | Student, Studenteq |
And I set the field "Show differences only" to "1"
And I click on "Get the overview" "button"
Then I should see "There are no differences to show between selected roles in this context"
Scenario: Compare different roles
When I set the following fields to these values:
| Capability: | moodle/course:changefullname, moodle/course:changeshortname, moodle/course:changeidnumber, moodle/course:changesummary |
| Roles: | Student, Studentdf |
And I set the field "Show differences only" to "1"
And I click on "Get the overview" "button"
Then I should not see "There are no differences to show between selected roles in this context"
And I should see "moodle/course:changefullname" in the "comparisontable" "table"
And I should see "moodle/course:changeshortname" in the "comparisontable" "table"
And I should not see "moodle/course:changesummary" in the "comparisontable" "table"
Scenario: Compare different roles but comparing capabilities that are equals on both
When I set the following fields to these values:
| Capability: | moodle/course:changeidnumber, moodle/course:changesummary |
| Roles: | Student, Studentdf |
And I set the field "Show differences only" to "1"
And I click on "Get the overview" "button"
Then I should see "There are no differences to show between selected roles in this context"
Scenario: Compare all roles without selecting specific role
When I set the following fields to these values:
| Capability: | moodle/course:changefullname, moodle/site:config |
And I set the field "Show differences only" to "1"
And I click on "Get the overview" "button"
Then I should not see "moodle/site:config" in the "comparisontable" "table"
And I should see "moodle/course:changefullname" in the "comparisontable" "table"
Scenario: Compare all roles without selecting specific role on not defined capability
When I set the following fields to these values:
| Capability: | moodle/site:config |
And I set the field "Show differences only" to "1"
And I click on "Get the overview" "button"
Then I should see "There are no differences to show between selected roles in this context"
Scenario: Comparing only one role
When I set the following fields to these values:
| Capability: | moodle/course:changefullname, moodle/course:changeshortname, moodle/course:changeidnumber, moodle/course:changesummary |
| Roles: | Student |
And I set the field "Show differences only" to "1"
And I click on "Get the overview" "button"
Then I should see "There are no differences to show between selected roles in this context"

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