Compare commits

..

862 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) 31059fd653 Moodle release 2.7.2 2014-09-06 13:01:52 +02:00
Eloy Lafuente (stronk7) cbdde9a495 weekly release 2.7.1+ 2014-09-04 19:55:11 +02:00
Eloy Lafuente (stronk7) ce65706ceb Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-09-04 19:55:06 +02:00
Marina Glancy 65f8dc31d8 MDL-46861 webservice: reverted unnecessary change in 2.7 2014-09-04 11:40:48 +08:00
Eloy Lafuente (stronk7) 779303d869 Merge branch 'MDL-47031-27-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_27_STABLE 2014-09-03 19:25:55 +02:00
Helen Foster 28c9a1993d MDL-47031 Merge English strings from the en_fix language pack 2014-09-03 10:59:31 +02:00
Marina Glancy 8f866fa1c3 Merge branch 'm27_MDL-46639' of git://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-09-03 16:59:16 +08:00
Dan Marsden a556c4d02c MDL-46639 SCORM: incorrect setting of launch param, it is done in scorm_parse_aicc 2014-09-03 20:21:31 +12:00
Charles Fulton 87c0820260 MDL-30414 block_private_files: convert button to inline link 2014-09-03 01:09:32 +02:00
Damyon Wiese 0444bcffc7 Merge branch 'wip-MDL-47052-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-09-02 15:30:46 +08:00
Marina Glancy 15990b65ac MDL-47052 report_participation: fixed bug when filtering by first letter 2014-09-02 15:01:32 +08:00
Michael de Raadt 1f3066f197 MDL-46619 Forum: link to the discussion only if users cannot see posts. 2014-09-02 10:10:05 +08:00
Michael de Raadt 532c25d5bd MDL-46619 Forum: only output last poster's name if user can view it. 2014-09-02 10:10:02 +08:00
Marina Glancy c256614eab Merge branch 'MDL-45952_27' of git://github.com/Syxton/moodle into MOODLE_27_STABLE 2014-09-02 09:58:58 +08:00
Eloy Lafuente (stronk7) 0f67177a54 Merge branch 'MDL-46633_m27' of https://github.com/shashirepo/moodle into MOODLE_27_STABLE 2014-09-02 02:12:22 +02:00
Eloy Lafuente (stronk7) 2e6e70ccd2 Merge branch 'wip_MDL-46679_m27_addonenv' of https://github.com/skodak/moodle into MOODLE_27_STABLE 2014-09-02 02:08:43 +02:00
Eloy Lafuente (stronk7) a13ae2ac2d Merge branch 'MDL-46979_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-09-02 01:48:56 +02:00
Eloy Lafuente (stronk7) e19f164fc7 Merge branch 'MDL-45909_install_M27' of https://github.com/nadavkav/moodle into MOODLE_27_STABLE 2014-09-02 01:46:34 +02:00
Eloy Lafuente (stronk7) 702c4b1206 Merge branch 'MDL-43639_updatePassEveryLogin_27' of https://github.com/moodlerooms/moodle into MOODLE_27_STABLE 2014-09-02 01:07:43 +02:00
Damyon Wiese 17a31c7a1f Merge branch 'MDL-46852-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-09-01 16:16:33 +08:00
Damyon Wiese 7b258d7186 Merge branch 'wip-MDL-46540-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-09-01 16:08:00 +08:00
Marina Glancy 609a129b84 MDL-46540 stats: missing include file
Thanks to Vadim Dvorovenko for finding a bug and providing a solution
2014-09-18 03:40:17 +08:00
Marina Glancy ecd01922e9 Merge branch 'MDL-46861_27_STABLE' of https://github.com/Lightwork-Marking/moodle into MOODLE_27_STABLE 2014-09-01 16:07:05 +08:00
Damyon Wiese c8782c56d7 Merge branch 'MDL-46902_m27' of git://github.com/markn86/moodle into MOODLE_27_STABLE 2014-09-01 15:54:18 +08:00
Damyon Wiese 4deed68f49 Merge branch 'MDL-46911-27' of https://github.com/bostelm/moodle into MOODLE_27_STABLE 2014-09-01 15:45:52 +08:00
Damyon Wiese 40b705e153 Merge branch 'm27_MDL-46985_7ZIP_RAR_MIME_types_missing' of https://github.com/scara/moodle into MOODLE_27_STABLE 2014-09-01 15:36:22 +08:00
Damyon Wiese 3b35ea4686 Merge branch 'm27_MDL-46961' of https://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-09-01 15:29:03 +08:00
Damyon Wiese 5a9dde69b1 Merge branch 'wip-mdl-46670-m27' of https://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-09-01 15:23:23 +08:00
Damyon Wiese a02ad260e0 Merge branch 'MDL-45818_m27' of git://github.com/markn86/moodle into MOODLE_27_STABLE 2014-09-01 15:17:57 +08:00
Marina Glancy 15f15ccddd Merge branch 'm27_MDL-46639' of git://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-09-01 14:34:52 +08:00
Marina Glancy 346e41d042 Merge branch 'MDL-46539-fix-27' of https://github.com/jmarthaler/moodle into MOODLE_27_STABLE 2014-09-01 14:34:40 +08:00
Frederic Massart 36bf61e152 MDL-46852 mod_lesson: More accurate comparison of shortanswer answers 2014-09-01 14:25:31 +08:00
Damyon Wiese bc180cd111 Merge branch 'wip-MDL-39233-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-09-01 13:40:38 +08:00
Damyon Wiese b10d7c59ae MDL-46619 Forum: whitespace fixes 2014-09-01 11:35:26 +08:00
Damyon Wiese 6aee251874 Merge branch 'MDL-46619-2.7-visisble-authors-qanda' of https://github.com/amandadoughty/moodle into MOODLE_27_STABLE 2014-09-01 11:00:35 +08:00
Damyon Wiese d1e9bdfbc8 Merge branch 'm27_MDL-46737' of https://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-09-01 10:55:22 +08:00
zbdd 0c18577317 MDL-37312 backup: Keep course idnumber on same site course restore
When the course idnumber is set during a same site course restore,
retain the course idnumber if there are no duplicates.
2014-09-01 10:44:50 +08:00
Rajesh Taneja 255221acdf MDL-46670 report_participation: Look for records in legacy and current
Priority log store will have current information, so
make sure to get information and aggregate that with
legacy data
2014-09-01 10:24:51 +08:00
Matteo Scaramuccia 93bd10c300 MDL-46985 Added 7-Zip and RAR MIME types. 2014-08-31 22:39:37 +02:00
Petr Skoda 03bdfbd37b MDL-39840 environment: add support for environment.xml in plugins
New features:

* environment.xml files in all types of plugins
* support for plugin strings via new optional plugin attribute in FEEDBACK
* support for class_name::method_name custom callbacks and classloader
2014-09-01 08:39:11 +12:00
AMOS bot d7de792dac Automatically generated installer lang files 2014-09-01 00:05:42 +08:00
Mark Nelson 763e5d6c83 MDL-45818 core_message: use system context if user no longer exists 2014-08-29 16:20:08 -07:00
Mark Nelson 436c7825b1 MDL-46902 core_course: display meaningful message when no courses found 2014-08-29 14:31:55 -07:00
AMOS bot 9074f5914f Automatically generated installer lang files 2014-08-30 00:05:30 +08:00
Paul Charsley 62ff078fcf MDL-46861 added missing required field areaname 2014-08-29 10:53:38 +12:00
Nadav Kavalerchik df174952fd MDL-45909 install/css: Left align input form fields on Install pages,in RTL mode 2014-08-28 22:58:02 +03:00
Tim Hunt 9d97806c7e MDL-46979 backup: remove duplicate string.
Thanks to Matt Sammarco for spotting this.
2014-08-28 20:45:00 +01:00
Eloy Lafuente (stronk7) e6f1c141bf weekly release 2.7.1+ 2014-08-28 19:12:21 +02:00
Eloy Lafuente (stronk7) 687f244a6f Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-08-28 19:12:14 +02:00
AMOS bot 461532ecfc Automatically generated installer lang files 2014-08-29 00:05:30 +08:00
shashirepo 16b6239a88 MDL-46633 chat: Chat send button gets stuck 2014-08-28 15:01:49 +05:30
Syxton 8121a2fad0 MDL-45952 feedback: non-respondents in groupings
Fixes feedback non-respondents list to show only members in groups in
the selected grouping if "Available for group members only" is selected.
2014-08-27 15:14:08 -04:00
Mark Nielsen d78e72a940 MDL-43639: Prevent user updated event on every login
If auth plugin prevents local passwords, then user
is updated and event is triggered on every login.
2014-08-27 11:24:51 -07:00
Jon Marthaler 16a175de06 MDL-46539 assign calendar: Fix lastcron value for assign cron 2014-08-27 11:15:38 -05:00
AMOS bot ec4f31f984 Automatically generated installer lang files 2014-08-28 00:05:33 +08:00
Damyon Wiese 323a7a151b Merge branch 'MDL-46812-27-fixup' of https://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-08-27 10:49:08 +08:00
Frederic Massart 14eb0c478d MDL-46812 gradereport_grader: Hide vertical scrollbar of scroller 2014-08-27 10:44:02 +08:00
Damyon Wiese e8b487e010 Merge branch 'wip-MDL-39888-27' of git://github.com/abgreeve/moodle into MOODLE_27_STABLE 2014-08-27 09:56:58 +08:00
Faisal Kaleem 641351118e MDL-46961 SCORM: JavaScript Hoisting issue. 2014-08-27 13:08:59 +12:00
Eloy Lafuente (stronk7) 12e42d2246 MDL-46875 tinymce: keep stable version YYYMMDD constant
Note this has been integrated together with previous commit
so nobody should get a "downgrade" ever (but Brian, I'm sorry :-)
2014-08-27 02:11:59 +02:00
Eloy Lafuente (stronk7) 0a668af390 Merge branch 'm27_MDL-46875' of https://github.com/totara/moodle into MOODLE_27_STABLE 2014-08-27 02:03:37 +02:00
Damyon Wiese 22290d726a Revert "Merge branch 'MDL-46917-27' of git://github.com/andrewnicols/moodle into MOODLE_27_STABLE"
This reverts commit 439f2e7e83, reversing
changes made to b523d5bc33.
2014-08-26 17:20:41 +08:00
Henning Bostelmann 03fc135cb6 MDL-46911 Database activity: jump to correct place in list after (un)approve 2014-08-26 10:17:07 +01:00
Marina Glancy 0459ed43e1 MDL-39233 mod_url: added unittest for get_course_content 2014-08-26 13:55:11 +08:00
Jason 928f531307 MDL-39233 mod_url: fix php notice 2014-08-26 13:55:10 +08:00
Damyon Wiese 767dfb307d MDL-46842 assign: Fix for unit tests - previous patch was completely ignoring manually reopening attempts. 2014-08-26 10:34:03 +08:00
Brian Barnes 3efe531af4 MDL-46875 tinymce: Fixed issue with full screen and spelling 2014-08-26 13:23:01 +12:00
Eloy Lafuente (stronk7) ef54b1272a Merge branch 'MDL-46477_m27' of https://github.com/shashirepo/moodle into MOODLE_27_STABLE 2014-08-26 02:24:31 +02:00
Eloy Lafuente (stronk7) 2e97e57edb Merge branch 'MDL-46753-27' of git://github.com/lameze/moodle into MOODLE_27_STABLE 2014-08-26 02:08:17 +02:00
Eloy Lafuente (stronk7) 2f64ea2a2e Merge branch 'm27_MDL-46842' of https://github.com/greg-or/moodle-mod_assign into MOODLE_27_STABLE 2014-08-26 01:59:25 +02:00
Eloy Lafuente (stronk7) 3fda0a9736 Merge branch 'MDL-46868_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-08-26 01:40:48 +02:00
Eloy Lafuente (stronk7) 0047e4612c Merge branch 'm27_MDL-46816' of https://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-08-26 00:10:50 +02:00
Eloy Lafuente (stronk7) 44088a5aeb Merge branch 'wip-MDL-46874-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-08-25 22:11:17 +02:00
Eloy Lafuente (stronk7) 2507ecbd3e Merge branch 'm27_MDL-46900' of https://github.com/totara/moodle into MOODLE_27_STABLE 2014-08-25 20:55:29 +02:00
Damyon Wiese 439f2e7e83 Merge branch 'MDL-46917-27' of git://github.com/andrewnicols/moodle into MOODLE_27_STABLE 2014-08-25 16:55:08 +08:00
Marina Glancy b523d5bc33 Merge branch 'MDL-46894_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-08-25 16:53:40 +08:00
Marina Glancy 63e0fee364 Merge branch 'MDL-46916_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-08-25 16:50:05 +08:00
Damyon Wiese 063c6e23d4 Merge branch 'MDL-46923_m27' of git://github.com/markn86/moodle into MOODLE_27_STABLE 2014-08-25 16:48:11 +08:00
Damyon Wiese 5c1f1690bb Merge branch 'wip_MDL-43918_m27_cm' of https://github.com/skodak/moodle into MOODLE_27_STABLE 2014-08-25 16:44:50 +08:00
Marina Glancy b46ad4bdd5 Merge branch 'M27_MDL46887_assignment_file_max_size' of git://github.com/Dave-B/moodle into MOODLE_27_STABLE 2014-08-25 16:29:33 +08:00
Marina Glancy 8001ddd8b2 Merge branch 'MDL-46895_27' of git://github.com/colchambers/moodle into MOODLE_27_STABLE 2014-08-25 16:28:02 +08:00
Rex Lorenzo b9894e1e9f MDL-46776 gradereport_grader: Improve Grader report user interface
* Adding assignments to test course generator to more easily test the grader report with large number of students and graded activities.
2014-08-25 16:20:49 +08:00
Dan Marsden 0e26b1d309 MDL-46639 mod_scorm: Fix load of simple AICC content
Thanks to Ian Wild for the report and suggested patch.
2014-08-25 20:01:45 +12:00
Marina Glancy 5cc6700f27 Merge branch 'MDL-46904-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-08-25 14:45:38 +08:00
Damyon Wiese 090f8f300d Merge branch 'wip-MDL-46812_M27' of git://github.com/lazydaisy/moodle into MOODLE_27_STABLE 2014-08-25 14:03:18 +08:00
Damyon Wiese fc36873f61 Merge branch 'wip-MDL-46703-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-08-25 13:53:52 +08:00
Marina Glancy 315392626b Merge branch 'MDL-46918_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-08-25 12:01:27 +08:00
Petr Skoda c27add8d87 MDL-43918 add more validation to $modulename parameter when fetching cms 2014-08-25 12:19:11 +12:00
Adrian Greeve ae18cf2461 MDL-39888 mnet: Added a notification that logs may not be displayed in the log report.
In Moodle 2.7+ we are using the new logging system and if legacy logs are not enabled
(on the client system) then no logs will be displayed.
2014-08-23 11:55:57 +08:00
Colin Chambers deab7fda59 MDL-46895 qtype_calculated_find_formula_errors not defined causes Calculated question type test to fail 2014-08-22 14:03:36 +01:00
Andrew Nicols af3085d2d5 MDL-46917 atto: Focus on the editor when the form label is selected 2014-08-22 15:00:20 +08:00
Eloy Lafuente (stronk7) 55a8f72251 MDL-46918 ddl: cover behavior with unit test 2014-08-21 18:33:39 +01:00
Tim Hunt af02385d49 MDL-46918 ddl: fix error when renaming table already exists 2014-08-21 18:33:39 +01:00
AMOS bot c5b3017b49 Automatically generated installer lang files 2014-08-22 00:05:31 +08:00
Tim Hunt 5ec684b353 MDL-46916 behat: improve question state test. 2014-08-21 14:15:22 +01:00
Tim Hunt 0a03803081 MDL-46894 make Behat backup steps more robust. 2014-08-21 14:15:08 +01:00
Tim Hunt 6527b097e8 MDL-46868 glossary / filter: performance, check modinfo sooner.
Since we need to check modinfo anyway, do that as soon as possible so we
can get a performance win if there are no glossaries in the course.
2014-08-21 14:14:56 +01:00
Dan Poltawski 8f5c4f6b34 MDL-46880 mod_forum: move cron to scheduled task
Note that this is a very basic conversion without doing any refactoring
to split the tasks up better. That will come in MDL-44734, this is about
being a safe backportable change to give admins better control over the
running of the forum cron task.

Conflicts:
	mod/forum/version.php
2014-08-21 13:46:33 +01:00
Amanda Doughty b1325427ec MDL-46619 Forum: author showing in Q and A forum 2014-08-21 13:13:15 +01:00
shashirepo 5de6795ec0 MDL-46477 chat:hard coded string in mod/chat 2014-08-21 17:32:34 +05:30
Mary Evans 0dc138d47c MDL-46812 grade/report/grader: Need to tie up loose ends in Gradebook after MDL-43824
Squashed commit of the following:

commit 4ae57a823ba6fa1d627d2bad296cdf905b1930ee
Author: Mary Evans <lazydaisy@visible-expression.co.uk>
Date:   Thu Aug 21 02:05:35 2014 +0100

    MDL-46812 grade/report/grader: Reset previous commit for left scroller.

commit 7e3d27d3cc9d22ffe8e1dbb54eb705a65153a6b0
Author: Mary Evans <lazydaisy@visible-expression.co.uk>
Date:   Thu Aug 21 01:23:09 2014 +0100

    MDL-46812 grade/report/grader: Added jsenabled css body class to rtl style.

commit 0b5c3341b79c4b4bfefcd82eef1940964448ccba
Author: Mary Evans <lazydaisy@visible-expression.co.uk>
Date:   Thu Aug 21 01:13:34 2014 +0100

    MDL-46812 theme_base: Removed more redundant CSS.

commit 8c44e8a4c644a9139d1750af498bed6a14decf5c
Author: Mary Evans <lazydaisy@visible-expression.co.uk>
Date:   Wed Aug 20 15:44:42 2014 +0100

    MDL-46812 theme_base: Removed redundent grade/report/grader CSS in style/grade.css

commit 7c69b546fab03163d3863044ab9d1d9130c1cdd9
Author: Mary Evans <lazydaisy@visible-expression.co.uk>
Date:   Thu Aug 14 12:50:14 2014 +0100

    MDL-46812 grade/report/grader: Need to tie up loose ends in Gradebook after MDL-43824

        1. fixed gradebook layout when JS is disabled
        2. added height and background color to scroller when JS is enabled
        3. removed redundent top margin in user-grades table
2014-08-21 11:23:27 +01:00
Mark Nelson f367cfcbef MDL-46923 core_behat: fixed typos in function names 2014-08-20 22:11:31 -07:00
Brian Barnes c2b526c484 MDL-46900 theme: allowed more than 1 nav collapse element 2014-08-21 15:01:58 +12:00
Marina Glancy b01092111c weekly release 2.7.1+ 2014-08-21 10:18:55 +08:00
Marina Glancy 8ef945280c Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-08-21 10:18:53 +08:00
AMOS bot fbfeb98d39 Automatically generated installer lang files 2014-08-21 00:05:30 +08:00
Damyon Wiese 24276da9ce MDL-46904 core_task: Gracefully handle rubbish entries in the tasks table. 2014-08-20 17:02:02 +08:00
Gregory Faller 1f316df7d9 MDL-46842: Reopen assignment submissions when using offline grading worksheet 2014-08-20 17:28:38 +09:30
Damyon Wiese 467aefd1a6 Merge branch 'MDL-45029-27' of git://github.com/lameze/moodle into MOODLE_27_STABLE
Conflicts:
	course/modlib.php
2014-08-20 13:58:58 +08:00
Simey Lameze f354a67357 MDL-45029 core_course: set aggregationcoef while creating a new course module 2014-08-20 12:07:34 +08:00
Mark Nelson 32193155f5 MDL-46188 core_course: use correct hide/show icon 2014-08-20 12:04:59 +08:00
Damyon Wiese b3f6c093aa Merge branch 'MDL-45029-27' of git://github.com/lameze/moodle into MOODLE_27_STABLE 2014-08-20 10:21:46 +08:00
Eloy Lafuente (stronk7) 82a678c91e Merge branch 'MDL-46302-atto-float-right' of git://github.com/uhunkler/moodle into MOODLE_27_STABLE 2014-08-20 00:57:22 +02:00
Mark Nielsen f3f21f18c4 MDL-46536: OAuth signature fails with inconsistent new lines
When the LTI intro contains a single \n or
\r newline character then the OAuth signature
fails.  All newlines should be \r\n

Conflicts:
	mod/lti/tests/locallib_test.php
2014-08-19 21:51:13 +02:00
AMOS bot 05c7b75672 Automatically generated installer lang files 2014-08-20 00:05:29 +08:00
Mark Nielsen 39c01271f0 MDL-46051 mod_lti: Not enough data passed to lti_extend_lti_services 2014-08-19 17:08:59 +02:00
Mark Nielsen c09f63c5ac MDL-46051 mod_lti: Fixing errors in unknown_service_api_called class
Also adding unit tests.
2014-08-19 17:08:47 +02:00
Eloy Lafuente (stronk7) 9f9bcb251c Merge branch 'MDL-46301' of https://github.com/michaelwheeler/moodle into MOODLE_27_STABLE 2014-08-19 15:37:26 +02:00
David Balch 39864d9e88 MDL-46887 mod_assign: Enforce module's maxbytes setting at submission. 2014-08-19 14:01:15 +01:00
Marina Glancy 2a46808ed3 Merge branch 'wip-mdl-46327-m27' of git://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-08-19 17:39:40 +08:00
Rajesh Taneja 4221300426 MDL-46327 phpunit: drop_table should be used, rather then drop_temp_table 2014-08-19 17:17:50 +08:00
Simey Lameze d14fe6017f MDL-45029 core_course: set aggregationcoef while creating a new course module 2014-08-19 17:08:10 +08:00
Marina Glancy cdc0a8db3f MDL-46538 theme_base: recompiled moodle.css 2014-08-19 16:52:42 +08:00
Marina Glancy 9ddb811866 Merge branch 'MDL-46538_M27' of git://github.com/lazydaisy/moodle into MOODLE_27_STABLE 2014-08-19 16:52:08 +08:00
Petr Skoda 29dd7397e2 MDL-46711 session: add support for multiple servers to memcache session driver
Includes proper definition of object properties which fixes handling of timout default.
2014-08-19 16:41:26 +08:00
Marina Glancy bef5900bdb Merge branch 'MDL-46281-MOODLE_27_STABLE' of git://github.com/lucisgit/moodle into MOODLE_27_STABLE 2014-08-19 16:22:24 +08:00
Marina Glancy 623379d82b Merge branch 'MDL-46829_M27' of git://github.com/lazydaisy/moodle into MOODLE_27_STABLE 2014-08-19 14:21:18 +08:00
Marina Glancy 8480fd9364 Merge branch 'MDL-46833-MOODLE_27_STABLE' of git://github.com/lucisgit/moodle into MOODLE_27_STABLE 2014-08-19 14:21:09 +08:00
Damyon Wiese 5faaf18173 Merge branch 'MDL-41513-Scrollbar_not_working-27' of https://github.com/MorrisR2/moodle into MOODLE_27_STABLE 2014-08-19 14:07:10 +08:00
Marina Glancy d23d771071 Merge branch 'wip-mdl-46817-m27' of git://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-08-19 14:04:05 +08:00
Marina Glancy 5f690a9be6 Merge branch 'MDL-43197-27-2nd' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-08-19 13:26:01 +08:00
Damyon Wiese 95dae00235 Merge branch 'MDL-46188_m27' of https://github.com/shashirepo/moodle into MOODLE_27_STABLE 2014-08-19 13:14:45 +08:00
Marina Glancy 7c4e3db7c0 MDL-46874 gradereport: replace usage of class hidden with dimmed_text 2014-08-19 12:56:11 +08:00
Michael Wheeler 0ed1b7d277 MDL-46794 install: Fixed typo in config-dist.php 2014-08-19 11:26:49 +08:00
Marina Glancy 690988d958 Merge branch 'm27_MDL-46775' of git://github.com/totara/moodle into MOODLE_27_STABLE 2014-08-19 11:21:52 +08:00
Marina Glancy 26b3b4e80e Merge branch 'wip-mdl-46327-m27' of git://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-08-19 10:50:34 +08:00
Marina Glancy a5e67c5bcc Merge branch 'wip-MDL-46791-MOODLE_27_STABLE' of git://github.com/satrun77/moodle into MOODLE_27_STABLE 2014-08-19 10:50:22 +08:00
Frederic Massart 01327cfcf5 MDL-43197 gradereport_user: Parents/mentors can see all the relevant grades 2014-08-19 10:48:11 +08:00
Rajesh Taneja 1b775e96c1 MDL-46327 phpunit: Fixed oracle fail 2014-08-19 10:13:55 +08:00
Marina Glancy ef467ee957 MDL-46691 mod_choice: apply filters to user input 2014-08-19 03:04:57 +02:00
James Henestofel 247b756248 MDL-42231 auth: custom profile fields to support numbers at the end.
For data mapping LDAP or CAS.  Change order of fieldname display checks to verify
custom profile fields first to allow custom field shortname to contain number at the end.
2014-08-19 02:43:44 +02:00
Eloy Lafuente (stronk7) 1eedfdf2c0 Merge branch 'MDL-44894_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-08-19 02:34:48 +02:00
Eloy Lafuente (stronk7) d4bbbedbde Merge branch 'wip_MDL-46552_m27_memcached' of https://github.com/skodak/moodle into MOODLE_27_STABLE 2014-08-19 02:29:06 +02:00
Eloy Lafuente (stronk7) c8abe81b99 Merge branch 'MDL-45874-27' of https://github.com/danielneis/moodle into MOODLE_27_STABLE 2014-08-19 02:12:19 +02:00
Eloy Lafuente (stronk7) 7943aabfbe Merge branch 'wip-MDL-46826-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-08-18 20:06:54 +02:00
Eloy Lafuente (stronk7) 2de77919d8 Merge branch 'wip-MDL-46589-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-08-18 19:48:42 +02:00
Marina Glancy 5094443f65 MDL-41284 stats: fix sql query from MDL-41284 2014-08-18 19:42:41 +02:00
Eric Merrill 9ec65dc485 MDL-46766 auth_cas: Upgrading to phpCAS 1.3.3 2014-08-18 16:38:55 +08:00
Simey Lameze 068ef548de MDL-46753 auth_cas: Replace hardcoded logout_return_url to user defined URL.
Credit goes to Mitsuru Udagawa, thanks!
2014-08-18 12:57:34 +08:00
Damyon Wiese bad563d2f4 Merge branch 'm27_MDL-46760' of https://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-08-18 12:41:12 +08:00
Rajesh Taneja 50eb74065b MDL-46817 behat: Step to check if value exist/not in table column 2014-08-18 10:01:06 +08:00
AMOS bot febd8afc8e Automatically generated installer lang files 2014-08-18 00:07:49 +08:00
Marina Glancy cac959739b MDL-46703 mod_data: limit the width of select element when editing templates
Thanks to Hittesh for the provided solution
2014-08-16 13:27:27 +08:00
Marina Glancy cef5600303 MDL-46589 scheduled task does not send emails
Thanks to  Luděk Šulák  for the patch
2014-08-16 12:48:16 +08:00
Mary Evans 63a2e24bc2 MDL-46538 theme_base/theme_bootstrapbase: Removed incorrect RTL CSS. 2014-08-16 01:11:31 +01:00
Daniel Neis 35eefad6b3 MDL-45874 Fix access to users reports in navigation when using separate groups 2014-08-15 17:06:39 -03:00
Rajesh Taneja c8121c53d1 MDL-46817 behat: Table selector support css
Previously table selector supported id and caption only.
But in few cases we don't have proper id, so added support
for css
2014-08-15 13:17:06 +08:00
Marina Glancy 74f6a6ae5b MDL-46826 forum: make sql query indexed, regression from MDL-31089 2014-08-15 11:46:01 +08:00
Ray Morris d560fb3e26 MDL-41513 mod_quiz: Scrollbar not working in JS Security Popup 2014-08-14 15:44:51 -05:00
Ruslan Kabalin 213220c159 MDL-46833 mod_assign: Fix assignment view when available for group members only.
When assignment is "Available for group members only" and no users with
mod/assign:submit role permision is enrolled (students),
groups_filter_users_by_course_module_visible is causing error (as $users
array is empty). The patch resolves the issue.
2014-08-14 16:04:54 +01:00
shashirepo baa476ce92 MDL-46188 course:show/hide button disappears after action 2014-08-14 20:32:31 +05:30
Mary Evans 795dc143c2 MDL-46829 theme_base: Fixed regression in Base casued by MDL-45031. 2014-08-14 14:27:06 +01:00
Tony Butler a18e060c5b MDL-46281 core_backup: Add class_exists check for backup_<mod>_activity_task
Signed-off-by: Tony Butler <tonyjbutler@gmail.com>
2014-08-14 12:57:15 +01:00
Mohamed Alsharaf 84ebf61b82 MDL-46791 question: fixed incorrect 5th param for tag_set() 2014-08-14 23:51:41 +12:00
Tim Hunt 300dff939f MDL-44894 question editing: fix validation with odd permissions
For users with edit permissions, but not add permissions, it was
impossible to save the editing form. The validation assuemd this value
was present, but it was not. Other code checks this field too, so I
added it rather than changing the validation and all the other uses.
2014-08-14 11:26:25 +01:00
Marina Glancy 2aa6dd4c60 weekly release 2.7.1+ 2014-08-14 14:52:31 +08:00
Marina Glancy e59d25c944 Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-08-14 14:52:27 +08:00
Dan Marsden a86531f20b MDL-46816 mod_asssign plagiarism: Remove unnecessary code. 2014-08-14 13:09:42 +12:00
Dan Marsden 239bfa31b0 MDL-46760 mod_scorm: Fix js error when preview mode disabled 2014-08-14 10:10:45 +12:00
Eloy Lafuente (stronk7) 9056ee506a MDL-45031 theme: fix tabs base line alignment by 1px.
Credit goes to Damyon Wiese, thanks!
2014-08-13 21:33:02 +02:00
Michael Wheeler 5a8fdd1c27 Normalize request header names. 2014-08-13 14:51:44 -04:00
AMOS bot be14be6175 Automatically generated installer lang files 2014-08-14 00:05:45 +08:00
Marina Glancy 0b09c8e48f Revert "Merge branch 'm27_MDL-46643' of git://github.com/totara/moodle into MOODLE_27_STABLE"
This reverts commit a62801941e, reversing
changes made to 0282c20862.
2014-08-13 16:30:07 +08:00
Andrew Nicols 90e4b26229 MDL-45759 mod_quiz: Correct behat test to reflect changes from a translation fix 2014-08-13 15:49:45 +08:00
Eloy Lafuente (stronk7) 8b9c45b666 Merge branch 'MDL-46697_27' of git://github.com/aolley/moodle into MOODLE_27_STABLE 2014-08-13 02:08:16 +02:00
Eloy Lafuente (stronk7) 2c3eea86fa Merge branch 'MDL-45031_M27' of git://github.com/lazydaisy/moodle into MOODLE_27_STABLE 2014-08-13 00:33:03 +02:00
Eloy Lafuente (stronk7) 39259ea58b Merge branch 'wip-MDL-46470-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE
Conflicts:
	theme/bootstrapbase/style/moodle.css
2014-08-13 00:26:16 +02:00
Tim Hunt 3ce36f6ac1 MDL-45642 questions: add required index to question_attempts.
It is important to be able to tell which behaviours are in use, and
without this index, it requires a complete scan of this table, which can
be very big, to verify that a behaviour is unused.
2014-08-12 11:38:26 +01:00
Dan Poltawski 6a9a7005b0 Merge branch 'MDL-43824-M27' of git://github.com/lazydaisy/moodle into MOODLE_27_STABLE
Conflicts:
	theme/bootstrapbase/style/moodle.css
2014-08-12 11:08:11 +01:00
Dan Poltawski 2d9145638c Merge branch 'm27_MDL-46718' of https://github.com/greg-or/moodle-mod_assign into MOODLE_27_STABLE 2014-08-12 11:02:18 +01:00
Marina Glancy 531b675632 Merge branch 'MDL-46308_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-08-12 16:02:54 +08:00
Marina Glancy c41d4355ac Merge branch 'MDL-21042_m27' of git://github.com/markn86/moodle into MOODLE_27_STABLE 2014-08-12 16:02:11 +08:00
Marina Glancy ac4bf23c02 Merge branch 'm27_MDL-46315' of git://github.com/totara/moodle into MOODLE_27_STABLE 2014-08-12 15:02:03 +08:00
Marina Glancy 51c59e8b9f Merge branch 'MDL-46600_import_failed_27' of git://github.com/andyjdavis/moodle into MOODLE_27_STABLE 2014-08-12 15:01:55 +08:00
Marina Glancy 606db83726 Merge branch 'wip_MDL-46480_m27_footernan' of git://github.com/skodak/moodle into MOODLE_27_STABLE 2014-08-12 15:01:46 +08:00
Marina Glancy a62801941e Merge branch 'm27_MDL-46643' of git://github.com/totara/moodle into MOODLE_27_STABLE 2014-08-12 13:31:41 +08:00
Marina Glancy 0282c20862 Merge branch 'MDL-43740_manual_none_27' of git://github.com/andyjdavis/moodle into MOODLE_27_STABLE 2014-08-12 13:29:30 +08:00
Simon Coggins 915e21170c MDL-46775: Fix call to unavailable function when loading an invalid JS file 2014-08-12 14:33:23 +12:00
Mary Evans 11b6abd02c MDL-45031 theme_base: Added style/tabs.css and updated config.php
also removed tabtree css from style/core.css to style/tabs.css.
2014-08-12 01:11:31 +01:00
Eloy Lafuente (stronk7) 6005337c33 Merge branch 'MDL-46676_2.7' of https://github.com/ikawhero/moodle into MOODLE_27_STABLE 2014-08-12 01:48:18 +02:00
Eloy Lafuente (stronk7) ea2833bc35 Merge branch 'MDL-46681_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-08-12 01:44:23 +02:00
Mary Evans 2271f1845c MDL-43824 core/grade/report/grader: Fix for misalignment of static rows with scale grades. 2014-08-11 23:53:36 +01:00
Dan Poltawski b4875aa348 Merge branch 'MDL-46496-27' of git://github.com/andrewnicols/moodle into MOODLE_27_STABLE 2014-08-11 14:38:35 +01:00
Dan Poltawski 3b4cc68ff4 Merge branch 'm27_MDL-44015' of https://github.com/greg-or/moodle-mod_assign into MOODLE_27_STABLE 2014-08-11 14:31:04 +01:00
Dan Poltawski 2f0d26c522 Merge branch 'MDL-46688_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-08-11 14:13:14 +01:00
Andrew Davis 3dd8bd5069 MDL-43740 core_grade: Thanks to Robert Russo for the patch. Removed the ability to set manual grade items to grade type "None" 2014-08-11 20:17:13 +08:00
Dan Poltawski eede6aae43 Merge branch 'MDL-45759-27' of git://github.com/andrewnicols/moodle into MOODLE_27_STABLE 2014-08-11 11:24:20 +01:00
Dan Poltawski a623fdf11b Merge branch 'wip-MDL-30668-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-08-11 10:41:42 +01:00
Marina Glancy 617144f163 Merge branch 'MDL-35984-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-08-11 17:24:48 +08:00
Dan Poltawski 61d3898de9 Merge branch 'MDL-46748-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-08-11 08:37:35 +01:00
Damyon Wiese ec297cc65b MDL-35984 Grades: Fix deprecation of grade_category::aggregate_values 2014-08-11 14:22:27 +08:00
Damyon Wiese 5e33ee65e5 MDL-35984 grade: Recalculate min/max for sum of grades when hidden grades are involved. 2014-08-11 14:22:27 +08:00
Damyon Wiese 3bf4cc3887 MDL-35984 grade: Add behat tests for grade aggregations 2014-08-11 14:22:27 +08:00
Andrew Nicols 4f88c9f38d MDL-45780 mod_quiz: Autosave should listen for textarea:change events too 2014-08-11 12:32:15 +08:00
Andrew Nicols 096ef13c79 MDL-45780 editor_atto: Update the textarea more often
This change updates the frequency of the textarea update to additionally
update it:
* on keypress; and
* on content paste.
2014-08-11 12:32:13 +08:00
Damyon Wiese c49e848571 MDL-46748 MathJax filter: Update setting default for https cdn url. 2014-08-11 12:03:54 +08:00
Damyon Wiese 25a0be8b27 MDL-46748 MathJax filter: Make misconfigured mathjax url less "fatal" for Atto. 2014-08-11 12:03:05 +08:00
Tim Hunt b760c63189 MDL-46308 qformat_xml: fix import of broken calculated questions.
Questions like this should not exist, of course. But they do, so we
should avoid generating errors in this case.
2014-08-08 17:59:15 +01:00
Tim Hunt b3569fb6fa MDL-46688 weblib: improve the highlight function.
Thanks to Joseph Baxter for suggesting some of the test cases.
2014-08-08 17:53:04 +01:00
Marina Glancy db14163584 MDL-30668 gradereport_grader: split user preferences into individual courses
This solves the DB exception when users were trying to insert very large string in DB
2014-08-08 15:16:32 +08:00
Andrew Nicols c58559191a MDL-46496 libraries: Add additional tests for jquery and jqueryUI
The additional tests add a clear example of the use of jquery UI images in
addition to working JavaScript.
2014-08-08 14:06:20 +08:00
Gregory Faller d86be9c53e MDL-46718: Return user to last accessed page when quick grading 2014-08-08 14:12:03 +09:30
Dan Marsden 7de6a916a2 MDL-46737 SCORM: correct dml syntax. 2014-08-08 15:10:11 +12:00
Andrew Nicols cf93e03ea0 MDL-45759 javascript: Handle setting of the confirm button fields post-init 2014-08-08 08:36:20 +08:00
Petr Skoda f2774239cb MDL-46480 fix get_htmlelement_size() to deal with hidden or non-block elements 2014-08-08 10:28:51 +12:00
Tim Hunt 5049dfceca MDL-46681 qtype_multichoice: disabled unused options
For questions set to 'One answer only', the 'Clear incorrect responses'
and 'Show the number of correct responses' hint options make not sense,
and are not used. Hence we disableIf them.
2014-08-07 14:23:07 +01:00
Marina Glancy 186af5a430 weekly release 2.7.1+ 2014-08-07 13:15:08 +08:00
Marina Glancy 7a4826bc3e Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-08-07 13:15:07 +08:00
Paul Holden 1b1432ab88 MDL-21042 report_security: don't display warning for riskbackup unnecessarily 2014-08-06 19:54:23 -07:00
Andrew Davis 5bfbec5521 MDL-46600 core_grades: made it explicit in the error message that a failed grade import means nothing was imported. 2014-08-07 09:17:04 +08:00
Shane Elliott eee25b4a13 MDL-46676 profilefield_datetime: Use moodle time API 2014-08-06 16:36:03 +08:00
Adam Olley a175c5d1ba MDL-46697 gradebook: Only count active users when needed (and only id)
The code only needs the id column to perform its count. On courses with a lot of users
fetching the whole user record for them all easily adds up to several hundred MB of
memory.
2014-08-06 15:58:11 +09:30
Gregory Faller d209e7161a MDL-44015: EditPDF scrolls instead of drawing on iOS 2014-08-06 14:42:53 +09:30
Marina Glancy ef494edcd6 MDL-46470 bootstrapbase: support linkedwhenselected attribute for tabs 2014-08-06 11:46:16 +08:00
Brian Barnes 20ada5de55 MDL-46643 calendar: improved tab order of calendar detail pages 2014-08-06 15:32:02 +12:00
Eloy Lafuente (stronk7) c21c4761d1 Merge branch 'm27_MDL-46625' of https://github.com/totara/moodle into MOODLE_27_STABLE 2014-08-05 13:04:37 +02:00
Brian Barnes 9ab9793c53 MDL-46315 themes: Fixed display inconsistancy with help modals 2014-08-05 13:08:17 +12:00
Eloy Lafuente (stronk7) 4a106a5759 Merge branch 'MDL-46641_27-delete-activity-step' of https://github.com/rlorenzo/moodle into MOODLE_27_STABLE 2014-08-05 02:27:35 +02:00
Petr Skoda b5256231a6 MDL-46552 session: add support for multiple servers in memcached session driver 2014-08-05 11:40:28 +12:00
Eloy Lafuente (stronk7) b29e02d57e Merge branch 'MDL-44149-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-08-04 17:10:58 +02:00
Damyon Wiese 95bb29b902 MDL-44149 Assign: Reopen attempts from quick grading (reopenuntilpass) 2014-08-04 15:55:10 +08:00
Marina Glancy 59fe1b009f Merge branch 'MDL-44794-27' of git://github.com/lameze/moodle into MOODLE_27_STABLE 2014-08-04 14:24:51 +08:00
Simey Lameze ab8571d19a MDL-44794 group: unit test for groups_get_user_groups method. 2014-08-04 11:35:32 +08:00
Simey Lameze 90ff64881e MDL-44794 group: unit test for get_groups method. 2014-08-04 11:35:32 +08:00
Marina Glancy 1818308bca Merge branch 'MDL-46457_27' of git://github.com/aolley/moodle into MOODLE_27_STABLE 2014-08-04 11:24:30 +08:00
Marina Glancy b47604e938 Merge branch 'MDL-46414-m27' of git://github.com/sammarshallou/moodle into MOODLE_27_STABLE 2014-08-04 11:24:17 +08:00
Eloy Lafuente (stronk7) c1ee5cf31b Merge branch 'MDL-46620-27' of https://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-08-03 20:01:44 +02:00
Rex Lorenzo 18f802f85a MDL-46641 behat: Delete activity step does not work without actions menu open 2014-07-31 11:32:53 -07:00
AMOS bot ea8c5bdc74 Automatically generated installer lang files 2014-08-01 00:05:36 +08:00
Dan Poltawski 6b7a5f86a0 weekly release 2.7.1+ 2014-07-31 09:37:24 +01:00
Dan Poltawski f28ce6eb2e Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-07-31 09:37:20 +01:00
Brian Barnes 5bb55eeb21 MDL-46625 theme: Added a way to target the current page 2014-07-31 13:21:16 +12:00
Eric Merrill ddb652c706 MDL-46620 messages Make sure full message is used for read marking
message_mark_message_read needs to have the full message object,
otherwise data will be lost.
2014-07-30 15:58:04 -04:00
sam marshall 648cc055c2 MDL-46414 Conditional availability: Dropdowns not set correctly when editing in IE
In IE, you cannot set the value of a dropdown to an integer; it has to be a string.
This caused a bug in several parts of the conditional availability editing
interface.
2014-07-29 18:35:21 +01:00
Dan Poltawski 0fbda60bb3 Merge branch 'MDL-46236_27' of git://github.com/nobelium/moodle into MOODLE_27_STABLE 2014-07-29 12:04:32 +01:00
AMOS bot 486ad6e842 Automatically generated installer lang files 2014-07-29 16:02:21 +08:00
Dan Poltawski 74980995b4 Merge branch 'wip-MDL-46338-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-07-29 08:50:37 +01:00
Marina Glancy 33c3193f06 Merge branch 'm27_MDL-46325' of git://github.com/totara/moodle into MOODLE_27_STABLE 2014-07-29 11:58:55 +08:00
Sam Hemelryk 95924516fa Merge branch 'MDL-43908-MOODLE_27_STABLE' of https://github.com/lucisgit/moodle into MOODLE_27_STABLE 2014-07-29 15:51:09 +12:00
Sam Hemelryk 1663aa1fb9 Merge branch 'MDL-45041_27_STABLE' of git://github.com/jleyva/moodle into MOODLE_27_STABLE 2014-07-29 15:47:22 +12:00
Sam Hemelryk 970536b659 Merge branch 'MDL-46460_27' of git://github.com/jleyva/moodle into MOODLE_27_STABLE 2014-07-29 15:44:34 +12:00
Marina Glancy b6fadf63d4 MDL-46338 enrol_self: Icon should indicate enrolment availability 2014-07-29 09:51:21 +08:00
Adam Olley f1213f3a75 MDL-46457 mod_lti: Render lti description through standard format_module_intro 2014-07-29 10:41:40 +09:30
Sam Hemelryk adac041f8c Merge branch 'MDL-45044-m27-master' of https://github.com/dthies/moodle into MOODLE_27_STABLE 2014-07-29 08:47:00 +12:00
Dan Poltawski acadd22a65 Merge branch 'MDL-46206-27' of git://github.com/jethac/moodle into MOODLE_27_STABLE 2014-07-28 17:25:05 +01:00
Dan Poltawski acafcb18f5 Merge branch 'MDL-45594_m27' of git://github.com/markn86/moodle into MOODLE_27_STABLE 2014-07-28 12:54:17 +01:00
Dan Poltawski 71f4cb812c Merge branch 'wip-MDL-46503-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-07-28 12:49:15 +01:00
Dan Poltawski b1f78408a5 Merge branch 'm27_MDL-45715' of https://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-07-28 12:47:32 +01:00
Dan Poltawski 1669cf37f0 Merge branch 'MDL-46459_27' of git://github.com/jleyva/moodle into MOODLE_27_STABLE 2014-07-28 11:59:03 +01:00
Dan Poltawski 71e7387f43 Merge branch 'MDL-46433-27' of git://github.com/lameze/moodle into MOODLE_27_STABLE 2014-07-28 11:49:38 +01:00
Dan Poltawski 4eb9f7dd72 Merge branch 'MDL-46504_27' of git://github.com/dmonllao/moodle into MOODLE_27_STABLE 2014-07-28 10:56:43 +01:00
Nobelium 568e9560af MDL-46236 mod_scorm : Setting lauch options for scorm in popup 2014-07-28 06:41:40 +00:00
Sam Hemelryk dc7fe6acca Merge branch 'wip_MDL-46449_m27_loginblock' of https://github.com/skodak/moodle into MOODLE_27_STABLE 2014-07-28 13:25:19 +12:00
Sam Hemelryk 786a6227d0 Merge branch 'MDL-43390_27' of git://github.com/dmonllao/moodle into MOODLE_27_STABLE 2014-07-28 12:22:51 +12:00
Sam Hemelryk fd9ee7dd8b Merge branch 'wip-MDL-46525-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-07-28 12:13:53 +12:00
Sam Hemelryk 8ba664e245 Merge branch 'MDL-46506-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-07-28 08:46:11 +12:00
Juan Leyva b88a31a654 MDL-45041 Web Service: add_user_device doesn't store entries for different users using the same push key 2014-07-25 10:40:08 +02:00
Juan Leyva 76dc0848c1 MDL-46460 Web Services: Invalid check of grades visibility for missing grades 2014-07-25 10:20:44 +02:00
Juan Leyva c838cb15d8 MDL-46459 Web Services: Incorrect return parameters get_grades external function 2014-07-25 09:31:43 +02:00
Damyon Wiese 3b1fec6fb2 MDL-46485 Assign: Fix when submitting to a group assignment from the default group 2014-07-25 15:20:36 +08:00
Damyon Wiese 4939d0d71a MDL-46485 Assign: New unit test to show error with group submission 2014-07-25 15:20:36 +08:00
Marina Glancy d61604b455 MDL-46525 enrol_cohort: fix JS error 2014-07-25 14:45:22 +08:00
Jason Fowler ec085021f2 MDL-46206 Accessibility: Add aria role to footer image 2014-07-25 14:36:06 +08:00
Brian Barnes 4c6481694e MDL-46325 behat: Fixed issue where 'teacher1' didn't exist 2014-07-25 15:44:26 +12:00
AMOS bot fdeb6af76e Automatically generated installer lang files 2014-07-24 22:41:56 +00:00
Petr Skoda ee7af1e19d MDL-46449 fix username prompt in login block when authloginviaemail enabled 2014-07-25 10:10:54 +12:00
Tony Butler 7561f3d64a MDL-43908 mod_assign: Order submissions by course id then cm id
Signed-off-by: Tony Butler <tonyjbutler@gmail.com>
2014-07-24 17:30:18 +01:00
Tony Butler a65c0da40d MDL-43908 mod_assign: Remove redundant code and improve SQL query
Signed-off-by: Tony Butler <tonyjbutler@gmail.com>
2014-07-24 17:30:09 +01:00
Tony Butler 1e07291026 MDL-43908 mod_assign: Prevent notifications for unavailable assignments
Signed-off-by: Tony Butler <tonyjbutler@gmail.com>
2014-07-24 17:29:59 +01:00
Tony Butler 1215c112c0 MDL-43908 mod_assign: Defer notifications for unavailable assignments
Signed-off-by: Tony Butler <tonyjbutler@gmail.com>
2014-07-24 17:29:40 +01:00
Daniel Thies 0e37d94b67 MDL-45044 filter_tex: properly escape excutable pathnames for Windows 2014-07-24 11:05:00 -05:00
uhunkler 3264dcece0 MDL-46302 correct atto img float right
Correct the atto image "float right" margin CSS
2014-07-24 17:24:37 +02:00
Dan Poltawski cc1dc858c0 weekly release 2.7.1+ 2014-07-24 09:51:04 +01:00
Dan Poltawski 6ca7efb157 Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-07-24 09:51:01 +01:00
Damyon Wiese 72d49e8419 MDL-46506 Assign: fix php warning on grant extension page
This code was missed when the extensionduedate was moved to the userflags table.
2014-07-24 11:26:23 +08:00
David Monllao cd2f4a87a4 MDL-46504 libraries: Fixing typo 2014-07-24 11:16:44 +08:00
Damyon Wiese b8ba7f3619 MDL-46017 Assign: Restore can't rely allocated marker fields existing in backup 2014-07-24 10:57:26 +08:00
Marina Glancy aa8ae42d24 MDL-46503 behat: cohort generator allows to create cohort in category 2014-07-24 10:04:12 +08:00
Mark Nelson 1c7509bc86 MDL-45594 core_message: added unit tests 2014-07-23 16:40:25 -07:00
Mark Nelson 7ed94cbe9c MDL-45594 core_message: ordered recent notifications by timecreated 2014-07-23 16:40:25 -07:00
Tim Hunt 7c7d086ae1 MDL-45594 simplify message_get_recent_conversations SQL
I am pretty sure that this new SQL is logically equivalent to
the original, and it passes Mark's unit tests. However, it is
hard to be 100% sure.
2014-07-23 16:40:25 -07:00
AMOS bot 725ce55546 Automatically generated installer lang files 2014-07-23 22:46:16 +00:00
Simey Lameze 1f55a12bf8 MDL-46433 blog: fix error message when creating an external blog 2014-07-23 16:12:05 +08:00
Dan Poltawski ee0f0b3986 Revert "Merge branch 'MDL-45594_m27' of git://github.com/markn86/moodle into MOODLE_27_STABLE"
This reverts commit 0cc8a0b4b2, reversing
changes made to 6d32f6300e.
2014-07-23 09:02:02 +01:00
Dan Poltawski 92d4bcd9f7 Merge branch 'MDL-46017-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-07-23 08:24:26 +01:00
Dan Marsden e7215ce5b7 MDL-45715 assign: disable marking allocation if markingworkflow is not set. 2014-07-23 19:21:30 +12:00
Sam Hemelryk 6dc0b5482b MDL-45724 cache: fixed warning structure bug 2014-07-23 15:24:35 +12:00
AMOS bot 45d7ec6123 Automatically generated installer lang files 2014-07-22 22:49:11 +00:00
Dan Poltawski a7e348e937 Merge branch 'MDL-37509-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-07-22 15:56:58 +01:00
Dan Poltawski eba7490c31 Merge branch 'MDL-34248_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-07-22 12:01:04 +01:00
Dan Poltawski a4798ada52 Merge branch '45724-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-07-22 09:07:25 +01:00
Sam Hemelryk 0cc8a0b4b2 Merge branch 'MDL-45594_m27' of git://github.com/markn86/moodle into MOODLE_27_STABLE 2014-07-22 11:12:17 +12:00
Sam Hemelryk 6d32f6300e Merge branch 'MDL-43063-27' of git://github.com/lameze/moodle into MOODLE_27_STABLE 2014-07-22 09:49:10 +12:00
Dan Poltawski 08348b8f86 Merge branch 'MDL-46386-27' of https://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-07-21 14:11:46 +01:00
Eric Merrill 519eec044c MDL-46386 question Whitelist the Atto editor from return blocking
Prevent the question engine from blocking return/enter key presses
from being sent to the Atto editor.
2014-07-21 09:08:52 -04:00
Dan Poltawski ab156686ff Merge branch '46335-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-07-21 09:59:06 +01:00
Dan Poltawski 1fc8ebf085 Merge branch 'MDL-46370_27' of https://github.com/moodlerooms/moodle into MOODLE_27_STABLE 2014-07-21 09:54:57 +01:00
Damyon Wiese 0086364857 MDL-46017 Assign: Fix restore of marking workflow data 2014-07-21 16:38:21 +08:00
Damyon Wiese 05cc5bf052 MDL-37509 Assign: Do not put description in calendar before it should be shown to students 2014-07-21 15:58:08 +08:00
Simey Lameze 8bd3dfd6f5 MDL-43063 core: fix phpdoc comment codechecker issue. 2014-07-21 10:14:12 +08:00
Julien Boulen 1c9e079b7c MDL-46206 Accessibility: Remove alt attribute for footer image 2014-07-21 08:21:06 +08:00
Sam Hemelryk 8b90e93c94 MDL-42909 course: fixed whitespace 2014-07-21 11:43:04 +12:00
Sam Hemelryk 94f0349745 Merge branch 'MDL-42909-27' of git://github.com/phalacee/moodle into MOODLE_27_STABLE 2014-07-21 11:35:54 +12:00
David Balch 50cc7daa0f MDL-40479 mod_assign: Fix the colour of grading success messages. 2014-07-21 11:33:04 +12:00
Brian Barnes 0a841ac85c MDL-46406 core_auth: Placed remember username before submit login form 2014-07-21 11:22:22 +12:00
Sam Hemelryk 28d6752d07 Merge branch 'mdl-46427-m27' of git://github.com/deraadt/moodle into MOODLE_27_STABLE 2014-07-21 11:12:11 +12:00
Willy Lee 1d0f235097 MDL-46159 course: Add search box to course management pages 2014-07-21 10:56:22 +12:00
Sam Hemelryk 93d7596d3f Merge branch 'MDL-45339-27' of git://github.com/xow/moodle into MOODLE_27_STABLE 2014-07-21 10:49:33 +12:00
Sam Hemelryk aa9f17df92 Merge branch 'm27_MDL-46363' of https://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-07-21 10:45:43 +12:00
Sam Hemelryk d251180b31 MDL-45724 cache: added cache API warnings to the admin notifications page 2014-07-21 09:48:54 +12:00
Sam Hemelryk 67a77fa36f MDL-45724 cache: admin screen now shows store warnings
Implemented a means by which cache store instance can communicate
warnings due to things such as conflicting configurations etc.
2014-07-21 09:39:15 +12:00
AMOS bot c3cf035fad Automatically generated installer lang files 2014-07-20 00:44:24 +00:00
AMOS bot 8a52ccea0c Automatically generated installer lang files 2014-07-19 00:41:49 +00:00
Michael de Raadt d35f49ba45 MDL-46427 Course: Correcting dimmed course link class on profile pages. 2014-07-18 15:43:05 +08:00
Jason Fowler 38748c6ada MDL-42909 Course: Fix title for move-targets 2014-07-18 14:43:10 +08:00
Mark Nelson 68fb3969e1 MDL-34248 core_backup: used API instead of inserting into the log table directly 2014-07-17 18:12:01 -07:00
Mark Nelson 527afcfb8c MDL-34248 core_backup: added missing end quotation 2014-07-17 18:12:00 -07:00
Jim Thorpe c62f8bc71f enrol_imsenterprise: MDL-46363 including course lib when create_course is
used
2014-07-18 11:27:15 +12:00
Sam Hemelryk d3c034f8e8 MDL-46335 backup: fixed casting issue with setting labels
The issue was that clean_param took an int and returned a string
and the result was used in an exact comparison.
The type change mean the comparison failed.
The solution was to ensure the param was cast as a string.
2014-07-18 08:29:53 +12:00
John Okely 5f399d0c52 MDL-45339 Libraries: Add a note to docblock of get_config, set_config, and unset_config to note they are used in lib/db/upgrade.php 2014-07-17 17:48:14 +08:00
Dan Poltawski a9e0505fde weekly release 2.7.1+ 2014-07-17 09:22:55 +01:00
Dan Poltawski 96d73266ef Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-07-17 09:22:51 +01:00
AMOS bot 66a0fea650 Automatically generated installer lang files 2014-07-17 00:52:51 +00:00
AMOS bot a4bba406ad Automatically generated installer lang files 2014-07-17 00:52:51 +00:00
Mark Nelson 20914ba26a MDL-45594 core_message: added unit tests 2014-07-16 17:06:39 -07:00
Mark Nelson 8b5520877b MDL-45594 core_message: ordered recent notifications by timecreated 2014-07-16 17:06:39 -07:00
Tim Hunt 7cacba3db3 MDL-45594 simplify message_get_recent_conversations SQL
I am pretty sure that this new SQL is logically equivalent to
the original, and it passes Mark's unit tests. However, it is
hard to be 100% sure.
2014-07-16 17:06:39 -07:00
Sam Chaffee f4c37747dc MDL-46370 Ajax and Javascript - Fixes docked blocks not expanding when using dock on right 2014-07-16 12:04:50 -06:00
Dan Poltawski 3e65f72a40 Revert "MDL-46226 core: pix_icon no longer sets title to the alt text"
This reverts commit 956ec418c6.
2014-07-16 13:45:35 +01:00
Dan Poltawski d613a0db57 Revert "MDL-46226 fix unit tests"
This reverts commit d927f222a9.
2014-07-16 13:45:32 +01:00
Rajesh Taneja 26f004f29b MDL-30431 behat: Fixed wiki behat 2014-07-16 09:18:51 +02:00
Eloy Lafuente (stronk7) 0ed87e5063 MDL-30431 mod_wiki: whitespace fix 2014-07-16 01:19:36 +02:00
Eloy Lafuente (stronk7) 87cc899c44 Merge branch 'MDL-30431_wiki_comments_27' of https://github.com/andyjdavis/moodle into MOODLE_27_STABLE 2014-07-16 01:16:19 +02:00
AMOS bot e1661a6346 Automatically generated installer lang files 2014-07-15 00:46:33 +00:00
Eloy Lafuente (stronk7) 3ba2b5c925 Merge branch 'MDL-46080_27' of https://github.com/jonof/moodle into MOODLE_27_STABLE 2014-07-14 23:30:25 +02:00
Sam Hemelryk 7c5d28c26c Merge branch 'MDL-42179-003-27' of https://github.com/dbezborodovrp/moodle into MOODLE_27_STABLE 2014-07-15 08:41:31 +12:00
Eloy Lafuente (stronk7) 67711964d1 Merge branch 'm27_MDL-31366' of git://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-07-14 18:17:44 +02:00
Dan Poltawski bf394372d8 Merge branch 'MDL-42752-27' of git://github.com/phalacee/moodle into MOODLE_27_STABLE 2014-07-14 16:09:29 +01:00
Dan Poltawski d927f222a9 MDL-46226 fix unit tests 2014-07-14 15:49:20 +01:00
Dan Poltawski bbcbbcd130 Merge branch 'MDL-46218_disabled2_27' of https://github.com/andyjdavis/moodle into MOODLE_27_STABLE 2014-07-14 15:33:13 +01:00
Eloy Lafuente (stronk7) cc0b20ba9d Merge branch 'm27_MDL-46197' of https://github.com/totara/moodle into MOODLE_27_STABLE 2014-07-14 16:25:21 +02:00
Dan Poltawski 8f15eebc22 Merge branch 'm27_MDL-46226' of https://github.com/totara/moodle into MOODLE_27_STABLE 2014-07-14 15:13:45 +01:00
Damien Bezborodov d8b6437fa9 MDL-42179 mod_assign: Time remaining issue for group assignment 2014-07-14 13:52:41 +09:30
David Monllao e257ad8372 MDL-43390 files: Only lock when locking is not prevented 2014-07-14 12:13:41 +08:00
Sam Hemelryk ba03dc18ad Merge branch 'MDL-42214_popup_blocked_27' of https://github.com/andyjdavis/moodle into MOODLE_27_STABLE 2014-07-14 15:27:46 +12:00
Sam Hemelryk 7c15d3b34c Merge branch 'MDL-46073_27' of https://github.com/totara/openbadges into MOODLE_27_STABLE 2014-07-14 15:15:57 +12:00
Andrew Davis 1c76803ec1 MDL-42214 core_message:prevented popup notifications of messages from blocked users 2014-07-14 10:11:14 +08:00
Andrew Davis 5660ceba8d MDL-30431 mod_wiki: clarified the logic around editing and deleting wiki comments and added behat tests 2014-07-14 08:16:39 +08:00
Sam Hemelryk ae59c35eb9 Merge branch 'MDL-45765-moodle27' of https://github.com/StudiUM/moodle into MOODLE_27_STABLE 2014-07-14 12:09:50 +12:00
Sam Hemelryk 3c129829ce MDL-46138 post integratino phpdoc fixes 2014-07-14 10:50:42 +12:00
Sam Hemelryk 050720be90 Merge branch 'MDL-46138-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-07-14 10:40:37 +12:00
Sam Hemelryk 7573d5ff21 Merge branch 'wip-MDL-46280-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-07-14 10:32:42 +12:00
Gilles-Philippe Leblanc b3656b26be MDL-22469 auth_cas: CAS module : parameter authCAS=NOCAS not properly handled 2014-07-14 10:21:48 +12:00
Sam Hemelryk 804c22b8f1 Merge branch 'MDL-31089_27' of git://github.com/dmonllao/moodle into MOODLE_27_STABLE 2014-07-14 09:51:39 +12:00
Sam Hemelryk 8716b6c89f Merge branch 'MDL-45562-27' of git://github.com/lameze/moodle into MOODLE_27_STABLE 2014-07-14 08:41:38 +12:00
Eloy Lafuente (stronk7) 8b3d19c2f5 Moodle release 2.7.1 2014-07-12 19:10:44 +02:00
David Monllao cf9ed67a4e MDL-31089 mod_forum: Filtering non-visible groups 2014-07-11 16:49:39 +08:00
Simey Lameze 417b6921d5 MDL-45562 blog: fixed issues when creating/editing an external blog. 2014-07-11 15:16:28 +08:00
Damyon Wiese f72a23d69b MDL-46138 tasks: The adhoc task is being too helpful with json_encoding/decoding. 2014-07-11 09:45:27 +08:00
Dan Marsden ca602b6beb MDL-31366 Feedback: decode htmlchars on output to excel 2014-07-11 13:28:59 +12:00
Brian Barnes 2b8647034a MDL-46197 core_calendar: Added label text to durations in minutes field 2014-07-11 09:09:10 +12:00
Brian Barnes 956ec418c6 MDL-46226 core: pix_icon no longer sets title to the alt text 2014-07-11 08:39:45 +12:00
Jean-Philippe Gaudreau 31d453f735 MDL-45765 Calendar import: Fix undefined variable in cron when updating calendar subscriptions 2014-07-10 16:09:04 -04:00
Eloy Lafuente (stronk7) b4d0a4479c weekly release 2.7+ 2014-07-10 19:15:41 +02:00
Eloy Lafuente (stronk7) 3e07b8a2f3 Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-07-10 19:15:37 +02:00
Ankit Agarwal 383776876b MDL-46148 qtype_calculated: low-level defence against bad formulas
This catches things like:
 * Malicious equations coming from backup files.
 * Malicious equations in old questions in the database.
2014-07-10 17:55:03 +08:00
Andrew Nicols 91c8d4da71 MDL-38990 mod_forum: Restrict ability to post to all groups in a forum
In order to post to all groups in a forum, you must have the
moodle/site:accessallgroups capability.

Thanks to Jakob Ackermann <jackermann@onlineschool.ca> for part of the fix
on this one.
2014-07-10 11:52:57 +08:00
Damyon Wiese 1721c8eb85 MDL-46148 questions: Added missing allow_commit for transaction 2014-07-10 11:36:57 +08:00
Andrew Davis ad3d9452bf MDL-46218 reshuffled access checks in blog and notes 2014-07-10 11:25:15 +08:00
Damyon Wiese c5f351435e Merge branch 'MDL-19270_moodle27stable' of https://github.com/nadavkav/moodle into MOODLE_27_STABLE
Conflicts:
	lib/graphlib.php
2014-07-10 09:58:44 +08:00
AMOS bot 03b06dedbc Automatically generated installer lang files 2014-07-10 00:47:09 +00:00
Tim Hunt da80885cc6 MDL-46148 qtype_calculatedsimple: fix notice
... when adding a dataset with a formula error.
2014-07-09 14:11:39 +01:00
Tim Hunt 94ac7a87fa MDL-46148 qtype_calculated: fix validation when importing.
In order to do this in a sane way, I cleaned up a lot of old mess,
inclduing:

1. Previously, qtype_calcuated used ->answeres when importing, and
->answer when saving the form. This was crazy, so I fixed it, and
stripped out the code that made the alternative variable name work.

2. Similarly, it could handle ->answer being either an array, such as
you would get form the HTML editor, or a simple string, which is what
you get form the form. I simplified that too.

3. Finally, I made import use a transaction around saving each
question, so we don't get half questions in the database when an error
occurs.
2014-07-09 14:11:38 +01:00
Tim Hunt 10b02d6d41 MDL-46148 qtype_calculated: removed unused method. 2014-07-09 14:11:38 +01:00
Nadav Kavalerchik ebb6f3e80b MDL-19270 - Quiz graph - Fix reverse display of Hebrew legend text in RTL mode 2014-07-09 16:07:56 +03:00
David Mudrák 7f4db6f4d9 MDL-46223 Fix frequently used comments in the marking guide
When the frequently used comment contains a character like >, re-use it
directly instead of its HTML entitiy.
2014-07-09 16:43:40 +08:00
David Mudrák 4fc5861cba MDL-46223 Improve the display of marking guide validation message 2014-07-09 16:43:37 +08:00
Dan Poltawski 40b205197c MDL-46227 fix typo 2014-07-09 08:23:14 +01:00
Dan Poltawski cb914a71aa MDL-44605 calendar: improved returnurl validation
Now we will only redirect to a local url (though sesskey was
already preventing this redirect from being open)
2014-07-09 01:06:35 +02:00
Eloy Lafuente (stronk7) 85f376892d Merge branch 'MDL-43849_27' of git://github.com/dmonllao/moodle into MOODLE_27_STABLE 2014-07-08 20:29:04 +02:00
Dan Poltawski e0708141f8 Merge branch 'MDL-45599-27-addons' of git://github.com/mudrd8mz/moodle into MOODLE_27_STABLE 2014-07-08 15:31:53 +01:00
Dan Poltawski 76b012d611 Merge branch 'MDL-44492_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-07-08 14:18:01 +01:00
Frederic Massart 53ca351f7a MDL-45471 javascript: Escape content of exception dialogs 2014-07-08 14:13:33 +01:00
Tim Hunt ea9f3057da MDL-44492 quiz: fix hilighting of graded attempt
In various places, when showing several attempts, we try to hilight the
most significant one (the one that gave the final grade if the quiz is
set to first/last/best attempt). That was not working because the table
zebra stripes were a more specific rule.

Also, the colour was inconsistent, not nice, and not very bootstrapy, so
I changed it.
2014-07-08 13:33:41 +01:00
Tim Hunt f1406d3b39 MDL-44492 quiz reports: revert some style overrides.
But add one more. This makes Clean theme look a lot better.
2014-07-08 13:33:38 +01:00
Tim Hunt 91251e4889 MDL-44492 Rough unit test for the report SQL.
We really ought to test more cases, but this hits one of the most tricky cases.
2014-07-08 13:33:36 +01:00
Tim Hunt 8994593332 MDL-44492 quiz reports: make show only graded attempt work.
It needs to only affect finished attempts, and the wording needs to be
modified to make it clear that is what it does.
2014-07-08 13:33:33 +01:00
Dan Poltawski 67b3704318 Merge branch 'MDL-45381_m27' of git://github.com/markn86/moodle into MOODLE_27_STABLE 2014-07-08 11:29:03 +01:00
Dan Poltawski 37e7d91b8c Merge branch 'MDL-45596-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-07-08 10:50:55 +01:00
Marina Glancy 3fe64cbd7d MDL-43948 forms: setting types to filemanager and editor elements 2014-07-08 10:47:35 +01:00
Dan Poltawski 22051a4e34 Merge branch 'MDL-46231-27-en_fix' of git://github.com/mudrd8mz/moodle into MOODLE_27_STABLE 2014-07-08 08:32:35 +01:00
Helen Foster e7cd680765 MDL-45599 Fix tiny grammatical errors in the plugin installer 2014-07-08 09:02:06 +02:00
Marina Glancy 84d2c6f761 Merge branch 'MDL-46229_27' of https://github.com/totara/openbadges into MOODLE_27_STABLE 2014-07-08 13:51:40 +08:00
Skylar Kelty f97581eda7 MDL-46227 Fix XSS in scheduled tasks 2014-07-08 13:38:01 +08:00
David Mudrák 2c0b608cda MDL-46223 Improve the marking guide output 2014-07-08 13:18:59 +08:00
David Mudrák eb1381de1d MDL-46223 Improve the rubric output 2014-07-08 13:18:58 +08:00
Marina Glancy c7bfbb01c6 MDL-46280 filter_activitynames: sort activities by length in reverse order 2014-07-08 10:55:25 +08:00
Sam Hemelryk 4eacb77012 Merge branch 'MDL-46016_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-07-08 14:28:02 +12:00
Sam Hemelryk 93835758f3 MDL-19270 core_text: added unit tests for strrev 2014-07-08 14:15:02 +12:00
Sam Hemelryk a238e7ed72 Merge branch 'MDL-19270_moodle27stable' of https://github.com/nadavkav/moodle into MOODLE_27_STABLE 2014-07-08 13:53:52 +12:00
Sam Hemelryk 98ac33bcb0 Merge branch 'MDL-46200-27' of git://github.com/danpoltawski/moodle into MOODLE_27_STABLE 2014-07-08 13:38:08 +12:00
Sam Hemelryk 0caa8c60d2 Merge branch 'mdl45982-moodle27' of https://github.com/tlock/moodle into MOODLE_27_STABLE 2014-07-08 13:26:58 +12:00
Sam Hemelryk 2dbdaedc3e Merge branch 'm27_MDL-46144' of https://github.com/totara/moodle into MOODLE_27_STABLE 2014-07-08 13:10:36 +12:00
Eloy Lafuente (stronk7) 30a264540b Merge branch '46208-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-07-08 02:13:44 +02:00
Sam Hemelryk 6d05bee940 Merge branch 'MDL-46212_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-07-08 10:45:01 +12:00
Sam Hemelryk 2535dfaf64 Merge branch 'MDL-46240-27' of git://github.com/danpoltawski/moodle into MOODLE_27_STABLE 2014-07-08 10:34:30 +12:00
Eloy Lafuente (stronk7) 35186e3725 Merge branch 'wip_MDL-45945_m27_mssqlcol' of https://github.com/skodak/moodle into MOODLE_27_STABLE 2014-07-08 00:32:09 +02:00
Sam Hemelryk bfe4417cb7 MDL-45678 cache: renamed new cache and better comments 2014-07-08 09:52:53 +12:00
Sam Hemelryk 6b6affec1f Merge branch 'MDL-45678-006-27' of https://github.com/dbezborodovrp/moodle into MOODLE_27_STABLE 2014-07-08 09:42:51 +12:00
Sam Hemelryk 9e13649c89 Merge branch 'wip_MDL-46126_m27_passnulls' of https://github.com/skodak/moodle into MOODLE_27_STABLE 2014-07-08 09:37:20 +12:00
Yuliya Bozhko 1465b22f7d MDL-46073 badges: Make sure html tags are not used in badge description
Signed-off-by: Yuliya Bozhko <yuliya.bozhko@totaralms.com>
2014-07-08 09:36:21 +12:00
Sam Hemelryk f549deed15 Merge branch 'MDL-43347-27' of https://github.com/mackensen/moodle into MOODLE_27_STABLE 2014-07-08 09:28:31 +12:00
Adrian Greeve ab59b7db71 MDL-46201 events: Sanitization of username before returning the description. 2014-07-07 18:19:11 +01:00
Yuliya Bozhko 200a2b7fad MDL-46042 badges: Clean up external badge data
Signed-off-by: Yuliya Bozhko <yuliya.bozhko@totaralms.com>
2014-07-07 16:37:44 +01:00
Dan Poltawski 9945bcec41 Merge branch 'MDL-42393-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-07-07 16:27:32 +01:00
Dan Poltawski b4ac5653ed Merge branch 'MDL-41389_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-07-07 16:10:26 +01:00
Osanda Malith Jayathissa 0207466e77 MDL-45683 user: Escaping Skype ID used in profile 2014-07-07 16:05:10 +01:00
Marina Glancy 2ca9e09dab MDL-45760 make sure to check permission before setting header 2014-07-07 15:06:40 +01:00
Tim Hunt 6eaf5ec8e3 MDL-46148 qtype_calculated: fix formula validation. 2014-07-07 14:34:02 +01:00
Frederic Massart 1d110af2d6 MDL-45417 mod_imscp: Prevent entity injections from package content 2014-07-07 13:03:05 +01:00
Frederic Massart 2d121036cc MDL-45463 mod_lti: Prevent XML entity injections from provider 2014-07-07 13:00:39 +01:00
Marina Glancy 61961447c2 MDL-45616 repositories: use json encoding instead of serialization 2014-07-07 15:17:42 +08:00
Marina Glancy 867f40990b MDL-45616 repositories: more clearly distinguish when we use source and when reference
Function repository::get_moodle_file() should always be called on packed reference and not on the source received from user.
Also added phpdocs to some other methods that were confusing source and reference
2014-07-07 15:17:42 +08:00
Jason Fowler da6ce47102 MDL-42752 File-picker: Fix tabbing to disabled icons 2014-07-07 14:30:17 +08:00
Dan Poltawski 78ba7d9e6b MDL-43848 messages: do not display message content in popups
The user is not in control of when these popups show up and it
may not be appropiate to have part of this content display whilst
in the presence of other users.
2014-07-07 13:46:35 +08:00
Nadav Kavalerchik 63010978b4 MDL-19270 - Quiz graph - Fix reverse display of Hebrew legend text in RTL mode 2014-07-06 19:00:23 +03:00
Helen Foster c5e9bc48f0 MDL-46231 Merge English strings from the en_fix language pack 2014-07-04 22:37:30 +02:00
Dan Poltawski cd90445d4a MDL-46200 fix missing space in failed login message 2014-07-04 14:55:43 +01:00
Dan Poltawski 0052796dbb MDL-46240 atto_collapse: fix icon url 2014-07-04 14:35:16 +01:00
David Mudrák b522356839 MDL-45599 Stop using the 'add-on' term
We now call them all as just 'plugins' for consistency. There where we need to
explicitly distinguish the source of the plugin, we say they are 'additional
plugins' on contrary to 'standards plugins' coming with the core.
2014-07-04 11:34:34 +02:00
David Mudrák 1d45b926f3 MDL-45599 Remove string editingnoncorelangfile from core_admin
This string mentions 'add-on' and has been greylisted in AMOS since 2.0. The
usage of it was removed in 00b41d.
2014-07-04 10:36:53 +02:00
Damien Bezborodov 0ba5f02b15 MDL-45678 assignsubmission_comments: Improve performance for permissions checking 2014-07-04 14:25:06 +09:30
Petr Skoda a31fdfb145 MDL-46126 upgrade: fix bogus nulls in user.password before changing precission
Note: there is no need to deal with Oracle empty strings here
because only MySQL running in non-strict mode is affected.
2014-07-04 16:29:40 +12:00
Frederic Massart d019ffd21f MDL-45596 roles: Escape filter value before using it in form field 2014-07-04 11:49:42 +08:00
Mark Nelson a93f8344ae MDL-41389 auth_db: added unit tests for events 2014-07-03 20:16:56 -07:00
Petr Skoda 2d7617aa18 MDL-45945 mssql: force default database collation in all tables including temp table 2014-07-04 15:05:24 +12:00
AMOS bot 84acc68175 Automatically generated installer lang files 2014-07-04 00:44:19 +00:00
Mark Nelson 38d8b7b703 MDL-46016 auth_shibboleth: updated misleading comment
Also generated a random string for the password field in case it is ever used.
2014-07-03 16:15:57 -07:00
Mark Nelson 69ddeb42e2 MDL-41389 auth_db: added user_updated/created event triggers 2014-07-03 14:28:44 -07:00
Sam Hemelryk 2bd9cd1077 MDL-46208 cachestore_mongo: fixed invalid collection name use 2014-07-04 08:11:24 +12:00
Tim Hunt 35588aa876 MDL-46212 question editing: extra answer fields notice.
It turns out that PHP does not interpret "$field[$key]" the way we were
expecting.
2014-07-03 13:40:38 +01:00
Dan Poltawski fc415ee908 weekly release 2.7+ 2014-07-03 10:53:27 +01:00
Dan Poltawski 10b4bda916 Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-07-03 10:53:24 +01:00
Marina Glancy 3708e1bb7c MDL-46163 question/quiz: fix elements ids and their labels 2014-07-03 10:13:23 +01:00
David Monllao e7e79055e1 MDL-43849 enrol_meta: Renaming methods according to what they test 2014-07-03 14:51:00 +08:00
David Monllao 3d4cf404df MDL-43849 mod_forum: Adding tests for observers 2014-07-03 14:50:52 +08:00
Frederic Massart 31c0efeac7 MDL-42393 calendar: Preventing open/close loop in events overlay 2014-07-03 10:17:41 +08:00
Yuliya Bozhko 3571cd46d2 MDL-46229 badges: Fix missing additional names fields
Signed-off-by: Yuliya Bozhko <yuliya.bozhko@totaralms.com>
2014-07-03 09:33:27 +12:00
Tim Hunt fa6db7b8c1 MDL-46163 quiz/questions: fix missing hidden fields.
I have done this by eliminating the duplication between the base class
and the subclass.

This was a regression introdcued by MDL-40313.
2014-07-02 15:04:56 +01:00
AMOS bot 947a90339a Automatically generated installer lang files 2014-07-02 00:44:40 +00:00
Eloy Lafuente (stronk7) dc30afaafc Merge branch 'wip-mdl-45889-m27' of https://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-07-02 00:36:26 +02:00
Eloy Lafuente (stronk7) 03a5278a38 Merge branch '45209-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-07-01 23:49:46 +02:00
Sam Hemelryk d683942c6a Merge branch 'wip-MDL-46147-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-07-02 09:31:25 +12:00
Mary Evans 24c0432bbc MDL-45507 theme_bootstrapbase: Fix regression for theme based custom menu
in renderers/core_renderer.php.
2014-07-02 09:22:43 +12:00
Eloy Lafuente (stronk7) c16de45a14 MDL-45961 user profile: track user on reset
It seems that redirect (after reset button) was also
missing the userid so the user track was lost.
2014-07-01 19:22:14 +02:00
Eloy Lafuente (stronk7) 9d19781014 Merge branch 'MDL-45961_MOODLE_27_STABLE' of https://github.com/NeillM/moodle into MOODLE_27_STABLE 2014-07-01 19:22:05 +02:00
Dan Poltawski ab6ae906cd Merge branch 'MDL-46063_27' of git://github.com/schach/moodle into MOODLE_27_STABLE 2014-07-01 17:29:16 +01:00
Dan Poltawski f45b59d427 Merge branch 'MDL-46036_survey_27' of https://github.com/andyjdavis/moodle into MOODLE_27_STABLE 2014-07-01 16:34:29 +01:00
Charles Fulton 3add7d878f MDL-43347 grades: convert keep highest to text field 2014-07-01 07:34:23 -07:00
Charles Fulton c9bd902bd3 MDL-43347 grades: consistent interface for drop lowest setting 2014-07-01 07:34:11 -07:00
Dan Poltawski 366124d222 Merge branch 'MDL-46107_27' of https://github.com/totara/openbadges into MOODLE_27_STABLE 2014-07-01 14:20:53 +01:00
Dan Poltawski 89203e11a7 Merge branch 'MDL-4013-stable27' of https://github.com/MorrisR2/moodle into MOODLE_27_STABLE 2014-07-01 14:16:22 +01:00
Dan Poltawski dd83fbfbbc Merge branch 'wip_MDL-46099_m27_userglobal' of https://github.com/skodak/moodle into MOODLE_27_STABLE 2014-07-01 10:39:15 +01:00
Marina Glancy 1fb374121a MDL-46147 modinfo: performance improvement for course page (check filterall) 2014-07-01 15:30:28 +08:00
Damyon Wiese f3163a2002 MDL-46147 modinfo: performance improvement for course page
This is a big win in a specific situation, ie filters enabled for content+headings,
and no activity descriptions visible on the course page.
2014-07-01 15:30:22 +08:00
Mark Nelson 65764352dd MDL-45381 mod_forum: updated unit tests for subscription created/deleted events 2014-06-30 23:35:37 -07:00
Mark Nelson 2c7b800f2f MDL-45381 mod_forum: changed event URL for subscription created/deleted events 2014-06-30 23:35:36 -07:00
Brian Barnes ed7d676329 MDL-46144 core_calendar:Fixed label linking in calendar 2014-07-01 13:44:56 +12:00
Sam Hemelryk b23bc0a148 Merge branch 'MDL-40805-27' of git://github.com/lameze/moodle into MOODLE_27_STABLE 2014-07-01 09:06:20 +12:00
Petr Skoda df9a669791 MDL-46099 session: fix use of references for session globals
This reverses the references used for global $USER and $SESSION,
the reason is that PHP does not allow references to references.
$USER is a reference to $GLOBALS['USER'] which means we cannot
put any references to it. Solution is to store the current user and session
objects in $GLOBALS['USER'] and $GLOBALS['SESSIOn'] are reference
them in $_SESSION.

This patch makes the session code behave the same way in CLI,
phpunit and normal web requests - this allows use to finally
unit test most aspects of the session code in Moodle.
2014-07-01 08:38:10 +12:00
Sam Hemelryk b1ab535efa Merge branch 'MDL-46118_27' of git://github.com/dmonllao/moodle into MOODLE_27_STABLE 2014-07-01 08:33:16 +12:00
Dan Poltawski 1e9dce0df4 Merge branch 'wip-mdl-45641-m27' of https://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-06-30 15:26:34 +01:00
Dan Poltawski 8dd0756226 Merge branch 'MDL-42467_database_27' of https://github.com/andyjdavis/moodle into MOODLE_27_STABLE 2014-06-30 15:09:53 +01:00
Dan Poltawski 8458e3d2c2 Merge branch 'MDL-45833_27' of git://github.com/dmonllao/moodle into MOODLE_27_STABLE 2014-06-30 13:27:16 +01:00
Dan Poltawski 951a64f6ef Merge branch 'MDL-46044-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-06-30 11:45:29 +01:00
Heiko Schach b336cf98b4 MDL-46063 feedback: Fix user pictures 2014-06-30 13:27:39 +03:00
Dan Poltawski b6ac868d71 Merge branch 'MDL-40228-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-06-30 08:55:39 +01:00
AMOS bot 57ce05c631 Automatically generated installer lang files 2014-06-29 00:42:51 +00:00
Ray Morris f0538cee92 MDL-4013 Question bank: Category selector renders as nested form (invalid html) 2014-06-27 10:00:11 -05:00
NeillM f4f4965a1c MDL-45961 Customise this page button on user profile page only works correctly for users own profile 2014-06-27 09:05:49 +01:00
Rajesh Taneja 93a593daab MDL-45641 event: Ldap user_signup unit test added 2014-06-27 15:43:49 +08:00
Rajesh Taneja c8c1a2cb10 MDL-45641 event: Manually trigger event where needed.
Some places, user_created_user and user_updated_user
events should be triggred after profile data is saved.
2014-06-27 15:43:49 +08:00
Rajesh Taneja 793ab11d95 MDL-45641 event: Removed multiple user_updated event trigger
user_updated event was being triggred while
setting password, which is not correct. It now
trigger user_password_updated event. Few more
modifications done:
1. Correct event is being triggred.
2. Event is only triggred when password is chnaged.
3. Password is updated via single api.
4. Updated unit test
2014-06-27 15:43:49 +08:00
Rajesh Taneja 47221d5fdd MDL-45641 event: Option to trigger user event manually
On some pages full user data is not stored before user_created/
user_updated event is triggred. So giving option to trigger that
manually, so it can be triggred after all data is saved
2014-06-27 15:43:49 +08:00
Damyon Wiese 1affa3ea22 MDL-46044 Assign: Add conditions to the inner query for performance 2014-06-27 15:01:17 +08:00
Damyon Wiese 70971d43eb MDL-46044 Assign: Modify myhome query to only use the maxattempt from the submission
Using mismatches from the submissions/grades tables does not make much sense, we
should always only consider only the maxattempt from the submissions table.
2014-06-27 14:23:17 +08:00
Damyon Wiese 99e0bb23bf MDL-46044 Assign: Move common setup to setUp method (share it for all of lib_test.php) 2014-06-27 14:18:10 +08:00
Damyon Wiese d95453d903 MDL-46044 Assign: Fix print_overview function when there are multiple attempts 2014-06-27 14:17:53 +08:00
Damyon Wiese 53fb01aef0 MDL-46044 Assign: Update unit test to test multiple attempts on overview page 2014-06-27 14:17:44 +08:00
David Monllao cfd5ba4101 MDL-46118 report_log: No results limit when downloading 2014-06-27 11:35:06 +08:00
David Monllao 5eb386fd09 MDL-45833 event: Removing courseid as the context is higher than course context 2014-06-27 11:25:07 +08:00
Yuliya Bozhko 594848bb15 MDL-46107 badges: Fix badges navigation and remove empty breadcrumbs on pages using Clean
Signed-off-by: Yuliya Bozhko <yuliya.bozhko@totaralms.com>
2014-06-27 12:48:01 +12:00
Sam Hemelryk 64fea720ce MDL-45209 course: fixed navbar when creating,editing courses 2014-06-27 09:39:45 +12:00
Eloy Lafuente (stronk7) 83d08fcc21 weekly release 2.7+ 2014-06-26 10:35:58 +02:00
Eloy Lafuente (stronk7) 01e7204646 Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-06-26 10:35:54 +02:00
Eloy Lafuente (stronk7) 3152864fd5 Revert " MDL-45044 filter_tex: properly escape excutable pathnames for Windows"
This reverts commit 7eac026a02.
2014-06-26 10:05:49 +02:00
Rajesh Taneja 2997bd6dce MDL-45889 behat: Allow admin config to set by shortname 2014-06-26 13:18:32 +08:00
Andrew Davis 083d5a6f0c MDL-46036 mod_survey: added logic to prevent user trying to download when there are no results 2014-06-26 11:18:29 +08:00
Rajesh Taneja c1ee80fef5 MDL-46061 behat: Fixed blur event problem for atto_image
atto_image look for blur event after changing width/height
Added a new step to get focus off the element, so this can
work.
2014-06-26 10:29:35 +08:00
Andrew Davis 0a9815d14e MDL-42467 mod_data: added code to delete cached RSS feeds when database or glossary entries are deleted 2014-06-26 09:30:18 +08:00
Damyon Wiese 3ac5a3544c MDL-45983 Atto equation editor: Exclude phantomjs from this behat test because it's buggy 2014-06-25 15:05:01 +08:00
Jonathon Fowler b7cb9c60c1 MDL-46080 assign: fix offline grading worksheet marker column 2014-06-25 12:23:34 +10:00
AMOS bot 6f5ca6613f Automatically generated installer lang files 2014-06-25 00:45:27 +00:00
AMOS bot a16755314a Automatically generated installer lang files 2014-06-25 00:45:27 +00:00
Eloy Lafuente (stronk7) a4919abf4f Merge branch 'MDL-46079-m27' of https://github.com/sammarshallou/moodle into MOODLE_27_STABLE 2014-06-25 01:33:37 +02:00
Eloy Lafuente (stronk7) 022a58af8d Merge branch 'MDL-45445_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-06-25 00:47:43 +02:00
Eloy Lafuente (stronk7) 6480ec0c48 Merge branch 'MDL-41258-27' of git://github.com/andrewnicols/moodle into MOODLE_27_STABLE 2014-06-24 20:10:48 +02:00
Damyon Wiese 1e4e4a05d7 Merge branch 'MDL-45652_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-06-24 16:59:42 +08:00
Damyon Wiese 9dc9608795 Merge branch 'MDL-10115-27' of git://github.com/xow/moodle into MOODLE_27_STABLE 2014-06-24 16:03:53 +08:00
John Okely e08d290469 MDL-10115 User profile: Use title to aid in the ellipsis link being understood by screen readers 2014-06-24 15:38:58 +08:00
Marina Glancy 80bb90c3ca Merge branch 'MDL-45933-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-06-24 13:52:42 +08:00
Marina Glancy a3ddcab336 Merge branch 'MDL-45983-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-06-24 13:52:14 +08:00
Marina Glancy a839769c23 Merge branch 'MDL-46061-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-06-24 13:32:25 +08:00
Marina Glancy 1eb503b379 Merge branch 'MDL-45044-m27-master' of git://github.com/dthies/moodle into MOODLE_27_STABLE 2014-06-24 13:29:06 +08:00
Damyon Wiese cc5f8bd53f Merge branch 'wip-MDL-46038-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-06-24 13:10:52 +08:00
Damyon Wiese bb512f7c1f Merge branch 'MDL-46035_survey_27' of https://github.com/andyjdavis/moodle into MOODLE_27_STABLE 2014-06-24 13:08:17 +08:00
Damyon Wiese 5b5a73019d Merge branch 'MDL-46046-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-06-24 11:48:02 +08:00
Damyon Wiese ce0b9bb7ca Merge branch 'MDL-46056-27' of git://github.com/mudrd8mz/moodle into MOODLE_27_STABLE 2014-06-24 11:35:21 +08:00
Damyon Wiese 38063e7d1b Merge branch 'MDL-44512-27' of git://github.com/jethac/moodle into MOODLE_27_STABLE 2014-06-24 10:58:17 +08:00
Damyon Wiese ee5b9e137d Merge branch 'MDL-44773-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-06-24 10:19:16 +08:00
Eloy Lafuente (stronk7) 55103810f0 Merge branch 'MDL-45721_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-06-24 01:00:10 +02:00
Eloy Lafuente (stronk7) e5b111f26b Merge branch 'MDL-39883-27' of git://github.com/ankitagarwal/moodle into MOODLE_27_STABLE 2014-06-24 00:48:56 +02:00
Eloy Lafuente (stronk7) 7c2e2133cc Merge branch 'MDL-45764_generalTool_27' of https://github.com/moodlerooms/moodle into MOODLE_27_STABLE 2014-06-24 00:03:34 +02:00
Damyon Wiese 3352ffcfa2 Merge branch 'MDL-45580-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-06-23 15:20:14 +08:00
Simey Lameze 8e74bfa8e8 MDL-40805 auth_cas : Trigger user_loggedout event before CAS logout. 2014-06-23 15:19:07 +08:00
Frederic Massart 9f630b6cc4 MDL-45580 assignfeedback_editpdf: Save readonly version in backup 2014-06-23 14:56:08 +08:00
Frederic Massart c2779c9f29 MDL-45580 assignfeedback_editpdf: Delete draft content on new submission 2014-06-23 14:56:08 +08:00
Frederic Massart 7fecbba80b MDL-45580 assignfeedback_editpdf: Store a readonly version of the PDF 2014-06-23 14:56:08 +08:00
Damyon Wiese 80b81e5094 Merge branch '37145-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-06-23 14:39:56 +08:00
Damyon Wiese 6e977fcdd6 Merge branch 'MDL-38693-27' of git://github.com/jethac/moodle into MOODLE_27_STABLE 2014-06-23 14:15:36 +08:00
Damyon Wiese 9c8c5f2d01 MDL-41746 External api: Allow multiple calls to validate_context at different levels
(Only from webservices)
2014-06-23 13:39:21 +08:00
Damyon Wiese 9134f3f0df Merge branch 'MDL-35453_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-06-23 12:30:41 +08:00
Damyon Wiese b093752289 Merge branch 'MDL-46086_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-06-23 12:26:31 +08:00
Mark Nielsen bd87c3e225 MDL-46013 theme: Uninstall theme unconditionally unsets configs 2014-06-23 11:34:59 +08:00
Marina Glancy 7bea1ea240 Merge branch 'MDL-44124-27' of git://github.com/ankitagarwal/moodle into MOODLE_27_STABLE 2014-06-23 11:34:10 +08:00
Sam Hemelryk afd6e7d542 MDL-37145 caching: noted recommendation for dedicated memcache servers
Several reports have been made about the unexpected purging of entire
memcached servers when MUC is configured to use Memcache and caches
get purged.
This is expected and occurs because the memcache extenions don't
provide isolated containers. Moodle data is stored along side any other
data in the cache and when caches get purged all data gets removed
whether it belongs to Moodle or not.

The docs cover this point and here I've added notes about this to both
config-dist.php and cache/README.md
2014-06-23 11:01:51 +12:00
AMOS bot e29eef4bde Automatically generated installer lang files 2014-06-21 00:43:37 +00:00
Tim Hunt 63dd180030 MDL-46086 quiz: fix unit test on Oracle 2014-06-20 22:29:28 +01:00
Tim Hunt 8eacbd5a32 MDL-35453 quiz reports: don't order by id.
We were using ORDER BY id even though there was a perfectly good
attempt column to order the attempts by one user at one quiz.

Also, Oracle was complaining:
Debug info: ORA-01799: a column may not be outer-joined to a subquery
2014-06-20 16:55:35 +01:00
sam marshall 680ff52414 MDL-46079 Restore: Can run out of memory in get_records call 2014-06-20 14:14:53 +01:00
Frederic Massart 884e310a3b MDL-40228 backup: Settings were ignored during automated backups 2014-06-20 15:38:29 +08:00
Daniel Thies 7eac026a02 MDL-45044 filter_tex: properly escape excutable pathnames for Windows 2014-06-19 21:34:10 -05:00
Andrew Davis deaddfb6b8 MDL-46035 mod_survey: a string change to make an error message always correct 2014-06-20 09:17:47 +08:00
Frederic Massart 85b40b18d5 MDL-46061 atto_image: Improved tests to cover sizing feature 2014-06-19 16:00:47 +08:00
Frederic Massart 3b6987cea3 MDL-46061 atto_image: Prevent error when image does not have a size 2014-06-19 16:00:47 +08:00
Jetha Chan 14ff3d59b3 MDL-44512 themes: fix for custom menu submenu arrows on RTL languages 2014-06-19 15:16:52 +08:00
Damyon Wiese dd02a787d8 weekly release 2.7+ 2014-06-19 14:13:25 +08:00
Damyon Wiese cefe7c7f59 Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-06-19 14:13:20 +08:00
Frederic Massart d9fc73dc7a MDL-44773 atto_accessibilitychecker: Improved image test coverage 2014-06-19 13:38:36 +08:00
Frederic Massart 3bc1e345ca MDL-44773 atto_accessibilitychecker: Set focus on clicked warnings 2014-06-19 13:38:35 +08:00
AMOS bot 5d3fe21ab2 Automatically generated installer lang files 2014-06-19 00:42:51 +00:00
David Mudrák 17db3e8af1 MDL-46056 Remove invalid string definition from the workshop module
The correct version of the string is defined above.
2014-06-19 00:33:24 +02:00
Frederic Massart a0da864ac2 MDL-46046 atto_accessibilityhelper: Remove dead code from the plugin 2014-06-18 16:52:48 +08:00
Ankit Agarwal 0978aab839 MDL-39883 events: Trigger a module created event when duplicating a module 2014-06-18 16:02:23 +08:00
Ankit Agarwal 7d947ad66c MDL-39883 events: Create a new api create_from_cm for module create event 2014-06-18 15:46:26 +08:00
Damyon Wiese 5e63c8e57e MDL-45933 Assign: Prevent fatal error when there are no users in the grading table 2014-06-18 15:17:36 +08:00
Ankit Agarwal 34bcea8159 MDL-44124 libraries: Allow rrules with only one part during rrule validation checks 2014-06-18 14:14:49 +08:00
Marina Glancy 2a56e3c8b9 MDL-46038 repositories: added forgotten global 2014-06-18 13:39:43 +08:00
Mark Nelson 1fb1c6d456 MDL-45652 core_backup: display warning on restore destination form when necessary data is missing 2014-06-17 21:56:21 -07:00
Mark Nelson 469e7dd82d MDL-45721 core_backup: only trigger the course_restored event when restoring a course 2014-06-17 19:38:30 -07:00
AMOS bot 1461f9d664 Automatically generated installer lang files 2014-06-18 00:42:28 +00:00
Eloy Lafuente (stronk7) 8791525d88 Merge branch 'MDL-45978_27' of git://github.com/grabs/moodle into MOODLE_27_STABLE 2014-06-17 11:54:50 +02:00
Andrew Nicols a0f39f2b57 MDL-41258 Forum: Add additional unit tests for forum digest settings 2014-06-17 16:07:59 +08:00
Damyon Wiese 6fc2264a8a MDL-45983 Atto equation editor: Various bugs when editing an existing equation
(And a behat test for it).
2014-06-17 15:21:20 +08:00
Andreas Grabs 8893b111c2 MDL-45978 logging - added missing parameter id 2014-06-17 07:05:58 +02:00
Damyon Wiese 3362673173 MDL-45582 Editpdf: Prevent debugging when there is no pdf 2014-06-17 10:19:55 +08:00
Damyon Wiese 49703ecf1d Merge branch 'm27_MDL-45582' of git://github.com/greg-or/moodle-mod_assign into MOODLE_27_STABLE
Conflicts:
	mod/assign/feedback/editpdf/locallib.php
2014-06-17 10:17:55 +08:00
Eloy Lafuente (stronk7) d56f3531b4 Merge branch 'MDL-45970_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-06-17 01:15:47 +02:00
Eloy Lafuente (stronk7) 902a36137a Merge branch 'MDL-45611-27' of git://github.com/phalacee/moodle into MOODLE_27_STABLE
Conflicts:
	theme/bootstrapbase/style/moodle.css
2014-06-17 01:12:02 +02:00
Eloy Lafuente (stronk7) 19e4d5ada8 Merge branch 'wip-mdl-45719-m27' of https://github.com/deraadt/moodle into MOODLE_27_STABLE 2014-06-17 01:03:58 +02:00
Eloy Lafuente (stronk7) d81917322f Merge branch 'MDL-45870-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-06-17 00:51:33 +02:00
Marina Glancy b657f6db05 Merge branch 'MDL-45940-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-06-16 17:28:30 +08:00
Marina Glancy abd980d36d Merge branch 'MDL-45901_Quiz_MOODLE-27-STABLE' of git://github.com/nadavkav/moodle into MOODLE_27_STABLE 2014-06-16 17:27:40 +08:00
Rajneel Totaram 7b27045680 MDL-45967 admin lang: Fix typo 2014-06-16 17:26:50 +08:00
Marina Glancy e4a56bd9dd Merge branch 'MDL-43274-27' of git://github.com/xow/moodle into MOODLE_27_STABLE 2014-06-16 17:24:10 +08:00
Jonathon Fowler 5807b224d9 MDL-42531 assign: refactor batch operations to use forms properly
Avoids a lot of ugly optional_param() use. Also fixes the
non-functional cancel buttons.
2014-06-16 16:43:54 +08:00
Gregory Faller 8b1596c257 MDL-45582: Apply grades and feedback to entire group does not work with Annotate PDF feature 2014-06-16 18:06:09 +09:30
John Okely 2649eefe1c MDL-43274 Course: Remove message about course logs from upgrade.txt 2014-06-16 16:23:51 +08:00
Damyon Wiese b3bb3a4422 MDL-45940 Assign: Improved access check
Call can_edit() instead of repeating a (slightly wrong) access check.
2014-06-16 16:20:34 +08:00
Damyon Wiese 6e10f195c5 Merge branch 'm27_MDL-45582' of git://github.com/greg-or/moodle-mod_assign into MOODLE_27_STABLE 2014-06-16 14:29:51 +08:00
Daniel Neis ab7c329acf MDL-35648 adding missing distinct selector in sql on participation report 2014-06-16 14:22:46 +08:00
Marina Glancy 95d39aabc7 Merge branch 'MDL-45935-27' of git://github.com/andrewnicols/moodle into MOODLE_27_STABLE 2014-06-16 14:22:42 +08:00
John Okely 6e515be94f MDL-10115 User profile: Use moodle_url and html_writer::link for course links on user profiles 2014-06-16 14:08:44 +08:00
Damyon Wiese b3b4f9a4a4 Merge branch 'MDL-31998_27' of git://github.com/grabs/moodle into MOODLE_27_STABLE 2014-06-16 12:07:40 +08:00
Gregory Faller c71d8267ed MDL-45582: Apply grades and feedback to entire group does not work with Annotate PDF feature 2014-06-16 12:44:23 +09:30
Damyon Wiese 1742e76777 Merge branch 'wip-mdl-46001-m27' of https://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-06-16 11:13:45 +08:00
Rajesh Taneja 2797fcc75e MDL-46001 atto_clear: modfied behat test to work on xvfb 2014-06-16 11:10:29 +08:00
Damyon Wiese 2538e2dab1 Merge branch 'MDL-45803_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-06-16 11:01:04 +08:00
John Okely 6bf5eeed56 MDL-43274 Course: Remove ability to delete logs on a course during reset 2014-06-16 09:54:20 +08:00
AMOS bot c14d87daaa Automatically generated installer lang files 2014-06-15 00:42:44 +00:00
Nadav Kavalerchik cb201e866b MDL-45901 - Quiz - Random question category question are not visible, in RTL mode 2014-06-14 00:42:30 +03:00
Mark Nelson cc6a8bc792 MDL-45445 events: added '(optional)' to event params where applicable 2014-06-12 20:47:21 -07:00
Mark Nelson fa71841e9d MDL-45445 events: documented the additional validation 2014-06-12 20:47:21 -07:00
Mark Nelson be7809f5fd MDL-45445 events: added missing 'other' validation 2014-06-12 20:47:20 -07:00
Mark Nelson 655cdde2dc MDL-45445 events: added missing 'relateduserid' validation 2014-06-12 20:47:20 -07:00
Mark Nelson 7f75f1507e MDL-45445 events: trivial changes 2014-06-12 20:47:20 -07:00
Jason Fowler 3fbf089303 MDL-45611 Questions: Fixing the layout of the 'points box' 2014-06-13 10:24:20 +08:00
Tim Lock 8a453265d2 MDL-45982: Implement displaying of non error messages from a provider. 2014-06-13 10:13:57 +09:30
AMOS bot 807d45073a Merge branch 'MOODLE_27_STABLE' into install_27_STABLE 2014-06-13 00:41:59 +00:00
Andreas Grabs 253bbbb668 MDL-31998 mod_feedback - Feedback depend questions bug 2014-06-13 01:44:59 +02:00
Tim Hunt 8fbc1919df MDL-45970 quiz editing: fix display of random questions.
The pass by reference meant the function was clobbering the variable in
the calling function. Once that was change, it was not strictly
necessary to rename the variable in the function, but I did anyway for
clarity.

Thanks to Rajesh Taneja for finding the problem, and identifying which
bit of code was broken. I really just made the patch.
2014-06-12 19:43:42 +01:00
Eloy Lafuente (stronk7) c41ace2f7a weekly release 2.7+ 2014-06-12 18:59:06 +02:00
Eloy Lafuente (stronk7) 3be351cabc Merge branch 'MDL-44871-27' of git://github.com/damyon/moodle into MOODLE_27_STABLE 2014-06-12 11:38:37 +02:00
Damyon Wiese 53bd21e7d8 MDL-42835 Scorm: Fix for JS error because no nodes are selected in the toc. 2014-06-12 10:00:56 +02:00
John Okely 217530dfca MDL-10115 User profile: Allow full list of courses to be viewed on a user's profile 2014-06-12 15:03:27 +08:00
Rajesh Taneja 30271d87aa MDL-45808 enrol_self: Fixed behat to observe the group key policy 2014-06-12 14:20:37 +08:00
Damyon Wiese f271df32ec MDL-44871 Atto: Add missing tags to behat tests @editor and @editor_atto 2014-06-12 11:15:17 +08:00
Rajesh Taneja 77ae35faba MDL-44871 behat: Hack to make equation editor visible 2014-06-12 11:11:17 +08:00
Damyon Wiese 32d746479b MDL-44871 Atto behat: Use one less page load to get to profile edit page 2014-06-12 11:11:17 +08:00
Damyon Wiese b18fd23232 MDL-44871 Atto: Move custom select text step to atto specific step definition. 2014-06-12 11:11:17 +08:00
Damyon Wiese bbd644ea34 MDL-44871 Atto behat tests: Modified the tests to work around focus bugs with workspaces
The main changes here are that the "select the text in" step was modified to select only the
first text node in the editor field, and to focus on it's parent instead of the entire editable div.

Some tests had to be modified to match the new behaviour, and another "real" bug was found in the table plugin.
2014-06-12 11:11:17 +08:00
Damyon Wiese c4bfba91c2 MDL-44871 Behat: Add tests for Atto functionalities (some of them) 2014-06-12 11:11:17 +08:00
AMOS bot 6e7a7aecf3 Automatically generated installer lang files 2014-06-12 00:43:36 +00:00
Mark Nelson 635493f6dd MDL-45803 mod_quiz: removed the quiz_fire_attempt_started function
Also commented in mod/quiz/upgrade.txt to inform developers.
2014-06-11 13:57:24 -07:00
Mark Nelson 0f583e0c91 MDL-45803 mod_quiz: removed usage of the function quiz_fire_attempt_started_event 2014-06-11 13:57:24 -07:00
Mark Nelson 1a7ded8989 MDL-45803 mod_quiz: prevented the attempt_started event from being triggered twice 2014-06-11 13:57:23 -07:00
Mark Nelson 159e18c977 MDL-45803 mod_quiz: added attempt snapshot for the attempt and preview started events 2014-06-11 13:57:23 -07:00
Damyon Wiese 801dea3298 MDL-45763 Question types: Allow saving '0' as question text. 2014-06-11 17:29:26 +08:00
Marina Glancy d468b949f1 MDL-39726 backup: fix SQL syntax for Oracle 2014-06-11 17:16:40 +08:00
Marina Glancy a0881872c7 MDL-39726 backup: fix SQL syntax for Oracle 2014-06-11 12:17:25 +08:00
Marina Glancy a9e9cd31e1 MDL-45763 question: fix SQL syntax for Oracle 2014-06-11 12:17:25 +08:00
Frederic Massart 0085d95576 MDL-45870 mod_assign: Behat test covering some outcome usage 2014-06-11 10:34:44 +08:00
Frederic Massart e4226ddc26 MDL-45870 mod_assign: Outcomes are saved for each group member 2014-06-11 10:34:44 +08:00
Eloy Lafuente (stronk7) 4c7169437b Merge branch 'm27_MDL-29708_Typo_Extra_Slashes' of https://github.com/scara/moodle into MOODLE_27_STABLE 2014-06-11 01:36:56 +02:00
Frederic Massart b2cdd35a46 MDL-45808 group: Observe the group key policy upon group creation 2014-06-10 23:02:58 +02:00
Eloy Lafuente (stronk7) aa0fad65e3 Merge branch 'MDL-45579-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-06-10 22:25:54 +02:00
Eloy Lafuente (stronk7) 4c06cef684 Merge branch 'MDL-45418_27' of git://github.com/stronk7/moodle into MOODLE_27_STABLE 2014-06-10 20:13:28 +02:00
Barbara Ramiro 6871df272d MDL-45943: Replacement for publisher icons 2014-06-10 19:31:22 +02:00
Jason Fowler 40a4427420 MDL-45418 Files: Adding upgrade steps for publisher docs
Conflicts:
	lib/db/upgrade.php
	version.php
2014-06-10 19:31:04 +02:00
James McLean f76b5133a5 MDL-45418 Files: Adding publisher docs to Filetypes 2014-06-10 19:27:46 +02:00
Eric Merrill d5a7b7873e MDL-45763 question: Correct random question text if set to true or false 2014-06-10 20:08:25 +08:00
Marina Glancy ffa71ca45e Merge branch 'MDL-45813-scheduled_task_27' of git://github.com/mudrd8mz/moodle into MOODLE_27_STABLE 2014-06-10 15:42:56 +08:00
Marina Glancy 5248eb8831 Merge branch 'MDL-20154-27' of git://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-06-10 15:42:13 +08:00
Damyon Wiese 5468d02e60 Merge branch '45524-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-06-10 15:31:00 +08:00
Marina Glancy 251fd097bb Merge branch '27STABLE-wip-MDL45846' of git://github.com/jennymgray/moodle into MOODLE_27_STABLE 2014-06-10 14:20:02 +08:00
Daniel Neis Araujo 3ac721e5a3 MDL-45245 html_writer::select_time does not respect 5th parameter "attributes" 2014-06-10 14:19:29 +08:00
Damyon Wiese ecd99dc88a Merge branch 'wip-mdl-44309-m27' of https://github.com/deraadt/moodle into MOODLE_27_STABLE 2014-06-10 14:08:03 +08:00
Damyon Wiese 3097fca71c Merge branch 'MDL-45761-27' of https://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-06-10 14:00:58 +08:00
Damyon Wiese bc1c896692 Merge branch 'MDL-45767_returnInstanceid_27' of https://github.com/moodlerooms/moodle into MOODLE_27_STABLE 2014-06-10 13:53:43 +08:00
Damyon Wiese 6a927661f2 Merge branch 'MDL-45763-27' of https://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-06-10 13:12:07 +08:00
Andrew Nicols 601d32ae66 MDL-45935 tests: Specify step names during backup/restore tests 2014-06-10 12:14:09 +08:00
Michael de Raadt 2dde0b96da MDL-45719 mod_lti - Pass language strings to inline JS to allow for escaping 2014-06-10 11:39:12 +08:00
Eloy Lafuente (stronk7) d420bf952f Merge branch 'MDL-45789_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-06-10 01:17:00 +02:00
Eloy Lafuente (stronk7) a02d7831b6 Merge branch 'MDL-45804_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-06-10 01:14:29 +02:00
Jetha Chan 604db7d557 MDL-42782 usability: fix for extreme course page indenting 2014-06-10 01:10:31 +02:00
Nobelium 41ab96e7ff MDL-42835 mod_scorm: Close tree nodes using TreeView API 2014-06-10 00:37:16 +02:00
Eloy Lafuente (stronk7) 9dfb59fa28 Merge branch 'MDL-45574-m27' of https://github.com/sammarshallou/moodle into MOODLE_27_STABLE 2014-06-09 21:49:18 +02:00
Eloy Lafuente (stronk7) ad94e63238 Merge branch 'wip-MDL-44501-27' of git://github.com/abgreeve/moodle into MOODLE_27_STABLE 2014-06-09 18:59:22 +02:00
Jenny Gray 82c0485aab MDL-45846 Libraries custom user agent device detection unit test added 2014-06-09 13:59:10 +01:00
Eloy Lafuente (stronk7) 4524454ff2 Merge branch 'wip-mdl-45769-m27' of https://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-06-09 13:25:17 +02:00
Andrew Nicols 658bba713a MDL-45560 report_log: Close sessions before download only
If the session is closed too early, then preferences made in the body of
the page will not be saved to the session.
2014-06-09 17:24:56 +08:00
Marina Glancy 238c388016 Merge branch 'MDL-45634-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-06-09 17:24:36 +08:00
David Mudrák 5e10e88673 MDL-45813 Fix variable name in scheduled task 2014-06-09 09:47:01 +02:00
Jetha Chan 7b6bad24ee MDL-38693 themes: amended z-indexes
Amended #dock z-index level from 11000 to 5000 across all themes; amended z-index style of #page-header in Overlay theme such that elements no longer occlude TinyMCE.
2014-06-09 14:16:24 +08:00
Damyon Wiese 11be1e8b2b Merge branch 'MDL-39726-27' of https://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-06-09 12:43:27 +08:00
Rajesh Taneja 42126ff6a5 MDL-45769 behat: use final versions of symfony and behat 2014-06-09 09:59:19 +08:00
Rajesh Taneja f12f99241c MDL-45769 Behat: Fixed behat, was failing because of xpath chaining 2014-06-09 09:59:13 +08:00
Damyon Wiese 8fde6e8ef9 Merge branch 'MDL-45714-27' of https://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-06-09 08:56:00 +08:00
Sam Hemelryk 36bd6f3319 MDL-45524 navigation: fixed non-expandable node behat tests 2014-06-09 09:34:02 +12:00
Sam Hemelryk 0f52f263ca MDL-44711 navigation: improved expandable course calculation 2014-06-09 09:34:02 +12:00
Matteo Scaramuccia b9e1842e02 MDL-29708 Fixed file_exception() arguments in rename(). 2014-06-07 09:56:24 +02:00
Matteo Scaramuccia 99261fdf05 MDL-29708 Fixed extra slashes in $string['storedfilenotcreated']. 2014-06-07 09:56:23 +02:00
sam marshall 07388eaded MDL-45574 Backup progress: Can time out with large number of files
When there are many files inside a single resource, it's possible
for the backup to time out because it does not report progress
while adding entries to the backup_ids table.
2014-06-06 10:42:27 +01:00
Jenny Gray d983601e46 MDL-45846 Libraries Reinstate custom user agent device detection 2014-06-06 09:12:58 +01:00
Sam Chaffee fd85f4eeb9 MDL-45767: Fixed DB error when returning to course from external tool
The instance ID is not always returned from the external
tool provider.
2014-06-05 09:38:07 -07:00
Eric Merrill c11ac48868 MDL-20154 quiz: Remove unused random questions
When a random question is removed from a quiz, and it is not
in use elsewhere, it should be deleted.
2014-06-05 11:06:59 -04:00
Eric Merrill 0d5c68bfd8 MDL-20154 questions: question_delete_question should not check perms
By Moodle convention, library functions should not implement permission
checks, they are to be handled by the invoking code.
2014-06-05 11:06:59 -04:00
Eloy Lafuente (stronk7) a6b91c8407 weekly release 2.7+ 2014-06-05 16:58:54 +02:00
Eloy Lafuente (stronk7) f6cac05e9c Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-06-05 16:58:49 +02:00
Eric Merrill 9a2938c57c MDL-45761 assign Set inline comment format properly when plugin is empty
If a plugin says it is empty, skip it for for building the inline
comment.

If not format was found in any plugins, set to FORMAT_HTML, which is
the default for feedback anyways.
2014-06-05 08:58:09 -04:00
Michael de Raadt f4d6bab1b4 MDL-44309 Administration - correcting inproperly assigned column classes in environment table 2014-06-05 10:52:43 +08:00
Mark Nielsen ebfbd63b3c MDL-45764 mod_lti: Fix adding General Tool
This error only occurs when a ltisource
plugin is present that implements the
get_types callback.
2014-06-04 08:10:19 -07:00
Eric Merrill 9ec7228b03 MDL-39726 backup: Move question files by context, not one at a time
Use question category contexts to send file to the file pool in bulk.
Questions are only restored in whole category chunks, so this is safe
to do.
2014-06-04 09:19:52 -04:00
Adrian Greeve 0a1f0c4b1f MDL-44501 mod_data: Only attempt to export when a file exists.
The error only occurs when portfolios are enabled and there is only one field which is
a file field.
2014-06-04 15:30:03 +08:00
Frederic Massart 7180fb19c1 MDL-45579 group: Behat tests to cover group enrolment key rules 2014-06-04 15:12:12 +08:00
Frederic Massart ac2015f2ce MDL-45579 group: Prevent duplicate enrolment keys in course groups 2014-06-04 15:12:12 +08:00
Marina Glancy 6fc8187375 Merge branch 'MDL-18162-27-2' of git://github.com/andrewnicols/moodle into MOODLE_27_STABLE 2014-06-04 12:59:42 +08:00
Andrew Nicols 81e433d505 MDL-18162 mod_forum: Correct @param type in phpdoc to use stdClass 2014-06-04 11:26:10 +08:00
Damyon Wiese 9fbdee633a Merge branch 'MDL-45568_m27' of git://github.com/markn86/moodle into MOODLE_27_STABLE 2014-06-04 10:20:15 +08:00
Mark Nelson f1dee5ce23 MDL-45568 events: fixed the description for the 'course_module_completion_updated' event 2014-06-03 17:26:22 -07:00
Mark Nelson 1ffce0c735 MDL-45789 mod_wiki: removed undefined "$this->other['itemid']" from the comments_viewed event description 2014-06-03 15:23:50 -07:00
Eloy Lafuente (stronk7) 3e307259ac Merge branch 'MDL-44620_master' of git://github.com/dmonllao/moodle into MOODLE_27_STABLE 2014-06-03 18:11:37 +02:00
Dan Poltawski 8455124070 Merge branch '45333-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-06-03 15:26:01 +01:00
Tim Hunt a1d932bd82 MDL-44054 quiz_statistics fix lang string concatenation. 2014-06-03 13:01:25 +01:00
Jason Fowler d9ef98fc80 MDL-42953 Themes: Fixing CSS for headers of central blocks 2014-06-03 12:12:37 +02:00
Damyon Wiese 4affd3c42e Merge branch 'MDL-45592_27' of git://github.com/grabs/moodle into MOODLE_27_STABLE 2014-06-03 16:14:56 +08:00
Damyon Wiese 8771f49c0a Merge branch 'MDL-45677_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-06-03 14:38:57 +08:00
Damyon Wiese b018b44b49 Merge branch 'm27_MDL-44098' of git://github.com/greg-or/moodle-mod_assign into MOODLE_27_STABLE 2014-06-03 12:49:59 +08:00
Damyon Wiese 3d4f5c6bf8 MDL-45781 mod_quiz: Shifted files did not match CI version 2014-06-03 12:14:07 +08:00
Frederic Massart 6bbdb16bb1 MDL-45634 editor_atto: Adding type button to toolbar buttons
This prevents the browser to assume that those buttons are submit
buttons. In which case the submit action was stolen and the form
could not be submitted pressing the 'enter' key.
2014-06-03 12:09:46 +08:00
Damyon Wiese 07783f9c20 Merge branch 'MDL-45781_27' of git://github.com/timhunt/moodle into MOODLE_27_STABLE 2014-06-03 11:57:54 +08:00
Andrew Nicols b19370bd35 MDL-18162 mod_forum: Correct phpdoc for forum_clean_search_terms 2014-06-03 15:19:41 +12:00
Eric Merrill 9d18c714b8 MDL-45714 backup: Less aggressive removal of old backup dirs
The old 4 hour standard was too aggressive and can cause backup files
to be removed while they were still in use. Now the same as cron,
1 week.
2014-06-02 21:50:48 -04:00
Eloy Lafuente (stronk7) 474dd3da66 Merge branch 'm27_MDL-45726' of https://github.com/danmarsden/moodle into MOODLE_27_STABLE 2014-06-03 02:20:34 +02:00
Mark Nelson 5095725a00 MDL-45804 mod_workshop: fixed objecttable specified for the submission_reassessed event 2014-06-02 16:35:15 -07:00
Sam Hemelryk 02da49597c Merge branch 'MDL-33763-27' of git://github.com/ankitagarwal/moodle into MOODLE_27_STABLE 2014-06-03 08:57:39 +12:00
Eric Merrill 5f86aa9d14 MDL-45763 question Random qtype should use '0' or '1' question text.
Some time ago, it when from using '0' for no-subcategories to blank.
Change to properly define '0' or '1', update old questions, and make
sure to fix newly restored questions.
2014-06-02 15:33:00 -04:00
Albert Gasset ae916b5d6a MDL-35514 mod_forum: Fixed warning message to students in forums with groups 2014-06-02 18:25:21 +02:00
AMOS bot ea66859873 Automatically generated installer lang files 2014-05-31 01:06:17 +00:00
Tim Hunt 23f43bb4c4 MDL-45781 quiz autosave: detect and report when the session is lost.
and also other errors.
2014-05-30 16:29:56 +01:00
AMOS bot 108d281f6b Automatically generated installer lang files 2014-05-30 01:24:20 +00:00
AMOS bot 4a0e272c5b Automatically generated installer lang files 2014-05-30 01:24:20 +00:00
Ciaran Irvine 647a688de3 MDL-45726 SCORM: Correct check for forcenewattempt 2014-05-30 09:48:50 +12:00
Sam Hemelryk 3f9ea21ae3 MDL-45333 output: navbar is now wrapped in a <nav> tag 2014-05-30 08:41:34 +12:00
Andreas Grabs 34a46904c2 MDL-45592 mod_feedback - unwanted linebreak after import or duplicating a feedback 2014-05-29 17:16:10 +02:00
Eloy Lafuente (stronk7) d73b1f3e71 weekly release 2.7+ 2014-05-29 12:51:41 +02:00
Eloy Lafuente (stronk7) 2c356d8ecd Merge branch 'install_27_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_27_STABLE 2014-05-29 12:51:36 +02:00
Damyon Wiese 62c7d543f6 MDL-45654 Cron: Fix for unit test that was causing integer overflow in 32 bit php 2014-05-29 16:29:58 +12:00
Rajesh Taneja 008cfb2a1f MDL-45698 behat: Added extra setting, to avoid timout issue 2014-05-29 14:52:57 +12:00
Sam Hemelryk 243f766222 Merge branch 'wip-mdl-45698-m27' of https://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-05-29 14:28:13 +12:00
Rajesh Taneja 2b9259ed7f MDL-45698 behat: Fixed behat and symfony versions 2014-05-29 09:47:55 +08:00
Sam Hemelryk c5d9d36e79 MDL-45654 cron: fixed dataprovider timestamp issue 2014-05-29 11:31:13 +12:00
Sam Hemelryk 296029fadf Merge branch 'wip-mdl-45565-m27' of https://github.com/rajeshtaneja/moodle into MOODLE_27_STABLE 2014-05-29 08:12:43 +12:00
Eloy Lafuente (stronk7) 7e78f9c4a5 MDL-45503 upgrade: add v2.7.0 sep lines 2014-05-28 01:16:36 +02:00
Simey Lameze 83bc3ccfdf MDL-45544 events: Add event user_profile_viewed trigger to user/profile.php. 2014-05-27 07:50:35 +01:00
Rajesh Taneja 6a001a3223 MDL-45565 phpunit: Changed testsuite_name, so as to avoid class collision 2014-05-27 09:45:16 +08:00
Rajesh Taneja 1974f5ade7 MDL-45565 core_message: Reset internal users in phpunit 2014-05-27 09:45:15 +08:00
Gregory Faller 837e3741fd MDL-44098: Late submissions with extension calculate period of lateness incorrectly 2014-05-27 11:13:41 +09:30
AMOS bot 4bdb702918 Automatically generated installer lang files 2014-05-26 16:46:54 +00:00
AMOS bot e588f20b6c Automatically generated installer lang files 2014-05-26 16:46:54 +00:00
Dan Poltawski ad7d8edf0c Merge branch 'MDL-45676_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-05-26 12:02:41 +01:00
Dan Poltawski 9f4a69a8cd Merge branch 'MDL-45675_m27' of https://github.com/markn86/moodle into MOODLE_27_STABLE 2014-05-26 11:58:57 +01:00
Andrew Nicols fd4c7d7b69 MDL-45682 editor_atto: Ensure that the current editor is active when saving selections 2014-05-26 11:24:11 +01:00
Jetha Chan e77b4ac0de MDL-44482 mod_lti: use localized dates
Fixed an issue where LTI external tools had creation datestamps of NaN/NaN/NaN under particular non-English languages.
2014-05-26 14:46:21 +08:00
Damyon Wiese 4fe4fbba9d MDL-45661 Assign: Clean bad data from DB after MDL-42526 2014-05-26 14:43:10 +08:00
Marina Glancy 331298218b MDL-45688 added missing library requirement 2014-05-26 12:47:52 +08:00
Damyon Wiese db52d4058d Merge branch '45499-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-05-26 12:11:39 +08:00
Mark Nelson b5d1353575 MDL-45629 mod_assign: removed use of '$this->objectid' in the submission_status_viewed event 2014-05-26 11:59:25 +08:00
Mark Nielsen fb3663ae5c MDL-44014 Navigation: Set the correct context when retrieved via AJAX 2014-05-26 11:59:19 +08:00
Mark Nelson 6825f882e2 MDL-45677 mod_assign: removed treatment of an array as an object 2014-05-25 20:25:31 -07:00
Mark Nelson 04b949a8f5 MDL-45676 mod_data: added missing additional name fields 2014-05-25 20:23:13 -07:00
Ankit Agarwal 86976c5bd9 MDL-33763 notes: Fix issue with incorrect node highlighting in the nav tree 2014-05-26 10:42:14 +08:00
Mark Nelson 33238bb24b MDL-45675 mod_data: initialise options as an empty array to avoid error when there are none 2014-05-25 19:29:44 -07:00
Mark Nelson 2b548c27ee MDL-45650 events: ensure correct objectid passed when triggering user_profile_viewed event 2014-05-26 13:59:52 +12:00
David Monllao e0cd7e44db MDL-45192 behat: Replacing specific-selector steps by a generic one
Having a I click on we can use all our selectors rather
than having multiple steps for the same purpose. This
step allow us to manage JS native dialogues without
having to fail a scenario.

Credit for Mohamed Alsharaf.
2014-05-26 13:57:23 +12:00
Mohamed Alsharaf 184cdf0d52 MDL-45192 assign: added behat script & new definitions to handle alert dialog
The behat script is to test the batch action to lock and unlock submissions.
The new definitions are to prevent the "unexpected alert open" error in Selenium.
2014-05-26 13:57:18 +12:00
Tim Hunt 472896acdd MDL-45660 question statistics: make comparison more robust. 2014-05-26 11:53:06 +12:00
Sam Hemelryk 1ff977a5e5 Merge branch 'MDL-45686_27' of git://github.com/jmvedrine/moodle into MOODLE_27_STABLE 2014-05-26 10:55:17 +12:00
Andrew Nicols 68a1c2a8d9 MDL-45635 javascript: Make core dialogue translatable 2014-05-26 10:38:59 +12:00
Simon Coggins db77228155 MDL-45623: Fix assigned users count on role delete confirmation page 2014-05-26 10:00:51 +12:00
Mark Nelson 8a0dcb91cc MDL-45607 events: changed the context passed to the user_profile_viewed event 2014-05-26 09:54:42 +12:00
Sam Hemelryk 11b5d9b763 Merge branch 'MDL-42526-27' of git://github.com/jamiepratt/moodle into MOODLE_27_STABLE 2014-05-26 09:02:53 +12:00
Sam Hemelryk dc195425ee MDL-45499 admin: fixed error when displaying page settings 2014-05-26 09:01:14 +12:00
Sam Hemelryk 72cf8ec5eb Merge branch 'MDL-45654-27' of https://github.com/rtcn2/moodle into MOODLE_27_STABLE 2014-05-26 08:58:13 +12:00
Jean-Michel Vedrine 1130c181f9 MDL-45686 qtype_multichoice get_num_selected_choices return wrong result 2014-05-25 09:23:26 +02:00
Rajesh Taneja 443d4dae06 MDL-45565 core_message: Added unit tests. 2014-05-23 16:48:18 +08:00
Rajesh Taneja a2720952c2 MDL-45565 core_message: Fixed strangers array
Strangers get mixed with noreply user and support user,
if  noreply/support users real user.
To avoid duplication use userid as array index. Also,
avoid fetching data again for noreply and support users,
if they are real users, then data is already feteched.
2014-05-23 16:48:15 +08:00
Eloy Lafuente (stronk7) 89262fa9f1 weekly release 2.7+ 2014-05-22 16:47:19 +02:00
James Pratt bc3c2a8eed MDL-42526 mod_assignment : fix record insert with assigment.id 0 2014-05-22 13:01:47 +07:00
Andrew Nicols fb7e5c42cd MDL-45239 editor_atto: On Android do not restore focus in the callbackWrapper
It seems that Android automatically focuses the cursor in the last position
when the content editable region is programatically re-focused.

Whilst this does not cause an issue on it's own, when combined with the
behaviour of the dictionary auto-completion to restore focus on the start
of the word when a word has not yet been finished, this was causing us to
change focus when pressing buttons.
2014-05-22 13:02:26 +08:00
Andrew Nicols 2e2a229f58 MDL-45536 atto_html: Update the textarea size when switching to HTML view 2014-05-22 11:47:37 +08:00
Rod Norfor d12b20d022 MDL-45654 cron: fix non-empty directories deletion
Remove errors when attempting to delete non-empty directories when
child directories do not get removed since the mtime was updated when
files were removed from the child directory.
2014-05-21 17:20:16 +01:00
Sam Hemelryk 5ce5bc6bdd MDL-44711 course: fixed navigation expansion in course tests 2014-05-21 20:58:27 +12:00
Marina Glancy 54c9048405 MDL-45469 profile: make sure profile fields can be initialised without arguments 2014-05-21 12:04:48 +08:00
Marina Glancy 7b04f1fa49 MDL-45371 behat: Tests for block glossary_random 2014-05-21 10:03:26 +08:00
Marina Glancy eebd7f8964 MDL-45320 behat: change to block selector 2014-05-21 09:32:18 +12:00
Marina Glancy 871af2ebc5 MDL-45320 block_html: behat tests 2014-05-21 09:32:14 +12:00
Marina Glancy 0d4b11ff88 MDL-45320 behat: Step definitions for blocks 2014-05-21 09:32:12 +12:00
David Monllao e342149a37 MDL-45294 behat: Updating block references to aria label value
Also improving moodle selectors xpath expressions
readability.
2014-05-21 09:31:50 +12:00
David Monllao 9054cd2a25 MDL-45294 behat: Supporting an aria-label as a block ref 2014-05-21 09:31:46 +12:00
Dan Poltawski 7d5e56cffd Merge branch '44711-27-r2' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-05-20 20:32:10 +08:00
Sam Hemelryk 137c0261ee MDL-44711 block_navigation: fixed typo in behat tests 2014-05-20 23:39:17 +12:00
Damyon Wiese 1c500e2157 MDL-45606 Unit test fix for MySQL and added a comment about the removed code. 2014-05-20 18:07:13 +08:00
Dan Poltawski 46021b98b2 Merge branch 'MDL-45496-m27' of https://github.com/micaherne/moodle into MOODLE_27_STABLE 2014-05-20 15:55:12 +08:00
Dan Poltawski 55739cdfb6 Merge branch 'MDL-45563-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-20 15:50:29 +08:00
Tim Hunt 63e5416f5b MDL-45618 Fix @since PHPdoc tags. 2014-05-20 15:03:34 +08:00
Jetha Chan 689a8f383c MDL-45525 themes: minor forum improvements
Fixed an RTL style that wasn't kicking in properly.

Conflicts:
	theme/bootstrapbase/style/moodle.css
2014-05-20 14:29:25 +08:00
Andrew Nicols 10f981a794 MDL-45536 theme: Use width auto for inputs and textareas specifying them
Conflicts:
	theme/bootstrapbase/style/moodle.css
2014-05-20 14:25:45 +08:00
Adrian Greeve 556a760d0c MDL-45512 comments: Added full date to comment details. 2014-05-20 14:22:32 +08:00
Michael Aherne 2ba0565d7d MDL-43669 messaging Enable sending email only from no-reply address 2014-05-20 14:16:05 +08:00
Tim Hunt 16d5729223 MDL-44333 quiz reports: use consitent name for user pref
The Marks for each question setting was not being saved properly as a
user preference.
2014-05-20 14:11:39 +08:00
Mark Nelson 38ef7ab379 MDL-45571 events: included enrolment method in the 'user_enrolment_created' event description 2014-05-20 14:08:14 +08:00
Damyon Wiese 740cb942ce Merge branch 'master_MDL-45583' of github.com:danmarsden/moodle into MOODLE_27_STABLE 2014-05-20 13:30:51 +08:00
Damyon Wiese 3725adf852 Merge branch 'MDL-45323-master' of git://github.com/lameze/moodle into MOODLE_27_STABLE 2014-05-20 13:28:09 +08:00
Dan Poltawski b9c49aefb2 Merge branch 'MDL-45501-27' of git://github.com/ankitagarwal/moodle into MOODLE_27_STABLE 2014-05-20 13:23:40 +08:00
Dan Poltawski 60f8e19ce1 Merge branch 'MDL-45566-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-20 13:17:41 +08:00
Damyon Wiese d0f43772fb Merge branch 'MDL-45476-master' of git://github.com/phalacee/moodle into MOODLE_27_STABLE 2014-05-20 13:12:16 +08:00
Dan Poltawski 106be68e82 Merge branch 'MDL-45545-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-20 12:21:12 +08:00
Marina Glancy f12ad8521f MDL-45469 Move profile tests to the location recognised by phpunit 2014-05-20 11:59:58 +08:00
Marina Glancy 9efa210e32 MDL-45466 forum: performance improvement for mass (un)subscriptions 2014-05-20 11:52:23 +08:00
Dan Poltawski 79b146cb5c MDL-44323 admin: use correct css class for warning
The notifyproblem notification is consistent with the rest of
the warnings we report.

Conflicts:
	theme/bootstrapbase/style/moodle.css
2014-05-20 15:48:48 +12:00
Sam Hemelryk 8711ce1f4a Merge branch 'MDL-44027-27' of git://github.com/danpoltawski/moodle into MOODLE_27_STABLE 2014-05-20 15:39:36 +12:00
Damyon Wiese 417fa07162 MDL-45605 Phpunit: Do not call gc_collect_cycles as part of reset.
This takes 25% of the time in running tests and there is no benefit. The
behaviour of destructors is the same before/after the patch.
2014-05-20 10:51:58 +08:00
Dan Poltawski 1910d01a86 Merge branch 'MDL-45546-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-20 10:24:42 +08:00
Dan Poltawski c9c530fd6e Merge branch '44711-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-05-20 10:14:22 +08:00
Sam Hemelryk dadeff80c9 Merge branch 'MDL-45603-27' of https://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-05-20 13:59:36 +12:00
sam marshall cc41096ad5 MDL-45469 Conditional availability: Restrict by text area broken
It has never worked, because the data for text area fields is not
loaded into the $USER object.

Changing it so that the dropdown list does not include these types
of field.
2014-05-20 09:52:36 +08:00
Tim Hunt db9987c267 MDL-44449 quiz access rules should have a delete hook.
So they can clean up their settings when the quiz is deleted.

See
https://github.com/moodleou/moodle-quizaccess_honestycheck/commit/babf149c2cc6dd734c272cd332b2032cc19db7d8
for an example of using this.
2014-05-20 09:51:16 +08:00
Dan Poltawski 8d8a5e8035 Merge branch 'MDL-45550-m27' of https://github.com/sammarshallou/moodle into MOODLE_27_STABLE 2014-05-20 09:30:19 +08:00
Andrew Nicols b60373f3e4 MDL-45479 atto_image: Improve the preview area
This changes the preview area:
* to show the image at the requested size; and
* to fix the scaling issues.
2014-05-20 13:20:17 +12:00
Damyon Wiese 1d8bebfeaf Merge branch '44974-27' of git://github.com/samhemelryk/moodle into MOODLE_27_STABLE 2014-05-20 09:00:35 +08:00
Ankit Agarwal 41d178f9da MDL-45543 availability: Use correct namespace for global classes 2014-05-20 12:07:39 +12:00
Sam Hemelryk d144e53188 Merge branch 'MDL-45477-m27' of https://github.com/sammarshallou/moodle into MOODLE_27_STABLE 2014-05-20 11:58:24 +12:00
sam marshall 49b50ef5ab MDL-45535 CSS chunking breaks media rules if CSS invalid (IE)
Invalid CSS with extra } symbols, which previously (by fluke)
worked, was broken by recent chunking improvements. This change
makes the chunking code robust against this (stupid) situation.
2014-05-20 11:57:54 +12:00
Sam Hemelryk 4fac06549a Merge branch 'MDL-44953-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-20 11:43:17 +12:00
Sam Hemelryk 7141921ad4 Merge branch 'MDL-45474-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-20 10:46:34 +12:00
Sam Hemelryk 70e78a4315 Merge branch 'MDL-37838-27' of git://github.com/danpoltawski/moodle into MOODLE_27_STABLE 2014-05-20 10:42:23 +12:00
Sam Hemelryk 520592c43d Merge branch 'MDL-45380-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE
Conflicts:
	theme/bootstrapbase/style/moodle.css
2014-05-20 08:53:18 +12:00
Dan Poltawski 553b1e6f6d MDL-45135 mod_glossary: fix RTL alignment of table
Tablelib has a specific 'hook' to allow alignment to be corrected for
RTL languages, but needs to be specified direction in lowercase.
2014-05-20 08:49:01 +12:00
Damyon Wiese bb5652829f Merge branch 'MDL-45130-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-19 21:27:47 +08:00
Damyon Wiese 288a79ccd4 Merge branch 'MDL-45472-master' of git://github.com/andrewnicols/moodle into MOODLE_27_STABLE 2014-05-19 20:47:27 +08:00
Damyon Wiese 8f6d8a5653 Merge branch 'MDL-45447-master' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-19 20:23:09 +08:00
Tim Hunt c64368bb1d MDL-43833 quiz reports: persist states settings between pages. 2014-05-19 20:12:09 +08:00
Damyon Wiese 177beaf23a Merge branch 'MDL-45527-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-19 20:05:25 +08:00
Tim Hunt 147d7af758 MDL-45455 quiz cron must rollback transaction on error. 2014-05-19 19:57:21 +08:00
Tony Butler 20bd24b70d MDL-45432 mod_assign Declare character encoding in onlinetext export
Signed-off-by: Tony Butler <tonyjbutler@gmail.com>
2014-05-19 18:48:06 +08:00
sam marshall 7c75924319 MDL-45478 Conditional availability: Custom user restriction missing
There was an error in the JavaScript and custom user field
restrictions did not show correctly when editing the form.

Behat tests didn't cover custom user fields, so I added a
scenario.
2014-05-19 17:30:43 +08:00
Andrew Nicols d90846033b MDL-45239 editor_atto: The editor cannot be active if it is not the active element
FireFox thinks that you can have an active selection on an element which
currently does not have focus. How this can be the case is a mystery.

Conflicts:
	lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js
2014-05-19 16:15:50 +08:00
Andrew Nicols da02a3c472 MDL-45468 editor_atto: Check that the common ancestor is within the editor
Conflicts:
	lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js
2014-05-19 16:15:43 +08:00
Andrew Nicols 61609ec274 MDL-41109 dndupload: Add missing error string 2014-05-19 15:07:59 +08:00
Dan Poltawski 228fc821e0 Merge branch 'wip-MDL-34914-m27' of git://github.com/marinaglancy/moodle into MOODLE_27_STABLE 2014-05-19 14:58:51 +08:00
Damyon Wiese d44071ee09 MDL-32543 upgrade: Increment the version bump 2014-05-19 13:02:10 +08:00
Damyon Wiese 91fae7e9b4 Merge branch 'MDL-32543' of https://github.com/danielneis/moodle into MOODLE_27_STABLE 2014-05-19 13:00:00 +08:00
Damyon Wiese 3e7b9158f4 Merge branch 'MDL-23566' of https://github.com/aolley/moodle into MOODLE_27_STABLE 2014-05-19 12:44:31 +08:00
Marina Glancy 95f9c8f716 Merge branch 'MDL-45537-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-19 12:39:43 +08:00
Marina Glancy 170392d4a0 Merge branch 'wip-MDL-45483-MOODLE_27_STABLE' of https://github.com/kwiliarty/moodle into MOODLE_27_STABLE 2014-05-19 12:37:59 +08:00
Damyon Wiese 3724b3aa8d Merge branch 'MDL-45533-27' of git://github.com/FMCorz/moodle into MOODLE_27_STABLE 2014-05-19 12:28:10 +08:00
Damyon Wiese 9af90f03bb Merge branch 'MDL-44634-27' of https://github.com/dbezborodovrp/moodle into MOODLE_27_STABLE 2014-05-19 12:14:42 +08:00
Jetha Chan 64a2dfba1f MDL-45561 themes: horizontal scroll in RTL base 2014-05-19 13:38:22 +12:00
Sam Hemelryk 043cf8bab7 MDL-44974 admin: repositioned call to initialise renderer 2014-05-19 08:41:27 +12:00
Sam Hemelryk 832393cfc9 MDL-44711 navigation: better handling of course expansion exception 2014-05-19 08:41:12 +12:00
Eric Merrill d8e7fa9196 MDL-45603 cache Fix the mappingsonly option to work as advertised. 2014-05-17 23:58:05 -04:00
Marina Glancy 075e999c1a MDL-34914 cohorts: more understandable filter of user list by cohort 2014-05-16 17:14:29 +08:00
Frederic Massart 8efb66741f MDL-45566 message: Send blocking events when user is not in contact list 2014-05-15 16:43:01 +08:00
Frederic Massart fa348b5d46 MDL-45563 message: Inverting IDs in description of event message_viewed 2014-05-15 16:17:03 +08:00
Frederic Massart ac2eafee91 MDL-45537 mod_assign: Requiring locallib for class assign 2014-05-15 15:52:48 +08:00
Damyon Wiese e6c69d835d weekly release 2.7+ 2014-05-15 15:32:36 +08:00
Ankit Agarwal bfa6c5080e MDL-45501 availability: Add uninstall support for conditional plugins 2014-05-15 14:07:05 +08:00
Damyon Wiese 0f0729b157 MDL-41383 Filepicker: whitespace fix 2014-05-15 13:33:04 +08:00
Jetha Chan f75d82450a MDL-41383: RTL fix for base when zoomed out 2014-05-15 13:29:03 +08:00
Damien Bezborodov 3dd33e3862 MDL-44634 Regression: link to user profile in comments block fails due to double URI encoding 2014-05-15 11:46:32 +09:30
Damien Bezborodov e3b98ac6b6 MDL-44634 Regression: link to user profile in comments block fails due to double URI encoding 2014-05-15 10:43:06 +09:30
sam marshall 3951213860 MDL-45550 Conditional availability: Missing lang string for save settings error 2014-05-14 11:48:33 +01:00
sam marshall 24b81e0566 MDL-45477 Behat: List of steps takes too long to load, times out
Increase time limit to 300 seconds (5 minutes).
2014-05-14 11:05:38 +01:00
Juan Leyva 0ab271dcfd MDL-36670 logging: action parameter length restricted to 40 chars 2014-05-14 16:35:18 +08:00
Frederic Massart b9cb39eaf6 MDL-45546 mod_forum: Login the user before getting its context 2014-05-14 16:16:40 +08:00
Frederic Massart c83407f033 MDL-45545 csslib: Chunking handles commas in media query definitions 2014-05-14 15:28:11 +08:00
Jetha Chan da75ffce68 MDL-41383 theme: filepicker zoom resiliency (base)
Fixed an issue that broke the file picker on base when initial zoom level is less than 100%.
2014-05-14 15:07:44 +08:00
Frederic Massart d48b1de9f7 MDL-45474 atto_undo: Remove notice when undo stack is empty 2014-05-13 17:49:26 +08:00
Dan Poltawski 38d1c9a886 MDL-44027 groups: remove some junk html 2014-05-13 16:17:14 +08:00
Damyon Wiese 1c48d7e188 Merge branch 'MDL-41383-27' of git://github.com/jethac/moodle into MOODLE_27_STABLE 2014-05-13 16:01:50 +08:00
Dan Poltawski 11b39253d2 Merge branch 'MDL-45523_m27' of https://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-05-13 14:46:55 +08:00
Dan Poltawski 56e84a7985 Merge branch 'MDL-45522_m27' of https://github.com/merrill-oakland/moodle into MOODLE_27_STABLE 2014-05-13 14:37:23 +08:00
Dan Poltawski 133f83d557 MDL-37838 block_courseoverview: fix pluaralisation logic
Note that this kind of handling of plurals is extremely limited, see:

https://moodle.org/mod/forum/discuss.php?d=85897
http://search.cpan.org/~petdance/Locale-Maketext-1.12/lib/Locale/Maketext/TPJ13.pod

However, this is a simple fix to the existing logic
2014-05-13 14:18:16 +08:00
Eric Merrill 17e57aa07d MDL-45523 quiz Cleanup duplicate question instances. 2014-05-12 16:01:32 -04:00
Eric Merrill 710b364b44 MDL-45522 quiz Check that sumgrade is valid before saving. 2014-05-12 15:21:44 -04:00
Frederic Massart 81d72831b8 MDL-44953 theme_more: Removing odd-looking text-shadow 2014-05-12 16:51:37 +08:00
Frederic Massart 3cfabf7190 MDL-45130 editor_atto: Remove debugging messages for missing plugins
This is no longer required as the toolbar configuration prevents
missing plugins from being set. However, even if we do not output
any notice, we ignore missing plugins to prevent errors in case
one was uninstalled but left in the editor toolbar.
2014-05-12 16:09:40 +08:00
Michael Aherne 0e5791a6cd MDL-45496 core Added space to logged in as line 2014-05-12 08:58:41 +01:00
Frederic Massart da3e5e0c5c MDL-45380 theme_bootstrapbase: Restore config override highlight 2014-05-12 15:50:08 +08:00
Rajesh Taneja ae3b9e1e1f MDL-45514 behat: Fixed should_not_exist timout param 2014-05-12 14:13:21 +08:00
Kevin Wiliarty 3485ecf225 MDL-45483 mod_forum: corrects values for maxattachments in forum settings 2014-05-11 23:51:57 -04:00
27339 changed files with 1007465 additions and 3289079 deletions
-249
View File
@@ -1,249 +0,0 @@
{
'plugins': [
'@babel',
'promise',
'jsdoc'
],
'extends': [
'eslint:recommended',
'plugin:promise/recommended'
],
'env': {
'browser': true,
// Enable ES6+ features by default.
// See http://eslint.org/docs/user-guide/configuring#specifying-environments
// Note: The YUI override must exactly match this when disabling the ES6+ version because those features are not supported by Shifter.
'es2020': true,
'amd': true
},
'globals': {
'M': true,
'Y': true
},
// Warn about unused eslint-disable statements.
'reportUnusedDisableDirectives': true,
'rules': {
// See http://eslint.org/docs/rules/ for all rules and explanations of all
// rules.
// === Possible Errors ===
'comma-dangle': 'off',
'no-console': 'error',
'no-empty': 'warn',
'no-extra-parens': 'off',
'no-prototype-builtins': 'off',
'no-unreachable': 'warn',
// === Best Practices ===
// (these mostly match our jshint config)
'array-callback-return': 'warn',
'block-scoped-var': 'warn',
'complexity': 'warn',
'consistent-return': 'warn',
'curly': 'error',
'dot-notation': 'warn',
'no-alert': 'warn',
'no-caller': 'error',
'no-div-regex': 'error',
'no-empty-function': 'warn',
'no-eq-null': 'error',
'no-eval': 'error',
'no-extend-native': 'error',
'no-extra-bind': 'warn',
'no-floating-decimal': 'warn',
'no-global-assign': 'warn',
'no-implied-eval': 'error',
'no-invalid-this': 'error',
'no-iterator': 'error',
'no-labels': 'error',
'no-loop-func': 'error',
'no-multi-spaces': 'warn',
'no-multi-str': 'error',
'no-new-func': 'error',
'no-new-wrappers': 'error',
'no-octal-escape': 'error',
'no-proto': 'error',
'no-redeclare': 'warn',
'no-restricted-globals': ['error', { 'name': 'Notification' }],
'no-return-assign': 'error',
'no-script-url': 'error',
'no-self-compare': 'error',
'no-sequences': 'warn',
'no-throw-literal': 'warn',
'no-unmodified-loop-condition': 'error',
'no-unused-expressions': 'error',
'no-useless-call': 'warn',
'no-useless-escape': 'warn',
'wrap-iife': ['error', 'any'],
// === Variables ===
'no-undef-init': 'error',
'no-unused-vars': ['error', { 'caughtErrors': 'none' }],
// === Stylistic Issues ===
'array-bracket-spacing': 'warn',
'block-spacing': 'warn',
'brace-style': ['warn', '1tbs'],
'camelcase': 'warn',
'capitalized-comments': ['warn', 'always', { 'ignoreConsecutiveComments': true }],
'comma-spacing': ['warn', { 'before': false, 'after': true }],
'comma-style': ['warn', 'last'],
'computed-property-spacing': 'error',
'consistent-this': 'off',
'eol-last': 'off',
'func-call-spacing': ['warn', 'never'],
'func-names': 'off',
'func-style': 'off',
// indent currently not doing well with our wrapping style, so disabled.
'indent': ['off', 4, { 'SwitchCase': 1 }],
'key-spacing': ['warn', { 'beforeColon': false, 'afterColon': true, 'mode': minimum }],
'keyword-spacing': 'warn',
'linebreak-style': ['error', 'unix'],
'lines-around-comment': 'off',
'max-len': ['error', 132],
'max-lines': 'off',
'max-depth': 'warn',
'max-nested-callbacks': ['warn', 5],
'max-params': 'off',
'max-statements': 'off',
'max-statements-per-line': ['warn', { max: 2 }],
'new-cap': ['warn', { 'properties': false }],
'new-parens': 'warn',
'newline-per-chained-call': 'off',
'no-array-constructor': 'off',
'no-bitwise': 'error',
'no-continue': 'off',
'no-inline-comments': 'off',
'no-lonely-if': 'off',
'no-mixed-operators': 'off',
'no-multiple-empty-lines': 'warn',
'no-negated-condition': 'off',
'no-nested-ternary': 'warn',
'no-new-object': 'off',
'no-plusplus': 'off',
'no-tabs': 'error',
'no-ternary': 'off',
'no-trailing-spaces': 'error',
'no-underscore-dangle': 'off',
'no-unneeded-ternary': 'off',
'no-whitespace-before-property': 'warn',
'object-curly-newline': 'off',
'object-curly-spacing': 'warn',
'object-property-newline': 'off',
'one-var': 'off',
'one-var-declaration-per-line': ['warn', 'initializations'],
'operator-assignment': 'off',
'operator-linebreak': 'off',
'padded-blocks': 'off',
'quote-props': ['warn', 'as-needed', {'unnecessary': false, 'keywords': true, 'numbers': true}],
'quotes': 'off',
'semi': 'error',
'semi-spacing': ['warn', {'before': false, 'after': true}],
'sort-vars': 'off',
'space-before-blocks': 'warn',
'space-before-function-paren': ['warn', 'never'],
'space-in-parens': 'warn',
'space-infix-ops': 'warn',
'space-unary-ops': 'warn',
'spaced-comment': 'warn',
'unicode-bom': 'error',
'wrap-regex': 'off',
// === Promises (override plugin:promise/recommended) ===
'promise/always-return': 'warn',
'promise/no-return-wrap': 'warn',
'promise/param-names': 'warn',
'promise/catch-or-return': ['warn', {terminationMethod: ['catch', 'fail', 'always'], allowFinally: true}],
'promise/no-native': 'warn',
'promise/avoid-new': 'warn',
// === Deprecations ===
"no-restricted-properties": ['warn', {
'object': 'M',
'property': 'str',
'message': 'Use "core/str" module or M.util.get_string()'
}],
},
overrides: [
{
files: ["**/yui/src/**/*.js"],
'env': {
// Disable ES6+ for YUI files.
'es2020': false,
},
// Disable some rules which we can't safely define for YUI rollups.
rules: {
'no-undef': 'off',
'no-unused-vars': 'off',
'no-unused-expressions': 'off',
// === JSDocs ===
"jsdoc/check-access": 'off',
"jsdoc/check-alignment": 'off',
"jsdoc/check-param-names": 'off',
"jsdoc/check-property-names": 'off',
"jsdoc/empty-tags": 'off',
"jsdoc/implements-on-classes": 'off',
"jsdoc/multiline-blocks": 'off',
"jsdoc/require-jsdoc": 'off',
"jsdoc/require-param": 'off',
"jsdoc/require-param-name": 'off',
"jsdoc/require-param-type": 'off',
"jsdoc/require-property": 'off',
"jsdoc/require-property-name": 'off',
"jsdoc/require-property-type": 'off',
}
},
{
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile.js", ".grunt/*.js", ".grunt/tasks/*.js", "jsdoc.conf.js"],
// We're using babel transpiling so use their parser
// for linting.
parser: '@babel/eslint-parser',
// Check AMD with some slightly stricter rules.
rules: {
'no-implicit-globals': 'error',
// Disable all of the rules that have babel versions.
'new-cap': 'off',
// Not using this rule for the time being because it isn't
// compatible with jQuery and ES6.
'no-invalid-this': 'off',
'object-curly-spacing': 'off',
'quotes': 'off',
'semi': 'off',
'no-unused-expressions': 'off',
// Enable all of the babel version of these rules.
'@babel/new-cap': ['warn', { 'properties': false }],
// Not using this rule for the time being because it isn't
// compatible with jQuery and ES6.
'@babel/no-invalid-this': 'off',
'@babel/object-curly-spacing': 'warn',
'@babel/semi': 'error',
'@babel/no-unused-expressions': 'error',
// === Promises ===
// We have Promise now that we're using ES6.
'promise/no-native': 'off',
'promise/avoid-new': 'off',
// === JSDocs ===
'jsdoc/check-access': 'error',
'jsdoc/check-alignment': 1, // Recommended.
'jsdoc/check-param-names': 'error',
'jsdoc/check-property-names': 'error',
'jsdoc/empty-tags': 'error',
'jsdoc/implements-on-classes': 'error',
'jsdoc/multiline-blocks': 'error',
'jsdoc/require-jsdoc': 'error',
'jsdoc/require-param': 'error',
'jsdoc/require-param-name': 'error',
'jsdoc/require-param-type': 'error',
'jsdoc/require-property': 'error',
'jsdoc/require-property-name': 'error',
'jsdoc/require-property-type': 'error'
},
parserOptions: {
'sourceType': 'module',
'requireConfigFile': false
}
}
]
}
-24
View File
@@ -1,24 +0,0 @@
{
"indentation": ["on",{
"Feature": 0,
"Background": 2,
"Scenario": 2,
"Examples": 4,
"example": 6,
"Step": 4,
"given": 4,
"and": 4
}],
"no-dupe-feature-names": "on",
"no-dupe-scenario-names": "off",
"no-empty-file": "on",
"no-files-without-scenarios": "on",
"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"]
}
-3
View File
@@ -1,3 +0,0 @@
**/yui/build/** -diff
**/amd/build/** -diff
lib/dml/oci_native_moodle_package.sql text eol=lf
-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');
-124
View File
@@ -1,124 +0,0 @@
name: Core
on:
push:
branches-ignore:
- master
- MOODLE_[0-9]+_STABLE
tags-ignore:
- v[0-9]+.[0-9]+.[0-9]+*
workflow_dispatch:
inputs:
phpunit_extra_options:
description: Additional options to apply to PHPUnit
required: false
default: ''
env:
php: 8.2
jobs:
Grunt:
runs-on: ubuntu-22.04
steps:
- name: Checking out code
uses: actions/checkout@v4
- name: Configuring node & npm
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- name: Installing node stuff
run: npm install
- name: Running grunt
run: npx grunt
- name: Looking for uncommitted changes
# Add all files to the git index and then run diff --cached to see all changes.
# This ensures that we get the status of all files, including new files.
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
run: |
git add .
git reset -- npm-shrinkwrap.json
git diff --cached --exit-code
PHPUnit:
runs-on: ${{ matrix.os }}
services:
exttests:
image: moodlehq/moodle-exttests
ports:
- 8080:80
redis:
image: redis
ports:
- 6379:6379
strategy:
fail-fast: false
matrix:
include:
# MySQL builds always run with the lowest PHP supported version.
- os: ubuntu-22.04
php: 8.0
extensions:
db: mysqli
# PostgreSQL builds always run with the highest PHP supported version.
- os: ubuntu-22.04
php: 8.2
db: pgsql
steps:
- name: Setting up DB mysql
if: ${{ matrix.db == 'mysqli' }}
uses: moodlehq/mysql-action@v1
with:
collation server: utf8mb4_bin
mysql version: 8.0
mysql database: test
mysql user: test
mysql password: test
use tmpfs: true
tmpfs size: '1024M'
extra conf: --skip-log-bin
- name: Setting up DB pgsql
if: ${{ matrix.db == 'pgsql' }}
uses: m4nu56/postgresql-action@v1
with:
postgresql version: 13
postgresql db: test
postgresql user: test
postgresql password: test
- name: Configuring git vars
uses: rlespinasse/github-slug-action@v4
- name: Setting up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: ${{ matrix.extensions }}
ini-values: max_input_vars=5000
coverage: none
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
uses: actions/checkout@v4
- name: Setting up PHPUnit
env:
dbtype: ${{ matrix.db }}
run: |
echo "pathtophp=$(which php)" >> $GITHUB_ENV # Inject installed pathtophp to env. The template config needs it.
cp .github/workflows/config-template.php config.php
mkdir ../moodledata
sudo locale-gen en_AU.UTF-8
php admin/tool/phpunit/cli/init.php --no-composer-self-update
- name: Running PHPUnit tests
env:
dbtype: ${{ matrix.db }}
phpunit_options: ${{ secrets.phpunit_options }}
run: vendor/bin/phpunit $phpunit_options ${{ inputs.phpunit_extra_options }}
-149
View File
@@ -1,149 +0,0 @@
name: Windows Testing
on:
workflow_dispatch:
inputs:
phpunit_extra_options:
description: Additional options to apply to PHPUnit
required: false
default: ''
env:
php: 8.2
jobs:
Grunt:
runs-on: windows-latest
steps:
- name: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checking out code
uses: actions/checkout@v4
- name: Configuring node & npm
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- name: Installing node stuff
run: npm ci
- name: Running grunt
run: npx grunt
- name: Looking for uncommitted changes
# Add all files to the git index and then run diff --cached to see all changes.
# This ensures that we get the status of all files, including new files.
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
run: |
git add .
git reset -- npm-shrinkwrap.json
git diff --cached --exit-code
PHPUnit:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
php: 8.2
# Ideally we should use mysql/mariadb, but they are 4x slower without tweaks and configuration
# so let's run only postgres (1.5h vs 6h) only, If some day we want to improve the mysql runs,
# this is the place to enable them.
# db: mysqli
db: pgsql
extensions: exif, fileinfo, gd, intl, pgsql, mysql, redis, soap, sodium, zip
- os: windows-latest
php: 8.0
db: pgsql
extensions: exif, fileinfo, gd, intl, pgsql, mysql, redis, soap, sodium
steps:
- name: Setting up DB mysql
if: ${{ matrix.db == 'mysqli' }}
uses: shogo82148/actions-setup-mysql@v1
with:
mysql-version: 8.0
user: test
password: test
- name: Creating DB mysql
if: ${{ matrix.db == 'mysqli' }}
run: mysql --host 127.0.0.1 -utest -ptest -e 'CREATE DATABASE IF NOT EXISTS test COLLATE = utf8mb4_bin;';
- name: Setting up DB pgsql
if: ${{ matrix.db == 'pgsql' }}
run: |
# TODO: Remove these conf. modifications when php74 or php80 are lowest.
# Change to old md5 auth, because php73 does not support it.
# #password_encryption = scram-sha-256
(Get-Content "$env:PGDATA\postgresql.conf"). `
replace('#password_encryption = scram-sha-256', 'password_encryption = md5') | `
Set-Content "$env:PGDATA\postgresql.conf"
(Get-Content "$env:PGDATA\pg_hba.conf"). `
replace('scram-sha-256', 'md5') | `
Set-Content "$env:PGDATA\pg_hba.conf"
$pgService = Get-Service -Name postgresql*
Set-Service -InputObject $pgService -Status running -StartupType automatic
Start-Process -FilePath "$env:PGBIN\pg_isready" -Wait -PassThru
& $env:PGBIN\psql --command="CREATE USER test PASSWORD 'test'" --command="\du"
- name: Creating DB pgsql
if: ${{ matrix.db == 'pgsql' }}
run: |
& $env:PGBIN\createdb --owner=test test
$env:PGPASSWORD = 'test'
& $env:PGBIN\psql --username=test --host=localhost --list test
- name: Configuring git vars
uses: rlespinasse/github-slug-action@v4
- name: Setting up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: ${{ matrix.extensions }}
ini-values: max_input_vars=5000
coverage: none
- name: Set git to use LF
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
uses: actions/checkout@v4
# Needs to be done after php is available, git configured and Moodle checkout has happened.
- name: Setting up moodle-exttests service
run: |
git clone https://github.com/moodlehq/moodle-exttests.git
nssm install php-built-in C:\tools\php\php.exe -S localhost:8080 -t D:\a\moodle\moodle\moodle-exttests
nssm start php-built-in
- name: Setting up redis service
run: |
choco install redis-64 --version 3.0.503 --no-progress
nssm install redis redis-server
nssm start redis
- name: Setting up PHPUnit
env:
dbtype: ${{ matrix.db }}
shell: bash
run: |
echo "pathtophp=$(which php)" >> $GITHUB_ENV # Inject installed pathtophp to env. The template config needs it.
cp .github/workflows/config-template.php config.php
mkdir ../moodledata
php admin/tool/phpunit/cli/init.php --no-composer-self-update
- name: Running PHPUnit tests
env:
dbtype: ${{ matrix.db }}
phpunit_options: ${{ secrets.phpunit_options }}
run: vendor/bin/phpunit $phpunit_options ${{ inputs.phpunit_extra_options }}
+5 -25
View File
@@ -9,23 +9,15 @@
#
# See gitignore(5) man page for more details
#
# Swap files (vim)
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Temporary files including undo
*~
#
/config.php
/lib/editor/tinymce/extra/tools/temp/
*~
*.swp
/tags
/TAGS
/cscope.*
/.patches/
/.idea/
.phpstorm.*
/nbproject/
CVS
.DS_Store
@@ -33,25 +25,13 @@ CVS
/.project
/.buildpath
/.cache
.phpunit.result.cache
phpunit.xml
# Composer support. Do not ignore composer.json, or composer.lock. These should be shipped by us.
# Composer support - only composer.json is to be in git, the rest is installed in each checkout.
composer.phar
composer.lock
/vendor/
/behat.yml
*/yui/build/*/*-coverage.js
/lib/yuilib/*/build/*/*-coverage.js
# lib/yuilib/version/module/module-coverage.js
/lib/yuilib/*/*/*-coverage.js
atlassian-ide-plugin.xml
/node_modules/
/.vscode/
moodle-plugin-ci.phar
.eslintignore
.stylelintignore
/jsdoc
/admin/tool/componentlibrary/docs
/admin/tool/componentlibrary/hugo/site/data/my-index.json
.hugo_build.lock
phpcs.xml
jsconfig.json
-169
View File
@@ -1,169 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This is a babel plugin to add the Moodle module names to the AMD modules
* as part of the transpiling process.
*
* In addition it will also add a return statement for the default export if the
* module is using default exports. This is a highly specific Moodle thing because
* we're transpiling to AMD and none of the existing Babel 7 plugins work correctly.
*
* This will fix the issue where an ES6 module using "export default Foo" will be
* transpiled into an AMD module that returns {default: Foo}; Instead it will now
* just simply return Foo.
*
* Note: This means all other named exports in that module are ignored and won't be
* exported.
*
* @copyright 2018 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
/* eslint-env node */
module.exports = ({template, types}) => {
const fs = require('fs');
const path = require('path');
const cwd = process.cwd();
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
/**
* Search the list of components that match the given file name
* and return the Moodle component for that file, if found.
*
* Throw an exception if no matching component is found.
*
* @throws {Error}
* @param {string} searchFileName The file name to look for.
* @return {string} Moodle component
*/
function getModuleNameFromFileName(searchFileName) {
searchFileName = fs.realpathSync(searchFileName);
const relativeFileName = searchFileName.replace(`${cwd}${path.sep}`, '').replace(/\\/g, '/');
const [componentPath, file] = relativeFileName.split('/amd/src/');
const fileName = file.replace('.js', '');
// Check subsystems first which require an exact match.
const componentName = ComponentList.getComponentFromPath(componentPath);
if (componentName) {
return `${componentName}/${fileName}`;
}
// This matches the previous PHP behaviour that would throw an exception
// if it couldn't parse an AMD file.
throw new Error(`Unable to find module name for ${searchFileName} (${componentPath}::${file}}`);
}
/**
* This is heavily inspired by the babel-plugin-add-module-exports plugin.
* See: https://github.com/59naga/babel-plugin-add-module-exports
*
* This is used when we detect a module using "export default Foo;" to make
* sure the transpiled code just returns Foo directly rather than an object
* with the default property (i.e. {default: Foo}).
*
* Note: This means that we can't support modules that combine named exports
* with a default export.
*
* @param {String} path
* @param {String} exportObjectName
*/
function addModuleExportsDefaults(path, exportObjectName) {
const rootPath = path.findParent(path => {
return path.key === 'body' || !path.parentPath;
});
// HACK: `path.node.body.push` instead of path.pushContainer(due doesn't work in Plugin.post).
// This is hardcoded to work specifically with AMD.
rootPath.node.body.push(template(`return ${exportObjectName}.default`)());
}
return {
pre() {
this.seenDefine = false;
this.addedReturnForDefaultExport = false;
},
visitor: {
// Plugin ordering is only respected if we visit the "Program" node.
// See: https://babeljs.io/docs/en/plugins.html#plugin-preset-ordering
//
// We require this to run after the other AMD module transformation so
// let's visit the "Program" node.
Program: {
exit(path) {
path.traverse({
CallExpression(path) {
// If we find a "define" function call.
if (!this.seenDefine && path.get('callee').isIdentifier({name: 'define'})) {
// We only want to modify the first instance of define that we find.
this.seenDefine = true;
// Get the Moodle component for the file being processed.
var moduleName = getModuleNameFromFileName(this.file.opts.filename);
// The function signature of `define()` is:
// define = function (name, deps, callback) {...}
// Ensure that if the moduel supplied its own name that it is replaced.
if (path.node.arguments.length > 0) {
// Ensure that there is only one name.
if (path.node.arguments[0].type === 'StringLiteral') {
// eslint-disable-next-line
console.log(`Replacing module name '${path.node.arguments[0].extra.rawValue}' with ${moduleName}`);
path.node.arguments.shift();
}
}
// Add the module name as the first argument to the define function.
path.node.arguments.unshift(types.stringLiteral(moduleName));
// Add a space after the define function in the built file so that previous versions
// of Moodle will not try to add the module name to the file when it's being served
// by PHP. This forces the regex in PHP to not match for this file.
path.node.callee.name = 'define ';
}
// Check for any Object.defineProperty('exports', 'default') calls.
if (!this.addedReturnForDefaultExport && path.get('callee').matchesPattern('Object.defineProperty')) {
const [identifier, prop] = path.get('arguments');
const objectName = identifier.get('name').node;
const propertyName = prop.get('value').node;
if ((objectName === 'exports' || objectName === '_exports') && propertyName === 'default') {
addModuleExportsDefaults(path, objectName);
this.addedReturnForDefaultExport = true;
}
}
},
AssignmentExpression(path) {
// Check for an exports.default assignments.
if (
!this.addedReturnForDefaultExport &&
(
path.get('left').matchesPattern('exports.default') ||
path.get('left').matchesPattern('_exports.default')
)
) {
const objectName = path.get('left.object.name').node;
addModuleExportsDefaults(path, objectName);
this.addedReturnForDefaultExport = true;
}
}
}, this);
}
}
}
};
};
-394
View File
@@ -1,394 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Helper functions for working with Moodle component names, directories, and sources.
*
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
/* eslint-env node */
/** @var {Object} A list of subsystems in Moodle */
const componentData = {};
/**
* Load details of all moodle modules.
*
* @returns {object}
*/
const fetchComponentData = () => {
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const gruntFilePath = process.cwd();
if (!Object.entries(componentData).length) {
componentData.subsystems = {};
componentData.pathList = [];
// Fetch the component definiitions from the distributed JSON file.
const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`));
// Build the list of moodle subsystems.
componentData.subsystems.lib = 'core';
componentData.pathList.push(process.cwd() + path.sep + 'lib');
for (const [component, thisPath] of Object.entries(components.subsystems)) {
if (thisPath) {
// Prefix "core_" to the front of the subsystems.
componentData.subsystems[thisPath] = `core_${component}`;
componentData.pathList.push(process.cwd() + path.sep + thisPath);
}
}
// The list of components incldues the list of subsystems.
componentData.components = componentData.subsystems;
// Go through each of the plugintypes.
Object.entries(components.plugintypes).forEach(([pluginType, pluginTypePath]) => {
// We don't allow any code in this place..?
glob.sync(`${pluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${pluginType}_${componentName}`;
componentData.components[`${pluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
// Look for any subplugins.
const subPluginConfigurationFile = `${componentPath}/db/subplugins.json`;
if (fs.existsSync(subPluginConfigurationFile)) {
const subpluginList = JSON.parse(fs.readFileSync(fs.realpathSync(subPluginConfigurationFile)));
Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => {
glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${subpluginType}_${componentName}`;
componentData.components[`${subpluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
});
});
}
});
});
}
return componentData;
};
/**
* Get the list of component paths.
*
* @param {string} relativeTo
* @returns {array}
*/
const getComponentPaths = (relativeTo = '') => fetchComponentData().pathList.map(componentPath => {
return componentPath.replace(relativeTo, '');
});
/**
* Get the list of paths to build AMD sources.
*
* @returns {Array}
*/
const getAmdSrcGlobList = () => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
globList.push(`${componentPath}/amd/src/*.js`);
globList.push(`${componentPath}/amd/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to build YUI sources.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getYuiSrcGlobList = relativeTo => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
const relativeComponentPath = componentPath.replace(relativeTo, '');
globList.push(`${relativeComponentPath}/yui/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to thirdpartylibs.xml.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getThirdPartyLibsList = relativeTo => {
const fs = require('fs');
const path = require('path');
return fetchComponentData().pathList
.map(componentPath => path.relative(relativeTo, componentPath) + '/thirdpartylibs.xml')
.map(componentPath => componentPath.replace(/\\/g, '/'))
.filter(path => fs.existsSync(path))
.sort();
};
/**
* Get the list of thirdparty library paths.
*
* @returns {array}
*/
const getThirdPartyPaths = () => {
const DOMParser = require('@xmldom/xmldom').DOMParser;
const fs = require('fs');
const path = require('path');
const xpath = require('xpath');
const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./'));
const libs = ['node_modules/', 'vendor/'];
const addLibToList = lib => {
if (!lib.match('\\*') && fs.statSync(lib).isDirectory()) {
// Ensure trailing slash on dirs.
lib = lib.replace(/\/?$/, '/');
}
// Look for duplicate paths before adding to array.
if (libs.indexOf(lib) === -1) {
libs.push(lib);
}
};
thirdpartyfiles.forEach(function(file) {
const dirname = path.dirname(file);
const xmlContent = fs.readFileSync(file, 'utf8');
const doc = new DOMParser().parseFromString(xmlContent);
const nodes = xpath.select("/libraries/library/location/text()", doc);
nodes.forEach(function(node) {
let lib = path.posix.join(dirname, node.toString());
addLibToList(lib);
});
});
return libs;
};
/**
* Find the name of the component matching the specified path.
*
* @param {String} path
* @returns {String|null} Name of matching component.
*/
const getComponentFromPath = path => {
const componentList = fetchComponentData().components;
if (componentList.hasOwnProperty(path)) {
return componentList[path];
}
return null;
};
/**
* Check whether the supplied path, relative to the Gruntfile.js, is in a known component.
*
* @param {String} checkPath The path to check. This can be with either Windows, or Linux directory separators.
* @returns {String|null}
*/
const getOwningComponentDirectory = checkPath => {
const path = require('path');
// Fetch all components into a reverse sorted array.
// This ensures that components which are within the directory of another component match first.
const pathList = Object.keys(fetchComponentData().components).sort().reverse();
for (const componentPath of pathList) {
// If the componentPath is the directory being checked, it will be empty.
// If the componentPath is a parent of the directory being checked, the relative directory will not start with ..
if (!path.relative(componentPath, checkPath).startsWith('..')) {
return componentPath;
}
}
return null;
};
/**
* Get the latest tag in a remote GitHub repository.
*
* @param {string} url The remote repository.
* @returns {Array}
*/
const getRepositoryTags = async(url) => {
const gtr = require('git-tags-remote');
try {
const tags = await gtr.get(url);
if (tags !== undefined) {
return tags;
}
} catch (error) {
return [];
}
return [];
};
/**
* Get the list of thirdparty libraries that could be upgraded.
*
* @returns {Array}
*/
const getThirdPartyLibsUpgradable = async() => {
const libraries = getThirdPartyLibsData().filter((library) => !!library.repository);
const upgradableLibraries = [];
const versionCompare = (a, b) => {
if (a === b) {
return 0;
}
const aParts = a.split('.');
const bParts = b.split('.');
for (let i = 0; i < Math.min(aParts.length, bParts.length); i++) {
const aPart = parseInt(aParts[i], 10);
const bPart = parseInt(bParts[i], 10);
if (aPart > bPart) {
// 1.1.0 > 1.0.9
return 1;
} else if (aPart < bPart) {
// 1.0.9 < 1.1.0
return -1;
} else {
// Same version.
continue;
}
}
if (aParts.length > bParts.length) {
// 1.0.1 > 1.0
return 1;
}
// 1.0 < 1.0.1
return -1;
};
for (let library of libraries) {
upgradableLibraries.push(
getRepositoryTags(library.repository).then((tagMap) => {
library.version = library.version.replace(/^v/, '');
const currentVersion = library.version.replace(/moodle-/, '');
const currentMajorVersion = library.version.split('.')[0];
const tags = [...tagMap]
.map((tagData) => tagData[0])
.filter((tag) => !tag.match(/(alpha|beta|rc)/))
.map((tag) => tag.replace(/^v/, ''))
.sort((a, b) => versionCompare(b, a));
if (!tags.length) {
library.warning = "Unable to find any comparable tags.";
return library;
}
library.latestVersion = tags[0];
tags.some((tag) => {
if (!tag) {
return false;
}
// See if the version part matches.
const majorVersion = tag.split('.')[0];
if (majorVersion === currentMajorVersion) {
library.latestSameMajorVersion = tag;
return true;
}
return false;
});
if (versionCompare(currentVersion, library.latestVersion) > 0) {
// Moodle somehow has a newer version than the latest version.
library.warning = `Newer version found: ${currentVersion} > ${library.latestVersion} for ${library.name}`;
return library;
}
if (library.version !== library.latestVersion) {
// Delete version and add it again at the end of the array. That way, current and new will stay closer.
delete library.version;
library.version = currentVersion;
return library;
}
return null;
})
);
}
return (await Promise.all(upgradableLibraries)).filter((library) => !!library);
};
/**
* Get the list of thirdparty libraries.
*
* @returns {Array}
*/
const getThirdPartyLibsData = () => {
const DOMParser = require('@xmldom/xmldom').DOMParser;
const fs = require('fs');
const xpath = require('xpath');
const path = require('path');
const libraryList = [];
const libraryFields = [
'location',
'name',
'version',
'repository',
];
const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./'));
thirdpartyfiles.forEach(function(libraryPath) {
const xmlContent = fs.readFileSync(libraryPath, 'utf8');
const doc = new DOMParser().parseFromString(xmlContent);
const libraries = xpath.select("/libraries/library", doc);
for (const library of libraries) {
const libraryData = [];
for (const field of libraryFields) {
libraryData[field] = xpath.select(`${field}/text()`, library)?.toString();
}
libraryData.location = path.join(path.dirname(libraryPath), libraryData.location);
libraryList.push(libraryData);
}
});
return libraryList.sort((a, b) => a.location.localeCompare(b.location));
};
module.exports = {
fetchComponentData,
getAmdSrcGlobList,
getComponentFromPath,
getComponentPaths,
getOwningComponentDirectory,
getYuiSrcGlobList,
getThirdPartyLibsList,
getThirdPartyPaths,
getThirdPartyLibsUpgradable,
};
-19
View File
@@ -1,19 +0,0 @@
# Moodle JavaScript Documentation
```
.-..-.
_____ | || |
/____/-.---_ .---. .---. .-.| || | .---.
| | _ _ |/ _ \/ _ \/ _ || |/ __ \
* | | | | | || |_| || |_| || |_| || || |___/
|_| |_| |_|\_____/\_____/\_____||_|\_____)
Moodle - the world's open source learning platform
```
## About
This generated documentation includes API documentation for JavaScript written in the AMD and ES2015 module formats within Moodle.
## Related information
See [https://moodledev.io](https://moodledev.io) for other related Developer Documentation.
-131
View File
@@ -1,131 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Helper functions for working with Moodle component names, directories, and sources.
*
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
/* eslint-env node */
// Do not include any plugins as stanard.
const plugins = [];
plugins.push('plugins/markdown');
/**
* Get the source configuration.
*
* @return {Object}
*/
const getSource = () => {
const glob = require('glob');
const path = require('path');
const ComponentList = require(path.resolve('.grunt/components.js'));
const thirdPartyPaths = ComponentList.getThirdPartyPaths();
const source = {
include: [],
includePattern: ".+\\.js$",
};
let includeList = [];
ComponentList.getAmdSrcGlobList().forEach(async pattern => {
includeList.push(...glob.sync(pattern));
});
const cwdLength = process.cwd().length + 1;
includeList.forEach(path => {
if (source.include.indexOf(path) !== -1) {
// Ensure no duplicates.
return;
}
const relPath = path.substring(cwdLength);
if (thirdPartyPaths.indexOf(relPath) !== -1) {
return;
}
source.include.push(path);
});
source.include.push('.grunt/jsdoc/README.md');
return source;
};
const tags = {
// Allow the use of unknown tags.
// We have a lot of legacy uses of these.
allowUnknownTags: true,
// We make use of jsdoc and closure dictionaries as standard.
dictionaries: [
'jsdoc',
'closure',
],
};
// Template configuraiton.
const templates = {
cleverLinks: false,
monospaceLinks: false,
};
module.exports = {
opts: {
destination: "./jsdoc/",
template: "node_modules/docdash",
},
plugins,
recurseDepth: 10,
source: getSource(),
sourceType: 'module',
tags,
templates,
docdash: {
collapse: true,
search: true,
sort: true,
sectionOrder: [
"Namespaces",
"Modules",
"Events",
"Classes",
"Externals",
"Mixins",
"Tutorials",
"Interfaces"
],
"menu": {
"Developer Docs": {
href: "https://moodledev.io",
target: "_blank",
"class": "menu-item",
id: "devdocs"
},
"MDN Docs": {
href: "https://developer.mozilla.org/en-US/docs/Web/JavaScript",
target: "_blank",
"class": "menu-item",
id: "mdndocs",
},
},
typedefs: true,
},
};
-142
View File
@@ -1,142 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* Component Library build tasks.
*
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Get a child path of the component library.
*
* @param {string} path
* @returns {string}
*/
const getCLPath = path => `admin/tool/componentlibrary/${path}`;
/**
* Get a spawn handler.
*
* This is a generic function to write the spawn output, and then to exit if required and mark the async task as
* complete.
*
* @param {Promise} done
* @returns {function}
*/
const getSpawnHandler = done => (error, result, code) => {
grunt.log.write(result);
if (error) {
grunt.log.error(result.stdout);
process.exit(code);
}
done();
};
/**
* Spawn a function against Node with the provided args.
*
* @param {array} args
* @returns {object}
*/
const spawnNodeCall = (args) => grunt.util.spawn({
cmd: 'node',
args,
}, getSpawnHandler(grunt.task.current.async()));
/**
* Build the docs using Hugo.
*
* @returns {Object} Reference to the spawned task
*/
const docsBuild = () => spawnNodeCall([
'node_modules/hugo-bin/cli.js',
'--config', getCLPath('config.yml'),
'--cleanDestinationDir',
]);
/**
* Build the docs index using the hugo-lunr-indexer.
*
* @returns {Object} Reference to the spawned task
*/
const indexBuild = () => spawnNodeCall([
'node_modules/hugo-lunr-indexer/bin/hli.js',
'-i', getCLPath('content/**'),
'-o', getCLPath('hugo/site/data/my-index.json'),
'-l', 'yaml',
'-d', '---',
]);
/**
* Build the hugo CSS.
*
* @returns {Object} Reference to the spawned task
*/
const cssBuild = () => spawnNodeCall([
'node_modules/sass/sass.js',
'--style', 'expanded',
'--source-map',
'--embed-sources',
'--precision', 6,
'--load-path', process.cwd(),
getCLPath('hugo/scss/docs.scss'),
getCLPath('hugo/dist/css/docs.css'),
]);
// Register the various component library tasks.
grunt.registerTask('componentlibrary:docsBuild', 'Build the component library', docsBuild);
grunt.registerTask('componentlibrary:cssBuild', 'Build the component library', cssBuild);
grunt.registerTask('componentlibrary:indexBuild', 'Build the component library', indexBuild);
grunt.registerTask('componentlibrary', 'Build the component library', [
'componentlibrary:docsBuild',
'componentlibrary:cssBuild',
'componentlibrary:indexBuild',
]);
grunt.config.merge({
watch: {
componentLibraryDocs: {
files: [
getCLPath('content/**/*.md'),
getCLPath('hugo'),
],
tasks: ['componentlibrary:docsBuild', 'componentlibrary:indexBuild'],
},
componentLibraryCSS: {
files: [
getCLPath('hugo/scss/**/*.scss'),
'hugo',
],
tasks: ['componentlibrary:cssBuild'],
},
},
});
// Add the 'componentlibrary' task as a startup task.
grunt.moodleEnv.startupTasks.push('componentlibrary');
return {
docsBuild,
cssBuild,
indexBuild,
};
};
-64
View File
@@ -1,64 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
const files = grunt.moodleEnv.files;
// Project configuration.
grunt.config.merge({
eslint: {
// Even though warnings dont stop the build we don't display warnings by default because
// at this moment we've got too many core warnings.
// To display warnings call: grunt eslint --show-lint-warnings
// To fail on warnings call: grunt eslint --max-lint-warnings=0
// Also --max-lint-warnings=-1 can be used to display warnings but not fail.
options: {
quiet: (!grunt.option('show-lint-warnings')) && (typeof grunt.option('max-lint-warnings') === 'undefined'),
maxWarnings: ((typeof grunt.option('max-lint-warnings') !== 'undefined') ? grunt.option('max-lint-warnings') : -1)
},
// Check AMD src files.
amd: {src: files ? files : grunt.moodleEnv.amdSrc},
// Check YUI module source files.
yui: {src: files ? files : grunt.moodleEnv.yuiSrc},
},
});
grunt.loadNpmTasks('grunt-eslint');
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
let changedFiles = Object.create(null);
const onChange = grunt.util._.debounce(function() {
const files = Object.keys(changedFiles);
grunt.config('eslint.amd.src', files);
grunt.config('eslint.yui.src', files);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', (action, filepath) => {
changedFiles[filepath] = action;
onChange();
});
};
-92
View File
@@ -1,92 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Get the list of feature files to pass to the gherkin linter.
*
* @returns {Array}
*/
const getGherkinLintTargets = () => {
if (grunt.moodleEnv.files) {
// Specific files were requested. Only check these.
return grunt.moodleEnv.files;
}
if (grunt.moodleEnv.inComponent) {
return [`${grunt.moodleEnv.runDir}/tests/behat/*.feature`];
}
return ['**/tests/behat/*.feature'];
};
const handler = function() {
const done = this.async();
const options = grunt.config('gherkinlint.options');
// Grab the gherkin-lint linter and required scaffolding.
const linter = require('gherkin-lint/dist/linter.js');
const featureFinder = require('gherkin-lint/dist/feature-finder.js');
const configParser = require('gherkin-lint/dist/config-parser.js');
const formatter = require('gherkin-lint/dist/formatters/stylish.js');
// Run the linter.
return linter.lint(
featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
configParser.getConfiguration(configParser.defaultConfigFileName)
)
.then(results => {
// Print the results out uncondtionally.
formatter.printResults(results);
return results;
})
.then(results => {
// Report on the results.
// The done function takes a bool whereby a falsey statement causes the task to fail.
return results.every(result => result.errors.length === 0);
})
.then(done); // eslint-disable-line promise/no-callback-in-promise
};
grunt.registerTask('gherkinlint', 'Run gherkinlint against the current directory', handler);
grunt.config.set('gherkinlint', {
options: {
files: getGherkinLintTargets(),
}
});
grunt.config.merge({
watch: {
gherkinlint: {
files: [grunt.moodleEnv.inComponent ? 'tests/behat/*.feature' : '**/tests/behat/*.feature'],
tasks: ['gherkinlint'],
},
},
});
// Add the 'gherkinlint' task as a startup task.
grunt.moodleEnv.startupTasks.push('gherkinlint');
return handler;
};
-100
View File
@@ -1,100 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Generate the PHPCS configuration.
*
* @param {Object} thirdPartyPaths
*/
const phpcsIgnore = (thirdPartyPaths) => {
const {toXML} = require('jstoxml');
const config = {
_name: 'ruleset',
_attrs: {
name: "MoodleCore",
},
_content: [
{
rule: {
_attrs: {
ref: './phpcs.xml.dist',
},
},
},
],
};
thirdPartyPaths.forEach(library => {
config._content.push({
'exclude-pattern': library,
});
});
grunt.file.write('phpcs.xml', toXML(config, {
header: true,
indent: ' ',
}) + "\n");
};
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
const handler = function() {
const path = require('path');
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
// An array of paths to third party directories.
const thirdPartyPaths = ComponentList.getThirdPartyPaths();
// Generate .eslintignore.
const eslintIgnores = [
'# Generated by "grunt ignorefiles"',
// Do not ignore the .grunt directory.
'!/.grunt',
// Ignore all yui/src meta directories and build directories.
'*/**/yui/src/*/meta/',
'*/**/build/',
].concat(thirdPartyPaths);
grunt.file.write('.eslintignore', eslintIgnores.join('\n') + '\n');
// Generate .stylelintignore.
const stylelintIgnores = [
'# Generated by "grunt ignorefiles"',
'**/yui/build/*',
'theme/boost/style/moodle.css',
'theme/classic/style/moodle.css',
'jsdoc/styles/*.css',
'admin/tool/componentlibrary/hugo/dist/css/docs.css',
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n') + '\n');
phpcsIgnore(thirdPartyPaths);
};
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', handler);
return handler;
};
-223
View File
@@ -1,223 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Function to generate the destination for the uglify task
* (e.g. build/file.min.js). This function will be passed to
* the rename property of files array when building dynamically:
* http://gruntjs.com/configuring-tasks#building-the-files-object-dynamically
*
* @param {String} destPath the current destination
* @param {String} srcPath the matched src path
* @return {String} The rewritten destination path.
*/
const babelRename = function(destPath, srcPath) {
destPath = srcPath.replace(`amd/src`, `amd/build`);
destPath = destPath.replace(/\.js$/, '.min.js');
return destPath;
};
module.exports = grunt => {
// Load the Ignorefiles tasks.
require('./ignorefiles')(grunt);
// Load the Shifter tasks.
require('./shifter')(grunt);
// Load ESLint.
require('./eslint')(grunt);
// Load jsconfig.
require('./jsconfig')(grunt);
// Load JSDoc.
require('./jsdoc')(grunt);
const path = require('path');
// Register JS tasks.
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
grunt.registerTask('amd', ['ignorefiles', 'eslint:amd', 'rollup']);
grunt.registerTask('js', ['amd', 'yui']);
// Register NPM tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-rollup');
const babelTransform = require('@babel/core').transform;
const babel = (options = {}) => {
return {
name: 'babel',
transform: (code, id) => {
grunt.log.debug(`Transforming ${id}`);
options.filename = id;
const transformed = babelTransform(code, options);
return {
code: transformed.code,
map: transformed.map
};
}
};
};
// Note: We have to use a rate limit plugin here because rollup runs all tasks asynchronously and in parallel.
// When we kick off a full run, if we kick off a rollup of every file this will fork-bomb the machine.
// To work around this we use a concurrent Promise queue based on the number of available processors.
const rateLimit = () => {
const queue = [];
let queueRunner;
const startQueue = () => {
if (queueRunner) {
return;
}
queueRunner = setTimeout(() => {
const limit = Math.max(1, require('os').cpus().length / 2);
grunt.log.debug(`Starting rollup with queue size of ${limit}`);
runQueue(limit);
}, 100);
};
// The queue runner will run the next `size` items in the queue.
const runQueue = (size = 1) => {
queue.splice(0, size).forEach(resolve => {
resolve();
});
};
return {
name: 'ratelimit',
// The options hook is run in parallel.
// We can return an unresolved Promise which is queued for later resolution.
options: async() => {
return new Promise(resolve => {
queue.push(resolve);
startQueue();
});
},
// When an item in the queue completes, start the next item in the queue.
buildEnd: () => {
runQueue();
},
};
};
const terser = require('rollup-plugin-terser').terser;
grunt.config.merge({
rollup: {
options: {
format: 'esm',
dir: 'output',
sourcemap: true,
treeshake: false,
context: 'window',
plugins: [
rateLimit(),
babel({
sourceMaps: true,
comments: false,
compact: false,
plugins: [
'transform-es2015-modules-amd-lazy',
'system-import-transformer',
// This plugin modifies the Babel transpiling for "export default"
// so that if it's used then only the exported value is returned
// by the generated AMD module.
//
// It also adds the Moodle plugin name to the AMD module definition
// so that it can be imported as expected in other modules.
path.resolve('.grunt/babel-plugin-add-module-to-define.js')
],
presets: [
['@babel/preset-env', {
targets: {
browsers: [
">0.3%",
"last 2 versions",
"not ie >= 0",
"not op_mini all",
"not Opera > 0",
"not dead"
]
},
modules: false,
useBuiltIns: false
}]
]
}),
terser({
// Do not mangle variables.
// Makes debugging easier.
mangle: false,
}),
],
},
dist: {
files: [{
expand: true,
src: grunt.moodleEnv.files ? grunt.moodleEnv.files : grunt.moodleEnv.amdSrc,
rename: babelRename
}],
},
},
});
grunt.config.merge({
watch: {
amd: {
files: grunt.moodleEnv.inComponent
? ['amd/src/*.js', 'amd/src/**/*.js']
: ['**/amd/src/**/*.js'],
tasks: ['amd']
},
},
});
// Add the 'js' task as a startup task.
grunt.moodleEnv.startupTasks.push('js');
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
let changedFiles = Object.create(null);
const onChange = grunt.util._.debounce(function() {
const files = Object.keys(changedFiles);
grunt.config('rollup.dist.files', [{expand: true, src: files, rename: babelRename}]);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
return {
babelRename,
};
};
-53
View File
@@ -1,53 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2022 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
const configuration = {
compilerOptions: {
baseUrl: ".",
paths: {
},
target: "es2015",
allowSyntheticDefaultImports: false,
},
exclude: [
"node_modules",
],
include: [],
};
module.exports = (grunt) => {
const handler = () => {
const jsconfigData = Object.assign({}, configuration);
const path = require('path');
const {fetchComponentData} = require(path.join(process.cwd(), '.grunt', 'components.js'));
const componentData = fetchComponentData().components;
for (const [thisPath, component] of Object.entries(componentData)) {
jsconfigData.compilerOptions.paths[`${component}/*`] = [`${thisPath}/amd/src/*`];
jsconfigData.include.push(`${thisPath}/amd/src/**/*`);
}
grunt.file.write('jsconfig.json', JSON.stringify(jsconfigData, null, " ") + "\n");
};
grunt.registerTask('jsconfig', 'Generate a jsconfig configuration compatible with the LSP', handler);
};
-36
View File
@@ -1,36 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
// Project configuration.
grunt.config.merge({
jsdoc: {
dist: {
options: {
configure: ".grunt/jsdoc/jsdoc.conf.js",
},
},
},
});
grunt.loadNpmTasks('grunt-jsdoc');
};
-40
View File
@@ -1,40 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
grunt.loadNpmTasks('grunt-sass');
grunt.config.merge({
sass: {
dist: {
files: {
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss",
"theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss"
}
},
options: {
implementation: require('sass'),
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
}
},
});
};
-155
View File
@@ -1,155 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/* eslint-env node */
module.exports = grunt => {
/**
* Shifter task. Is configured with a path to a specific file or a directory,
* in the case of a specific file it will work out the right module to be built.
*
* Note that this task runs the invidiaul shifter jobs async (becase it spawns
* so be careful to to call done().
*/
const handler = function() {
const done = this.async();
const options = grunt.config('shifter.options');
const async = require('async');
const path = require('path');
// Run the shifter processes one at a time to avoid confusing output.
async.eachSeries(options.paths, function(src, filedone) {
var args = [];
args.push(path.normalize(process.cwd() + '/node_modules/shifter/bin/shifter'));
// Always ignore the node_modules directory.
args.push('--excludes', 'node_modules');
// Determine the most appropriate options to run with based upon the current location.
if (grunt.file.isMatch('**/yui/**/*.js', src)) {
// When passed a JS file, build our containing module (this happen with
// watch).
grunt.log.debug('Shifter passed a specific JS file');
src = path.dirname(path.dirname(src));
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src', src)) {
// When in a src directory --walk all modules.
grunt.log.debug('In a src directory');
args.push('--walk');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*', src)) {
// When in module, only build our module.
grunt.log.debug('In a module directory');
options.recursive = false;
} else if (grunt.file.isMatch('**/yui/src/*/js', src)) {
// When in module src, only build our module.
grunt.log.debug('In a source directory');
src = path.dirname(src);
options.recursive = false;
}
if (grunt.option('watch')) {
grunt.fail.fatal('The --watch option has been removed, please use `grunt watch` instead');
}
// Add the stderr option if appropriate
if (grunt.option('verbose')) {
args.push('--lint-stderr');
}
if (grunt.option('no-color')) {
args.push('--color=false');
}
var execShifter = function() {
grunt.log.ok("Running shifter on " + src);
grunt.util.spawn({
cmd: "node",
args: args,
opts: {cwd: src, stdio: 'inherit', env: process.env}
}, function(error, result, code) {
if (code) {
grunt.fail.fatal('Shifter failed with code: ' + code);
} else {
grunt.log.ok('Shifter build complete.');
filedone();
}
});
};
// Actually run shifter.
if (!options.recursive) {
execShifter();
} else {
// Check that there are yui modules otherwise shifter ends with exit code 1.
if (grunt.file.expand({cwd: src}, '**/yui/src/**/*.js').length > 0) {
args.push('--recursive');
execShifter();
} else {
grunt.log.ok('No YUI modules to build.');
filedone();
}
}
}, done);
};
// Register the shifter task.
grunt.registerTask('shifter', 'Run Shifter against the current directory', handler);
// Configure it.
grunt.config.set('shifter', {
options: {
recursive: true,
// Shifter takes a relative path.
paths: grunt.moodleEnv.files ? grunt.moodleEnv.files : [grunt.moodleEnv.runDir]
}
});
grunt.config.merge({
watch: {
yui: {
files: grunt.moodleEnv.inComponent
? ['yui/src/*.json', 'yui/src/**/*.js']
: ['**/yui/src/**/*.js'],
tasks: ['yui']
},
},
});
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
let changedFiles = Object.create(null);
const onChange = grunt.util._.debounce(function() {
const files = Object.keys(changedFiles);
grunt.config('shifter.options.paths', files);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', (action, filepath) => {
changedFiles[filepath] = action;
onChange();
});
return handler;
};
-46
View File
@@ -1,46 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
const handler = function() {
const path = require('path');
// Are we in a YUI directory?
if (path.basename(path.resolve(grunt.moodleEnv.cwd, '../../')) == 'yui') {
grunt.task.run('yui');
// Are we in an AMD directory?
} else if (grunt.moodleEnv.inAMD) {
grunt.task.run('amd');
} else {
// Run all of the requested startup tasks.
grunt.moodleEnv.startupTasks.forEach(taskName => grunt.task.run(taskName));
}
};
// Register the startup task.
grunt.registerTask('startup', 'Run the correct tasks for the current directory', handler);
return handler;
};
-35
View File
@@ -1,35 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
// Load the ignorefiles tasks.
require('./ignorefiles')(grunt);
// Load the Style Lint tasks.
require('./stylelint')(grunt);
// Load the SASS tasks.
require('./sass')(grunt);
// Add the 'css' task as a startup task.
grunt.moodleEnv.startupTasks.push('css');
};
-183
View File
@@ -1,183 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2021 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
const getCssConfigForFiles = files => {
return {
stylelint: {
css: {
// Use a fully-qualified path.
src: files,
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
}
}
}
},
},
};
};
const getScssConfigForFiles = files => {
return {
stylelint: {
scss: {
options: {syntax: 'scss'},
src: files,
},
},
};
};
/**
* Register any stylelint tasks.
*
* @param {Object} grunt
* @param {Array} files
* @param {String} fullRunDir
*/
const registerStyleLintTasks = () => {
const glob = require('glob');
// The stylelinters do not handle the case where a configuration was provided but no files were included.
// Keep track of whether any files were found.
let hasCss = false;
let hasScss = false;
// The stylelint processors do not take a path argument. They always check all provided values.
// As a result we must check through each glob and determine if any files match the current directory.
const scssFiles = [];
const cssFiles = [];
const requestedFiles = grunt.moodleEnv.files;
if (requestedFiles) {
// Grunt was called with a files argument.
// Check whether each of the requested files matches either the CSS or SCSS source file list.
requestedFiles.forEach(changedFilePath => {
let matchesGlob;
// Check whether this watched path matches any watched SCSS file.
matchesGlob = grunt.moodleEnv.scssSrc.some(watchedPathGlob => {
return glob.sync(watchedPathGlob).indexOf(changedFilePath) !== -1;
});
if (matchesGlob) {
scssFiles.push(changedFilePath);
hasScss = true;
}
// Check whether this watched path matches any watched CSS file.
matchesGlob = grunt.moodleEnv.cssSrc.some(watchedPathGlob => {
return glob.sync(watchedPathGlob).indexOf(changedFilePath) !== -1;
});
if (matchesGlob) {
cssFiles.push(changedFilePath);
hasCss = true;
}
});
} else {
// Grunt was called without a list of files.
// The start directory (runDir) may be a child dir of the project.
// Check each scssSrc file to see if it's in the start directory.
// This means that we can lint just mod/*/styles.css if started in the mod directory.
grunt.moodleEnv.scssSrc.forEach(path => {
if (path.startsWith(grunt.moodleEnv.runDir)) {
scssFiles.push(path);
hasScss = true;
}
});
grunt.moodleEnv.cssSrc.forEach(path => {
if (path.startsWith(grunt.moodleEnv.runDir)) {
cssFiles.push(path);
hasCss = true;
}
});
}
// Register the tasks.
const scssTasks = ['sass'];
if (hasScss) {
grunt.config.merge(getScssConfigForFiles(scssFiles));
scssTasks.unshift('stylelint:scss');
}
scssTasks.unshift('ignorefiles');
const cssTasks = ['ignorefiles'];
if (hasCss) {
grunt.config.merge(getCssConfigForFiles(cssFiles));
cssTasks.push('stylelint:css');
}
// The tasks must be registered, even if empty to ensure a consistent command list.
// They jsut won't run anything.
grunt.registerTask('scss', scssTasks);
grunt.registerTask('rawcss', cssTasks);
};
// Register CSS tasks.
grunt.loadNpmTasks('grunt-stylelint');
// Register the style lint tasks.
registerStyleLintTasks();
grunt.registerTask('css', ['scss', 'rawcss']);
const getCoreThemeMatches = () => {
const scssMatch = 'scss/**/*.scss';
if (grunt.moodleEnv.inTheme) {
return [scssMatch];
}
if (grunt.moodleEnv.runDir.startsWith('theme')) {
return [`*/${scssMatch}`];
}
return [`theme/*/${scssMatch}`];
};
// Add the watch configuration for rawcss, and scss.
grunt.config.merge({
watch: {
rawcss: {
files: [
'**/*.css',
],
excludes: [
'**/moodle.css',
'**/editor.css',
'jsdoc/styles/*.css',
],
tasks: ['rawcss']
},
scss: {
files: getCoreThemeMatches(),
tasks: ['scss']
},
},
});
};
-42
View File
@@ -1,42 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* @copyright 2023 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = grunt => {
/**
* Generate upgradable third-party libraries (utilising thirdpartylibs.xml data)
*/
grunt.registerTask('upgradablelibs', 'Generate upgradable third-party libraries', async function() {
const done = this.async();
const path = require('path');
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
// An array of third party libraries that have a newer version in their repositories.
const thirdPartyLibs = await ComponentList.getThirdPartyLibsUpgradable({progress: true});
for (let library of thirdPartyLibs) {
grunt.log.ok(JSON.stringify(Object.assign({}, library), null, 4));
}
done();
});
};
-272
View File
@@ -1,272 +0,0 @@
/**
* This is a wrapper task to handle the grunt watch command. It attempts to use
* Watchman to monitor for file changes, if it's installed, because it's much faster.
*
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
* watcher for backwards compatibility.
*/
/* eslint-env node */
module.exports = grunt => {
/**
* This is a wrapper task to handle the grunt watch command. It attempts to use
* Watchman to monitor for file changes, if it's installed, because it's much faster.
*
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
* watcher for backwards compatibility.
*/
const watchHandler = function() {
const async = require('async');
const watchTaskDone = this.async();
let watchInitialised = false;
let watchTaskQueue = {};
let processingQueue = false;
const watchman = require('fb-watchman');
const watchmanClient = new watchman.Client();
// Grab the tasks and files that have been queued up and execute them.
var processWatchTaskQueue = function() {
if (!Object.keys(watchTaskQueue).length || processingQueue) {
// If there is nothing in the queue or we're already processing then wait.
return;
}
processingQueue = true;
// Grab all tasks currently in the queue.
var queueToProcess = watchTaskQueue;
// Reset the queue.
watchTaskQueue = {};
async.forEachSeries(
Object.keys(queueToProcess),
function(task, next) {
var files = queueToProcess[task];
var filesOption = '--files=' + files.join(',');
grunt.log.ok('Running task ' + task + ' for files ' + filesOption);
// Spawn the task in a child process so that it doesn't kill this one
// if it failed.
grunt.util.spawn(
{
// Spawn with the grunt bin.
grunt: true,
// Run from current working dir and inherit stdio from process.
opts: {
cwd: grunt.moodleEnv.fullRunDir,
stdio: 'inherit'
},
args: [task, filesOption]
},
function(err, res, code) {
if (code !== 0) {
// The grunt task failed.
grunt.log.error(err);
}
// Move on to the next task.
next();
}
);
},
function() {
// No longer processing.
processingQueue = false;
// Once all of the tasks are done then recurse just in case more tasks
// were queued while we were processing.
processWatchTaskQueue();
}
);
};
const originalWatchConfig = grunt.config.get(['watch']);
const watchConfig = Object.keys(originalWatchConfig).reduce(function(carry, key) {
if (key == 'options') {
return carry;
}
const value = originalWatchConfig[key];
const taskNames = value.tasks;
const files = value.files;
let excludes = [];
if (value.excludes) {
excludes = value.excludes;
}
taskNames.forEach(function(taskName) {
carry[taskName] = {
files,
excludes,
};
});
return carry;
}, {});
watchmanClient.on('error', function(error) {
// We have to add an error handler here and parse the error string because the
// example way from the docs to check if Watchman is installed doesn't actually work!!
// See: https://github.com/facebook/watchman/issues/509
if (error.message.match('Watchman was not found')) {
// If watchman isn't installed then we should fallback to the other watch task.
grunt.log.ok('It is recommended that you install Watchman for better performance using the "watch" command.');
// Fallback to the old grunt-contrib-watch task.
grunt.renameTask('watch-grunt', 'watch');
grunt.task.run(['watch']);
// This task is finished.
watchTaskDone(0);
} else {
grunt.log.error(error);
// Fatal error.
watchTaskDone(1);
}
});
watchmanClient.on('subscription', function(resp) {
if (resp.subscription !== 'grunt-watch') {
return;
}
resp.files.forEach(function(file) {
grunt.log.ok('File changed: ' + file.name);
var fullPath = grunt.moodleEnv.fullRunDir + '/' + file.name;
Object.keys(watchConfig).forEach(function(task) {
const fileGlobs = watchConfig[task].files;
var match = fileGlobs.some(function(fileGlob) {
return grunt.file.isMatch(`**/${fileGlob}`, fullPath);
});
if (match) {
// If we are watching a subdirectory then the file.name will be relative
// to that directory. However the grunt tasks expect the file paths to be
// relative to the Gruntfile.js location so let's normalise them before
// adding them to the queue.
var relativePath = fullPath.replace(grunt.moodleEnv.gruntFilePath + '/', '');
if (task in watchTaskQueue) {
if (!watchTaskQueue[task].includes(relativePath)) {
watchTaskQueue[task] = watchTaskQueue[task].concat(relativePath);
}
} else {
watchTaskQueue[task] = [relativePath];
}
}
});
});
processWatchTaskQueue();
});
process.on('SIGINT', function() {
// Let the user know that they may need to manually stop the Watchman daemon if they
// no longer want it running.
if (watchInitialised) {
grunt.log.ok('The Watchman daemon may still be running and may need to be stopped manually.');
}
process.exit();
});
// Initiate the watch on the current directory.
watchmanClient.command(['watch-project', grunt.moodleEnv.fullRunDir], function(watchError, watchResponse) {
if (watchError) {
grunt.log.error('Error initiating watch:', watchError);
watchTaskDone(1);
return;
}
if ('warning' in watchResponse) {
grunt.log.error('warning: ', watchResponse.warning);
}
var watch = watchResponse.watch;
var relativePath = watchResponse.relative_path;
watchInitialised = true;
watchmanClient.command(['clock', watch], function(clockError, clockResponse) {
if (clockError) {
grunt.log.error('Failed to query clock:', clockError);
watchTaskDone(1);
return;
}
// Generate the expression query used by watchman.
// Documentation is limited, but see https://facebook.github.io/watchman/docs/expr/allof.html for examples.
// We generate an expression to match any value in the files list of all of our tasks, but excluding
// all value in the excludes list of that task.
//
// [anyof, [
// [allof, [
// [anyof, [
// ['match', validPath, 'wholename'],
// ['match', validPath, 'wholename'],
// ],
// [not,
// [anyof, [
// ['match', invalidPath, 'wholename'],
// ['match', invalidPath, 'wholename'],
// ],
// ],
// ],
var matchWholeName = fileGlob => ['match', fileGlob, 'wholename'];
var matches = Object.keys(watchConfig).map(function(task) {
const matchAll = [];
matchAll.push(['anyof'].concat(watchConfig[task].files.map(matchWholeName)));
if (watchConfig[task].excludes.length) {
matchAll.push(['not', ['anyof'].concat(watchConfig[task].excludes.map(matchWholeName))]);
}
return ['allof'].concat(matchAll);
});
matches = ['anyof'].concat(matches);
var sub = {
expression: matches,
// Which fields we're interested in.
fields: ["name", "size", "type"],
// Add our time constraint.
since: clockResponse.clock
};
if (relativePath) {
/* eslint-disable camelcase */
sub.relative_root = relativePath;
}
watchmanClient.command(['subscribe', watch, 'grunt-watch', sub], function(subscribeError) {
if (subscribeError) {
// Probably an error in the subscription criteria.
grunt.log.error('failed to subscribe: ', subscribeError);
watchTaskDone(1);
return;
}
grunt.log.ok('Listening for changes to files in ' + grunt.moodleEnv.fullRunDir);
});
});
});
};
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
grunt.renameTask('watch', 'watch-grunt');
// Register the new watch handler.
grunt.registerTask('watch', 'Run tasks on file changes', watchHandler);
grunt.config.merge({
watch: {
options: {
nospawn: true // We need not to spawn so config can be changed dynamically.
},
},
});
return watchHandler;
};
-2
View File
@@ -1,2 +0,0 @@
**/amd/**
/*.js
+22 -32
View File
@@ -1,58 +1,48 @@
// NOTE: We use eslint now. This file is used only by shifter. We keep the configuration
// here because shifter uses jshint after modules have been concating. Eslint can't
// currently do this.
{
"asi": false,
"bitwise": true,
"boss": false,
"browser": true,
"yui": true,
"bitwise": true,
"curly": true,
"eqeqeq": true,
"forin": false,
"immed": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nomen": false,
"onevar": false,
"plusplus": false,
"regexp": false,
"strict": false,
"trailing": true,
"unused": true,
"white": false,
"asi": false,
"boss": false,
"debug": false,
"eqeqeq": false,
"eqnull": false,
"es5": false,
"esnext": false,
"evil": false,
"expr": false,
"forin": false,
"funcscope": false,
"globalstrict": false,
"immed": true,
"indent": 4,
"iterator": false,
"lastsemic": false,
"latedef": true,
"laxbreak": true,
"laxcomma": false,
"loopfunc": false,
"maxerr": 500,
"maxlen": 132,
"multistr": false,
"newcap": true,
"noarg": true,
"noempty": true,
"nomen": false,
"onecase": false,
"onevar": false,
"passfail": false,
"plusplus": false,
"predef": [
"M",
"define",
"require"
],
"proto": false,
"regexdash": false,
"regexp": false,
"scripturl": false,
"shadow": false,
"smarttabs": false,
"strict": false,
"sub": false,
"supernew": false,
"trailing": true,
"undef": true,
"unused": true,
"white": false,
"yui": true
"maxerr": 500,
"maxlen": 180,
"passfail": false,
"latedef": true
}
-1
View File
@@ -1 +0,0 @@
lts/gallium
-95
View File
@@ -1,95 +0,0 @@
{
"plugins": [
"stylelint-csstree-validator"
],
"rules": {
"csstree/validator": true,
"at-rule-empty-line-before": [ "always",
{"except": [ "blockless-after-blockless"], ignore: ["after-comment", "inside-block"]}
],
"at-rule-name-case": "lower",
"at-rule-name-space-after": "always-single-line",
"at-rule-no-unknown": null, # Enabled for non-scss in grunt.
"at-rule-semicolon-newline-after": "always",
"at-rule-semicolon-space-before": "never",
"block-closing-brace-newline-after": "always",
"block-closing-brace-newline-before": "always",
"block-closing-brace-space-before": "always-single-line",
"block-no-empty": true,
"block-opening-brace-newline-after": "always",
"block-opening-brace-space-after": "always-single-line",
"block-opening-brace-space-before": "always",
"color-hex-case": ["lower", { "severity": "warning" }],
"color-hex-length": ["short", { "severity": "warning" }],
"color-no-invalid-hex": true,
"declaration-bang-space-after": "never",
"declaration-bang-space-before": "always",
"declaration-block-no-duplicate-properties": true,
"declaration-block-no-shorthand-property-overrides": true,
"declaration-block-semicolon-newline-after": "always-multi-line",
"declaration-block-semicolon-space-after": "always-single-line",
"declaration-block-semicolon-space-before": "never",
"declaration-block-single-line-max-declarations": 1,
"declaration-block-trailing-semicolon": "always",
"declaration-colon-newline-after": "always-multi-line",
"declaration-colon-space-after": "always-single-line",
"declaration-colon-space-before": "never",
"declaration-no-important": true,
"font-family-no-duplicate-names": true,
"function-calc-no-unspaced-operator": true,
"function-comma-newline-after": "always-multi-line",
"function-comma-space-after": "always-single-line",
"function-comma-space-before": "never",
"function-linear-gradient-no-nonstandard-direction": true,
"function-max-empty-lines": 0,
"function-name-case": "lower",
"function-parentheses-newline-inside": "always-multi-line",
"function-parentheses-space-inside": "never-single-line",
"function-url-scheme-blacklist": ["data"],
"function-whitespace-after": "always",
"indentation": 4,
"keyframe-declaration-no-important": true,
"length-zero-no-unit": [true, { "severity": "warning" }],
"max-empty-lines": 2,
"max-line-length": [132, { "severity": "warning" }],
"media-feature-colon-space-after": "always",
"media-feature-colon-space-before": "never",
"media-feature-parentheses-space-inside": "never",
"media-feature-range-operator-space-after": "always",
"media-feature-range-operator-space-before": "always",
"media-query-list-comma-newline-after": "always-multi-line",
"media-query-list-comma-space-after": "always-single-line",
"media-query-list-comma-space-before": "never",
"no-empty-source": true,
"no-eol-whitespace": true,
"no-extra-semicolons": [true, { "severity": "warning" }],
"no-invalid-double-slash-comments": true,
"no-unknown-animations": true,
"property-case": "lower",
"property-no-unknown": true,
"selector-attribute-brackets-space-inside": "never",
"selector-attribute-operator-space-after": "never",
"selector-attribute-operator-space-before": "never",
"selector-combinator-space-after": "always",
"selector-combinator-space-before": "always",
"selector-list-comma-newline-after": "always",
"selector-list-comma-space-before": "never",
"selector-max-empty-lines": 0,
"selector-pseudo-class-case": "lower",
"selector-pseudo-class-no-unknown": true,
"selector-pseudo-class-parentheses-space-inside": "never",
"selector-pseudo-element-case": "lower",
"selector-pseudo-element-no-unknown": true,
"selector-type-case": "lower",
"selector-type-no-unknown": true,
"string-no-newline": true,
"time-min-milliseconds": 100,
"unit-blacklist": ["pt"],
"unit-case": "lower",
"unit-no-unknown": true,
"value-keyword-case": ["lower", {"ignoreKeywords": ["/(@|$)/"]}],
"value-list-comma-newline-after": "always-multi-line",
"value-list-comma-space-after": "always-single-line",
"value-list-comma-space-before": "never",
}
}
-56
View File
@@ -1,56 +0,0 @@
CONTRIBUTING TO MOODLE
======================
Moodle is made by people like you. We are members of a big worldwide community
of developers, designers, teachers, testers, translators and other users. We
work in universities, schools, companies and other places. You are very welcome
to join us and contribute to the project.
See <https://moodledev.io/general/community/contribute> for the many ways you
can help, not only with coding.
Moodle is open to community contributions to core, though all code must go
through peer-review, automated behaviour testing, continuous integration and
human post-integration checks.
Pull requests
-------------
Please do not open pull requests via Github. The repository there is just a
mirror of the official repository at <https://git.moodle.org>. Issues are
reported and patches provided via <https://tracker.moodle.org>. See below for
more information.
Moodle core bug fixes and new features
--------------------------------------
During the years of intensive development, a mature process of including
submitted patches has evolved.
* Every bug fix or new feature must have a tracker issue.
* You publish the branch implementing the fix or new feature in your public
clone of the moodle.git repository (typically on Github).
* Your patch is peer-reviewed, discussed, integrated, tested and then released
as a part of moodle.git.
* New features are developed on the master branch. Bug fixes are also
backported to currently supported maintenance (stable) branches.
For further details, see <https://moodledev.io/general/development/process>.
Moodle plugins
--------------
Moodle has a framework for additional plugins to extend its functionality. We
have a Moodle plugins directory <https://moodle.org/plugins/> where you can
register and maintain your plugin. Plugins hosted in the plugins directory can
be easily installed and updated via the Moodle administration interface.
* You are expected to have a public source code repository with your plugin
code.
* After registering your plugin in the plugins directory it is reviewed before
being published.
* You are expected to continuously release updated versions of the plugin via
the plugins directory. We do not pull from your code repository; you must do
it explicitly.
For further details, see <https://moodledev.io/general/community/plugincontribution>.
-267
View File
@@ -1,267 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/* jshint node: true, browser: false */
/* eslint-env node */
/**
* Grunt configuration for Moodle.
*
* @copyright 2014 Andrew Nicols
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Setup the Grunt Moodle environment.
*
* @param {Grunt} grunt
* @returns {Object}
*/
const setupMoodleEnvironment = grunt => {
const fs = require('fs');
const path = require('path');
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
const getAmdConfiguration = () => {
// If the cwd is the amd directory in the current component then it will be empty.
// If the cwd is a child of the component's AMD directory, the relative directory will not start with ..
let inAMD = !path.relative(`${componentDirectory}/amd`, cwd).startsWith('..');
// Globbing pattern for matching all AMD JS source files.
let amdSrc = [];
if (inComponent) {
amdSrc.push(
componentDirectory + "/amd/src/*.js",
componentDirectory + "/amd/src/**/*.js"
);
} else {
amdSrc = ComponentList.getAmdSrcGlobList();
}
return {
inAMD,
amdSrc,
};
};
const getYuiConfiguration = () => {
let yuiSrc = [];
if (inComponent) {
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
} else {
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
}
return {
yuiSrc,
};
};
const getStyleConfiguration = () => {
const ComponentList = require(path.join(process.cwd(), '.grunt', 'components.js'));
// Build the cssSrc and scssSrc.
// Valid paths are:
// [component]/styles.css; and either
// [theme/[themename]]/scss/**/*.scss; or
// [theme/[themename]]/style/*.css.
//
// If a theme has scss, then it is assumed that the style directory contains generated content.
let cssSrc = [];
let scssSrc = [];
const checkComponentDirectory = componentDirectory => {
const isTheme = componentDirectory.startsWith('theme/');
if (isTheme) {
const scssDirectory = `${componentDirectory}/scss`;
if (fs.existsSync(scssDirectory)) {
// This theme has an SCSS directory.
// Include all scss files within it recursively, but do not check for css files.
scssSrc.push(`${scssDirectory}/*.scss`);
scssSrc.push(`${scssDirectory}/**/*.scss`);
} else {
// This theme has no SCSS directory.
// Only hte CSS files in the top-level directory are checked.
cssSrc.push(`${componentDirectory}/style/*.css`);
}
} else {
// This is not a theme.
// All other plugin types are restricted to a single styles.css in their top level.
cssSrc.push(`${componentDirectory}/styles.css`);
}
};
if (inComponent) {
checkComponentDirectory(componentDirectory);
} else {
ComponentList.getComponentPaths(`${gruntFilePath}/`).forEach(componentPath => {
checkComponentDirectory(componentPath);
});
}
return {
cssSrc,
scssSrc,
};
};
/**
* Calculate the cwd, taking into consideration the `root` option (for Windows).
*
* @param {Object} grunt
* @returns {String} The current directory as best we can determine
*/
const getCwd = grunt => {
let cwd = fs.realpathSync(process.env.PWD || process.cwd());
// Windows users can't run grunt in a subdirectory, so allow them to set
// the root by passing --root=path/to/dir.
if (grunt.option('root')) {
const root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) {
cwd = fs.realpathSync(path.join(__dirname, root));
grunt.log.ok('Setting root to ' + cwd);
} else {
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
return cwd;
};
// Detect directories:
// * gruntFilePath The real path on disk to this Gruntfile.js
// * cwd The current working directory, which can be overridden by the `root` option
// * relativeCwd The cwd, relative to the Gruntfile.js
// * componentDirectory The root directory of the component if the cwd is in a valid component
// * inComponent Whether the cwd is in a valid component
// * runDir The componentDirectory or cwd if not in a component, relative to Gruntfile.js
// * fullRunDir The full path to the runDir
const gruntFilePath = fs.realpathSync(process.cwd());
const cwd = getCwd(grunt);
const relativeCwd = path.relative(gruntFilePath, cwd);
const componentDirectory = ComponentList.getOwningComponentDirectory(relativeCwd);
const inComponent = !!componentDirectory;
const inTheme = !!componentDirectory && componentDirectory.startsWith('theme/');
const runDir = inComponent ? componentDirectory : relativeCwd;
const fullRunDir = fs.realpathSync(gruntFilePath + path.sep + runDir);
const {inAMD, amdSrc} = getAmdConfiguration();
const {yuiSrc} = getYuiConfiguration();
const {cssSrc, scssSrc} = getStyleConfiguration();
let files = null;
if (grunt.option('files')) {
// Accept a comma separated list of files to process.
files = grunt.option('files').split(',');
}
grunt.log.debug('============================================================================');
grunt.log.debug(`= Node version: ${process.versions.node}`);
grunt.log.debug(`= grunt version: ${grunt.package.version}`);
grunt.log.debug(`= process.cwd: '` + process.cwd() + `'`);
grunt.log.debug(`= process.env.PWD: '${process.env.PWD}'`);
grunt.log.debug(`= path.sep '${path.sep}'`);
grunt.log.debug('============================================================================');
grunt.log.debug(`= gruntFilePath: '${gruntFilePath}'`);
grunt.log.debug(`= relativeCwd: '${relativeCwd}'`);
grunt.log.debug(`= componentDirectory: '${componentDirectory}'`);
grunt.log.debug(`= inComponent: '${inComponent}'`);
grunt.log.debug(`= runDir: '${runDir}'`);
grunt.log.debug(`= fullRunDir: '${fullRunDir}'`);
grunt.log.debug('============================================================================');
if (inComponent) {
grunt.log.ok(`Running tasks for component directory ${componentDirectory}`);
}
return {
amdSrc,
componentDirectory,
cwd,
cssSrc,
files,
fullRunDir,
gruntFilePath,
inAMD,
inComponent,
inTheme,
relativeCwd,
runDir,
scssSrc,
yuiSrc,
};
};
/**
* Verify tha tthe current NodeJS version matches the required version in package.json.
*
* @param {Grunt} grunt
*/
const verifyNodeVersion = grunt => {
const semver = require('semver');
// Verify the node version is new enough.
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
var actual = semver.valid(process.version);
if (!semver.satisfies(actual, expected)) {
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
}
};
/**
* Grunt configuration.
*
* @param {Grunt} grunt
*/
module.exports = function(grunt) {
// Verify that the Node version meets our requirements.
verifyNodeVersion(grunt);
// Setup the Moodle environemnt within the Grunt object.
grunt.moodleEnv = setupMoodleEnvironment(grunt);
/**
* Add the named task.
*
* @param {string} name
* @param {Grunt} grunt
*/
const addTask = (name, grunt) => {
const path = require('path');
const taskPath = path.resolve(`./.grunt/tasks/${name}.js`);
grunt.log.debug(`Including tasks for ${name} from ${taskPath}`);
require(path.resolve(`./.grunt/tasks/${name}.js`))(grunt);
};
// Startup tasks.
grunt.moodleEnv.startupTasks = [];
// Add Moodle task configuration.
addTask('gherkinlint', grunt);
addTask('ignorefiles', grunt);
addTask('javascript', grunt);
addTask('style', grunt);
addTask('componentlibrary', grunt);
addTask('watch', grunt);
addTask('startup', grunt);
addTask('upgradablelibs', grunt);
// Register the default task.
grunt.registerTask('default', ['startup']);
};
-20
View File
@@ -1,20 +0,0 @@
MOODLE INSTALLATION
===================
Here is a short summary of the installation process (which can take just a few
minutes):
1. Move the Moodle files into your web directory.
2. Create a single database for Moodle to store all its tables in (or choose an
existing database).
3. Visit your Moodle site with a browser. You should be taken to the
install.php script, which will lead you through creating a config.php file
and then setting up Moodle, creating an admin account etc.
4. Set up a cron task to call the file admin/cron.php every minute.
For more information, see <https://docs.moodle.org/en/Installing_Moodle>.
Good luck and have fun!
-7
View File
@@ -1,7 +0,0 @@
*** PLEASE DO NOT OPEN PULL REQUESTS VIA GITHUB ***
The moodle.git repository at Github is just a mirror of the official repository. We do not accept pull requests at Github.
See CONTRIBUTING.txt guidelines for how to contribute patches for Moodle. Thank you.
--
+22 -21
View File
@@ -1,28 +1,29 @@
.-..-.
_____ | || |
/____/-.---_ .---. .---. .-.| || | .---.
| | _ _ |/ _ \/ _ \/ _ || |/ __ \
* | | | | | || |_| || |_| || |_| || || |___/
|_| |_| |_|\_____/\_____/\_____||_|\_____)
QUICK INSTALL
=============
Moodle - the world's open source learning platform
For the impatient, here is a basic outline of the
installation process, which normally takes me only
a few minutes:
Moodle <https://moodle.org> is a learning platform designed to provide
educators, administrators and learners with a single robust, secure and
integrated system to create personalised learning environments.
1) Move the Moodle files into your web directory.
You can download Moodle <https://download.moodle.org> and run it on your own
web server, ask one of our Moodle Partners <https://moodle.com/partners/> to
assist you, or have a MoodleCloud site <https://moodle.com/cloud/> set up for
you.
2) Create a single database for Moodle to store all
its tables in (or choose an existing database).
Moodle is widely used around the world by universities, schools, companies and
all manner of organisations and individuals.
3) Visit your Moodle site with a browser, you should
be taken to the install.php script, which will lead
you through creating a config.php file and then
setting up Moodle, creating an admin account etc.
Moodle is provided freely as open source software, under the GNU General Public
License <https://moodledev.io/general/license>.
4) Set up a cron task to call the file admin/cron.php
every five minutes or so.
Moodle is written in PHP and JavaScript and uses an SQL database for storing
the data.
See <https://docs.moodle.org> for details of Moodle's many features.
For more information, see the INSTALL DOCUMENTATION:
http://docs.moodle.org/en/Installing_Moodle
Good luck and have fun!
Martin Dougiamas, Lead Developer
+28 -60
View File
@@ -1,66 +1,34 @@
MOODLE TRADEMARKS POLICY
========================
The Moodle Trademark
--------------------
The brand and word "Moodle" has trade mark protection in many countries around
the world. Various Moodle™ trade marks are owned by either Moodle Pty Ltd or
one of its associated entities. The law obligates trade mark owners to police
their trade marks and prevent the use of confusingly similar names by
third parties.
We have created a more concise and thorough set of Trademark Guidelines
(https://moodle.com/wp-content/uploads/2023/02/Moodle-Trademark-Guidelines-2023-4.pdf)
to help you understand how to comply with Moodle's trade mark requirements.
The Trademark Guidelines will also assist our Moodle Certified Partners and the
community to understand some of the principles that inform Moodle's stance
whenever potential infringement has been detected by us or our community.
We need to be clear about use of the word "Moodle" and how we restrict its use
when promoting commercial Moodle™ branded services. The proper use of
trade marks reliably assures consumers about the quality of the associated
products or services and where they have been derived from. Because the
Moodle LMS is made available under the open source GNU General Public License'
that permits you to modify the copyrighted software, the distribution of such
modified software in combination with Moodle trade marks can potentially
mislead others in the community. To be clear, the GNU GPL does not include an
implied right or licence to use Moodle's trade marks.
We do all this to protect the very business model that allows us to continue
developing various Moodle software solutions for you.
Allowed uses of "Moodle"
------------------------
Moodle Trademark License
------------------------
The following uses don't require any permission at all:
The name Moodle™ is a registered trademark of the Moodle Trust.
* Referring to the software or the Moodle project as the "Moodle™ software"
or the "Moodle™ project"
* Describing your own implementation of the Moodle™ software platform
(including within corporate settings).
* Describing a Moodle-based community hub.
* Describing certain software you've made that integrates with Moodle™
branded software (e.g. a Moodle™ integration feature on another system).
A key part of the business model that allows us to produce and
distribute Moodle as completely Free open source software is that
we restrict the commercial use of the Moodle trademark to those
who have contracted to support Moodle development (Moodle Partners).
Restricted uses of "Moodle"
---------------------------
If you are intending to use the name (and/or logo) to advertise
generic Moodle™ services (eg Moodle Hosting, Moodle Support,
Moodle Certification, Moodle Training, Moodle Consulting,
Moodle Customisation, Moodle Courseware Development, Moodle
Theme design, Moodle Integrations, Moodle Installations, etc)
or as the name of a software package, then you must seek
direct permission in writing from the Moodle Trust via the
moodle.com helpdesk, in accordance with normal trademark
restrictions.
The following uses are generally prohibited without explicit and direct
permission being granted to you by Moodle Pty Ltd. We do this to protect the
Moodle™ project from software and sites which could confuse people. If in
doubt, reach out for clarification at <trademarks@moodle.com>
There are no restrictions on how you use the name in other
contexts (for example, if you use Moodle just to provide
courses then you can use the name freely to refer to it.)
* You can't use the word "Moodle" or any Moodle logos for commercial purposes
without prior written permission from Moodle HQ.
* You can't use "Moodle" in the name of your software (including Mobile apps).
* You can't use "Moodle" in your company name.
* You can't use "Moodle" in your domain name.
* You can't use "Moodle" in advertising-related keywords (such as Adsense).
* You can't use "Moodle" to describe services around Moodle
(such as hosting, training, support, consulting, course creation services,
theme development, customisation, installation, integration, analytics
and certification) that cause consumers to be confused that you are
associated with Moodle HQ if you are not.
This applies even if you do not charge for the services.
Note that usually only Moodle Partners have this permission.
If you aren't sure of a particular case, please ask us via
http://moodle.com/helpdesk: we'll be happy to either provide
you with official permission in writing or help you fix
your wording.
Martin Dougiamas
Executive Director
Moodle Trust
http://moodle.com
-3
View File
@@ -1,3 +0,0 @@
define("core_admin/block_management_table",["exports","./plugin_management_table","core_table/dynamic","core/ajax","core/pending","core/notification"],(function(_exports,_plugin_management_table,_dynamic,_ajax,_pending,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_plugin_management_table=_interopRequireDefault(_plugin_management_table),_pending=_interopRequireDefault(_pending);class _default extends _plugin_management_table.default{constructor(){super(),this.addClickHandler(this.handleBlockProtectToggle)}setBlockProtectState(plugin,state){return(0,_ajax.call)([{methodname:"core_admin_set_block_protection",args:{plugin:plugin,state:state}}])[0]}async handleBlockProtectToggle(tableRoot,e){const stateToggle=e.target.closest('[data-action="toggleprotectstate"]');if(stateToggle){e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:processAction");await this.setBlockProtectState(stateToggle.dataset.plugin,"1"===stateToggle.dataset.targetState?1:0);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]);updatedRoot.querySelector('[data-action="toggleprotectstate"][data-plugin="'.concat(stateToggle.dataset.plugin,'"]')).focus(),pendingPromise.resolve()}}}return _exports.default=_default,_exports.default}));
//# sourceMappingURL=block_management_table.min.js.map
@@ -1 +0,0 @@
{"version":3,"file":"block_management_table.min.js","sources":["../src/block_management_table.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\nimport PluginManagementTable from './plugin_management_table';\nimport {refreshTableContent} from 'core_table/dynamic';\nimport {call as fetchMany} from 'core/ajax';\nimport Pending from 'core/pending';\nimport {fetchNotifications} from 'core/notification';\n\nexport default class extends PluginManagementTable {\n constructor() {\n super();\n this.addClickHandler(this.handleBlockProtectToggle);\n }\n\n /**\n * Set the block protection state.\n *\n * @param {string} plugin\n * @param {number} state\n * @returns {Promise}\n */\n setBlockProtectState(plugin, state) {\n return fetchMany([{\n methodname: 'core_admin_set_block_protection',\n args: {\n plugin,\n state,\n },\n }])[0];\n }\n\n /**\n * Handle toggling of block protection.\n *\n * @param {HTMLElement} tableRoot\n * @param {Event} e\n */\n async handleBlockProtectToggle(tableRoot, e) {\n const stateToggle = e.target.closest('[data-action=\"toggleprotectstate\"]');\n if (stateToggle) {\n e.preventDefault();\n const pendingPromise = new Pending('core_table/dynamic:processAction');\n\n await this.setBlockProtectState(\n stateToggle.dataset.plugin,\n stateToggle.dataset.targetState === '1' ? 1 : 0\n );\n\n const [updatedRoot] = await Promise.all([\n refreshTableContent(tableRoot),\n fetchNotifications(),\n ]);\n\n // Refocus on the link that as pressed in the first place.\n updatedRoot.querySelector(`[data-action=\"toggleprotectstate\"][data-plugin=\"${stateToggle.dataset.plugin}\"]`).focus();\n pendingPromise.resolve();\n }\n }\n}\n"],"names":["PluginManagementTable","constructor","addClickHandler","this","handleBlockProtectToggle","setBlockProtectState","plugin","state","methodname","args","tableRoot","e","stateToggle","target","closest","preventDefault","pendingPromise","Pending","dataset","targetState","updatedRoot","Promise","all","querySelector","focus","resolve"],"mappings":"uhBAqB6BA,iCACzBC,2BAESC,gBAAgBC,KAAKC,0BAU9BC,qBAAqBC,OAAQC,cAClB,cAAU,CAAC,CACdC,WAAY,kCACZC,KAAM,CACFH,OAAAA,OACAC,MAAAA,UAEJ,kCASuBG,UAAWC,SAChCC,YAAcD,EAAEE,OAAOC,QAAQ,yCACjCF,YAAa,CACbD,EAAEI,uBACIC,eAAiB,IAAIC,iBAAQ,0CAE7Bd,KAAKE,qBACPO,YAAYM,QAAQZ,OACgB,MAApCM,YAAYM,QAAQC,YAAsB,EAAI,SAG3CC,mBAAqBC,QAAQC,IAAI,EACpC,gCAAoBZ,YACpB,wCAIJU,YAAYG,wEAAiEX,YAAYM,QAAQZ,cAAYkB,QAC7GR,eAAeS"}
-3
View File
@@ -1,3 +0,0 @@
define("core_admin/plugin_management_table",["exports","core_table/dynamic","core_table/local/dynamic/selectors","core/ajax","core/pending","core/notification"],(function(_exports,_dynamic,Selectors,_ajax,_pending,_notification){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,Selectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Selectors),_pending=(obj=_pending)&&obj.__esModule?obj:{default:obj};let watching=!1;return _exports.default=class{constructor(){!function(obj,key,value){key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}(this,"clickHandlers",[]),this.addClickHandler(this.handleStateToggle),this.addClickHandler(this.handleMoveUpDown),this.registerEventListeners()}static init(){watching||(watching=!0,new this)}addClickHandler(handler){this.clickHandlers.push(handler.bind(this))}registerEventListeners(){document.addEventListener("click",function(e){const tableRoot=this.getTableRoot(e);tableRoot&&this.clickHandlers.forEach((handler=>handler(tableRoot,e)))}.bind(this))}getTableRoot(e){const tableRoot=e.target.closest(Selectors.main.region);return tableRoot||!1}setPluginState(methodname,plugin,state){return(0,_ajax.call)([{methodname:methodname,args:{plugin:plugin,state:state}}])[0]}setPluginOrder(methodname,plugin,direction){return(0,_ajax.call)([{methodname:methodname,args:{plugin:plugin,direction:direction}}])[0]}async handleStateToggle(tableRoot,e){const stateToggle=e.target.closest('[data-action="togglestate"][data-toggle-method]');if(stateToggle){e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:togglestate");await this.setPluginState(stateToggle.dataset.toggleMethod,stateToggle.dataset.plugin,"1"===stateToggle.dataset.state?0:1);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]);updatedRoot.querySelector('[data-action="togglestate"][data-plugin="'.concat(stateToggle.dataset.plugin,'"]')).focus(),pendingPromise.resolve()}}async handleMoveUpDown(tableRoot,e){const actionLink=e.target.closest('[data-action="move"][data-method][data-direction]');if(!actionLink)return;e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:processAction");await this.setPluginOrder(actionLink.dataset.method,actionLink.dataset.plugin,"up"===actionLink.dataset.direction?-1:1);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]),exactMatch=updatedRoot.querySelector('[data-action="move"][data-plugin="'.concat(actionLink.dataset.plugin,'"][data-direction="').concat(actionLink.dataset.direction,'"]'));var _updatedRoot$querySel;exactMatch?exactMatch.focus():null===(_updatedRoot$querySel=updatedRoot.querySelector('[data-action="move"][data-plugin="'.concat(actionLink.dataset.plugin,'"]')))||void 0===_updatedRoot$querySel||_updatedRoot$querySel.focus();pendingPromise.resolve()}},_exports.default}));
//# sourceMappingURL=plugin_management_table.min.js.map
File diff suppressed because one or more lines are too long
-72
View File
@@ -1,72 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
import PluginManagementTable from './plugin_management_table';
import {refreshTableContent} from 'core_table/dynamic';
import {call as fetchMany} from 'core/ajax';
import Pending from 'core/pending';
import {fetchNotifications} from 'core/notification';
export default class extends PluginManagementTable {
constructor() {
super();
this.addClickHandler(this.handleBlockProtectToggle);
}
/**
* Set the block protection state.
*
* @param {string} plugin
* @param {number} state
* @returns {Promise}
*/
setBlockProtectState(plugin, state) {
return fetchMany([{
methodname: 'core_admin_set_block_protection',
args: {
plugin,
state,
},
}])[0];
}
/**
* Handle toggling of block protection.
*
* @param {HTMLElement} tableRoot
* @param {Event} e
*/
async handleBlockProtectToggle(tableRoot, e) {
const stateToggle = e.target.closest('[data-action="toggleprotectstate"]');
if (stateToggle) {
e.preventDefault();
const pendingPromise = new Pending('core_table/dynamic:processAction');
await this.setBlockProtectState(
stateToggle.dataset.plugin,
stateToggle.dataset.targetState === '1' ? 1 : 0
);
const [updatedRoot] = await Promise.all([
refreshTableContent(tableRoot),
fetchNotifications(),
]);
// Refocus on the link that as pressed in the first place.
updatedRoot.querySelector(`[data-action="toggleprotectstate"][data-plugin="${stateToggle.dataset.plugin}"]`).focus();
pendingPromise.resolve();
}
}
}
-179
View File
@@ -1,179 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
import {refreshTableContent} from 'core_table/dynamic';
import * as Selectors from 'core_table/local/dynamic/selectors';
import {call as fetchMany} from 'core/ajax';
import Pending from 'core/pending';
import {fetchNotifications} from 'core/notification';
let watching = false;
export default class {
/**
* @property {function[]} clickHandlers a list of handlers to call on click.
*/
clickHandlers = [];
constructor() {
this.addClickHandler(this.handleStateToggle);
this.addClickHandler(this.handleMoveUpDown);
this.registerEventListeners();
}
/**
* Initialise an instance of the class.
*
* This is just a way of making it easier to initialise an instance of the class from PHP.
*/
static init() {
if (watching) {
return;
}
watching = true;
new this();
}
/**
* Add a click handler to the list of handlers.
*
* @param {Function} handler A handler to call on a click event
*/
addClickHandler(handler) {
this.clickHandlers.push(handler.bind(this));
}
/**
* Register the event listeners for this instance.
*/
registerEventListeners() {
document.addEventListener('click', function(e) {
const tableRoot = this.getTableRoot(e);
if (!tableRoot) {
return;
}
this.clickHandlers.forEach((handler) => handler(tableRoot, e));
}.bind(this));
}
/**
* Get the table root from an event.
*
* @param {Event} e
* @returns {HTMLElement|bool}
*/
getTableRoot(e) {
const tableRoot = e.target.closest(Selectors.main.region);
if (!tableRoot) {
return false;
}
return tableRoot;
}
/**
* Set the plugin state (enabled or disabled)
*
* @param {string} methodname The web service to call
* @param {string} plugin The name of the plugin to set the state for
* @param {number} state The state to set
* @returns {Promise}
*/
setPluginState(methodname, plugin, state) {
return fetchMany([{
methodname,
args: {
plugin,
state,
},
}])[0];
}
setPluginOrder(methodname, plugin, direction) {
return fetchMany([{
methodname,
args: {
plugin,
direction,
},
}])[0];
}
/**
* Handle state toggling.
*
* @param {HTMLElement} tableRoot
* @param {Event} e
*/
async handleStateToggle(tableRoot, e) {
const stateToggle = e.target.closest('[data-action="togglestate"][data-toggle-method]');
if (stateToggle) {
e.preventDefault();
const pendingPromise = new Pending('core_table/dynamic:togglestate');
await this.setPluginState(
stateToggle.dataset.toggleMethod,
stateToggle.dataset.plugin,
stateToggle.dataset.state === '1' ? 0 : 1
);
const [updatedRoot] = await Promise.all([
refreshTableContent(tableRoot),
fetchNotifications(),
]);
// Refocus on the link that as pressed in the first place.
updatedRoot.querySelector(`[data-action="togglestate"][data-plugin="${stateToggle.dataset.plugin}"]`).focus();
pendingPromise.resolve();
}
}
async handleMoveUpDown(tableRoot, e) {
const actionLink = e.target.closest('[data-action="move"][data-method][data-direction]');
if (!actionLink) {
return;
}
e.preventDefault();
const pendingPromise = new Pending('core_table/dynamic:processAction');
await this.setPluginOrder(
actionLink.dataset.method,
actionLink.dataset.plugin,
actionLink.dataset.direction === 'up' ? -1 : 1,
);
const [updatedRoot] = await Promise.all([
refreshTableContent(tableRoot),
fetchNotifications(),
]);
// Refocus on the link that as pressed in the first place.
const exactMatch = updatedRoot.querySelector(
`[data-action="move"][data-plugin="${actionLink.dataset.plugin}"][data-direction="${actionLink.dataset.direction}"]`
);
if (exactMatch) {
exactMatch.focus();
} else {
// The move link is not present anymore, so we need to focus on the other one.
updatedRoot.querySelector(`[data-action="move"][data-plugin="${actionLink.dataset.plugin}"]`)?.focus();
}
pendingPromise.resolve();
}
}
-113
View File
@@ -1,113 +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/>.
/**
* Allows admin to configure antiviruses.
*
* @package core_antivirus
* @copyright 2015 Ruslan Kabalin, Lancaster University.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
$action = required_param('action', PARAM_ALPHANUMEXT);
$antivirus = required_param('antivirus', PARAM_PLUGIN);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$PAGE->set_url('/admin/antiviruses.php', array('action' => $action, 'antivirus' => $antivirus));
$PAGE->set_context(context_system::instance());
require_admin();
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageantiviruses";
// Get currently installed and enabled antivirus plugins.
$availableantiviruses = \core\antivirus\manager::get_available();
if (!empty($antivirus) and empty($availableantiviruses[$antivirus])) {
redirect ($returnurl);
}
$activeantiviruses = explode(',', $CFG->antiviruses);
foreach ($activeantiviruses as $key => $active) {
if (empty($availableantiviruses[$active])) {
unset($activeantiviruses[$key]);
}
}
if (!confirm_sesskey()) {
redirect($returnurl);
}
$needsupdate = false;
switch ($action) {
case 'disable':
// Remove from enabled list.
$class = \core_plugin_manager::resolve_plugininfo_class('antivirus');
$class::enable_plugin($antivirus, false);
break;
case 'enable':
// Add to enabled list.
if (!in_array($antivirus, $activeantiviruses)) {
$class = \core_plugin_manager::resolve_plugininfo_class('antivirus');
$class::enable_plugin($antivirus, true);
}
break;
case 'down':
$key = array_search($antivirus, $activeantiviruses);
// Check auth plugin is valid.
if ($key !== false) {
// Move down the list.
if ($key < (count($activeantiviruses) - 1)) {
$fsave = $activeantiviruses[$key];
$activeantiviruses[$key] = $activeantiviruses[$key + 1];
$activeantiviruses[$key + 1] = $fsave;
$needsupdate = true;
}
}
break;
case 'up':
$key = array_search($antivirus, $activeantiviruses);
// Check auth is valid.
if ($key !== false) {
// Move up the list.
if ($key >= 1) {
$fsave = $activeantiviruses[$key];
$activeantiviruses[$key] = $activeantiviruses[$key - 1];
$activeantiviruses[$key - 1] = $fsave;
$needsupdate = true;
}
}
break;
default:
break;
}
if ($needsupdate) {
$new = implode(',', $activeantiviruses);
add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core');
set_config('antiviruses', $new);
core_plugin_manager::reset_caches();
}
redirect ($returnurl);
+29 -16
View File
@@ -11,7 +11,8 @@ require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
require_admin();
require_login();
require_capability('moodle/site:config', context_system::instance());
$returnurl = new moodle_url('/admin/settings.php', array('section'=>'manageauths'));
@@ -28,7 +29,7 @@ if (empty($CFG->auth)) {
}
if (!empty($auth) and !exists_auth_plugin($auth)) {
throw new \moodle_exception('pluginnotinstalled', 'auth', $returnurl, $auth);
print_error('pluginnotinstalled', 'auth', $returnurl, $auth);
}
////////////////////////////////////////////////////////////////////////////////
@@ -40,31 +41,43 @@ if (!confirm_sesskey()) {
switch ($action) {
case 'disable':
// Remove from enabled list.
$class = \core_plugin_manager::resolve_plugininfo_class('auth');
$class::enable_plugin($auth, false);
// remove from enabled list
$key = array_search($auth, $authsenabled);
if ($key !== false) {
unset($authsenabled[$key]);
set_config('auth', implode(',', $authsenabled));
}
if ($auth == $CFG->registerauth) {
set_config('registerauth', '');
}
\core\session\manager::gc(); // Remove stale sessions.
core_plugin_manager::reset_caches();
break;
case 'enable':
// Add to enabled list.
$class = \core_plugin_manager::resolve_plugininfo_class('auth');
$class::enable_plugin($auth, true);
// add to enabled list
if (!in_array($auth, $authsenabled)) {
$authsenabled[] = $auth;
$authsenabled = array_unique($authsenabled);
set_config('auth', implode(',', $authsenabled));
}
\core\session\manager::gc(); // Remove stale sessions.
core_plugin_manager::reset_caches();
break;
case 'down':
$key = array_search($auth, $authsenabled);
// check auth plugin is valid
if ($key === false) {
throw new \moodle_exception('pluginnotenabled', 'auth', $returnurl, $auth);
print_error('pluginnotenabled', 'auth', $returnurl, $auth);
}
// move down the list
if ($key < (count($authsenabled) - 1)) {
$fsave = $authsenabled[$key];
$authsenabled[$key] = $authsenabled[$key + 1];
$authsenabled[$key + 1] = $fsave;
$value = implode(',', $authsenabled);
add_to_config_log('auth', $CFG->auth, $value, 'core');
set_config('auth', $value);
set_config('auth', implode(',', $authsenabled));
}
break;
@@ -72,16 +85,14 @@ switch ($action) {
$key = array_search($auth, $authsenabled);
// check auth is valid
if ($key === false) {
throw new \moodle_exception('pluginnotenabled', 'auth', $returnurl, $auth);
print_error('pluginnotenabled', 'auth', $returnurl, $auth);
}
// move up the list
if ($key >= 1) {
$fsave = $authsenabled[$key];
$authsenabled[$key] = $authsenabled[$key - 1];
$authsenabled[$key - 1] = $fsave;
$value = implode(',', $authsenabled);
add_to_config_log('auth', $CFG->auth, $value, 'core');
set_config('auth', $value);
set_config('auth', implode(',', $authsenabled));
}
break;
@@ -90,3 +101,5 @@ switch ($action) {
}
redirect($returnurl);
+189
View File
@@ -0,0 +1,189 @@
<?php
/**
* Edit configuration for an individual auth plugin
*/
require_once '../config.php';
require_once $CFG->libdir.'/adminlib.php';
$auth = required_param('auth', PARAM_PLUGIN);
$PAGE->set_pagetype('admin-auth-' . $auth);
admin_externalpage_setup('authsetting'.$auth);
$authplugin = get_auth_plugin($auth);
$err = array();
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageauths";
// save configuration changes
if ($frm = data_submitted() and confirm_sesskey()) {
$authplugin->validate_form($frm, $err);
if (count($err) == 0) {
// save plugin config
if ($authplugin->process_config($frm)) {
// save field lock configuration
foreach ($frm as $name => $value) {
if (preg_match('/^lockconfig_(.+?)$/', $name, $matches)) {
$plugin = "auth/$auth";
$name = $matches[1];
set_config($name, $value, $plugin);
}
}
redirect($returnurl);
exit;
}
} else {
foreach ($err as $key => $value) {
$focus = "form.$key";
}
}
} else {
$frmlegacystyle = get_config('auth/'.$auth);
$frmnewstyle = get_config('auth_'.$auth);
$frm = (object)array_merge((array)$frmlegacystyle, (array)$frmnewstyle);
}
$user_fields = $authplugin->userfields;
//$user_fields = array("firstname", "lastname", "email", "phone1", "phone2", "institution", "department", "address", "city", "country", "description", "idnumber", "lang");
/// Get the auth title (from core or own auth lang files)
$authtitle = $authplugin->get_title();
/// Get the auth descriptions (from core or own auth lang files)
$authdescription = $authplugin->get_description();
// output configuration form
echo $OUTPUT->header();
// choose an authentication method
echo "<form id=\"authmenu\" method=\"post\" action=\"auth_config.php\">\n";
echo "<div>\n";
echo "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n";
echo "<input type=\"hidden\" name=\"auth\" value=\"".$auth."\" />\n";
// auth plugin description
echo $OUTPUT->box_start();
echo $OUTPUT->heading($authtitle);
echo $OUTPUT->box_start('informationbox');
echo $authdescription;
echo $OUTPUT->box_end();
echo "<hr />\n";
$authplugin->config_form($frm, $err, $user_fields);
echo $OUTPUT->box_end();
echo '<p style="text-align: center"><input type="submit" value="' . get_string("savechanges") . "\" /></p>\n";
echo "</div>\n";
echo "</form>\n";
$PAGE->requires->string_for_js('unmaskpassword', 'core_form');
$PAGE->requires->yui_module('moodle-auth-passwordunmask', 'M.auth.passwordunmask');
echo $OUTPUT->footer();
exit;
/// Functions /////////////////////////////////////////////////////////////////
// Good enough for most auth plugins
// but some may want a custom one if they are offering
// other options
// Note: lockconfig_ fields have special handling.
function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts, $updateopts, $customfields = array()) {
global $DB, $OUTPUT;
echo '<tr><td colspan="3">';
if ($retrieveopts) {
echo $OUTPUT->heading(get_string('auth_data_mapping', 'auth'));
} else {
echo $OUTPUT->heading(get_string('auth_fieldlocks', 'auth'));
}
echo '</td></tr>';
$lockoptions = array ('unlocked' => get_string('unlocked', 'auth'),
'unlockedifempty' => get_string('unlockedifempty', 'auth'),
'locked' => get_string('locked', 'auth'));
$updatelocaloptions = array('oncreate' => get_string('update_oncreate', 'auth'),
'onlogin' => get_string('update_onlogin', 'auth'));
$updateextoptions = array('0' => get_string('update_never', 'auth'),
'1' => get_string('update_onupdate', 'auth'));
$pluginconfig = get_config("auth/$auth");
// Helptext is on a field with rowspan.
if (empty($helptext)) {
$helptext = '&nbsp;';
}
// If we have custom fields then merge them with user fields.
if (!empty($customfields)) {
$user_fields = array_merge($user_fields, $customfields);
}
if (!empty($customfields)) {
$customfieldname = $DB->get_records('user_info_field', null, '', 'shortname, name');
}
foreach ($user_fields as $field) {
// Define some vars we'll work with.
if (!isset($pluginconfig->{"field_map_$field"})) {
$pluginconfig->{"field_map_$field"} = '';
}
if (!isset($pluginconfig->{"field_updatelocal_$field"})) {
$pluginconfig->{"field_updatelocal_$field"} = '';
}
if (!isset($pluginconfig->{"field_updateremote_$field"})) {
$pluginconfig->{"field_updateremote_$field"} = '';
}
if (!isset($pluginconfig->{"field_lock_$field"})) {
$pluginconfig->{"field_lock_$field"} = '';
}
// Define the fieldname we display to the user.
$fieldname = $field;
if ($fieldname === 'lang') {
$fieldname = get_string('language');
} elseif (!empty($customfields) && in_array($field, $customfields)) {
// If custom field then pick name from database.
$fieldshortname = str_replace('profile_field_', '', $fieldname);
$fieldname = $customfieldname[$fieldshortname]->name;
} elseif (preg_match('/^(.+?)(\d+)$/', $fieldname, $matches)) {
$fieldname = get_string($matches[1]) . ' ' . $matches[2];
} elseif ($fieldname == 'url') {
$fieldname = get_string('webpage');
} else {
$fieldname = get_string($fieldname);
}
if ($retrieveopts) {
$varname = 'field_map_' . $field;
echo '<tr valign="top"><td align="right">';
echo '<label for="lockconfig_'.$varname.'">'.$fieldname.'</label>';
echo '</td><td>';
echo "<input id=\"lockconfig_{$varname}\" name=\"lockconfig_{$varname}\" type=\"text\" size=\"30\" value=\"{$pluginconfig->$varname}\" />";
echo '<div style="text-align: right">';
echo '<label for="menulockconfig_field_updatelocal_'.$field.'">'.get_string('auth_updatelocal', 'auth') . '</label>&nbsp;';
echo html_writer::select($updatelocaloptions, "lockconfig_field_updatelocal_{$field}", $pluginconfig->{"field_updatelocal_$field"}, false);
echo '<br />';
if ($updateopts) {
echo '<label for="menulockconfig_field_updateremote_'.$field.'">'.get_string('auth_updateremote', 'auth') . '</label>&nbsp;';
echo html_writer::select($updateextoptions, "lockconfig_field_updateremote_{$field}", $pluginconfig->{"field_updateremote_$field"}, false);
echo '<br />';
}
echo '<label for="menulockconfig_field_lock_'.$field.'">'.get_string('auth_fieldlock', 'auth') . '</label>&nbsp;';
echo html_writer::select($lockoptions, "lockconfig_field_lock_{$field}", $pluginconfig->{"field_lock_$field"}, false);
echo '</div>';
} else {
echo '<tr valign="top"><td align="right">';
echo '<label for="menulockconfig_field_lock_'.$field.'">'.$fieldname.'</label>';
echo '</td><td>';
echo html_writer::select($lockoptions, "lockconfig_field_lock_{$field}", $pluginconfig->{"field_lock_$field"}, false);
}
echo '</td>';
if (!empty($helptext)) {
echo '<td rowspan="' . count($user_fields) . '">' . $helptext . '</td>';
$helptext = '';
}
echo '</tr>';
}
}
+234 -79
View File
@@ -1,94 +1,249 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Allows the admin to configure blocks (hide/show, uninstall and configure)
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// Allows the admin to configure blocks (hide/show, uninstall and configure)
require_once('../config.php');
require_once("{$CFG->libdir}/adminlib.php");
require_once("{$CFG->libdir}/blocklib.php");
require_once("{$CFG->libdir}/tablelib.php");
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/tablelib.php');
admin_externalpage_setup('manageblocks');
admin_externalpage_setup('manageblocks');
$plugin = optional_param('plugin', '', PARAM_PLUGIN);
$action = optional_param('action', '', PARAM_ALPHA);
$unprotect = optional_param('unprotect', 0, PARAM_PLUGIN);
$protect = optional_param('protect', 0, PARAM_PLUGIN);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$hide = optional_param('hide', 0, PARAM_INT);
$show = optional_param('show', 0, PARAM_INT);
$unprotect = optional_param('unprotect', 0, PARAM_INT);
$protect = optional_param('protect', 0, PARAM_INT);
$strmanageblocks = get_string('manageblocks');
/// Print headings
// If data submitted, then process and store.
if (!empty($plugin) && !empty($action) && confirm_sesskey()) {
$manager = \core_plugin_manager::resolve_plugininfo_class('block');
$pluginname = get_string('pluginname', "block_{$plugin}");
$strmanageblocks = get_string('manageblocks');
$struninstall = get_string('uninstallplugin', 'core_admin');
$strversion = get_string('version');
$strhide = get_string('hide');
$strshow = get_string('show');
$strsettings = get_string('settings');
$strcourses = get_string('blockinstances', 'admin');
$strname = get_string('name');
$strshowblockcourse = get_string('showblockcourse');
$strprotecthdr = get_string('blockprotect', 'admin'). $OUTPUT->help_icon('blockprotect','admin');
$strprotect = get_string('blockprotect', 'admin');
$strunprotect = get_string('blockunprotect', 'admin');
if ($action === 'disable' && $manager::enable_plugin($plugin, 0)) {
\core\notification::add(
get_string('plugin_disabled', 'core_admin', $pluginname),
\core\notification::SUCCESS
);
// Settings not required - only pages.
admin_get_root(true, false);
} else if ($action === 'enable' && $manager::enable_plugin($plugin, 1)) {
\core\notification::add(
get_string('plugin_enabled', 'core_admin', $pluginname),
\core\notification::SUCCESS
);
/// If data submitted, then process and store.
// Settings not required - only pages.
admin_get_root(true, false);
if (!empty($hide) && confirm_sesskey()) {
if (!$block = $DB->get_record('block', array('id'=>$hide))) {
print_error('blockdoesnotexist', 'error');
}
$DB->set_field('block', 'visible', '0', array('id'=>$block->id)); // Hide block
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
// Redirect back to the page with out any params.
redirect(new moodle_url('/admin/blocks.php'));
}
if (!empty($show) && confirm_sesskey() ) {
if (!$block = $DB->get_record('block', array('id'=>$show))) {
print_error('blockdoesnotexist', 'error');
}
$DB->set_field('block', 'visible', '1', array('id'=>$block->id)); // Show block
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
}
if (!empty($protect) && confirm_sesskey()) {
block_manager::protect_block($protect);
$pluginname = get_string('pluginname', "block_{$protect}");
\core\notification::add(
get_string('blockprotected', 'core_admin', $pluginname),
\core\notification::SUCCESS
);
// Settings not required - only pages.
admin_get_root(true, false);
}
if (!isset($CFG->undeletableblocktypes) || (!is_array($CFG->undeletableblocktypes) && !is_string($CFG->undeletableblocktypes))) {
$undeletableblocktypes = array('navigation', 'settings');
} else if (is_string($CFG->undeletableblocktypes)) {
$undeletableblocktypes = explode(',', $CFG->undeletableblocktypes);
} else {
$undeletableblocktypes = $CFG->undeletableblocktypes;
}
if (!empty($unprotect) && confirm_sesskey()) {
block_manager::unprotect_block($unprotect);
$pluginname = get_string('pluginname', "block_{$unprotect}");
\core\notification::add(
get_string('blockunprotected', 'core_admin', $pluginname),
\core\notification::SUCCESS
);
// Settings not required - only pages.
admin_get_root(true, false);
}
if (!empty($protect) && confirm_sesskey()) {
if (!$block = $DB->get_record('block', array('id'=>$protect))) {
print_error('blockdoesnotexist', 'error');
}
if (!in_array($block->name, $undeletableblocktypes)) {
$undeletableblocktypes[] = $block->name;
set_config('undeletableblocktypes', implode(',', $undeletableblocktypes));
}
admin_get_root(true, false); // settings not required - only pages
}
if (!empty($unprotect) && confirm_sesskey()) {
if (!$block = $DB->get_record('block', array('id'=>$unprotect))) {
print_error('blockdoesnotexist', 'error');
}
if (in_array($block->name, $undeletableblocktypes)) {
$undeletableblocktypes = array_diff($undeletableblocktypes, array($block->name));
set_config('undeletableblocktypes', implode(',', $undeletableblocktypes));
}
admin_get_root(true, false); // settings not required - only pages
}
echo $OUTPUT->header();
echo $OUTPUT->heading($strmanageblocks);
/// Main display starts here
/// Get and sort the existing blocks
if (!$blocks = $DB->get_records('block', array(), 'name ASC')) {
print_error('noblocks', 'error'); // Should never happen
}
$incompatible = array();
/// Print the table of all blocks
$table = new flexible_table('admin-blocks-compatible');
$table->define_columns(array('name', 'instances', 'version', 'hideshow', 'undeletable', 'settings', 'uninstall'));
$table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strprotecthdr, $strsettings, $struninstall));
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
$table->set_attribute('class', 'admintable blockstable generaltable');
$table->set_attribute('id', 'compatibleblockstable');
$table->setup();
$tablerows = array();
// Sort blocks using current locale.
$blocknames = array();
foreach ($blocks as $blockid=>$block) {
$blockname = $block->name;
if (file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
$blocknames[$blockid] = get_string('pluginname', 'block_'.$blockname);
} else {
$blocknames[$blockid] = $blockname;
}
}
core_collator::asort($blocknames);
foreach ($blocknames as $blockid=>$strblockname) {
$block = $blocks[$blockid];
$blockname = $block->name;
$dbversion = get_config('block_'.$block->name, 'version');
if (!file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
$blockobject = false;
$strblockname = '<span class="notifyproblem">'.$strblockname.' ('.get_string('missingfromdisk').')</span>';
$plugin = new stdClass();
$plugin->version = $dbversion;
} else {
$plugin = new stdClass();
$plugin->version = '???';
if (file_exists("$CFG->dirroot/blocks/$blockname/version.php")) {
include("$CFG->dirroot/blocks/$blockname/version.php");
}
if (!$blockobject = block_instance($block->name)) {
$incompatible[] = $block;
continue;
}
}
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$blockname, 'manage')) {
$uninstall = html_writer::link($uninstallurl, $struninstall);
} else {
$uninstall = '';
}
$settings = ''; // By default, no configuration
if ($blockobject and $blockobject->has_config()) {
$blocksettings = admin_get_root()->locate('blocksetting' . $block->name);
if ($blocksettings instanceof admin_externalpage) {
$settings = '<a href="' . $blocksettings->url . '">' . get_string('settings') . '</a>';
} else if ($blocksettings instanceof admin_settingpage) {
$settings = '<a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=blocksetting'.$block->name.'">'.$strsettings.'</a>';
} else {
$settings = '<a href="block.php?block='.$blockid.'">'.$strsettings.'</a>';
}
}
// MDL-11167, blocks can be placed on mymoodle, or the blogs page
// and it should not show up on course search page
$totalcount = $DB->count_records('block_instances', array('blockname'=>$blockname));
$count = $DB->count_records('block_instances', array('blockname'=>$blockname, 'pagetypepattern'=>'course-view-*'));
if ($count>0) {
$blocklist = "<a href=\"{$CFG->wwwroot}/course/search.php?blocklist=$blockid&amp;sesskey=".sesskey()."\" ";
$blocklist .= "title=\"$strshowblockcourse\" >$totalcount</a>";
}
else {
$blocklist = "$totalcount";
}
$class = ''; // Nothing fancy, by default
if (!$blockobject) {
// ignore
$visible = '';
} else if ($blocks[$blockid]->visible) {
$visible = '<a href="blocks.php?hide='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strhide.'">'.
'<img src="'.$OUTPUT->pix_url('t/hide') . '" class="iconsmall" alt="'.$strhide.'" /></a>';
} else {
$visible = '<a href="blocks.php?show='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strshow.'">'.
'<img src="'.$OUTPUT->pix_url('t/show') . '" class="iconsmall" alt="'.$strshow.'" /></a>';
$class = 'dimmed_text';
}
if ($dbversion == $plugin->version) {
$version = $dbversion;
} else {
$version = "$dbversion ($plugin->version)";
}
if (!$blockobject) {
// ignore
$undeletable = '';
} else if (in_array($blockname, $undeletableblocktypes)) {
$undeletable = '<a href="blocks.php?unprotect='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strunprotect.'">'.
'<img src="'.$OUTPUT->pix_url('t/unlock') . '" class="iconsmall" alt="'.$strunprotect.'" /></a>';
} else {
$undeletable = '<a href="blocks.php?protect='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strprotect.'">'.
'<img src="'.$OUTPUT->pix_url('t/lock') . '" class="iconsmall" alt="'.$strprotect.'" /></a>';
}
$row = array(
$strblockname,
$blocklist,
$version,
$visible,
$undeletable,
$settings,
$uninstall,
);
$table->add_data($row, $class);
}
$table->print_html();
if (!empty($incompatible)) {
echo $OUTPUT->heading(get_string('incompatibleblocks', 'blockstable', 'admin'));
$table = new flexible_table('admin-blocks-incompatible');
$table->define_columns(array('block', 'uninstall'));
$table->define_headers(array($strname, $struninstall));
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
$table->set_attribute('class', 'incompatibleblockstable generaltable');
$table->setup();
foreach ($incompatible as $block) {
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$block->name, 'manage')) {
$uninstall = html_writer::link($uninstallurl, $struninstall);
} else {
$uninstall = '';
}
$table->add_data(array(
$block->name,
$uninstall,
));
}
$table->print_html();
}
echo $OUTPUT->footer();
echo $OUTPUT->header();
echo $OUTPUT->heading($strmanageblocks);
echo $OUTPUT->notification(get_string('noteunneededblocks', 'admin'), 'info', false);
// Print the table of all blocks.
$table = new \core_admin\table\block_management_table();
$table->out();
echo $OUTPUT->footer();
+26 -30
View File
@@ -30,6 +30,7 @@ $category = required_param('category', PARAM_SAFEDIR);
$return = optional_param('return','', PARAM_ALPHA);
$adminediting = optional_param('adminedit', -1, PARAM_BOOL);
/// no guest autologin
require_login(0, false);
$PAGE->set_context(context_system::instance());
$PAGE->set_url('/admin/category.php', array('category' => $category));
@@ -41,47 +42,40 @@ $adminroot = admin_get_root(); // need all settings
$settingspage = $adminroot->locate($category, true);
if (empty($settingspage) or !($settingspage instanceof admin_category)) {
throw new \moodle_exception('categoryerror', 'error', "$CFG->wwwroot/$CFG->admin/");
print_error('categoryerror', 'admin', "$CFG->wwwroot/$CFG->admin/");
}
if (!($settingspage->check_access())) {
throw new \moodle_exception('accessdenied', 'admin');
print_error('accessdenied', 'admin');
}
$hassiteconfig = has_capability('moodle/site:config', $PAGE->context);
if ($hassiteconfig) {
$PAGE->add_header_action($OUTPUT->render_from_template('core_admin/header_search_input', [
'action' => new moodle_url('/admin/search.php'),
]));
}
$statusmsg = '';
$errormsg = '';
if ($data = data_submitted() and confirm_sesskey()) {
$count = admin_write_settings($data);
if (admin_write_settings($data)) {
$statusmsg = get_string('changessaved');
}
if (empty($adminroot->errors)) {
// No errors. Did we change any setting? If so, then indicate success.
if ($count) {
$statusmsg = get_string('changessaved');
} else {
switch ($return) {
case 'site': redirect("$CFG->wwwroot/");
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
}
switch ($return) {
case 'site': redirect("$CFG->wwwroot/");
case 'admin': redirect("$CFG->wwwroot/$CFG->admin/");
}
} else {
$errormsg = get_string('errorwithsettings', 'admin');
$firsterror = reset($adminroot->errors);
}
$adminroot = admin_get_root(true); //reload tree
$settingspage = $adminroot->locate($category, true);
}
if ($PAGE->user_allowed_editing() && $adminediting != -1) {
$USER->editing = $adminediting;
}
$buttons = null;
if ($PAGE->user_allowed_editing() && !$PAGE->theme->haseditswitch) {
if ($PAGE->user_allowed_editing()) {
$url = clone($PAGE->url);
if ($PAGE->user_is_editing()) {
$caption = get_string('blockseditoff');
@@ -96,7 +90,7 @@ if ($PAGE->user_allowed_editing() && !$PAGE->theme->haseditswitch) {
$savebutton = false;
$outputhtml = '';
foreach ($settingspage->children as $childpage) {
if ($childpage->is_hidden() || !$childpage->check_access()) {
if ($childpage->is_hidden()) {
continue;
}
if ($childpage instanceof admin_externalpage) {
@@ -127,15 +121,14 @@ foreach ($settingspage->children as $childpage) {
}
if ($savebutton) {
$outputhtml .= html_writer::start_tag('div', array('class' => 'form-buttons'));
$outputhtml .= html_writer::empty_tag('input', array('class' => 'btn btn-primary form-submit', 'type' => 'submit', 'value' => get_string('savechanges','admin')));
$outputhtml .= html_writer::empty_tag('input', array('class' => 'form-submit', 'type' => 'submit', 'value' => get_string('savechanges','admin')));
$outputhtml .= html_writer::end_tag('div');
}
$PAGE->set_title(implode(moodle_page::TITLE_SEPARATOR, $settingspage->visiblepath));
$visiblepathtosection = array_reverse($settingspage->visiblepath);
$PAGE->set_title("$SITE->shortname: " . implode(": ",$visiblepathtosection));
$PAGE->set_heading($SITE->fullname);
if ($buttons) {
$PAGE->set_button($buttons);
}
$PAGE->set_button($buttons);
echo $OUTPUT->header();
@@ -145,7 +138,13 @@ if ($errormsg !== '') {
echo $OUTPUT->notification($statusmsg, 'notifysuccess');
}
echo $OUTPUT->heading(get_string('admincategory', 'admin', $settingspage->visiblename), 2);
$path = array_reverse($settingspage->visiblepath);
if (is_array($path)) {
$visiblename = join(' / ', $path);
} else {
$visiblename = $path;
}
echo $OUTPUT->heading(get_string('admincategory', 'admin', $visiblename), 2);
echo html_writer::start_tag('form', array('action' => '', 'method' => 'post', 'id' => 'adminsettings'));
echo html_writer::start_tag('div');
@@ -157,7 +156,4 @@ echo $outputhtml;
echo html_writer::end_tag('fieldset');
echo html_writer::end_tag('form');
// Add the form change checker.
$PAGE->requires->js_call_amd('core_form/changechecker', 'watchFormById', ['adminsettings']);
echo $OUTPUT->footer();
echo $OUTPUT->footer();
@@ -1,127 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\admin;
use admin_setting;
use core_plugin_manager;
use core_text;
/**
* Admin setting plugin manager.
*
* @package core_admin
* @subpackage admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_setting_plugin_manager extends admin_setting {
/** @var core_plugin_manager The plugin manager instance */
protected core_plugin_manager $pluginmanager;
/** @var string The plugintype that this manager covers */
protected string $plugintype;
/** @var string The class of the management table to use */
protected string $tableclass;
public function __construct(
string $plugintype,
string $tableclass,
string $name,
string $visiblename,
string $description = '',
string $defaultsetting = '',
) {
$this->nosave = true;
$this->pluginmanager = core_plugin_manager::instance();
$this->plugintype = $plugintype;
$this->tableclass = $tableclass;
parent::__construct($name, $visiblename, $description, $defaultsetting);
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_setting(): bool {
return true;
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_defaultsetting(): bool {
return true;
}
/**
* Always returns '', does not write anything
*
* @return string Always returns ''
*/
// phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
public function write_setting($data): string {
// Do not write any setting.
return '';
}
/**
* Checks if $query is one of the available editors
*
* @param string $query The string to search for
* @return bool Returns true if found, false if not
*/
public function is_related($query) {
if (parent::is_related($query)) {
return true;
}
$plugins = $this->pluginmanager->get_installed_plugins($this->plugintype);
foreach (array_keys($plugins) as $plugin) {
$plugin = "{$this->plugintype}_{$plugin}";
if (str_contains($plugin, $query)) {
return true;
}
$pluginname = get_string('pluginname', $plugin);
if (strpos(core_text::strtolower($pluginname), $query) !== false) {
return true;
}
}
return false;
}
/**
* Builds the XHTML to display the control
*
* @param string $data Unused
* @param string $query
* @return string
*/
public function output_html($data, $query = ''): string {
$table = new $this->tableclass();
if (!($table instanceof \core_admin\table\plugin_management_table)) {
throw new \coding_exception("{$this->tableclass} must be an instance of \\core_admin\\table\\plugin_management_table");
}
return highlight($query, $table->get_content());
}
}
-97
View File
@@ -1,97 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\external;
use block_manager;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
/**
* Web Service to control the state of a plugin.
*
* @package core_admin
* @category external
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class set_block_protection extends external_api {
/**
* Returns description of method parameters
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
'state' => new external_value(PARAM_INT, 'The target state', VALUE_REQUIRED),
]);
}
/**
* Set the block protection state.
*
* @param string $plugin The name of the plugin
* @param int $state The target state
* @return null
*/
public static function execute(
string $plugin,
int $state,
): array {
[
'plugin' => $plugin,
'state' => $state,
] = self::validate_parameters(self::execute_parameters(), [
'plugin' => $plugin,
'state' => $state,
]);
$context = \context_system::instance();
self::validate_context($context);
require_capability('moodle/site:config', $context);
[, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
$displayname = get_string('pluginname', $plugin);
if ($state) {
block_manager::protect_block($pluginname);
\core\notification::add(
get_string('blockprotected', 'core_admin', $displayname),
\core\notification::SUCCESS
);
} else {
block_manager::unprotect_block($pluginname);
\core\notification::add(
get_string('blockunprotected', 'core_admin', $displayname),
\core\notification::SUCCESS
);
}
return [];
}
/**
* Describe the return structure of the external service.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([]);
}
}
-84
View File
@@ -1,84 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
/**
* Web Service to control the order of a plugin.
*
* @package core_admin
* @category external
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class set_plugin_order extends external_api {
/**
* Returns description of method parameters
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
'direction' => new external_value(PARAM_INT, 'The direction to move', VALUE_REQUIRED),
]);
}
/**
* Set the plugin state.
*
* @param string $plugin The name of the plugin
* @param int $direction The direction to move the plugin
* @return array
*/
public static function execute(
string $plugin,
int $direction,
): array {
[
'plugin' => $plugin,
'direction' => $direction,
] = self::validate_parameters(self::execute_parameters(), [
'plugin' => $plugin,
'direction' => $direction,
]);
$context = \context_system::instance();
self::validate_context($context);
require_capability('moodle/site:config', $context);
[$plugintype, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
$manager::change_plugin_order($pluginname, $direction);
return [];
}
/**
* Describe the return structure of the external service.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([]);
}
}
-98
View File
@@ -1,98 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\external;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
/**
* Web Service to control the state of a plugin.
*
* @package core_admin
* @category external
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class set_plugin_state extends external_api {
/**
* Returns description of method parameters
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
'state' => new external_value(PARAM_INT, 'The target state', VALUE_REQUIRED),
]);
}
/**
* Set the plugin state.
*
* @param string $plugin The name of the plugin
* @param int $state The target state
* @return null
*/
public static function execute(
string $plugin,
int $state,
): array {
[
'plugin' => $plugin,
'state' => $state,
] = self::validate_parameters(self::execute_parameters(), [
'plugin' => $plugin,
'state' => $state,
]);
$context = \context_system::instance();
self::validate_context($context);
require_capability('moodle/site:config', $context);
[$plugintype, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
$displayname = get_string('pluginname', $plugin);
if ($manager::enable_plugin($pluginname, $state)) {
if (!empty($state)) {
\core\notification::add(
get_string('plugin_enabled', 'core_admin', $displayname),
\core\notification::SUCCESS
);
} else {
\core\notification::add(
get_string('plugin_disabled', 'core_admin', $displayname),
\core\notification::SUCCESS
);
}
}
return [];
}
/**
* Describe the return structure of the external service.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([]);
}
}
-76
View File
@@ -1,76 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Form for selective purging of caches.
*
* @package core
* @copyright 2018 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\form;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/formslib.php');
/**
* Form for selecting which caches to purge on admin/purgecaches.php
*
* @package core
* @copyright 2018 The Open University
* @author Mark Johnson <mark.johnson@open.ac.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class purge_caches extends \moodleform {
/**
* Define a "Purge all caches" button, and a fieldset with checkboxes for selectively purging separate caches.
*/
public function definition() {
$mform = $this->_form;
$mform->addElement('hidden', 'returnurl', $this->_customdata['returnurl']);
$mform->setType('returnurl', PARAM_LOCALURL);
$mform->addElement('submit', 'all', get_string('purgecaches', 'admin'));
$mform->addElement('header', 'purgecacheheader', get_string('purgeselectedcaches', 'admin'));
$checkboxes = [
$mform->createElement('advcheckbox', 'theme', '', get_string('purgethemecache', 'admin')),
$mform->createElement('advcheckbox', 'lang', '', get_string('purgelangcache', 'admin')),
$mform->createElement('advcheckbox', 'js', '', get_string('purgejscache', 'admin')),
$mform->createElement('advcheckbox', 'template', '', get_string('purgetemplates', 'admin')),
$mform->createElement('advcheckbox', 'filter', '', get_string('purgefiltercache', 'admin')),
$mform->createElement('advcheckbox', 'muc', '', get_string('purgemuc', 'admin')),
$mform->createElement('advcheckbox', 'other', '', get_string('purgeothercaches', 'admin'))
];
$mform->addGroup($checkboxes, 'purgeselectedoptions');
$mform->addElement('submit', 'purgeselectedcaches', get_string('purgeselectedcaches', 'admin'));
}
/**
* If the "Purge selected caches" button was pressed, ensure at least one cache was selected.
*
* @param array $data
* @param array $files
* @return array Error messages
*/
public function validation($data, $files) {
$errors = [];
if (isset($data['purgeselectedcaches']) && empty(array_filter($data['purgeselectedoptions']))) {
$errors['purgeselectedoptions'] = get_string('purgecachesnoneselected', 'admin');
}
return $errors;
}
}
@@ -1,92 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Testing outgoing mail configuration form
*
* @package core
* @copyright 2019 Victor Deniz <victor@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\form;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/formslib.php');
/**
* Test mail form
*
* @package core
* @copyright 2019 Victor Deniz <victor@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class testoutgoingmailconf_form extends \moodleform {
/**
* Add elements to form
*/
public function definition() {
$mform = $this->_form;
// Recipient.
$options = ['maxlength' => '100', 'size' => '25', 'autocomplete' => 'email'];
$mform->addElement('text', 'recipient', get_string('testoutgoingmailconf_toemail', 'admin'), $options);
$mform->setType('recipient', PARAM_EMAIL);
$mform->addRule('recipient', get_string('required'), 'required');
// From user.
$options = ['maxlength' => '100', 'size' => '25'];
$mform->addElement('text', 'from', get_string('testoutgoingmailconf_fromemail', 'admin'), $options);
$mform->setType('from', PARAM_TEXT);
$mform->addHelpButton('from', 'testoutgoingmailconf_fromemail', 'admin');
// Additional subject text.
$options = ['size' => '25'];
$mform->addElement('text', 'additionalsubject', get_string('testoutgoingmailconf_subjectadditional', 'admin'), $options);
$mform->setType('additionalsubject', PARAM_TEXT);
$buttonarray = array();
$buttonarray[] = $mform->createElement('submit', 'send', get_string('testoutgoingmailconf_sendtest', 'admin'));
$buttonarray[] = $mform->createElement('cancel');
$mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
$mform->closeHeaderBefore('buttonar');
}
/**
* Validate Form field, should be a valid email format or a username that matches with a Moodle user.
*
* @param array $data
* @param array $files
* @return array
* @throws \dml_exception|\coding_exception
*/
public function validation($data, $files): array {
$errors = parent::validation($data, $files);
if (isset($data['from']) && $data['from']) {
$userfrom = \core_user::get_user_by_username($data['from']);
if (!$userfrom && !validate_email($data['from'])) {
$errors['from'] = get_string('testoutgoingmailconf_fromemail_invalid', 'admin');
}
}
return $errors;
}
}
@@ -1,71 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* External admin page class that allows a callback to be provided to determine whether page can be accessed
*
* @package core_admin
* @copyright 2019 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\externalpage;
use admin_externalpage;
defined('MOODLE_INTERNAL') || die();
require_once("{$CFG->libdir}/adminlib.php");
/**
* Admin externalpage class
*
* @package core_admin
* @copyright 2019 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class accesscallback extends admin_externalpage {
/** @var callable $accesscheckcallback */
protected $accesscheckcallback;
/**
* Class constructor
*
* @param string $name
* @param string $visiblename
* @param string $url
* @param callable $accesscheckcallback The callback method that will be executed to check whether user has access to
* this page. The setting instance ($this) is passed as an argument to the callback. Should return boolean value
* @param bool $hidden
*/
public function __construct(string $name, string $visiblename, string $url, callable $accesscheckcallback,
bool $hidden = false) {
$this->accesscheckcallback = $accesscheckcallback;
parent::__construct($name, $visiblename, $url, [], $hidden);
}
/**
* Determines if the current user has access to this external page based on access callback
*
* @return bool
*/
public function check_access() {
return ($this->accesscheckcallback)($this);
}
}
@@ -1,206 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Auto complete admin setting.
*
* @package core_admin
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/adminlib.php');
/**
* Auto complete setting class.
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @copyright 2020 The Open University
*/
class autocomplete extends \admin_setting_configmultiselect {
/** @var boolean Should we allow typing new entries to the field? */
protected $tags = false;
/** @var string Name of an AMD module to send/process ajax requests. */
protected $ajax = '';
/** @var string Placeholder text for an empty list. */
protected $placeholder = '';
/** @var bool Whether the search has to be case-sensitive. */
protected $casesensitive = false;
/** @var bool Show suggestions by default - but this can be turned off. */
protected $showsuggestions = true;
/** @var string String that is shown when there are no selections. */
protected $noselectionstring = '';
/** @var string Delimiter to store values in database. */
protected $delimiter = ',';
/** @var string Should be multiple choices? */
protected $multiple = true;
/** @var string The link to manage choices. */
protected $manageurl = true;
/** @var string The text to display in manage link. */
protected $managetext = true;
/**
* Constructor
*
* @param string $name unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting'
* for ones in config_plugins.
* @param string $visiblename localised
* @param string $description long localised info
* @param array $defaultsetting array of selected items
* @param array $choices options for autocomplete field
* @param array $attributes settings for autocomplete field
*/
public function __construct($name, $visiblename, $description, $defaultsetting, $choices, $attributes = null) {
if ($attributes === null) {
$attributes = [];
}
$this->placeholder = get_string('search');
$this->noselectionstring = get_string('noselection', 'form');
$defaultattributes = [
'tags',
'showsuggestions',
'placeholder',
'noselectionstring',
'ajax',
'casesensitive',
'delimiter',
'multiple',
'manageurl',
'managetext'
];
foreach ($defaultattributes as $attributename) {
if (isset($attributes[$attributename])) {
$this->$attributename = $attributes[$attributename];
}
}
parent::__construct($name, $visiblename, $description, $defaultsetting, $choices);
}
/**
* Returns the select setting(s)
*
* @return mixed null or array. Null if no settings else array of setting(s)
*/
public function get_setting() {
$result = $this->config_read($this->name);
if (is_null($result)) {
return null;
}
if ($result === '') {
return [];
}
return explode($this->delimiter, $result);
}
/**
* Saves setting(s) provided through $data
*
* @param array $data
*/
public function write_setting($data) {
if (!is_array($data)) {
return ''; // Ignore it.
}
if (!$this->load_choices() || empty($this->choices)) {
return '';
}
unset($data['xxxxx']);
$save = [];
foreach ($data as $value) {
if (!array_key_exists($value, $this->choices)) {
continue; // Ignore it.
}
$save[] = $value;
}
return ($this->config_write($this->name, implode($this->delimiter, $save)) ? '' : get_string('errorsetting', 'admin'));
}
/**
* Returns XHTML autocomplete field
*
* @param array $data Array of values to select by default
* @param string $query
* @return string XHTML autocomplete field
*/
public function output_html($data, $query = '') {
global $OUTPUT;
if (!$this->load_choices() or empty($this->choices)) {
return '';
}
$default = $this->get_defaultsetting();
if (empty($default)) {
$default = [];
}
if (is_null($data)) {
$data = [];
}
$context = [
'id' => $this->get_id(),
'name' => $this->get_full_name()
];
$defaults = [];
$options = [];
$template = 'core_admin/local/settings/autocomplete';
foreach ($this->choices as $value => $name) {
if (in_array($value, $default)) {
$defaults[] = $name;
}
$options[] = [
'value' => $value,
'text' => $name,
'selected' => in_array($value, $data),
'disabled' => false
];
}
$context['options'] = $options;
$context['tags'] = $this->tags;
$context['placeholder'] = $this->placeholder;
$context['casesensitive'] = $this->casesensitive;
$context['multiple'] = $this->multiple;
$context['showsuggestions'] = $this->showsuggestions;
$context['manageurl'] = $this->manageurl;
$context['managetext'] = $this->managetext;
if (is_null($default)) {
$defaultinfo = null;
} if (!empty($defaults)) {
$defaultinfo = implode(', ', $defaults);
} else {
$defaultinfo = get_string('none');
}
$element = $OUTPUT->render_from_template($template, $context);
return format_admin_setting($this, $this->visiblename, $element, $this->description, true, '', $defaultinfo, $query);
}
}
-197
View File
@@ -1,197 +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/>.
/**
* File size admin setting.
*
* @package core_admin
* @copyright 2019 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/adminlib.php');
/**
* An admin setting to support entering and displaying of file sizes in Bytes, KB, MB or GB.
*
* @copyright 2019 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class filesize extends \admin_setting {
/** @var int The byte unit. Number of bytes in a byte */
const UNIT_B = 1;
/** @var int The kilobyte unit (number of bytes in a kilobyte) */
const UNIT_KB = 1024;
/** @var int The megabyte unit (number of bytes in a megabyte) */
const UNIT_MB = 1048576;
/** @var int The gigabyte unit (number of bytes in a gigabyte) */
const UNIT_GB = 1073741824;
/** @var int default size unit */
protected $defaultunit;
/**
* Constructor
*
* @param string $name unique ascii name, either 'mysetting' for settings that in config,
* or 'myplugin/mysetting' for ones in config_plugins.
* @param string $visiblename localised name
* @param string $description localised long description
* @param int|null $defaultvalue Value of the settings in bytes
* @param int|null $defaultunit GB, MB, etc. (in bytes)
*/
public function __construct(string $name, string $visiblename, string $description,
int $defaultvalue = null, int $defaultunit = null) {
$defaultsetting = self::parse_bytes($defaultvalue);
if ($defaultunit && array_key_exists($defaultunit, self::get_units())) {
$this->defaultunit = $defaultunit;
} else {
$this->defaultunit = self::UNIT_MB;
}
parent::__construct($name, $visiblename, $description, $defaultsetting);
}
/**
* Returns selectable units.
*
* @return array
*/
protected static function get_units(): array {
return [
self::UNIT_GB => get_string('sizegb'),
self::UNIT_MB => get_string('sizemb'),
self::UNIT_KB => get_string('sizekb'),
self::UNIT_B => get_string('sizeb'),
];
}
/**
* Converts bytes to some more user friendly string.
*
* @param int $bytes The number of bytes we want to convert from
* @return string
*/
protected static function get_size_text(int $bytes): string {
if (empty($bytes)) {
return get_string('none');
}
return display_size($bytes, 0);
}
/**
* Finds suitable units for given file size.
*
* @param int $bytes The number of bytes
* @return array Parsed file size in the format of ['v' => value, 'u' => unit]
*/
protected static function parse_bytes(int $bytes): array {
foreach (self::get_units() as $unit => $unused) {
if ($bytes % $unit === 0) {
return ['v' => (int)($bytes / $unit), 'u' => $unit];
}
}
return ['v' => (int)$bytes, 'u' => self::UNIT_B];
}
/**
* Get the selected file size as array.
*
* @return array|null An array containing 'v' => xx, 'u' => xx, or null if not set
*/
public function get_setting(): ?array {
$bytes = $this->config_read($this->name);
if (is_null($bytes)) {
return null;
}
$bytes = intval($bytes);
return self::parse_bytes($bytes);
}
/**
* Store the file size as bytes.
*
* @param array $data Must be form 'h' => xx, 'm' => xx
* @return string The error string if any
*/
public function write_setting($data): string {
if (!is_array($data)) {
return '';
}
if (!is_numeric($data['v']) || $data['v'] < 0) {
return get_string('errorsetting', 'admin');
}
// Calculate size in bytes, ensuring we don't overflow PHP_INT_MAX.
$bytes = $data['v'] * $data['u'];
$result = (is_int($bytes) && $this->config_write($this->name, $bytes));
return ($result ? '' : get_string('errorsetting', 'admin'));
}
/**
* Returns file size text+select fields.
*
* @param array $data The current setting value. Must be form 'v' => xx, 'u' => xx.
* @param string $query Admin search query to be highlighted.
* @return string File size text+select fields and wrapping div(s).
*/
public function output_html($data, $query = ''): string {
global $OUTPUT;
$default = $this->get_defaultsetting();
if (is_number($default)) {
$defaultinfo = self::get_size_text($default);
} else if (is_array($default)) {
$defaultinfo = self::get_size_text($default['v'] * $default['u']);
} else {
$defaultinfo = null;
}
$inputid = $this->get_id() . 'v';
$units = self::get_units();
$defaultunit = $this->defaultunit;
$context = (object) [
'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,
'name' => $title,
'selected' => ($data['v'] == 0 && $unit == $defaultunit) || $unit == $data['u']
];
}, array_keys($units), $units)
];
$element = $OUTPUT->render_from_template('core_admin/setting_configfilesize', $context);
return format_admin_setting($this, $this->visiblename, $element, $this->description, $inputid, '', $defaultinfo, $query);
}
}
@@ -1,37 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A settings page which can be viewed with a link directly.
*
* @package core_admin
* @copyright 2021 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
use moodle_url;
interface linkable_settings_page {
/**
* Get the URL to view this settings page.
*
* @return moodle_url
*/
public function get_settings_page_url(): moodle_url;
}
@@ -1,74 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Payment gateway admin setting.
*
* @package core_admin
* @copyright 2020 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
/**
* Generic class for managing plugins in a table that allows re-ordering and enable/disable of each plugin.
*/
class manage_payment_gateway_plugins extends \admin_setting_manage_plugins {
/**
* Get the admin settings section title (use get_string).
*
* @return string
*/
public function get_section_title() {
return get_string('type_paygw_plural', 'plugin');
}
/**
* Get the type of plugin to manage.
*
* @return string
*/
public function get_plugin_type() {
return 'paygw';
}
/**
* Get the name of the second column.
*
* @return string
*/
public function get_info_column_name() {
return get_string('supportedcurrencies', 'core_payment');
}
/**
* Get the type of plugin to manage.
*
* @param plugininfo The plugin info class.
* @return string
*/
public function get_info_column($plugininfo) {
$codes = $plugininfo->get_supported_currencies();
$currencies = [];
foreach ($codes as $c) {
$currencies[$c] = new \lang_string($c, 'core_currencies');
}
return implode(get_string('listsep', 'langconfig') . ' ', $currencies);
}
}
@@ -1,121 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Admin setting to show current scheduled task's status.
*
* @package core
* @copyright 2021 Universitat Rovira i Virgili
* @author Jordi Pujol-Ahulló <jpahullo@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\local\settings;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/moodlelib.php');
use admin_setting_description;
use core\task\manager;
use core\task\scheduled_task;
use html_writer;
use lang_string;
use moodle_url;
use stdClass;
/**
* This admin setting tells whether a given scheduled task is enabled, providing a link to its configuration page.
*
* The goal of this setting is to help contextualizing the configuration settings with related scheduled task status,
* providing the big picture of that part of the system.
*
* @package core
* @copyright 2021 Universitat Rovira i Virgili
* @author Jordi Pujol-Ahulló <jpahullo@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class setting_scheduled_task_status extends admin_setting_description {
/**
* @var string fully qualified class name of a scheduled task.
*/
private $classname;
/**
* @var string additional text to append to the description.
*/
private $extradescription;
/**
* setting_scheduled_task_status constructor.
* @param string $name unique setting name.
* @param string $scheduledtaskclassname full classpath class name of the scheduled task.
* @param string $extradescription extra detail to append to the scheduled task status to add context in the setting
* page.
*/
public function __construct(string $name, string $scheduledtaskclassname, string $extradescription = '') {
$visiblename = new lang_string('task_status', 'admin');
$this->classname = $scheduledtaskclassname;
$this->extradescription = $extradescription;
parent::__construct($name, $visiblename, '');
}
/**
* Calculates lazily the content of the description.
* @param mixed $data nothing expected in this case.
* @param string $query nothing expected in this case.
* @return string the HTML content to print for this setting.
*/
public function output_html($data, $query = ''): string {
if (empty($this->description)) {
$this->description = $this->get_task_description();
}
return parent::output_html($data, $query);
}
/**
* Returns the HTML to print as the description.
* @return string description to be printed.
*/
private function get_task_description(): string {
$task = manager::get_scheduled_task($this->classname);
if ($task->is_enabled()) {
$taskenabled = get_string('enabled', 'admin');
} else {
$taskenabled = get_string('disabled', 'admin');
}
$taskenabled = strtolower($taskenabled);
$gotourl = new moodle_url(
'/admin/tool/task/scheduledtasks.php',
[],
scheduled_task::get_html_id($this->classname)
);
if (!empty($this->extradescription)) {
$this->extradescription = '<br />' . $this->extradescription;
}
$taskdetail = new stdClass();
$taskdetail->class = $this->classname;
$taskdetail->name = $task->get_name();
$taskdetail->status = $taskenabled;
$taskdetail->gotourl = $gotourl->out(false);
$taskdetail->extradescription = $this->extradescription;
return html_writer::tag('p', get_string('task_status_desc', 'admin', $taskdetail));
}
}
-41
View File
@@ -1,41 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for core_admin.
*
* @package core_admin
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for core_admin implementing null_provider.
*
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() : string {
return 'privacy:metadata';
}
}
@@ -1,128 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
declare(strict_types=1);
namespace core_admin\reportbuilder\datasource;
use core_admin\reportbuilder\local\entities\task_log;
use core_reportbuilder\datasource;
use core_reportbuilder\local\entities\user;
use core_reportbuilder\local\filters\select;
/**
* Task logs datasource
*
* @package core_admin
* @copyright 2022 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_logs extends datasource {
/**
* Return user friendly name of the report source
*
* @return string
*/
public static function get_name(): string {
return get_string('tasklogs', 'core_admin');
}
/**
* Initialise report
*/
protected function initialise(): void {
$tasklogentity = new task_log();
$tasklogalias = $tasklogentity->get_table_alias('task_log');
$this->set_main_table('task_log', $tasklogalias);
$this->add_entity($tasklogentity);
// Join the user entity to represent the associated user.
$userentity = new user();
$useralias = $userentity->get_table_alias('user');
$this->add_entity($userentity->add_join("
LEFT JOIN {user} {$useralias}
ON {$useralias}.id = {$tasklogalias}.userid")
);
// Add report elements from each of the entities we added to the report.
$this->add_all_from_entities();
}
/**
* Return the columns that will be added to the report upon creation
*
* @return string[]
*/
public function get_default_columns(): array {
return [
'task_log:name',
'task_log:starttime',
'task_log:duration',
'task_log:result',
];
}
/**
* Return the column sorting that will be added to the report upon creation
*
* @return int[]
*/
public function get_default_column_sorting(): array {
return [
'task_log:starttime' => SORT_DESC,
];
}
/**
* Return the filters that will be added to the report upon creation
*
* @return string[]
*/
public function get_default_filters(): array {
return [
'task_log:timestart',
'task_log:result',
];
}
/**
* Return the conditions that will be added to the report upon creation
*
* @return string[]
*/
public function get_default_conditions(): array {
return [
'task_log:type',
'task_log:timestart',
'task_log:result',
];
}
/**
* Return the condition values that will be set for the report upon creation
*
* @return array
*/
public function get_default_condition_values(): array {
return [
'task_log:type_operator' => select::EQUAL_TO,
'task_log:type_value' => \core\task\database_logger::TYPE_SCHEDULED,
];
}
}
@@ -1,427 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\reportbuilder\local\entities;
use core_reportbuilder\local\filters\date;
use core_reportbuilder\local\filters\duration;
use core_reportbuilder\local\filters\number;
use core_reportbuilder\local\filters\select;
use core_reportbuilder\local\filters\text;
use core_reportbuilder\local\filters\autocomplete;
use core_reportbuilder\local\helpers\format;
use lang_string;
use core_reportbuilder\local\entities\base;
use core_reportbuilder\local\report\column;
use core_reportbuilder\local\report\filter;
use stdClass;
use core_collator;
/**
* Task log entity class implementation
*
* @package core_admin
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_log extends base {
/** @var int Result success */
protected const SUCCESS = 0;
/** @var int Result failed */
protected const FAILED = 1;
/**
* Database tables that this entity uses and their default aliases
*
* @return array
*/
protected function get_default_table_aliases(): array {
return ['task_log' => 'tl'];
}
/**
* The default title for this entity in the list of columns/conditions/filters in the report builder
*
* @return lang_string
*/
protected function get_default_entity_title(): lang_string {
return new lang_string('entitytasklog', 'admin');
}
/**
* Initialise the entity
*
* @return base
*/
public function initialise(): base {
$columns = $this->get_all_columns();
foreach ($columns as $column) {
$this->add_column($column);
}
// All the filters defined by the entity can also be used as conditions.
$filters = $this->get_all_filters();
foreach ($filters as $filter) {
$this
->add_filter($filter)
->add_condition($filter);
}
return $this;
}
/**
* Returns list of all available columns
*
* @return column[]
*/
protected function get_all_columns(): array {
global $DB;
$tablealias = $this->get_table_alias('task_log');
// Name column.
$columns[] = (new column(
'name',
new lang_string('name'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_field("$tablealias.classname")
->set_is_sortable(true)
->add_callback(static function(string $classname): string {
$output = '';
if (class_exists($classname)) {
$task = new $classname;
if ($task instanceof \core\task\task_base) {
$output = $task->get_name();
}
}
$output .= \html_writer::tag('div', "\\{$classname}", [
'class' => 'small text-muted',
]);
return $output;
});
// Component column.
$columns[] = (new column(
'component',
new lang_string('plugin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_field("{$tablealias}.component")
->set_is_sortable(true);
// Type column.
$columns[] = (new column(
'type',
new lang_string('tasktype', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_field("{$tablealias}.type")
->set_is_sortable(true)
->add_callback(static function($value): string {
if (\core\task\database_logger::TYPE_SCHEDULED === (int) $value) {
return get_string('task_type:scheduled', 'admin');
}
return get_string('task_type:adhoc', 'admin');
});
// Start time column.
$columns[] = (new column(
'starttime',
new lang_string('task_starttime', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TIMESTAMP)
->add_field("{$tablealias}.timestart")
->set_is_sortable(true)
->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
// End time column.
$columns[] = (new column(
'endtime',
new lang_string('task_endtime', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TIMESTAMP)
->add_field("{$tablealias}.timeend")
->set_is_sortable(true)
->add_callback([format::class, 'userdate'], get_string('strftimedatetimeshortaccurate', 'core_langconfig'));
// Duration column.
$columns[] = (new column(
'duration',
new lang_string('task_duration', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_FLOAT)
->add_field("{$tablealias}.timeend - {$tablealias}.timestart", 'duration')
->set_is_sortable(true)
->add_callback(static function(float $value): string {
$duration = round($value, 2);
if (empty($duration)) {
// The format_time function returns 'now' when the difference is exactly 0.
// Note: format_time performs concatenation in exactly this fashion so we should do this for consistency.
return '0 ' . get_string('secs', 'moodle');
}
return format_time($duration);
});
// Hostname column.
$columns[] = (new column(
'hostname',
new lang_string('hostname', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_field("$tablealias.hostname")
->set_is_sortable(true);
// PID column.
$columns[] = (new column(
'pid',
new lang_string('pid', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_field("{$tablealias}.pid")
->set_is_sortable(true)
// Although this is an integer column, it doesn't make sense to perform numeric aggregation on it.
->set_disabled_aggregation(['avg', 'count', 'countdistinct', 'max', 'min', 'sum']);
// Database column.
$columns[] = (new column(
'database',
new lang_string('task_dbstats', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_fields("{$tablealias}.dbreads, {$tablealias}.dbwrites")
->set_is_sortable(true, ["{$tablealias}.dbreads", "{$tablealias}.dbwrites"])
->add_callback(static function(int $value, stdClass $row): string {
$output = '';
$output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
$output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
return $output;
})
// Although this is an integer column, it doesn't make sense to perform numeric aggregation on it.
->set_disabled_aggregation(['avg', 'count', 'countdistinct', 'max', 'min', 'sum']);
// Database reads column.
$columns[] = (new column(
'dbreads',
new lang_string('task_dbreads', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_fields("{$tablealias}.dbreads")
->set_is_sortable(true);
// Database writes column.
$columns[] = (new column(
'dbwrites',
new lang_string('task_dbwrites', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_fields("{$tablealias}.dbwrites")
->set_is_sortable(true);
// Result column.
$columns[] = (new column(
'result',
new lang_string('task_result', 'admin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_BOOLEAN)
// For accurate aggregation, we need to return boolean success = true by xor'ing the field value.
->add_field($DB->sql_bitxor("{$tablealias}.result", 1), 'success')
->set_is_sortable(true)
->add_callback(static function(bool $success): string {
if (!$success) {
return get_string('task_result:failed', 'admin');
}
return get_string('success');
});
return $columns;
}
/**
* Return list of all available filters
*
* @return filter[]
*/
protected function get_all_filters(): array {
global $DB;
$tablealias = $this->get_table_alias('task_log');
// Name filter (Filter by classname).
$filters[] = (new filter(
autocomplete::class,
'name',
new lang_string('classname', 'tool_task'),
$this->get_entity_name(),
"{$tablealias}.classname"
))
->add_joins($this->get_joins())
->set_options_callback(static function(): array {
global $DB;
$classnames = $DB->get_fieldset_sql('SELECT DISTINCT classname FROM {task_log} ORDER BY classname ASC');
$options = [];
foreach ($classnames as $classname) {
if (class_exists($classname)) {
$task = new $classname;
$options[$classname] = $task->get_name();
}
}
core_collator::asort($options);
return $options;
});
// Component filter.
$filters[] = (new filter(
text::class,
'component',
new lang_string('plugin'),
$this->get_entity_name(),
"{$tablealias}.component"
))
->add_joins($this->get_joins());
// Type filter.
$filters[] = (new filter(
select::class,
'type',
new lang_string('tasktype', 'admin'),
$this->get_entity_name(),
"{$tablealias}.type"
))
->add_joins($this->get_joins())
->set_options([
\core\task\database_logger::TYPE_ADHOC => new lang_string('task_type:adhoc', 'admin'),
\core\task\database_logger::TYPE_SCHEDULED => new lang_string('task_type:scheduled', 'admin'),
]);
// Output filter (Filter by task output).
$filters[] = (new filter(
text::class,
'output',
new lang_string('task_logoutput', 'admin'),
$this->get_entity_name(),
$DB->sql_cast_to_char("{$tablealias}.output")
))
->add_joins($this->get_joins());
// Start time filter.
$filters[] = (new filter(
date::class,
'timestart',
new lang_string('task_starttime', 'admin'),
$this->get_entity_name(),
"{$tablealias}.timestart"
))
->add_joins($this->get_joins())
->set_limited_operators([
date::DATE_ANY,
date::DATE_RANGE,
date::DATE_PREVIOUS,
date::DATE_CURRENT,
]);
// End time.
$filters[] = (new filter(
date::class,
'timeend',
new lang_string('task_endtime', 'admin'),
$this->get_entity_name(),
"{$tablealias}.timeend"
))
->add_joins($this->get_joins())
->set_limited_operators([
date::DATE_ANY,
date::DATE_RANGE,
date::DATE_PREVIOUS,
date::DATE_CURRENT,
]);
// Duration filter.
$filters[] = (new filter(
duration::class,
'duration',
new lang_string('task_duration', 'admin'),
$this->get_entity_name(),
"{$tablealias}.timeend - {$tablealias}.timestart"
))
->add_joins($this->get_joins());
// Database reads.
$filters[] = (new filter(
number::class,
'dbreads',
new lang_string('task_dbreads', 'admin'),
$this->get_entity_name(),
"{$tablealias}.dbreads"
))
->add_joins($this->get_joins());
// Database writes.
$filters[] = (new filter(
number::class,
'dbwrites',
new lang_string('task_dbwrites', 'admin'),
$this->get_entity_name(),
"{$tablealias}.dbwrites"
))
->add_joins($this->get_joins());
// Result filter.
$filters[] = (new filter(
select::class,
'result',
new lang_string('task_result', 'admin'),
$this->get_entity_name(),
"{$tablealias}.result"
))
->add_joins($this->get_joins())
->set_options([
self::SUCCESS => get_string('success'),
self::FAILED => get_string('task_result:failed', 'admin'),
]);
return $filters;
}
}
@@ -1,159 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\reportbuilder\local\systemreports;
use context_system;
use core_admin\reportbuilder\local\entities\task_log;
use core_reportbuilder\local\entities\user;
use core_reportbuilder\local\report\action;
use lang_string;
use moodle_url;
use pix_icon;
use core_reportbuilder\system_report;
/**
* Task logs system report class implementation
*
* @package core_admin
* @copyright 2021 David Matamoros <davidmc@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_logs extends system_report {
/**
* Initialise report, we need to set the main table, load our entities and set columns/filters
*/
protected function initialise(): void {
// Our main entity, it contains all of the column definitions that we need.
$entitymain = new task_log();
$entitymainalias = $entitymain->get_table_alias('task_log');
$this->set_main_table('task_log', $entitymainalias);
$this->add_entity($entitymain);
// Any columns required by actions should be defined here to ensure they're always available.
$this->add_base_fields("{$entitymainalias}.id");
// We can join the "user" entity to our "main" entity and use the fullname column from the user entity.
$entityuser = new user();
$entituseralias = $entityuser->get_table_alias('user');
$this->add_entity($entityuser->add_join(
"LEFT JOIN {user} {$entituseralias} ON {$entituseralias}.id = {$entitymainalias}.userid"
));
// Now we can call our helper methods to add the content we want to include in the report.
$this->add_columns();
$this->add_filters();
$this->add_actions();
// Set if report can be downloaded.
$this->set_downloadable(true, get_string('tasklogs', 'admin'));
}
/**
* Validates access to view this report
*
* @return bool
*/
protected function can_view(): bool {
return has_capability('moodle/site:config', context_system::instance());
}
/**
* Get the visible name of the report
*
* @return string
*/
public static function get_name(): string {
return get_string('entitytasklog', 'admin');
}
/**
* Adds the columns we want to display in the report
*
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
* unique identifier
*/
public function add_columns(): void {
$columns = [
'task_log:name',
'task_log:type',
'user:fullname',
'task_log:starttime',
'task_log:duration',
'task_log:hostname',
'task_log:pid',
'task_log:database',
'task_log:result',
];
$this->add_columns_from_entities($columns);
// It's possible to override the display name of a column, if you don't want to use the value provided by the entity.
if ($column = $this->get_column('user:fullname')) {
$column->set_title(new lang_string('user', 'admin'));
}
// It's possible to set a default initial sort direction for one column.
$this->set_initial_sort_column('task_log:starttime', SORT_DESC);
}
/**
* Adds the filters we want to display in the report
*
* They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
* unique identifier
*/
protected function add_filters(): void {
$filters = [
'task_log:name',
'task_log:type',
'task_log:output',
'task_log:result',
'task_log:timestart',
'task_log:duration',
];
$this->add_filters_from_entities($filters);
}
/**
* Add the system report actions. An extra column will be appended to each row, containing all actions added here
*
* Note the use of ":id" placeholder which will be substituted according to actual values in the row
*/
protected function add_actions(): void {
// Action to view individual task log on a popup window.
$this->add_action((new action(
new moodle_url('/admin/tasklogs.php', ['logid' => ':id']),
new pix_icon('e/search', ''),
[],
true,
new lang_string('view'),
)));
// Action to download individual task log.
$this->add_action((new action(
new moodle_url('/admin/tasklogs.php', ['logid' => ':id', 'download' => true]),
new pix_icon('t/download', ''),
[],
false,
new lang_string('download'),
)));
}
}
@@ -1,118 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\table;
use core_plugin_manager;
use dml_exception;
use html_writer;
use moodle_url;
use stdClass;
/**
* Activity Module admin settings.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class activity_management_table extends plugin_management_table {
public function setup() {
$this->set_attribute('id', 'modules');
$this->set_attribute('class', 'admintable generaltable');
parent::setup();
}
protected function get_table_id(): string {
return 'module-administration-table';
}
protected function get_plugintype(): string {
return 'mod';
}
public function guess_base_url(): void {
$this->define_baseurl(
new moodle_url('/admin/modules.php')
);
}
protected function get_action_url(array $params = []): moodle_url {
return new moodle_url('/admin/modules.php', $params);
}
protected function get_column_list(): array {
$columns = parent::get_column_list();
return array_merge(
array_slice($columns, 0, 1, true),
['activities' => get_string('activities')],
array_slice($columns, 1, null, true),
);
}
protected function col_name(stdClass $row): string {
global $OUTPUT;
$status = $row->plugininfo->get_status();
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
return html_writer::span(
get_string('pluginmissingfromdisk', 'core', $row->plugininfo),
'notifyproblem'
);
}
return html_writer::span(
html_writer::img(
$OUTPUT->image_url('monologo', $row->plugininfo->name),
'',
[
'class' => 'icon',
],
) . get_string('modulename', $row->plugininfo->name)
);
}
/**
* Show the number of activities present, with a link to courses containing activity if relevant.
*
* @param mixed $row
* @return string
*/
protected function col_activities(stdClass $row): string {
global $DB, $OUTPUT;
try {
$count = $DB->count_records_select($row->plugininfo->name, "course <> 0");
} catch (dml_exception $e) {
$count = -1;
}
if ($count > 0) {
return $OUTPUT->action_link(
new moodle_url('/course/search.php', [
'modulelist' => $row->plugininfo->name,
]),
$count,
null,
['title' => get_string('showmodulecourse')]
);
} else if ($count < 0) {
return get_string('error');
} else {
return $count;
}
}
}
@@ -1,153 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\table;
use html_writer;
use moodle_url;
use stdClass;
/**
* Tiny admin settings.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class block_management_table extends \core_admin\table\plugin_management_table {
/** @var plugininfo[] A list of blocks which cannot be deleted */
protected array $undeletableblocktypes;
/** @var stdClass[] A list of basic block data */
protected array $blockdata;
/** @var array<string,int> A list of course counts */
protected array $courseblocks;
public function __construct() {
global $DB;
parent::__construct();
$this->undeletableblocktypes = \block_manager::get_undeletable_block_types();
$sql = 'SELECT b.name,
b.id,
COUNT(DISTINCT binst.id) as totalcount
FROM {block} b
LEFT JOIN {block_instances} binst ON binst.blockname = b.name
GROUP BY b.id,
b.name
ORDER BY b.name ASC';
$this->blockdata = $DB->get_records_sql($sql);
$sql = "SELECT blockname
FROM {block_instances}
WHERE pagetypepattern = 'course-view-*'
GROUP BY blockname";
$this->courseblocks = $DB->get_records_sql($sql);
}
protected function get_plugintype(): string {
return 'block';
}
public function guess_base_url(): void {
$this->define_baseurl(
new moodle_url('/admin/blocks.php')
);
}
protected function get_action_url(array $params = []): moodle_url {
return new moodle_url('/admin/blocks.php', $params);
}
protected function get_table_js_module(): string {
return 'core_admin/block_management_table';
}
protected function get_column_list(): array {
$columns = parent::get_column_list();
return array_merge(
array_slice($columns, 0, 1, true),
['instances' => get_string('blockinstances', 'admin')],
array_slice($columns, 1, 2, true),
['protect' => get_string('blockprotect', 'admin')],
array_slice($columns, 3, null, true),
);
}
protected function get_columns_with_help(): array {
return [
'protect' => new \help_icon('blockprotect', 'admin'),
];
}
/**
* Render the instances column
* @param stdClass $row
* @return string
*/
protected function col_instances(stdClass $row): string {
$blockdata = $this->blockdata[$row->plugininfo->name];
if (array_key_exists($blockdata->name, $this->courseblocks)) {
return html_writer::link(
new moodle_url('/course/search.php', [
'blocklist' => $blockdata->id,
]),
$blockdata->totalcount,
);
}
return $blockdata->totalcount;
}
/**
* Render the protect column.
*
* @param stdClass $row
* @return string
*/
protected function col_protect(stdClass $row): string {
global $OUTPUT;
$params = [
'sesskey' => sesskey(),
];
$protected = in_array($row->plugininfo->name, $this->undeletableblocktypes);
$pluginname = $row->plugininfo->displayname;
if ($protected) {
$params['unprotect'] = $row->plugininfo->name;
$icon = $OUTPUT->pix_icon('t/unlock', get_string('blockunprotectblock', 'admin', $pluginname));
} else {
$params['protect'] = $row->plugininfo->name;
$icon = $OUTPUT->pix_icon('t/lock', get_string('blockprotectblock', 'admin', $pluginname));
}
return html_writer::link(
$this->get_action_url($params),
$icon,
[
'data-action' => 'toggleprotectstate',
'data-plugin' => $row->plugin,
'data-target-state' => $protected ? 0 : 1,
],
);
return '';
}
}
@@ -1,63 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\table;
use moodle_url;
/**
* Tiny admin settings.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class editor_management_table extends \core_admin\table\plugin_management_table {
protected function get_plugintype(): string {
return 'editor';
}
public function guess_base_url(): void {
$this->define_baseurl(
new moodle_url('/admin/settings.php', ['section' => 'manageeditors'])
);
}
protected function get_action_url(array $params = []): moodle_url {
return new moodle_url('/admin/editors.php', $params);
}
protected function order_plugins(array $plugins): array {
global $CFG;
// The Editor list is stored in an ordered string.
$activeeditors = explode(',', $CFG->texteditors);
$sortedplugins = [];
foreach ($activeeditors as $editor) {
if (isset($plugins[$editor])) {
$sortedplugins[$editor] = $plugins[$editor];
unset($plugins[$editor]);
}
}
$otherplugins = parent::order_plugins($plugins);
return array_merge(
$sortedplugins,
$otherplugins
);
}
}
-285
View File
@@ -1,285 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\table;
use core_plugin_manager;
use flexible_table;
use html_writer;
use stdClass;
defined('MOODLE_INTERNAL') || die();
require_once("{$CFG->libdir}/tablelib.php");
/**
* Plugin Management table.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class hook_list_table extends flexible_table {
/** @var \core\plugininfo\base[] The plugin list */
protected array $plugins = [];
/** @var int The number of enabled plugins of this type */
protected int $enabledplugincount = 0;
/** @var core_plugin_manager */
protected core_plugin_manager $pluginmanager;
/** @var string The plugininfo class for this plugintype */
protected string $plugininfoclass;
/** @var stdClass[] The list of emitted hooks with metadata */
protected array $emitters;
public function __construct() {
global $CFG;
$this->define_baseurl('/admin/hooks.php');
parent::__construct('core_admin-hook_list_table');
// Add emitted hooks.
$this->emitters = \core\hook\manager::discover_known_hooks();
$this->setup_column_configuration();
$this->setup();
}
/**
* Set up the column configuration for this table.
*/
protected function setup_column_configuration(): void {
$columnlist = [
'details' => get_string('hookname', 'core_admin'),
'callbacks' => get_string('hookcallbacks', 'core_admin'),
'deprecates' => get_string('hookdeprecates', 'core_admin'),
];
$this->define_columns(array_keys($columnlist));
$this->define_headers(array_values($columnlist));
$columnswithhelp = [
'callbacks' => new \help_icon('hookcallbacks', 'admin'),
];
$columnhelp = array_map(function (string $column) use ($columnswithhelp): ?\renderable {
if (array_key_exists($column, $columnswithhelp)) {
return $columnswithhelp[$column];
}
return null;
}, array_keys($columnlist));
$this->define_help_for_headers($columnhelp);
}
/**
* Print the table.
*/
public function out(): void {
// All hook consumers referenced from the db/hooks.php files.
$hookmanager = \core\hook\manager::get_instance();
$allhooks = (array)$hookmanager->get_all_callbacks();
// Add any unused hooks.
foreach (array_keys($this->emitters) as $classname) {
if (isset($allhooks[$classname])) {
continue;
}
$allhooks[$classname] = [];
}
// Order rows by hook name, putting core first.
\core_collator::ksort($allhooks);
$corehooks = [];
foreach ($allhooks as $classname => $consumers) {
if (str_starts_with($classname, 'core\\')) {
$corehooks[$classname] = $consumers;
unset($allhooks[$classname]);
}
}
$allhooks = array_merge($corehooks, $allhooks);
foreach ($allhooks as $classname => $consumers) {
$this->add_data_keyed(
$this->format_row((object) [
'classname' => $classname,
'callbacks' => $consumers,
]),
$this->get_row_class($classname),
);
}
$this->finish_output(false);
}
protected function col_details(stdClass $row): string {
return $row->classname .
$this->get_description($row) .
html_writer::div($this->get_tags_for_row($row));
}
/**
* Show the name column content.
*
* @param stdClass $row
* @return string
*/
protected function get_description(stdClass $row): string {
if (!array_key_exists($row->classname, $this->emitters)) {
return '';
}
return html_writer::tag(
'small',
clean_text(markdown_to_html($this->emitters[$row->classname]['description']), FORMAT_HTML),
);
}
protected function col_deprecates(stdClass $row): string {
if (!class_exists($row->classname)) {
return '';
}
$rc = new \ReflectionClass($row->classname);
if (!$rc->implementsInterface(\core\hook\deprecated_callback_replacement::class)) {
return '';
}
$deprecates = call_user_func([$row->classname, 'get_deprecated_plugin_callbacks']);
if (count($deprecates) === 0) {
return '';
}
$content = html_writer::start_tag('ul');
foreach ($deprecates as $deprecatedmethod) {
$content .= html_writer::tag('li', $deprecatedmethod);
}
$content .= html_writer::end_tag('ul');
return $content;
}
protected function col_callbacks(stdClass $row): string {
global $CFG;
$hookclass = $row->classname;
$cbinfo = [];
foreach ($row->callbacks as $definition) {
$iscallable = is_callable($definition['callback'], false, $callbackname);
$isoverridden = isset($CFG->hooks_callback_overrides[$hookclass][$definition['callback']]);
$info = "{$callbackname}&nbsp;({$definition['priority']})";
if (!$iscallable) {
$info .= '&nbsp;';
$info .= $this->get_tag(
get_string('error'),
'danger',
get_string('hookcallbacknotcallable', 'core_admin', $callbackname),
);
}
if ($isoverridden) {
// The lang string meaning should be close enough here.
$info .= $this->get_tag(
get_string('hookconfigoverride', 'core_admin'),
'warning',
get_string('hookconfigoverride_help', 'core_admin'),
);
}
$cbinfo[] = $info;
}
if ($cbinfo) {
$output = html_writer::start_tag('ol');
foreach ($cbinfo as $callback) {
$class = '';
if ($definition['disabled']) {
$class = 'dimmed_text';
}
$output .= html_writer::tag('li', $callback, ['class' => $class]);
}
$output .= html_writer::end_tag('ol');
return $output;
} else {
return '';
}
}
/**
* Get the HTML to display the badge with tooltip.
*
* @param string $tag The main text to display
* @param null|string $type The pill type
* @param null|string $tooltip The content of the tooltip
* @return string
*/
protected function get_tag(
string $tag,
?string $type = null,
?string $tooltip = null,
): string {
$attributes = [];
if ($type === null) {
$type = 'info';
}
if ($tooltip) {
$attributes['data-toggle'] = 'tooltip';
$attributes['title'] = $tooltip;
}
return html_writer::span($tag, "badge badge-{$type}", $attributes);
}
/**
* Get the code to display a set of tags for this table row.
*
* @param stdClass $row
* @return string
*/
protected function get_tags_for_row(stdClass $row): string {
if (!array_key_exists($row->classname, $this->emitters)) {
// This hook has been defined in the db/hooks.php file
// but does not refer to a hook in this version of Moodle.
return $this->get_tag(
get_string('hookunknown', 'core_admin'),
'warning',
get_string('hookunknown_desc', 'core_admin'),
);
}
if (!class_exists($row->classname)) {
// This hook has been defined in a hook discovery agent, but the class it refers to could not be found.
return $this->get_tag(
get_string('hookclassmissing', 'core_admin'),
'warning',
get_string('hookclassmissing_desc', 'core_admin'),
);
}
$tags = $this->emitters[$row->classname]['tags'] ?? [];
$taglist = array_map(function($tag): string {
if (is_array($tag)) {
return $this->get_tag(...$tag);
}
return $this->get_tag($tag, 'badge badge-info');
}, $tags);
return implode("\n", $taglist);
}
protected function get_row_class(string $classname): string {
return '';
}
}
@@ -1,71 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\table;
use moodle_url;
use stdClass;
/**
* Media plugin admin settings.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class media_management_table extends \core_admin\table\plugin_management_table {
/** @var array The list of used extensions */
protected array $usedextensions = [];
protected function get_plugintype(): string {
return 'media';
}
protected function get_action_url(array $params = []): moodle_url {
return new moodle_url('/admin/media.php', $params);
}
protected function get_column_list(): array {
$columns = parent::get_column_list();
return array_merge(
array_slice($columns, 0, 1, true),
['supports' => get_string('supports', 'core_media')],
array_slice($columns, 1, null, true),
);
}
protected function col_name(stdClass $row): string {
global $OUTPUT, $PAGE;
$name = $row->plugininfo->name;
if ($PAGE->theme->resolve_image_location('icon', 'media_' . $name, false)) {
$icon = $OUTPUT->pix_icon('icon', '', "media_{$name}", ['class' => 'icon pluginicon']);
} else {
$icon = $OUTPUT->pix_icon('spacer', '', 'moodle', ['class' => 'icon pluginicon noicon']);
}
$help = '';
if (get_string_manager()->string_exists('pluginname_help', 'media_' . $name)) {
$help = '&nbsp;' . $OUTPUT->help_icon('pluginname', 'media_' . $name);
}
return $icon . $row->plugininfo->displayname . $help;
}
protected function col_supports(stdClass $row): string {
return $row->plugininfo->supports($this->usedextensions);
}
}
@@ -1,503 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\table;
use context_system;
use core_plugin_manager;
use core_table\dynamic as dynamic_table;
use flexible_table;
use html_writer;
use moodle_url;
use stdClass;
defined('MOODLE_INTERNAL') || die();
require_once("{$CFG->libdir}/tablelib.php");
/**
* Plugin Management table.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class plugin_management_table extends flexible_table implements dynamic_table {
/** @var \core\plugininfo\base[] The plugin list */
protected array $plugins = [];
/** @var int The number of enabled plugins of this type */
protected int $enabledplugincount = 0;
/** @var core_plugin_manager */
protected core_plugin_manager $pluginmanager;
/** @var string The plugininfo class for this plugintype */
protected string $plugininfoclass;
public function __construct() {
global $CFG;
parent::__construct($this->get_table_id());
require_once($CFG->libdir . '/adminlib.php');
// Fetch the plugininfo class.
$this->pluginmanager = core_plugin_manager::instance();
$this->plugininfoclass = $this->pluginmanager::resolve_plugininfo_class($this->get_plugintype());
$this->guess_base_url();
$this->plugins = $this->get_sorted_plugins();
$this->enabledplugincount = count(array_filter($this->plugins, function ($plugin) {
return $plugin->is_enabled();
}));
$this->setup_column_configuration();
$this->set_filterset(new plugin_management_table_filterset());
$this->setup();
}
/**
* Get the list of sorted plugins.
*
* @return \core\plugininfo\base[]
*/
protected function get_sorted_plugins(): array {
if ($this->plugininfoclass::plugintype_supports_ordering()) {
return $this->plugininfoclass::get_sorted_plugins();
} else {
$plugins = $this->pluginmanager->get_plugins_of_type($this->get_plugintype());
return self::sort_plugins($plugins);
}
}
/**
* Sort the plugins list.
*
* Note: This only applies to plugins which do not support ordering.
*
* @param \core\plugininfo\base[] $plugins
* @return \core\plugininfo\base[]
*/
protected function sort_plugins(array $plugins): array {
// The asort functions work by reference.
\core_collator::asort_objects_by_property($plugins, 'displayname');
return $plugins;
}
/**
* Set up the column configuration for this table.
*/
protected function setup_column_configuration(): void {
$columnlist = $this->get_column_list();
$this->define_columns(array_keys($columnlist));
$this->define_headers(array_values($columnlist));
$columnswithhelp = $this->get_columns_with_help();
$columnhelp = array_map(function (string $column) use ($columnswithhelp): ?\renderable {
if (array_key_exists($column, $columnswithhelp)) {
return $columnswithhelp[$column];
}
return null;
}, array_keys($columnlist));
$this->define_help_for_headers($columnhelp);
}
/**
* Set the standard order of the plugins.
*
* @param array $plugins
* @return array
*/
protected function order_plugins(array $plugins): array {
uasort($plugins, function ($a, $b) {
if ($a->is_enabled() && !$b->is_enabled()) {
return -1;
} else if (!$a->is_enabled() && $b->is_enabled()) {
return 1;
}
return strnatcasecmp($a->name, $b->name);
});
return $plugins;
}
/**
* Get the plugintype for this table.
*
* @return string
*/
abstract protected function get_plugintype(): string;
/**
* Get the action URL for this table.
*
* The action URL is used to perform all actions when JS is not available.
*
* @param array $params
* @return moodle_url
*/
abstract protected function get_action_url(array $params = []): moodle_url;
/**
* Provide a default implementation for guessing the base URL from the action URL.
*/
public function guess_base_url(): void {
$this->define_baseurl($this->get_action_url());
}
/**
* Get the web service method used to toggle state.
*
* @return null|string
*/
protected function get_toggle_service(): ?string {
return 'core_admin_set_plugin_state';
}
/**
* Get the web service method used to order plugins.
*
* @return null|string
*/
protected function get_sortorder_service(): ?string {
return 'core_admin_set_plugin_order';
}
/**
* Get the ID of the table.
*
* @return string
*/
protected function get_table_id(): string {
return 'plugin_management_table-' . $this->get_plugintype();
}
/**
* Get a list of the column titles
* @return string[]
*/
protected function get_column_list(): array {
$columns = [
'name' => get_string('name', 'core'),
'version' => get_string('version', 'core'),
];
if ($this->supports_disabling()) {
$columns['enabled'] = get_string('pluginenabled', 'core_plugin');
}
if ($this->supports_ordering()) {
$columns['order'] = get_string('order', 'core');
}
$columns['settings'] = get_string('settings', 'core');
$columns['uninstall'] = get_string('uninstallplugin', 'core_admin');
return $columns;
}
protected function get_columns_with_help(): array {
return [];
}
/**
* Get the context for this table.
*
* @return context_system
*/
public function get_context(): context_system {
return context_system::instance();
}
/**
* Get the table content.
*/
public function get_content(): string {
ob_start();
$this->out();
$content = ob_get_contents();
ob_end_clean();
return $content;
}
/**
* Print the table.
*/
public function out(): void {
$plugintype = $this->get_plugintype();
foreach ($this->plugins as $plugininfo) {
$plugin = "{$plugintype}_{$plugininfo->name}";
$rowdata = (object) [
'plugin' => $plugin,
'plugininfo' => $plugininfo,
'name' => $plugininfo->displayname,
'version' => $plugininfo->versiondb,
];
$this->add_data_keyed(
$this->format_row($rowdata),
$this->get_row_class($rowdata)
);
}
$this->finish_output(false);
}
/**
* This table is not downloadable.
* @param bool $downloadable
* @return bool
*/
// phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
public function is_downloadable($downloadable = null): bool {
return false;
}
/**
* Show the name column content.
*
* @param stdClass $row
* @return string
*/
protected function col_name(stdClass $row): string {
$status = $row->plugininfo->get_status();
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
return html_writer::span(
get_string('pluginmissingfromdisk', 'core', $row->plugininfo),
'notifyproblem'
);
}
if ($row->plugininfo->is_installed_and_upgraded()) {
return $row->plugininfo->displayname;
}
return html_writer::span(
$row->plugininfo->displayname,
'notifyproblem'
);
}
/**
* Show the enable/disable column content.
*
* @param stdClass $row
* @return string
*/
protected function col_enabled(stdClass $row): string {
global $OUTPUT;
$enabled = $row->plugininfo->is_enabled();
$params = [
'sesskey' => sesskey(),
'plugin' => $row->plugininfo->name,
'action' => $enabled ? 'disable' : 'enable',
];
if ($enabled) {
$icon = $OUTPUT->pix_icon('t/hide', get_string('disableplugin', 'core_admin', $row->plugininfo->displayname));
} else {
$icon = $OUTPUT->pix_icon('t/show', get_string('enableplugin', 'core_admin', $row->plugininfo->displayname));
}
return html_writer::link(
$this->get_action_url($params),
$icon,
[
'data-toggle-method' => $this->get_toggle_service(),
'data-action' => 'togglestate',
'data-plugin' => $row->plugin,
'data-state' => $enabled ? 1 : 0,
],
);
}
protected function col_order(stdClass $row): string {
global $OUTPUT;
if (!$this->supports_ordering()) {
return '';
}
if (!$row->plugininfo->is_enabled()) {
return '';
}
if ($this->enabledplugincount <= 1) {
// There is only one row.
return '';
}
$hasup = true;
$hasdown = true;
if (empty($this->currentrow)) {
// This is the top row.
$hasup = false;
}
if ($this->currentrow === ($this->enabledplugincount - 1)) {
// This is the last row.
$hasdown = false;
}
if ($this->supports_ordering()) {
$dataattributes = [
'data-method' => $this->get_sortorder_service(),
'data-action' => 'move',
'data-plugin' => $row->plugin,
];
} else {
$dataattributes = [];
}
if ($hasup) {
$upicon = html_writer::link(
$this->get_action_url([
'sesskey' => sesskey(),
'action' => 'up',
'plugin' => $row->plugininfo->name,
]),
$OUTPUT->pix_icon('t/up', get_string('moveup')),
array_merge($dataattributes, ['data-direction' => 'up']),
);
} else {
$upicon = $OUTPUT->spacer();
}
if ($hasdown) {
$downicon = html_writer::link(
$this->get_action_url([
'sesskey' => sesskey(),
'action' => 'down',
'plugin' => $row->plugininfo->name,
]),
$OUTPUT->pix_icon('t/down', get_string('movedown')),
array_merge($dataattributes, ['data-direction' => 'down']),
);
} else {
$downicon = $OUTPUT->spacer();
}
// For now just add the up/down icons.
return html_writer::span($upicon . $downicon);
}
/**
* Show the settings column content.
*
* @param stdClass $row
* @return string
*/
protected function col_settings(stdClass $row): string {
if ($settingsurl = $row->plugininfo->get_settings_url()) {
return html_writer::link($settingsurl, get_string('settings'));
}
return '';
}
/**
* Show the Uninstall column content.
*
* @param stdClass $row
* @return string
*/
protected function col_uninstall(stdClass $row): string {
$status = $row->plugininfo->get_status();
if ($status === core_plugin_manager::PLUGIN_STATUS_NEW) {
return get_string('status_new', 'core_plugin');
}
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
$uninstall = get_string('status_missing', 'core_plugin') . '<br/>';
} else {
$uninstall = '';
}
if ($uninstallurl = $this->pluginmanager->get_uninstall_url($row->plugin)) {
$uninstall .= html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'));
}
return $uninstall;
}
/**
* Get the JS module used to manage this table.
*
* This should be a class which extends 'core_admin/plugin_management_table'.
*
* @return string
*/
protected function get_table_js_module(): string {
return 'core_admin/plugin_management_table';
}
/**
* Add JS specific to this implementation.
*
* @return string
*/
protected function get_dynamic_table_html_end(): string {
global $PAGE;
$PAGE->requires->js_call_amd($this->get_table_js_module(), 'init');
return parent::get_dynamic_table_html_end();
}
/**
* Get any class to add to the row.
*
* @param mixed $row
* @return string
*/
protected function get_row_class($row): string {
$plugininfo = $row->plugininfo;
if ($plugininfo->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
return '';
}
if (!$plugininfo->is_enabled()) {
return 'dimmed_text';
}
return '';
}
public static function get_filterset_class(): string {
return self::class . '_filterset';
}
/**
* Whether this plugin type supports the disabling of plugins.
*
* @return bool
*/
protected function supports_disabling(): bool {
return $this->plugininfoclass::plugintype_supports_disabling();
}
/**
* Whether this table should show ordering fields.
*
* @return bool
*/
protected function supports_ordering(): bool {
return $this->plugininfoclass::plugintype_supports_ordering();
}
}
@@ -1,27 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\table;
/**
* This file contains the dynamic interface.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class plugin_management_table_filterset extends \core_table\local\filter\filterset {
}
@@ -1,44 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_admin\table;
use moodle_url;
/**
* Admin tool settings.
*
* @package core_admin
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tool_plugin_management_table extends \core_admin\table\plugin_management_table {
protected function get_plugintype(): string {
return 'tool';
}
protected function get_column_list(): array {
$columns = parent::get_column_list();
unset($columns['settings']);
return $columns;
}
protected function get_action_url(array $params = []): moodle_url {
return new moodle_url('/admin/settings.php', array_merge(['section' => 'toolsmanagement'], $params));
}
}
-174
View File
@@ -1,174 +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");
list($options, $unrecognized) = cli_get_params(
[
'help' => false,
'showsql' => false,
'showdebugging' => false,
'execute' => false,
'keep-alive' => 0,
'ignorelimits' => false,
'force' => false,
'id' => null,
'classname' => null,
'taskslimit' => null,
'failed' => false,
], [
'h' => 'help',
'e' => 'execute',
'k' => 'keep-alive',
'i' => 'ignorelimits',
'f' => 'force',
'c' => 'classname',
'l' => 'taskslimit',
]
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
$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
-f, --force Run even if cron is disabled
--id Run (failed) task with id
-c, --classname Run tasks with a certain classname (FQN)
-l, --taskslimit=N Run at most N tasks
--failed Run only tasks that failed, ie those with a fail delay
Run all queued tasks:
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
Run all queued tasks of specific class:
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --classname=\\\\core_course\\\\task\\\\course_delete_modules
Double backslash for the shell escape reasons.
Run a specific task:
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --id=123456
Run a specific task with debugging:
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --id=123456 --showsql --showdebugging
To profile a long running task:
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --taskslimit=1 --classname='\\some\\class\\name' --ignorelimits
EOT;
if ($options['help']) {
echo $help;
exit(0);
}
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 (!get_config('core', 'cron_enabled') && !$options['force']) {
mtrace('Cron is disabled. Use --force to override.');
exit(1);
}
// Common debugging options.
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql']) {
$DB->set_debug(true);
}
if (!empty($CFG->showcronsql)) {
$DB->set_debug(true);
}
if (!empty($CFG->showcrondebugging)) {
set_debugging(DEBUG_DEVELOPER, true);
}
// Process params.
core_php_time_limit::raise();
// Increase memory limit.
raise_memory_limit(MEMORY_EXTRA);
// Emulate normal session - we use admin account by default.
\core\cron::setup_user();
\core\local\cli\shutdown::script_supports_graceful_exit();
$humantimenow = date('r', time());
mtrace("Server Time: {$humantimenow}\n");
$classname = $options['classname'];
// Run a single adhoc task only, if requested.
if (!empty($options['id'])) {
$taskid = (int) $options['id'];
\core\cron::run_adhoc_task($taskid);
exit(0);
}
// Run all failed tasks.
if (!empty($options['failed'])) {
\core\cron::run_failed_adhoc_tasks($classname);
exit(0);
}
// Examine params and determine if we should run.
$execute = (bool) $options['execute'];
$keepalive = empty($options['keep-alive']) ? 0 : (int) $options['keep-alive'];
$taskslimit = empty($options['taskslimit']) ? null : (int) $options['taskslimit'];
$checklimits = empty($options['ignorelimits']);
if ($classname || $keepalive || $taskslimit) {
$execute = true;
}
// Output the help text if no criteria for running the adhoc tasks are given.
if (!$execute) {
echo $help;
exit(0);
}
\core\cron::run_adhoc_tasks(time(), $keepalive, $checklimits, null, $taskslimit, $classname);
+6 -5
View File
@@ -28,8 +28,9 @@
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require(dirname(dirname(dirname(__FILE__))).'/config.php');
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),
@@ -79,10 +80,10 @@ if (!empty($CFG->showcrondebugging)) {
$starttime = microtime();
// Emulate normal session.
\core\cron::setup_user();
/// emulate normal session
cron_setup_user();
// Start output log.
/// Start output log
$timenow = time();
mtrace("Server Time: ".date('r',$timenow)."\n\n");
@@ -95,4 +96,4 @@ backup_cron_automated_helper::run_automated_backup(backup_cron_automated_helper:
mtrace("Automated cron backups completed correctly");
$difftime = microtime_diff($starttime, microtime());
mtrace("Execution took ".$difftime." seconds");
mtrace("Execution took ".$difftime." seconds");
+1 -1
View File
@@ -25,7 +25,7 @@
define('CLI_SCRIPT', 1);
require(__DIR__.'/../../config.php');
require(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once($CFG->libdir.'/clilib.php');
require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
-119
View File
@@ -1,119 +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/>.
/**
* Build and store theme CSS.
*
* @package core
* @subpackage cli
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @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/csslib.php");
require_once("$CFG->libdir/outputlib.php");
$longparams = [
'themes' => null,
'direction' => null,
'help' => false,
'verbose' => false
];
$shortmappings = [
't' => 'themes',
'd' => 'direction',
'h' => 'help',
'v' => 'verbose'
];
// Get CLI params.
list($options, $unrecognized) = cli_get_params($longparams, $shortmappings);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
echo
"Compile the CSS for one or more installed themes.
Existing CSS caches will replaced.
By default all themes will be recompiled unless otherwise specified.
Options:
-t, --themes A comma separated list of themes to be compiled
-d, --direction Only compile a single direction (either ltr or rtl)
-v, --verbose Print info comments to stdout
-h, --help Print out this help
Example:
\$ sudo -u www-data /usr/bin/php admin/cli/build_theme_css.php --themes=boost --direction=ltr
";
die;
}
if (empty($options['verbose'])) {
$trace = new null_progress_trace();
} else {
$trace = new text_progress_trace();
}
cli_heading('Build theme css');
// Determine which themes we need to build.
$themenames = [];
if (is_null($options['themes'])) {
$trace->output('No themes specified. Finding all installed themes.');
$themenames = array_keys(core_component::get_plugin_list('theme'));
} else {
if (is_string($options['themes'])) {
$themenames = explode(',', $options['themes']);
} else {
cli_error('--themes must be a comma separated list of theme names');
}
}
$trace->output('Checking that each theme is correctly installed...');
$themeconfigs = [];
foreach ($themenames as $themename) {
if (is_null(theme_get_config_file_path($themename))) {
cli_error("Unable to find theme config for {$themename}");
}
// Load the config for the theme.
$themeconfigs[] = theme_config::load($themename);
}
$directions = ['ltr', 'rtl'];
if (!is_null($options['direction'])) {
if (!in_array($options['direction'], $directions)) {
cli_error("--direction must be either ltr or rtl");
}
$directions = [$options['direction']];
}
$trace->output('Building CSS for themes: ' . implode(', ', $themenames));
theme_build_css_for_themes($themeconfigs, $directions);
exit(0);
-185
View File
@@ -1,185 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI script allowing to get and set config values.
*
* This is technically just a thin wrapper for {@link get_config()} and
* {@link set_config()} functions.
*
* @package core
* @subpackage cli
* @copyright 2017 David Mudrák <david@moodle.com>
* @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');
$usage = "Displays the current value of the given site setting. Allows to set it to the given value, too.
Usage:
# php cfg.php [--component=<componentname>] [--json] [--shell-arg]
# php cfg.php --name=<configname> [--component=<componentname>] [--shell-arg] [--no-eol]
# php cfg.php --name=<configname> [--component=<componentname>] --set=<value>
# php cfg.php --name=<configname> [--component=<componentname>] --unset
# php cfg.php [--help|-h]
Options:
-h --help Print this help.
--component=<frankenstyle> Name of the component the variable is part of. Defaults to core.
--name=<configname> Name of the configuration variable to get/set. If missing, print all
configuration variables of the given component.
--set=<value> Set the given variable to this value.
--unset Unset the given variable.
--shell-arg Escape output values so that they can be directly used as shell script arguments.
--json Encode output list of values using JSON notation.
--no-eol Do not include the trailing new line character when printing the value.
The list of all variables of the given component can be printed as
tab-separated list (default) or JSON object (--json). Particular values are
printed as raw text values, optionally escaped so that they can be directly
used as shell script arguments (--shell-arg). Single values are displayed with
trailing new line by default, unless explicitly disabled (--no-eol).
In the read mode, the script exits with success status 0 if the requested value
is found. If the requested variable is not set, the script exits with status 3.
When listing all variables of the component, the exit status is always 0 even
if no variables for the given component are found. When setting/unsetting a
value, the exit status is 0. When attempting to set/unset a value that has
already been hard-set in config.php, the script exits with error status 4. In
case of unexpected error, the script exits with error status 1.
Examples:
# php cfg.php
Prints tab-separated list of all core configuration variables and their values.
# php cfg.php --json
Prints list of all core configuration variables and their values as a JSON object.
# php cfg.php --name=release
Prints the given configuration variable - e.g. \$CFG->release in this case.
# php cfg.php --component=tool_recyclebin
# Prints tab-separated list of the plugin's configuration variables.
# export DATAROOT=\$(php cfg.php --name=dataroot --shell-arg --no-eol)
Stores the given configuration variable in the shell variable, escaped
so that it can be safely used as a shell argument.
# php cfg.php --name=theme --set=classic
Sets the given configuration variable to the given value.
# php cfg.php --name=noemailever --unset
Unsets the previously configured variable.
";
list($options, $unrecognised) = cli_get_params([
'help' => false,
'component' => null,
'name' => null,
'set' => null,
'unset' => false,
'shell-arg' => false,
'json' => false,
'no-eol' => false,
], [
'h' => 'help'
]);
if ($unrecognised) {
$unrecognised = implode(PHP_EOL.' ', $unrecognised);
cli_error(get_string('cliunknowoption', 'core_admin', $unrecognised));
}
if ($options['help']) {
cli_writeln($usage);
exit(2);
}
if ($options['unset'] || $options['set'] !== null) {
// Unset the variable or set it to the given value.
if (empty($options['name'])) {
cli_error('Missing configuration variable name', 2);
}
// Check that the variable is not hard-set in the main config.php already.
$component = $options['component'];
if (!empty($component)) {
$componentsettings = $CFG->forced_plugin_settings[$component] ?? [];
$settinginconfig = array_key_exists($options['name'], $componentsettings);
} else {
$settinginconfig = array_key_exists($options['name'], $CFG->config_php_settings);
}
if ($settinginconfig) {
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']);
}
exit(0);
}
if ($options['name'] === null) {
// List all variables provided by the component (defaults to core).
$got = get_config($options['component']);
if ($options['json']) {
cli_writeln(json_encode($got));
} else {
foreach ($got as $name => $value) {
if ($options['shell-arg']) {
$value = escapeshellarg($value);
}
cli_writeln($name."\t".$value);
}
}
exit(0);
} else {
// Display the value of a single variable.
$got = get_config($options['component'], $options['name']);
if ($got === false) {
cli_error('No such configuration variable found.', 3);
}
if ($options['shell-arg']) {
$got = escapeshellarg($got);
}
if ($options['json']) {
$got = json_encode($got);
}
if ($options['no-eol']) {
cli_write($got);
} else {
cli_writeln($got);
}
exit(0);
}
-76
View File
@@ -1,76 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Validate that the current db structure matches the install.xml files.
*
* @package core
* @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Petr Skoda <petr.skoda@totaralms.com>
*/
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir.'/clilib.php');
$help = "Validate database structure
Options:
-h, --help Print out this help.
Example:
\$ sudo -u www-data /usr/bin/php admin/cli/check_database_schema.php
";
list($options, $unrecognized) = cli_get_params(
array(
'help' => false,
),
array(
'h' => 'help',
)
);
if ($options['help']) {
echo $help;
exit(0);
}
if (empty($CFG->version)) {
echo "Database is not yet installed.\n";
exit(2);
}
$dbmanager = $DB->get_manager();
$schema = $dbmanager->get_install_xml_schema();
if (!$errors = $dbmanager->check_database_schema($schema)) {
echo "Database structure is ok.\n";
exit(0);
}
foreach ($errors as $table => $items) {
cli_separator();
echo "$table\n";
foreach ($items as $item) {
echo " * $item\n";
}
}
cli_separator();
exit(1);
-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);
+10 -135
View File
@@ -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
@@ -29,32 +30,13 @@
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/clilib.php');
require(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once($CFG->libdir.'/clilib.php'); // cli only functions
require_once($CFG->libdir.'/cronlib.php');
// Now get cli option.
[$options, $unrecognized] = cli_get_params(
[
'help' => false,
'stop' => false,
'list' => false,
'force' => false,
'enable' => false,
'disable' => false,
'disable-wait' => false,
'keep-alive' => null,
],
[
'h' => 'help',
's' => 'stop',
'l' => 'list',
'f' => 'force',
'e' => 'enable',
'd' => 'disable',
'w' => 'disable-wait',
'k' => 'keep-alive',
]
);
// now get cli options
list($options, $unrecognized) = cli_get_params(array('help'=>false),
array('h'=>'help'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
@@ -63,19 +45,10 @@ if ($unrecognized) {
if ($options['help']) {
$help =
"Execute periodic cron actions.
"Execute periodic cron actions.
Options:
-h, --help Print out this help
-s, --stop Notify all other running cron processes to stop after the current task
-l, --list Show the list of currently running tasks and how long they have been running
-f, --force Execute task even if cron is disabled
-e, --enable Enable cron
-d, --disable Disable cron
-w, --disable-wait=600 Disable cron and wait until all tasks finished or fail after N seconds (optional param)
-k, --keep-alive=N Keep this script alive for N seconds and poll for new tasks
The default value can be set by administrators in:
Site administration > Server > Tasks > Task processing > Keep alive time
-h, --help Print out this help
Example:
\$sudo -u www-data /usr/bin/php admin/cli/cron.php
@@ -85,102 +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;
}
if ($options['enable']) {
set_config('cron_enabled', 1);
mtrace('Cron has been enabled for the site.');
exit(0);
}
if ($options['disable']) {
set_config('cron_enabled', 0);
\core\task\manager::clear_static_caches();
mtrace('Cron has been disabled for the site.');
exit(0);
}
if ($options['list']) {
$tasks = \core\task\manager::get_running_tasks();
mtrace('The list of currently running tasks:');
$format = "%7s %-12s %-9s %-20s %-52s\n";
printf(
$format,
'PID',
'HOST',
'TYPE',
'TIME',
'CLASSNAME'
);
foreach ($tasks as $task) {
printf(
$format,
$task->pid,
substr($task->hostname, 0, 12),
$task->type,
format_time(time() - $task->timestarted),
substr($task->classname, 0, 52)
);
}
exit(0);
}
if ($wait = $options['disable-wait']) {
$started = time();
if (true === $wait) {
// Default waiting time.
$waitsec = 600;
} else {
$waitsec = $wait;
$wait = true;
}
set_config('cron_enabled', 0);
\core\task\manager::clear_static_caches();
mtrace('Cron has been disabled for the site.');
mtrace('Allocating ' . format_time($waitsec) . ' for the tasks to finish.');
$lastcount = 0;
while ($wait) {
$tasks = \core\task\manager::get_running_tasks();
if (count($tasks) == 0) {
mtrace('');
mtrace('All scheduled and adhoc tasks finished.');
exit(0);
}
if (time() - $started >= $waitsec) {
mtrace('');
mtrace('Wait time (' . format_time($waitsec) . ') elapsed, but ' . count($tasks) . ' task(s) still running.');
mtrace('Exiting with code 1.');
exit(1);
}
if (count($tasks) !== $lastcount) {
mtrace('');
mtrace(count($tasks) . " tasks currently running.", '');
$lastcount = count($tasks);
} else {
mtrace('.', '');
}
sleep(1);
}
}
if (!get_config('core', 'cron_enabled') && !$options['force']) {
mtrace('Cron is disabled. Use --force to override.');
exit(1);
}
\core\local\cli\shutdown::script_supports_graceful_exit();
$keepalive = $options['keep-alive'];
\core\cron::run_main_process($keepalive);
cron_run();
-65
View File
@@ -1,65 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI script to reset dashboards.
*
* @package core
* @subpackage cli
* @copyright 2021 Brendan Heywood (brendan@catalyst-au.net)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require_once($CFG->libdir.'/clilib.php');
require_once($CFG->dirroot.'/my/lib.php');
list($options, $unrecognized) = cli_get_params([
'help' => false,
'execute' => false,
], [
'h' => 'help',
'e' => 'execute',
]);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2);
}
if (!$options['execute']) {
$help = <<<EOF
Resets Moodle dashboards for all users
Options:
-h, --help Print out this help
-e, --execute Actually run the reset
Example:
\$ sudo -u www-data /usr/bin/php admin/cli/dashboard_reset.php -e
EOF;
echo $help;
exit(0);
}
$progressbar = new progress_bar();
$progressbar->create();
my_reset_page_for_all_users(MY_PAGE_PRIVATE, 'my-index', $progressbar);
-123
View File
@@ -1,123 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI script to delete a course.
*
* @package core
* @subpackage cli
* @author Mikhail Golenkov <mikhailgolenkov@catalyst-au.net>
* @copyright 2022 Catalyst IT
* @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');
list($options, $unrecognized) = cli_get_params(
[
'courseid' => false,
'help' => false,
'showsql' => false,
'showdebugging' => false,
'disablerecyclebin' => false,
'non-interactive' => false,
], [
'c' => 'courseid',
'h' => 'help',
]
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help'] || empty($options['courseid'])) {
$help = <<<EOT
CLI script to delete a course.
Options:
-h, --help Print out this help
--showsql Show sql queries before they are executed
--showdebugging Show developer level debugging information
--disablerecyclebin Skip backing up the course
--non-interactive No interactive questions or confirmations
-c, --courseid Course id to be deleted
Example:
\$sudo -u www-data /usr/bin/php admin/cli/delete_course.php --courseid=123456
\$sudo -u www-data /usr/bin/php admin/cli/delete_course.php --courseid=123456 --showdebugging
\$sudo -u www-data /usr/bin/php admin/cli/delete_course.php --courseid=123456 --disablerecyclebin
EOT;
echo $help;
die;
}
$interactive = empty($options['non-interactive']);
if ($options['showdebugging']) {
mtrace('Enabling debugging...');
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql']) {
mtrace('Enabling SQL debugging...');
$DB->set_debug(true);
}
if (CLI_MAINTENANCE) {
cli_error('CLI maintenance mode active, CLI execution suspended');
}
if (moodle_needs_upgrading()) {
cli_error('Moodle upgrade pending, CLI execution suspended');
}
$course = $DB->get_record('course', array('id' => $options['courseid']));
if (empty($course)) {
cli_error('Course not found');
}
mtrace('Deleting course id ' . $course->id);
mtrace('Course name: ' . $course->fullname);
mtrace('Short name: ' . $course->shortname);
if ($interactive) {
mtrace('');
$input = cli_input('Are you sure you wish to delete this course? (y/N)', 'N', ['y', 'Y', 'n', 'N']);
if (strtolower($input) != 'y') {
exit(0);
}
}
if ($options['disablerecyclebin']) {
mtrace('Disabling recycle bin...');
$overrideconfig = ['tool_recyclebin' => ['coursebinenable' => false, 'categorybinenable' => false]];
$CFG->forced_plugin_settings = array_merge($CFG->forced_plugin_settings, $overrideconfig);
}
core_php_time_limit::raise();
delete_course($course);
mtrace('Updating course count in categories...');
fix_course_sortorder();
mtrace('Done!');
-209
View File
@@ -1,209 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This script allows you to view and change the emailstop flag of any user.
*
* @package core
* @subpackage cli
* @copyright 2023 Stephan Robotta (stephan.robotta@bfh.ch)
* @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');
// Define the input options.
$longparams = [
'email' => '',
'help' => false,
'id' => '',
'quiet' => false,
'stop' => '',
'username' => '',
];
$shortparams = [
'e' => 'email',
'h' => 'help',
'i' => 'id',
'q' => 'quiet',
's' => 'stop',
'u' => 'username',
];
// Define exit codes.
$exitsuccess = 0;
$exitunknownoption = 1;
$exitmissinguserarg = 2;
$exittoomanyuserarg = 3;
$exitnosearchargs = 4;
$exitnousersfound = 5;
$exitinvalidstopflag = 6;
$exiterrordb = 7;
// Now get cli options that are set by the caller.
list($options, $unrecognized) = cli_get_params($longparams, $shortparams);
$verbose = empty($options['quiet']);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
if ($verbose) {
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), $exitunknownoption);
}
exit($exitunknownoption);
}
if ($options['help']) {
$help =
"Set/unset or show status of emailstop flag for a user, identified by username or email.
There are no security checks here because anybody who is able to
execute this file may execute any PHP too.
Options:
-h, --help Print out this help
-e, --email=email Specify user by email, separate many users by comma
-i, --id=id Specify user by id, separate many users by comma
-q, --quiet No output to stdout
-s, --stop=0|1|off|on Set new value for emailstop flag
-u, --username=username Specify user by username, separate many users by comma
Example:
\$sudo -u www-data /usr/bin/php admin/cli/emailstop.php --email=student1@example.com --stop=1
\$sudo -u www-data /usr/bin/php admin/cli/emailstop.php --email=student1@example.com,student2@example.com
\$sudo -u www-data /usr/bin/php admin/cli/emailstop.php --u=student1,student2 -s=on
";
echo $help;
exit($exitsuccess);
}
$cntempty = 0;
$cntfilled = 0;
$searchargs = [];
// Try to find out which option is used to fetch the users from. Also do sanitize etc.
foreach (['email', 'username', 'id'] as $option) {
if (empty($options[$option])) {
$cntempty++;
} else {
$cntfilled++;
$argname = $option;
// The search args must be: split by the comma, trimmed, and empty elements filtered out.
$searchargs = array_flip(array_filter(
array_map(
function ($item) {
return trim($item);
},
explode(',', $options[$option])
),
function ($item) {
return $item !== '';
}
));
}
}
if ($cntempty === 3) {
if ($verbose) {
cli_error('One of username, email, or id must be set.', $exitmissinguserarg);
}
exit($exitmissinguserarg);
}
if ($cntfilled > 1) {
if ($verbose) {
cli_error('Only one of email, username, or id can be set to identify a user.', $exittoomanyuserarg);
}
exit($exittoomanyuserarg);
}
if (empty($searchargs)) {
if ($verbose) {
cli_error('No values are provided for users.', $exitnosearchargs);
}
exit($exitnosearchargs);
}
try {
$users = $DB->get_records_list('user', $argname, array_keys($searchargs));
} catch (Exception $e) {
if ($verbose) {
cli_error("Could not fetch data from db by {$argname}: '{$options[$argname]}'.", $exiterrordb);
}
exit($exiterrordb);
}
if (empty($users)) {
if ($verbose) {
cli_error("Can not find any user by {$argname}: '{$options[$argname]}'.", $exitnousersfound);
}
exit($exitnousersfound);
}
// No stop flag set, then just print the user and the current emailstop flag state.
if ($options['stop'] === '') {
foreach ($users as $user) {
if ($verbose) {
echo 'user=' . $user->{$argname} . ' - emailstop=' . (int)$user->emailstop . PHP_EOL;
unset($searchargs[$user->{$argname}]);
}
}
if ($verbose) {
foreach (array_keys($searchargs) as $arg) {
echo 'user=' . $arg . ' - not found' . PHP_EOL;
}
}
exit($exitsuccess);
}
// Allowed values for the stop flag enabled are 1 and on, for disabled are 0 and off.
$validvalues = ['0', '1', 'off', 'on'];
$stopflag = strtolower($options['stop']);
if (!in_array($stopflag, $validvalues)) {
if ($verbose) {
cli_error('Value for the emailstop flag must be one of: ' . implode(', ', $validvalues) . '.', $exitinvalidstopflag);
}
exit($exitinvalidstopflag);
}
foreach ($validvalues as $value) {
if ($value === $stopflag) {
$stopflag = ($value === '1' || $value === 'on') ? 1 : 0;
break;
}
}
// Update each user with the stop flag to be set if it is necessary.
foreach ($users as $user) {
$line = 'Update user ' . $user->{$argname} . ($argname !== 'id' ? ' (' . $user->id . ')' : '') . ' - ';
if ((int)$user->emailstop !== $stopflag) {
$DB->set_field('user', 'emailstop', $stopflag, ['id' => $user->id]);
$line .= 'ok';
} else {
$line .= 'already done';
}
if ($verbose) {
echo $line . PHP_EOL;
unset($searchargs[$user->{$argname}]);
}
}
if ($verbose) {
foreach (array_keys($searchargs) as $arg) {
echo 'user=' . $arg . ' - not found' . PHP_EOL;
}
}
exit($exitsuccess);
-1
View File
@@ -73,7 +73,6 @@ foreach ($rs as $user) {
echo "Redeleting user $user->id: $user->username ($user->email)\n";
delete_user($user);
}
$rs->close();
cli_heading('Deleting all leftovers');
-138
View File
@@ -1,138 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Fix orphaned calendar events that were broken by MDL-67494.
*
* This script will look for all the calendar events which userids
* where broken by a wrong upgrade step, affecting to Moodle 3.9.5
* and up.
*
* It performs checks to both:
* a) Detect if the site was affected (ran the wrong upgrade step).
* b) Look for orphaned calendar events, categorising them as:
* - standard: site / category / course / group / user events
* - subscription: events created via subscriptions.
* - action: normal action events, created to show common important dates.
* - override: user and group override events, particular, that some activities support.
* - custom: other events, not being any of the above, common or particular.
* By specifying it (--fix) try to recover as many broken events (missing userid) as
* possible. Standard, subscription, action, override events in core are fully supported but
* override or custom events should be fixed by each plugin as far as there isn't any standard
* API (plugin-wise) to launch a rebuild of the calendar events.
*
* @package core
* @copyright 2021 onwards Simey Lameze <simey@moodle.com>
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require_once(__DIR__ . '/../../config.php');
require_once($CFG->libdir . "/clilib.php");
require_once($CFG->libdir . '/db/upgradelib.php');
// Supported options.
$long = ['fix' => false, 'help' => false];
$short = ['f' => 'fix', 'h' => 'help'];
// CLI options.
[$options, $unrecognized] = cli_get_params($long, $short);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
$help = <<<EOT
Fix orphaned calendar events.
This script detects calendar events that have had their
userid lost. By default it will perform various checks
and report them, showing the site status in an easy way.
Also, optionally (--fix), it wil try to recover as many
lost userids as possible from different sources. Note that
this script aims to process well-know events in core,
leaving custom events in 3rd part plugins mostly unmodified
because there isn't any consistent way to regenerate them.
For more details: https://tracker.moodle.org/browse/MDL-71156
Options:
-h, --help Print out this help.
-f, --fix Fix the orphaned calendar events in the DB.
If not specified only check and report problems to STDERR.
Usage:
- Only report: \$ sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_calendar_events.php
- Report and fix: \$ sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_calendar_events.php -f
EOT;
cli_writeln($help);
die;
}
// Check various usual pre-requisites.
if (empty($CFG->version)) {
cli_error('Database is not yet installed.');
}
$admin = get_admin();
if (!$admin) {
cli_error('Error: No admin account was found.');
}
if (moodle_needs_upgrading()) {
cli_error('Moodle upgrade pending, script execution suspended.');
}
// Do everything as admin by default.
\core\session\manager::set_user($admin);
// Report current site status.
cli_heading('Checking the site status');
$needsfix = upgrade_calendar_site_status();
// Report current calendar events status.
cli_heading('Checking the calendar events status');
$info = upgrade_calendar_events_status();
$hasbadevents = $info['total']->bad > 0 || $info['total']->bad != $info['other']->bad;
$needsfix = $needsfix || $hasbadevents;
// If, selected, fix as many calendar events as possible.
if ($options['fix']) {
// If the report has told us that the fix was not needed... ask for confirmation!
if (!$needsfix) {
cli_writeln("This site DOES NOT NEED to run the calendar events fix.");
$input = cli_input('Are you completely sure that you want to run the fix? (y/N)', 'N', ['y', 'Y', 'n', 'N']);
if (strtolower($input) != 'y') {
exit(0);
}
cli_writeln("");
}
cli_heading('Fixing as many as possible calendar events');
upgrade_calendar_events_fix_remaining($info);
// Report current (after fix) calendar events status.
cli_heading('Checking the calendar events status (after fix)');
upgrade_calendar_events_status();
} else if ($needsfix) {
// Fix option was not provided but problem events have been found. Notify the user and provide info how to fix these events.
cli_writeln("This site NEEDS to run the calendar events fix!");
cli_writeln("To fix the calendar events, re-run this script with the --fix option.");
}
@@ -1,103 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This script fixes orphaned question categories.
*
* Orphaned question categories have had their associated context deleted
* but the category itself remains in the database with an invalid context.
*
* @package core
* @subpackage cli
* @copyright 2013 Tyler Bannister (tyler.bannister@remote-learner.net)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require_once($CFG->libdir.'/clilib.php');
require_once($CFG->libdir.'/questionlib.php');
$long = array('fix' => false, 'help' => false);
$short = array('f' => 'fix', 'h' => 'help');
// Now get cli options.
list($options, $unrecognized) = cli_get_params($long, $short);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
$help =
"Fix orphaned question categories.
This scripts detects question categories that have had their
context deleted, thus severing them from their original purpose.
This script will find the orphaned categories and delete the unused
questions in each category found. Used questions will not be
deleted, instead they will be moved to a rescue question category.
Options:
-h, --help Print out this help
-f, --fix Fix the orphaned question categories in the DB.
If not specified only check and report problems to STDERR.
Example:
\$sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_question_categories.php
\$sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_question_categories.php -f
";
echo $help;
die;
}
cli_heading('Checking for orphaned categories');
$sql = 'SELECT qc.id, qc.contextid, qc.name
FROM {question_categories} qc
LEFT JOIN {context} c ON qc.contextid = c.id
WHERE c.id IS NULL';
$categories = $DB->get_recordset_sql($sql);
$i = 0;
foreach ($categories as $category) {
$i += 1;
echo "Found orphaned category: {$category->name}\n";
if (!empty($options['fix'])) {
echo "Cleaning...";
// One transaction per category.
$transaction = $DB->start_delegated_transaction();
question_category_delete_safe($category);
$transaction->allow_commit();
echo " Done!\n";
}
}
if (($i > 0) && !empty($options['fix'])) {
echo "Found and removed {$i} orphaned question categories\n";
} else if ($i > 0) {
echo "Found {$i} orphaned question categories. To fix, run:\n";
echo "\$sudo -u www-data /usr/bin/php admin/cli/fix_orphaned_question_categories.php --fix\n";
} else {
echo "No orphaned question categories found.\n";
}
$categories->close();
-75
View File
@@ -1,75 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Generates a secure key for the current server (presuming it does not already exist).
*
* @package core_admin
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use \core\encryption;
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/clilib.php');
// Get cli options.
[$options, $unrecognized] = cli_get_params(
['help' => false, 'method' => null],
['h' => 'help']);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
echo "Generate secure key
This script manually creates a secure key within the secret data root folder (configured in
config.php as \$CFG->secretdataroot). You must run it using an account with access to write
to that folder.
In normal use Moodle automatically creates the key; this script is intended when setting up
a new Moodle system, for cases where the secure folder is not on shared storage and the key
may be manually installed on multiple servers.
Options:
-h, --help Print out this help
--method <method> Generate key for specified encryption method instead of default (sodium)
Example:
php admin/cli/generate_key.php
";
exit;
}
$method = $options['method'];
if (encryption::key_exists($method)) {
echo 'Key already exists: ' . encryption::get_key_file($method) . "\n";
exit;
}
// Creates key with default permissions (no chmod).
echo "Generating key...\n";
encryption::create_key($method, false);
echo "\nKey created: " . encryption::get_key_file($method) . "\n\n";
echo "If the key folder is not shared storage, then key files should be copied to all servers.\n";
+196 -298
View File
@@ -69,21 +69,15 @@ Options:
--prefix=STRING Table prefix for above database tables. Default is mdl_
--fullname=STRING The fullname of the site
--shortname=STRING The shortname of the site
--summary=STRING The summary to be displayed on the front page
--adminuser=USERNAME Username for the moodle admin account. Default is admin
--adminpass=PASSWORD Password for the moodle admin account,
required in non-interactive mode.
--adminemail=STRING Email address for the moodle admin account.
--sitepreset=STRING Admin site preset to be applied during the installation process.
--supportemail=STRING Email address for support and help.
--upgradekey=STRING The upgrade key to be set in the config.php, leave empty to not set it.
--non-interactive No interactive questions, installation fails if any
problem encountered.
--agree-license Indicates agreement with software license,
required in non-interactive mode.
--allow-unstable Install even if the version is not marked as stable yet,
required in non-interactive mode.
--skip-database Stop the installation before installing the database.
-h, --help Print out this help
Example:
@@ -92,7 +86,7 @@ Example:
// distro specific customisation
$distrolibfile = __DIR__.'/../../install/distrolib.php';
$distrolibfile = dirname(dirname(dirname(__FILE__))).'/install/distrolib.php';
$distro = null;
if (file_exists($distrolibfile)) {
require_once($distrolibfile);
@@ -102,7 +96,7 @@ if (file_exists($distrolibfile)) {
}
// Nothing to do if config.php exists
$configfile = __DIR__.'/../../config.php';
$configfile = dirname(dirname(dirname(__FILE__))).'/config.php';
if (file_exists($configfile)) {
require($configfile);
require_once($CFG->libdir.'/clilib.php');
@@ -126,11 +120,10 @@ $olddir = getcwd();
chdir(dirname($_SERVER['argv'][0]));
// Servers should define a default timezone in php.ini, but if they don't then make sure something is defined.
if (!function_exists('date_default_timezone_set') or !function_exists('date_default_timezone_get')) {
fwrite(STDERR, "Timezone functions are not available.\n");
exit(1);
// This is a quick hack. Ideally we should ask the admin for a value. See MDL-22625 for more on this.
if (function_exists('date_default_timezone_set') and function_exists('date_default_timezone_get')) {
@date_default_timezone_set(@date_default_timezone_get());
}
date_default_timezone_set(@date_default_timezone_get());
// make sure PHP errors are displayed - helps with diagnosing of problems
@error_reporting(E_ALL);
@@ -148,15 +141,20 @@ define('PHPUNIT_TEST', false);
define('IGNORE_COMPONENT_CACHE', true);
// Check that PHP is of a sufficient version as soon as possible.
require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
moodle_require_minimum_php_version();
// Check that PHP is of a sufficient version
if (version_compare(phpversion(), "5.4.4") < 0) {
$phpversion = phpversion();
// do NOT localise - lang strings would not work here and we CAN NOT move it after installib
fwrite(STDERR, "Moodle 2.7 or later requires at least PHP 5.4.4 (currently using version $phpversion).\n");
fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
exit(1);
}
// set up configuration
global $CFG;
$CFG = new stdClass();
$CFG->lang = 'en';
$CFG->dirroot = dirname(dirname(__DIR__));
$CFG->dirroot = dirname(dirname(dirname(__FILE__)));
$CFG->libdir = "$CFG->dirroot/lib";
$CFG->wwwroot = "http://localhost";
$CFG->httpswwwroot = $CFG->wwwroot;
@@ -169,7 +167,7 @@ $CFG->debug = (E_ALL | E_STRICT);
$CFG->debugdisplay = true;
$CFG->debugdeveloper = true;
$parts = explode('/', str_replace('\\', '/', dirname(__DIR__)));
$parts = explode('/', str_replace('\\', '/', dirname(dirname(__FILE__))));
$CFG->admin = array_pop($parts);
//point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else
@@ -217,11 +215,11 @@ 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'),
'sqlsrv' => moodle_database::get_driver_instance('sqlsrv', 'native'), // MS SQL*Server PHP driver
'mssql' => moodle_database::get_driver_instance('mssql', 'native'), // FreeTDS driver
);
foreach ($databases as $type=>$database) {
if ($database->driver_installed() !== true) {
@@ -241,7 +239,7 @@ list($options, $unrecognized) = cli_get_params(
'chmod' => isset($distro->directorypermissions) ? sprintf('%04o',$distro->directorypermissions) : '2777', // let distros set dir permissions
'lang' => $CFG->lang,
'wwwroot' => '',
'dataroot' => empty($distro->dataroot) ? str_replace('\\', '/', dirname(dirname(dirname(__DIR__))).'/moodledata'): $distro->dataroot, // initialised later after including libs or by distro
'dataroot' => empty($distro->dataroot) ? str_replace('\\', '/', dirname(dirname(dirname(dirname(__FILE__)))).'/moodledata'): $distro->dataroot, // initialised later after including libs or by distro
'dbtype' => empty($distro->dbtype) ? $defaultdb : $distro->dbtype, // let distro skip dbtype selection
'dbhost' => empty($distro->dbhost) ? 'localhost' : $distro->dbhost, // let distros set dbhost
'dbname' => 'moodle',
@@ -252,17 +250,11 @@ list($options, $unrecognized) = cli_get_params(
'prefix' => 'mdl_',
'fullname' => '',
'shortname' => '',
'summary' => '',
'adminuser' => 'admin',
'adminpass' => '',
'adminemail' => '',
'sitepreset' => '',
'supportemail' => '',
'upgradekey' => '',
'non-interactive' => false,
'agree-license' => false,
'allow-unstable' => false,
'skip-database' => false,
'help' => false
),
array(
@@ -271,21 +263,13 @@ 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);
$languages = get_string_manager()->get_list_of_translations();
if (array_key_exists($lang, $languages)) {
if (file_exists($CFG->dirroot.'/install/lang/'.$lang)) {
$CFG->lang = $lang;
}
// Set up site admin preset.
$sitepreset = clean_param($options['sitepreset'], PARAM_RAW);
if (!empty($sitepreset)) {
$CFG->setsitepresetduringinstall = $sitepreset;
}
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
@@ -297,41 +281,28 @@ if ($options['help']) {
}
//Print header
cli_logo();
echo PHP_EOL;
echo get_string('cliinstallheader', 'install', $CFG->target_release)."\n";
//Fist select language
if ($interactive) {
cli_separator();
$languages = get_string_manager()->get_list_of_translations();
// Do not put the langs into columns because it is not compatible with RTL.
$langlist = implode("\n", $languages);
$default = $CFG->lang;
cli_heading(get_string('chooselanguagehead', 'install'));
if (array_key_exists($default, $languages)) {
echo $default.' - '.$languages[$default]."\n";
}
if ($default !== 'en') {
echo 'en - English (en)'."\n";
}
echo '? - '.get_string('availablelangs', 'install')."\n";
cli_heading(get_string('availablelangs', 'install'));
echo $langlist."\n";
$prompt = get_string('clitypevaluedefault', 'admin', $CFG->lang);
$error = '';
do {
echo $error;
$input = cli_input($prompt, $default);
$input = clean_param($input, PARAM_SAFEDIR);
if ($input === '?') {
echo implode("\n", $languages)."\n";
$error = "\n";
if (!file_exists($CFG->dirroot.'/install/lang/'.$input)) {
$error = get_string('cliincorrectvalueretry', 'admin')."\n";
} else {
$input = clean_param($input, PARAM_SAFEDIR);
if (!array_key_exists($input, $languages)) {
$error = get_string('cliincorrectvalueretry', 'admin')."\n";
} else {
$error = '';
}
$error = '';
}
} while ($error !== '');
$CFG->lang = $input;
@@ -403,6 +374,7 @@ if ($interactive) {
$CFG->wwwroot = $wwwroot;
$CFG->httpswwwroot = $CFG->wwwroot;
//We need dataroot before lang download
$CFG->dataroot = $options['dataroot'];
if ($interactive) {
@@ -453,7 +425,6 @@ if ($interactive) {
}
}
$CFG->tempdir = $CFG->dataroot.'/temp';
$CFG->backuptempdir = $CFG->tempdir.'/backup';
$CFG->cachedir = $CFG->dataroot.'/cache';
$CFG->localcachedir = $CFG->dataroot.'/localcache';
@@ -525,105 +496,100 @@ if ($interactive) {
$database = $databases[$CFG->dbtype];
// We cannot do any validation until all DB connection data is provided.
$hintdatabase = '';
do {
echo $hintdatabase;
// Ask for db host.
if ($interactive) {
cli_separator();
cli_heading(get_string('databasehost', 'install'));
if ($options['dbhost'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
$CFG->dbhost = cli_input($prompt, $options['dbhost']);
// ask for db host
if ($interactive) {
cli_separator();
cli_heading(get_string('databasehost', 'install'));
if ($options['dbhost'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbhost']);
} else {
$CFG->dbhost = $options['dbhost'];
$prompt = get_string('clitypevalue', 'admin');
}
$CFG->dbhost = cli_input($prompt, $options['dbhost']);
// Ask for db name.
if ($interactive) {
cli_separator();
cli_heading(get_string('databasename', 'install'));
if ($options['dbname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
$CFG->dbname = cli_input($prompt, $options['dbname']);
} else {
$CFG->dbhost = $options['dbhost'];
}
// ask for db name
if ($interactive) {
cli_separator();
cli_heading(get_string('databasename', 'install'));
if ($options['dbname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbname']);
} else {
$CFG->dbname = $options['dbname'];
$prompt = get_string('clitypevalue', 'admin');
}
$CFG->dbname = cli_input($prompt, $options['dbname']);
// Ask for db prefix.
if ($interactive) {
cli_separator();
cli_heading(get_string('dbprefix', 'install'));
//TODO: solve somehow the prefix trouble for oci.
if ($options['prefix'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
$CFG->prefix = cli_input($prompt, $options['prefix']);
} else {
$CFG->dbname = $options['dbname'];
}
// ask for db prefix
if ($interactive) {
cli_separator();
cli_heading(get_string('dbprefix', 'install'));
//TODO: solve somehow the prefix trouble for oci
if ($options['prefix'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['prefix']);
} else {
$CFG->prefix = $options['prefix'];
$prompt = get_string('clitypevalue', 'admin');
}
$CFG->prefix = cli_input($prompt, $options['prefix']);
// Ask for db port.
if ($interactive) {
cli_separator();
cli_heading(get_string('databaseport', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
$CFG->dboptions['dbport'] = (int) cli_input($prompt, $options['dbport']);
} else {
$CFG->prefix = $options['prefix'];
}
// ask for db port
if ($interactive) {
cli_separator();
cli_heading(get_string('databaseport', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbport']);
$CFG->dboptions['dbport'] = (int)cli_input($prompt, $options['dbport']);
} else {
$CFG->dboptions['dbport'] = (int)$options['dbport'];
}
if ($CFG->dboptions['dbport'] <= 0) {
$CFG->dboptions['dbport'] = '';
}
// ask for db socket
if ($CFG->ostype === 'WINDOWS') {
$CFG->dboptions['dbsocket'] = '';
} else if ($interactive and empty($CFG->dboptions['dbport'])) {
cli_separator();
cli_heading(get_string('databasesocket', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
$CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
} else {
$CFG->dboptions['dbsocket'] = $options['dbsocket'];
}
// ask for db user
if ($interactive) {
cli_separator();
cli_heading(get_string('databaseuser', 'install'));
if ($options['dbuser'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
} else {
$CFG->dboptions['dbport'] = (int) $options['dbport'];
}
if ($CFG->dboptions['dbport'] <= 0) {
$CFG->dboptions['dbport'] = '';
$prompt = get_string('clitypevalue', 'admin');
}
$CFG->dbuser = cli_input($prompt, $options['dbuser']);
// Ask for db socket.
if ($CFG->ostype === 'WINDOWS') {
$CFG->dboptions['dbsocket'] = '';
} else if ($interactive and empty($CFG->dboptions['dbport'])) {
cli_separator();
cli_heading(get_string('databasesocket', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbsocket']);
$CFG->dboptions['dbsocket'] = cli_input($prompt, $options['dbsocket']);
} else {
$CFG->dboptions['dbsocket'] = $options['dbsocket'];
}
// Ask for db user.
if ($interactive) {
cli_separator();
cli_heading(get_string('databaseuser', 'install'));
if ($options['dbuser'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbuser']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
$CFG->dbuser = cli_input($prompt, $options['dbuser']);
} else {
$CFG->dbuser = $options['dbuser'];
}
// Ask for db password.
if ($interactive) {
cli_separator();
cli_heading(get_string('databasepass', 'install'));
} else {
$CFG->dbuser = $options['dbuser'];
}
// ask for db password
if ($interactive) {
cli_separator();
cli_heading(get_string('databasepass', 'install'));
do {
if ($options['dbpass'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['dbpass']);
} else {
@@ -631,171 +597,113 @@ do {
}
$CFG->dbpass = cli_input($prompt, $options['dbpass']);
if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation.
$distro = distro_pre_create_db($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']),
$distro);
if (function_exists('distro_pre_create_db')) { // Hook for distros needing to do something before DB creation
$distro = distro_pre_create_db($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersist'=>0, 'dbport'=>$CFG->dboptions['dbport'], 'dbsocket'=>$CFG->dboptions['dbsocket']), $distro);
}
$hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
$hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersist'=>0, 'dbport'=>$CFG->dboptions['dbport'], 'dbsocket'=>$CFG->dboptions['dbsocket']));
} while ($hint_database !== '');
} else {
$CFG->dbpass = $options['dbpass'];
$hintdatabase = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix,
array('dbpersist' => 0, 'dbport' => $CFG->dboptions['dbport'], 'dbsocket' => $CFG->dboptions['dbsocket']));
if ($hintdatabase !== '') {
cli_error(get_string('dbconnectionerror', 'install'));
}
}
} 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'));
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']));
} 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']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
// Ask for the support email address.
if ($interactive) {
cli_separator();
cli_heading(get_string('clisupportemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['supportemail']);
$options['supportemail'] = cli_input($prompt, $options['supportemail']);
}
// Validate that the support email address provided is valid.
if (!empty($options['supportemail']) && !validate_email($options['supportemail'])) {
$a = (object)['option' => 'supportemail', 'value' => $options['supportemail']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
} else {
$CFG->dbpass = $options['dbpass'];
$hint_database = install_db_validate($database, $CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->prefix, array('dbpersist'=>0, 'dbport'=>$CFG->dboptions['dbport'], 'dbsocket'=>$CFG->dboptions['dbsocket']));
if ($hint_database !== '') {
cli_error(get_string('dbconnectionerror', 'install'));
}
}
// Ask for the upgrade key.
// ask for fullname
if ($interactive) {
cli_separator();
cli_heading(get_string('upgradekeyset', 'admin'));
if ($options['upgradekey'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['upgradekey']);
$options['upgradekey'] = cli_input($prompt, $options['upgradekey']);
cli_heading(get_string('fullsitename', 'moodle'));
if ($options['fullname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
$options['upgradekey'] = cli_input($prompt);
}
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));
}
}
// Set the upgrade key if it was provided.
if ($options['upgradekey'] !== '') {
$CFG->upgradekey = $options['upgradekey'];
// 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));
}
}
// 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);
}
}
// 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 {
if (!$options['agree-license'] && !$skipdatabase) {
cli_error(get_string('climustagreelicense', 'install'));
$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));
}
}
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
@@ -843,17 +751,7 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
cli_error(get_string('pluginschecktodo', 'admin'));
}
if (!$skipdatabase) {
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.
// This will build a cached version of the current theme for the user
// to immediately start browsing the site.
require_once($CFG->libdir.'/upgradelib.php');
upgrade_themes();
} else {
echo get_string('cliskipdatabase', 'install')."\n";
}
install_cli_database($options, $interactive);
echo get_string('cliinstallfinished', 'install')."\n";
exit(0); // 0 means success
+14 -42
View File
@@ -52,24 +52,26 @@ Options:
--lang=CODE Installation and default site language. Default is en.
--adminuser=USERNAME Username for the moodle admin account. Default is admin.
--adminpass=PASSWORD Password for the moodle admin account.
--adminemail=STRING Email address for the moodle admin account.
--agree-license Indicates agreement with software license.
--fullname=STRING Name of the site
--shortname=STRING Name of the site
--summary=STRING The summary to be displayed on the front page
--supportemail=STRING Email address for support and help.
-h, --help Print out this help
Example:
\$sudo -u www-data /usr/bin/php admin/cli/install_database.php --lang=cs --adminpass=soMePass123 --agree-license
";
// Check that PHP is of a sufficient version as soon as possible.
require_once(__DIR__.'/../../lib/phpminimumversionlib.php');
moodle_require_minimum_php_version();
// Check that PHP is of a sufficient version
if (version_compare(phpversion(), "5.4.4") < 0) {
$phpversion = phpversion();
// do NOT localise - lang strings would not work here and we CAN NOT move it after installib
fwrite(STDERR, "Moodle 2.7 or later requires at least PHP 5.4.4 (currently using version $phpversion).\n");
fwrite(STDERR, "Please upgrade your server software or install older Moodle version.\n");
exit(1);
}
// Nothing to do if config.php does not exist
$configfile = __DIR__.'/../../config.php';
$configfile = dirname(dirname(dirname(__FILE__))).'/config.php';
if (!file_exists($configfile)) {
fwrite(STDERR, 'config.php does not exist, can not continue'); // do not localize
fwrite(STDERR, "\n");
@@ -84,6 +86,11 @@ require_once($CFG->libdir.'/installlib.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/componentlib.class.php');
// make sure no tables are installed yet
if ($DB->get_tables() ) {
cli_error(get_string('clitablesexist', 'install'));
}
$CFG->early_install_lang = true;
get_string_manager(true);
@@ -95,11 +102,8 @@ list($options, $unrecognized) = cli_get_params(
'lang' => 'en',
'adminuser' => 'admin',
'adminpass' => '',
'adminemail' => '',
'fullname' => '',
'shortname' => '',
'summary' => '',
'supportemail' => '',
'agree-license' => false,
'help' => false
),
@@ -108,22 +112,12 @@ list($options, $unrecognized) = cli_get_params(
)
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
// We show help text even if tables are installed.
if ($options['help']) {
echo $help;
die;
}
// Make sure no tables are installed yet.
if ($DB->get_tables() ) {
cli_error(get_string('clitablesexist', 'install'));
}
if (!$options['agree-license']) {
cli_error('You have to agree to the license. --help prints out the help'); // TODO: localize
}
@@ -132,21 +126,6 @@ if ($options['adminpass'] === true or $options['adminpass'] === '') {
cli_error('You have to specify admin password. --help prints out the help'); // TODO: localize
}
// 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));
}
// Validate that the supportemail provided was an e-mail address.
if (!empty($options['supportemail']) && !validate_email($options['supportemail'])) {
$a = (object) [
'option' => 'supportemail',
'value' => $options['supportemail']
];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
$options['lang'] = clean_param($options['lang'], PARAM_SAFEDIR);
if (!file_exists($CFG->dirroot.'/install/lang/'.$options['lang'])) {
$options['lang'] = 'en';
@@ -196,12 +175,5 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
install_cli_database($options, true);
// This needs to happen at the end to ensure it occurs after all caches
// have been purged for the last time.
// This will build a cached version of the current theme for the user
// to immediately start browsing the site.
require_once($CFG->libdir.'/upgradelib.php');
upgrade_themes();
echo get_string('cliinstallfinished', 'install')."\n";
exit(0); // 0 means success
-55
View File
@@ -1,55 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI script to kill all user sessions without asking for confirmation.
*
* @package core
* @subpackage cli
* @copyright 2017 Alexander Bias <alexander.bias@uni-ulm.de>
* @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');
list($options, $unrecognized) = cli_get_params(array('help' => false), array('h' => 'help'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized), 2);
}
if ($options['help']) {
$help =
"Kill all Moodle sessions
Options:
-h, --help Print out this help
Example:
\$sudo -u www-data /usr/bin/php admin/cli/kill_all_sessions.php
";
echo $help;
exit(0);
}
\core\session\manager::kill_all_sessions();
exit(0);
+11 -128
View File
@@ -24,7 +24,7 @@
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once($CFG->libdir.'/clilib.php'); // cli only functions
if ($DB->get_dbfamily() !== 'mysql') {
@@ -53,7 +53,7 @@ Options:
-h, --help Print out this help
Example:
\$ sudo -u www-data /usr/bin/php admin/cli/mysql_collation.php --collation=utf8mb4_unicode_ci
\$ sudo -u www-data /usr/bin/php admin/cli/mysql_collation.php --collation=utf8_general_ci
";
if (!empty($options['collation'])) {
@@ -64,71 +64,6 @@ if (!empty($options['collation'])) {
cli_error("Error: collation '$collation' is not available on this server!");
}
$collationinfo = explode('_', $collation);
$charset = reset($collationinfo);
$engine = strtolower($DB->get_dbengine());
// Do checks for utf8mb4.
if (strpos($collation, 'utf8mb4') === 0) {
// Do we have the right engine?
if ($engine !== 'innodb' && $engine !== 'xtradb') {
cli_error("Error: '$collation' requires InnoDB or XtraDB set as the engine.");
}
// Are we using Barracuda?
if ($DB->get_row_format() != 'Barracuda') {
// Try setting it here.
try {
$DB->execute("SET GLOBAL innodb_file_format=Barracuda");
} catch (dml_exception $e) {
cli_error("Error: '$collation' requires the file format to be set to Barracuda.
An attempt was made to change the format, but it failed. Please try doing this manually.");
}
echo "GLOBAL SETTING: innodb_file_format changed to Barracuda\n";
}
// Is one file per table being used?
if (!$DB->is_file_per_table_enabled()) {
try {
$DB->execute("SET GLOBAL innodb_file_per_table=1");
} catch (dml_exception $e) {
cli_error("Error: '$collation' requires the setting 'innodb_file_per_table' be set to 'ON'.
An attempt was made to change the format, but it failed. Please try doing this manually.");
}
echo "GLOBAL SETTING: innodb_file_per_table changed to 1\n";
}
// Is large prefix set?
if (!$DB->is_large_prefix_enabled()) {
try {
$DB->execute("SET GLOBAL innodb_large_prefix=1");
} catch (dml_exception $e) {
cli_error("Error: '$collation' requires the setting 'innodb_large_prefix' be set to 'ON'.
An attempt was made to change the format, but it failed. Please try doing this manually.");
}
echo "GLOBAL SETTING: innodb_large_prefix changed to 1\n";
}
}
$sql = "SHOW VARIABLES LIKE 'collation_database'";
if (!$dbcollation = $DB->get_record_sql($sql)) {
cli_error("Error: Could not access collation information on the database.");
}
$sql = "SHOW VARIABLES LIKE 'character_set_database'";
if (!$dbcharset = $DB->get_record_sql($sql)) {
cli_error("Error: Could not access character set information on the database.");
}
if ($dbcollation->value !== $collation || $dbcharset->value !== $charset) {
// Try to convert the DB.
echo "Converting database to '$collation' for $CFG->wwwroot:\n";
$sql = "ALTER DATABASE `$CFG->dbname` DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
try {
$DB->change_database_structure($sql);
} catch (exception $e) {
cli_error("Error: Tried to alter the database with no success. Please try manually changing the database
to the new collation and character set and then run this script again.");
}
echo "DATABASE CONVERTED\n";
}
echo "Converting tables and columns to '$collation' for $CFG->wwwroot:\n";
$prefix = $DB->get_prefix();
$prefix = str_replace('_', '\\_', $prefix);
@@ -145,25 +80,12 @@ if (!empty($options['collation'])) {
$skipped++;
} else {
try {
$DB->change_database_structure("ALTER TABLE `$table->name` CONVERT TO CHARACTER SET $charset COLLATE $collation");
echo "CONVERTED\n";
$converted++;
} catch (ddl_exception $e) {
$result = mysql_set_row_format($table->name, $charset, $collation, $engine);
if ($result) {
echo "CONVERTED\n";
$converted++;
} else {
// We don't know what the problem is. Stop the conversion.
cli_error("Error: Tried to convert $table->name, but there was a problem. Please check the details of this
table and try again.");
die();
}
}
$DB->change_database_structure("ALTER TABLE $table->name DEFAULT COLLATE = $collation");
echo "CONVERTED\n";
$converted++;
}
$sql = "SHOW FULL COLUMNS FROM `$table->name` WHERE collation IS NOT NULL";
$sql = "SHOW FULL COLUMNS FROM $table->name WHERE collation IS NOT NULL";
$rs2 = $DB->get_recordset_sql($sql);
foreach ($rs2 as $column) {
$column = (object)array_change_key_case((array)$column, CASE_LOWER);
@@ -174,36 +96,22 @@ if (!empty($options['collation'])) {
continue;
}
// Check for utf8mb4 collation.
$rowformat = $DB->get_row_format_sql($engine, $collation);
if ($column->type === 'tinytext' or $column->type === 'mediumtext' or $column->type === 'text' or $column->type === 'longtext') {
$notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
$default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
// primary, unique and inc are not supported for texts
$sql = "ALTER TABLE `$table->name`
MODIFY COLUMN $column->field $column->type
CHARACTER SET $charset
COLLATE $collation $notnull $default";
$sql = "ALTER TABLE $table->name MODIFY COLUMN $column->field $column->type COLLATE $collation $notnull $default";
$DB->change_database_structure($sql);
} else if (strpos($column->type, 'varchar') === 0) {
$notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
$default = !is_null($column->default) ? "DEFAULT '$column->default'" : '';
if ($rowformat != '') {
$sql = "ALTER TABLE `$table->name` $rowformat";
$DB->change_database_structure($sql);
}
$sql = "ALTER TABLE `$table->name`
MODIFY COLUMN $column->field $column->type
CHARACTER SET $charset
COLLATE $collation $notnull $default";
// primary, unique and inc are not supported for texts
$sql = "ALTER TABLE $table->name MODIFY COLUMN $column->field $column->type COLLATE $collation $notnull $default";
$DB->change_database_structure($sql);
} else {
echo "ERROR (unknown column type: $column->type)\n";
$errors++;
$error++;
continue;
}
echo "CONVERTED\n";
@@ -272,9 +180,7 @@ function mysql_get_collations() {
global $DB;
$collations = array();
$sql = "SHOW COLLATION
WHERE Collation LIKE 'utf8\_%' AND Charset = 'utf8'
OR Collation LIKE 'utf8mb4\_%' AND Charset = 'utf8mb4'";
$sql = "SHOW COLLATION WHERE Collation LIKE 'utf8\_%' AND Charset = 'utf8'";
$rs = $DB->get_recordset_sql($sql);
foreach ($rs as $collation) {
$collations[$collation->collation] = $collation->collation;
@@ -303,26 +209,3 @@ function mysql_get_column_collations($tablename) {
$rs->close();
return $collations;
}
function mysql_set_row_format($tablename, $charset, $collation, $engine) {
global $DB;
$sql = "SELECT row_format
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema = DATABASE() AND table_name = ?";
$rs = $DB->get_record_sql($sql, array($tablename));
if ($rs) {
if ($rs->row_format == 'Compact' || $rs->row_format == 'Redundant') {
$rowformat = $DB->get_row_format_sql($engine, $collation);
// Try to convert to compressed format and then try updating the collation again.
$DB->change_database_structure("ALTER TABLE `$tablename` $rowformat");
$DB->change_database_structure("ALTER TABLE `$tablename` CONVERT TO CHARACTER SET $charset COLLATE $collation");
} else {
// Row format may not be the problem. Can not diagnose problem. Send fail reply.
return false;
}
} else {
return false;
}
return true;
}
-202
View File
@@ -1,202 +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/>.
/**
* MySQL table row compression tool tool.
*
* @package core
* @copyright 2014 Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Petr Skoda <petr.skoda@totaralms.com>
*/
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require_once($CFG->libdir . '/clilib.php');
if ($DB->get_dbfamily() !== 'mysql') {
cli_error('This script is used for MySQL databases only.');
}
$engine = strtolower($DB->get_dbengine());
if ($engine !== 'innodb' and $engine !== 'xtradb') {
cli_error('This script is for MySQL servers using InnoDB or XtraDB engines only.');
}
list($options, $unrecognized) = cli_get_params(
array('help' => false, 'info' => false, 'list' => false, 'fix' => false, 'showsql' => false),
array('h' => 'help', 'i' => 'info', 'l' => 'list', 'f' => 'fix', 's' => 'showsql')
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
$help =
"Script for detection of row size problems in MySQL InnoDB tables.
By default InnoDB storage table is using legacy Antelope file format
which has major restriction on database row size.
Use this script to detect and fix database tables with potential data
overflow problems.
Options:
-i, --info Show database information
-l, --list List problematic tables
-f, --fix Attempt to fix all tables (requires SUPER privilege)
-s, --showsql Print SQL statements for fixing of tables
-h, --help Print out this help
Example:
\$ sudo -u www-data /usr/bin/php admin/cli/mysql_compressed_rows.php -l
";
/** @var mysql_sql_generator $generator */
$generator = $DB->get_manager()->generator;
$info = $DB->get_server_info();
$filepertable = $DB->get_record_sql("SHOW VARIABLES LIKE 'innodb_file_per_table'");
$filepertable = $filepertable ? $filepertable->value : '';
$fileformat = $DB->get_record_sql("SHOW VARIABLES LIKE 'innodb_file_format'");
$fileformat = $fileformat ? $fileformat->value : '';
$prefix = $DB->get_prefix();
$database = $CFG->dbname;
if (!empty($options['info'])) {
echo "Database version: " . $info['description'] . "\n";
echo "Database name: $database\n";
echo "Database engine: " . $DB->get_dbengine() . "\n";
echo "innodb_file_per_table: $filepertable\n";
echo "innodb_file_format: $fileformat\n";
exit(0);
} else if (!empty($options['list'])) {
$problem = false;
foreach ($DB->get_tables(false) as $table) {
$columns = $DB->get_columns($table, false);
$size = $generator->guess_antelope_row_size($columns);
$format = $DB->get_row_format($table);
if ($size <= $generator::ANTELOPE_MAX_ROW_SIZE) {
continue;
}
echo str_pad($prefix . $table, 32, ' ', STR_PAD_RIGHT);
echo str_pad($format, 11, ' ', STR_PAD_RIGHT);
if ($format === 'Compact' or $format === 'Redundant') {
$problem = true;
echo " (needs fixing)\n";
} else if ($format !== 'Compressed' and $format !== 'Dynamic') {
echo " (unknown)\n";
} else {
echo "\n";
}
}
if ($problem) {
exit(1);
}
exit(0);
} else if (!empty($options['fix'])) {
$fixtables = array();
foreach ($DB->get_tables(false) as $table) {
$columns = $DB->get_columns($table, false);
$size = $generator->guess_antelope_row_size($columns);
$format = $DB->get_row_format($table);
if ($size <= $generator::ANTELOPE_MAX_ROW_SIZE) {
continue;
}
if ($format === 'Compact' or $format === 'Redundant') {
$fixtables[$table] = $table;
}
}
if (!$fixtables) {
echo "No changes necessary\n";
exit(0);
}
if ($filepertable !== 'ON') {
try {
$DB->execute("SET GLOBAL innodb_file_per_table=1");
} catch (dml_exception $e) {
echo "Cannot enable GLOBAL innodb_file_per_table setting, use --showsql option and execute the statements manually.";
throw $e;
}
}
if ($fileformat !== 'Barracuda') {
try {
$DB->execute("SET GLOBAL innodb_file_format=Barracuda");
} catch (dml_exception $e) {
echo "Cannot change GLOBAL innodb_file_format setting, use --showsql option and execute the statements manually.";
throw $e;
}
}
if (!$DB->is_compressed_row_format_supported(false)) {
echo "MySQL server is not compatible with compressed row format.";
exit(1);
}
foreach ($fixtables as $table) {
$DB->change_database_structure("ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed");
echo str_pad($prefix . $table, 32, ' ', STR_PAD_RIGHT) . " ... Compressed\n";
}
exit(0);
} else if (!empty($options['showsql'])) {
$fixtables = array();
foreach ($DB->get_tables(false) as $table) {
$columns = $DB->get_columns($table, false);
$size = $generator->guess_antelope_row_size($columns);
$format = $DB->get_row_format($table);
if ($size <= $generator::ANTELOPE_MAX_ROW_SIZE) {
continue;
}
if ($format === 'Compact' or $format === 'Redundant') {
$fixtables[$table] = $table;
}
}
if (!$fixtables) {
echo "No changes necessary\n";
exit(0);
}
echo "Copy the following SQL statements and execute them using account with SUPER privilege:\n\n";
echo "USE $database;\n";
echo "SET SESSION sql_mode=STRICT_ALL_TABLES;\n";
echo "SET GLOBAL innodb_file_per_table=1;\n";
echo "SET GLOBAL innodb_file_format=Barracuda;\n";
foreach ($fixtables as $table) {
echo "ALTER TABLE `{$prefix}$table` ROW_FORMAT=Compressed;\n";
}
echo "\n";
exit(0);
} else {
echo $help;
die;
}
+180
View File
@@ -0,0 +1,180 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* MySQL engine conversion tool.
*
* @package core
* @subpackage cli
* @copyright 2009 Petr Skoda (http://skodak.org)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once($CFG->libdir.'/clilib.php'); // cli only functions
if ($DB->get_dbfamily() !== 'mysql') {
cli_error('This function is designed for MySQL databases only!');
}
// now get cli options
list($options, $unrecognized) = cli_get_params(array('help'=>false, 'list'=>false, 'engine'=>false, 'available'=>false),
array('h'=>'help', 'l'=>'list', 'a'=>'available'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
$help =
"MySQL engine conversions script.
It is recommended to stop the web server before the conversion.
Do not use MyISAM if possible, because it is not ACID compliant
and does not support transactions.
Options:
--engine=ENGINE Convert MySQL tables to different engine
-l, --list Show table information
-a, --available Show list of available engines
-h, --help Print out this help
Example:
\$sudo -u www-data /usr/bin/php admin/cli/mysql_engine.php --engine=InnoDB
";
if (!empty($options['engine'])) {
$engines = mysql_get_engines();
$engine = clean_param($options['engine'], PARAM_ALPHA);
if (!isset($engines[strtoupper($engine)])) {
cli_error("Error: engine '$engine' is not available on this server!");
}
echo "Converting tables to '$engine' for $CFG->wwwroot:\n";
$prefix = $DB->get_prefix();
$prefix = str_replace('_', '\\_', $prefix);
$sql = "SHOW TABLE STATUS WHERE Name LIKE BINARY '$prefix%'";
$rs = $DB->get_recordset_sql($sql);
$converted = 0;
$skipped = 0;
$errors = 0;
foreach ($rs as $table) {
if (strtoupper($table->engine) === strtoupper($engine)) {
$newengine = mysql_get_table_engine($table->name);
echo str_pad($table->name, 40). " - NO CONVERSION NEEDED ($newengine)\n";
$skipped++;
continue;
}
echo str_pad($table->name, 40). " - ";
try {
$DB->change_database_structure("ALTER TABLE {$table->name} ENGINE = $engine");
$newengine = mysql_get_table_engine($table->name);
if (strtoupper($newengine) !== strtoupper($engine)) {
echo "ERROR ($newengine)\n";
$errors++;
continue;
}
echo "DONE ($newengine)\n";
$converted++;
} catch (moodle_exception $e) {
echo $e->getMessage()."\n";
$errors++;
continue;
}
}
$rs->close();
echo "Converted: $converted, skipped: $skipped, errors: $errors\n";
exit(0); // success
} else if (!empty($options['list'])) {
echo "List of tables for $CFG->wwwroot:\n";
$prefix = $DB->get_prefix();
$prefix = str_replace('_', '\\_', $prefix);
$sql = "SHOW TABLE STATUS WHERE Name LIKE BINARY '$prefix%'";
$rs = $DB->get_recordset_sql($sql);
$counts = array();
foreach ($rs as $table) {
if (isset($counts[$table->engine])) {
$counts[$table->engine]++;
} else {
$counts[$table->engine] = 1;
}
echo str_pad($table->engine, 10);
echo $table->name . "\n";
}
$rs->close();
echo "\n";
echo "Table engines summary for $CFG->wwwroot:\n";
foreach ($counts as $engine => $count) {
echo "$engine: $count\n";
}
exit(0); // success
} else if (!empty($options['available'])) {
echo "List of available MySQL engines for $CFG->wwwroot:\n";
$engines = mysql_get_engines();
foreach ($engines as $engine) {
echo " $engine\n";
}
die;
} else {
echo $help;
die;
}
// ========== Some functions ==============
function mysql_get_engines() {
global $DB;
$sql = "SHOW Engines";
$rs = $DB->get_recordset_sql($sql);
$engines = array();
foreach ($rs as $engine) {
if (strtoupper($engine->support) !== 'YES' and strtoupper($engine->support) !== 'DEFAULT') {
continue;
}
$engines[strtoupper($engine->engine)] = $engine->engine;
if (strtoupper($engine->support) === 'DEFAULT') {
$engines[strtoupper($engine->engine)] .= ' (default)';
}
}
$rs->close();
return $engines;
}
function mysql_get_table_engine($tablename) {
global $DB;
$engine = null;
$sql = "SHOW TABLE STATUS WHERE Name = '$tablename'"; // no special chars expected here
$rs = $DB->get_recordset_sql($sql);
if ($rs->valid()) {
$record = $rs->current();
$engine = $record->engine;
}
$rs->close();
return $engine;
}
+8 -31
View File
@@ -15,8 +15,6 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI script to purge caches without asking for confirmation.
*
* @package core
* @subpackage cli
* @copyright 2011 David Mudrak <david@moodle.com>
@@ -25,19 +23,10 @@
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once($CFG->libdir.'/clilib.php');
$longoptions = [
'help' => false,
'muc' => false,
'theme' => false,
'lang' => false,
'js' => false,
'filter' => false,
'other' => false
];
list($options, $unrecognized) = cli_get_params($longoptions, ['h' => 'help']);
list($options, $unrecognized) = cli_get_params(array('help' => false), array('h' => 'help'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
@@ -45,32 +34,20 @@ if ($unrecognized) {
}
if ($options['help']) {
// The indentation of this string is "wrong" but this is to avoid a extra whitespace in console output.
$help = <<<EOF
Invalidates Moodle internal caches
Specific caches can be defined (alone or in combination) using arguments. If none are specified,
all caches will be purged.
$help =
"Invalidates all Moodle internal caches
Options:
-h, --help Print out this help
--muc Purge all MUC caches (includes lang cache)
--theme Purge theme cache
--lang Purge language string cache
--js Purge JavaScript cache
--filter Purge text filter cache
--other Purge all file caches and other miscellaneous caches (may include MUC
if using cachestore_file).
Example:
\$ sudo -u www-data /usr/bin/php admin/cli/purge_caches.php
EOF;
\$sudo -u www-data /usr/bin/php admin/cli/purge_caches.php
";
echo $help;
exit(0);
}
purge_caches(array_filter($options));
purge_all_caches();
exit(0);
exit(0);
+13 -40
View File
@@ -26,26 +26,13 @@
define('CLI_SCRIPT', true);
require(__DIR__.'/../../config.php');
require(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once($CFG->libdir.'/clilib.php'); // cli only functions
// Define the input options.
$longparams = array(
'help' => false,
'username' => '',
'password' => '',
'ignore-password-policy' => false
);
$shortparams = array(
'h' => 'help',
'u' => 'username',
'p' => 'password',
'i' => 'ignore-password-policy'
);
// now get cli options
list($options, $unrecognized) = cli_get_params($longparams, $shortparams);
list($options, $unrecognized) = cli_get_params(array('help'=>false),
array('h'=>'help'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
@@ -60,43 +47,29 @@ There are no security checks here because anybody who is able to
execute this file may execute any PHP too.
Options:
-h, --help Print out this help
-u, --username=username Specify username to change
-p, --password=newpassword Specify new password
--ignore-password-policy Ignore password policy when setting password
-h, --help Print out this help
Example:
\$sudo -u www-data /usr/bin/php admin/cli/reset_password.php
\$sudo -u www-data /usr/bin/php admin/cli/reset_password.php --username=rosaura --password=jiu3jiu --ignore-password-policy
";
"; //TODO: localize - to be translated later when everything is finished
echo $help;
die;
}
if ($options['username'] == '' ) {
cli_heading('Password reset');
$prompt = "Enter username (manual authentication only)";
$username = cli_input($prompt);
} else {
$username = $options['username'];
}
cli_heading('Password reset'); // TODO: localize
$prompt = "enter username (manual authentication only)"; // TODO: localize
$username = cli_input($prompt);
if (!$user = $DB->get_record('user', array('auth'=>'manual', 'username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id))) {
cli_error("Can not find user '$username'");
}
if ($options['password'] == '' ) {
$prompt = "Enter new password";
$password = cli_input($prompt);
} else {
$password = $options['password'];
}
$prompt = "Enter new password"; // TODO: localize
$password = cli_input($prompt);
$errmsg = '';//prevent eclipse warning
if (!$options['ignore-password-policy'] ) {
if (!check_password_policy($password, $errmsg, $user)) {
cli_error(html_to_text($errmsg, 0));
}
if (!check_password_policy($password, $errmsg)) {
cli_error($errmsg);
}
$hashedpassword = hash_internal_user_password($password);
@@ -105,4 +78,4 @@ $DB->set_field('user', 'password', $hashedpassword, array('id'=>$user->id));
echo "Password changed\n";
exit(0); // 0 means success.
exit(0); // 0 means success
-109
View File
@@ -1,109 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This script allows to restore a course from CLI.
*
* @package core
* @subpackage cli
* @copyright 2020 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', 1);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/clilib.php');
require_once($CFG->dirroot . "/backup/util/includes/restore_includes.php");
list($options, $unrecognized) = cli_get_params([
'file' => '',
'categoryid' => '',
'showdebugging' => false,
'help' => false,
], [
'f' => 'file',
'c' => 'categoryid',
's' => 'showdebugging',
'h' => 'help',
]);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help'] || !($options['file']) || !($options['categoryid'])) {
$help = <<<EOL
Restore backup into provided category.
Options:
-f, --file=STRING Path to the backup file.
-c, --categoryid=INT ID of the category to restore too.
-s, --showdebugging Show developer level debugging information
-h, --help Print out this help.
Example:
\$sudo -u www-data /usr/bin/php admin/cli/restore_backup.php --file=/path/to/backup/file.mbz --categoryid=1\n
EOL;
echo $help;
exit(0);
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if (!$admin = get_admin()) {
throw new \moodle_exception('noadmins');
}
if (!file_exists($options['file'])) {
throw new \moodle_exception('filenotfound');
}
if (!$category = $DB->get_record('course_categories', ['id' => $options['categoryid']], 'id')) {
throw new \moodle_exception('invalidcategoryid');
}
$backupdir = restore_controller::get_tempdir_name(SITEID, $USER->id);
$path = make_backup_temp_directory($backupdir);
cli_heading(get_string('extractingbackupfileto', 'backup', $path));
$fp = get_file_packer('application/vnd.moodle.backup');
$fp->extract_to_pathname($options['file'], $path);
cli_heading(get_string('preprocessingbackupfile'));
try {
list($fullname, $shortname) = restore_dbops::calculate_course_names(0, get_string('restoringcourse', 'backup'),
get_string('restoringcourseshortname', 'backup'));
$courseid = restore_dbops::create_new_course($fullname, $shortname, $category->id);
$rc = new restore_controller($backupdir, $courseid, backup::INTERACTIVE_NO,
backup::MODE_GENERAL, $admin->id, backup::TARGET_NEW_COURSE);
$rc->execute_precheck();
$rc->execute_plan();
$rc->destroy();
} catch (Exception $e) {
cli_heading(get_string('cleaningtempdata'));
fulldelete($path);
throw new \moodle_exception('generalexceptionmessage', 'error', '', $e->getMessage());
}
cli_heading(get_string('restoredcourseid', 'backup', $courseid));
exit(0);
-199
View File
@@ -1,199 +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");
list($options, $unrecognized) = cli_get_params(
[
'help' => false,
'list' => false,
'execute' => false,
'showsql' => false,
'showdebugging' => false,
'force' => false,
'disable' => false,
'enable' => false,
], [
'h' => 'help',
'f' => 'force',
]
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
$commands = ['list', 'execute', 'disable', 'enable'];
$hascommand = count(array_filter($commands, fn($command) => $options[$command])) > 0;
if ($options['help'] || !$hascommand) {
$help =
"Scheduled cron tasks.
Options:
--disable=\\some\\task Disable scheduled task
--enable=\\some\\task Enable scheduled task
--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
-f, --force Execute task even if cron is disabled
Example:
\$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
";
echo $help;
die;
}
if ($options['showdebugging'] || !empty($CFG->showcrondebugging)) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql'] || !empty($CFG->showcronsql)) {
$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 (moodle_needs_upgrading()) {
mtrace("Moodle upgrade pending, cannot manage tasks.");
exit(1);
}
if ($disable = $options['disable']) {
if (!$task = \core\task\manager::get_scheduled_task($disable)) {
mtrace("Task '$disable' not found");
exit(1);
}
try {
$task->disable();
mtrace("Disabled '$disable'");
} catch (Exception $e) {
mtrace("$e->getMessage()");
exit(1);
}
} else if ($enable = $options['enable']) {
if (!$task = \core\task\manager::get_scheduled_task($enable)) {
mtrace("Task '$enable' not found");
exit(1);
}
try {
$task->enable();
mtrace("Enabled '$enable'");
} catch (Exception $e) {
mtrace("$e->getMessage()");
exit(1);
}
} else if ($execute = $options['execute']) {
if (!$task = \core\task\manager::get_scheduled_task($execute)) {
mtrace("Task '$execute' not found");
exit(1);
}
if (!get_config('core', 'cron_enabled') && !$options['force']) {
mtrace('Cron is disabled. Use --force to override.');
exit(1);
}
\core\task\manager::scheduled_task_starting($task);
// Increase memory limit.
raise_memory_limit(MEMORY_EXTRA);
// Emulate normal session - we use admin account by default.
\core\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);
}
\core\cron::run_inner_scheduled_task($task);
}
-183
View File
@@ -1,183 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI script to uninstall plugins.
*
* @package core
* @subpackage cli
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/clilib.php');
require_once($CFG->libdir . '/adminlib.php');
$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
--run Execute uninstall. If this option is not set, then the script will be run in a dry mode.
--showsql Show sql queries before they are executed.
--showdebugging Show developer level debugging information.
Examples:
# 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.
# php uninstall_plugins.php --purge-missing
A dry run of uninstalling all missing plugins.
# php uninstall_plugins.php --purge-missing --run
Run uninstall of all missing plugins.
# php uninstall_plugins.php --plugins=mod_assign,mod_forum
A dry run of uninstalling mod_assign and mod_forum plugins.
# php uninstall_plugins.php --plugins=mod_assign,mod_forum --run
Run uninstall for mod_assign and mod_forum plugins.
";
list($options, $unrecognised) = cli_get_params([
'help' => false,
'show-all' => false,
'show-contrib' => false,
'show-missing' => false,
'purge-missing' => false,
'plugins' => false,
'run' => false,
'showsql' => false,
'showdebugging' => false,
], [
'h' => 'help'
]);
if ($unrecognised) {
$unrecognised = implode(PHP_EOL.' ', $unrecognised);
cli_error(get_string('cliunknowoption', 'core_admin', $unrecognised));
}
if ($options['help']) {
cli_writeln($help);
exit(0);
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql']) {
$DB->set_debug(true);
}
$pluginman = core_plugin_manager::instance();
$plugininfo = $pluginman->get_plugins();
if ($options['show-all'] || $options['show-missing'] || $options['show-contrib']) {
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']) {
cli_writeln($pluginstring);
} else {
if ($plugin->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
cli_writeln($pluginstring);
}
}
}
}
exit(0);
}
if ($options['purge-missing']) {
foreach ($plugininfo as $type => $plugins) {
foreach ($plugins as $name => $plugin) {
if ($plugin->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
$pluginstring = $plugin->component . "\t" . $plugin->displayname;
if ($pluginman->can_uninstall_plugin($plugin->component)) {
if ($options['run']) {
cli_writeln('Uninstalling: ' . $pluginstring);
$progress = new progress_trace_buffer(new text_progress_trace(), true);
$pluginman->uninstall_plugin($plugin->component, $progress);
$progress->finished();
cli_write($progress->get_buffer());
} else {
cli_writeln('Will be uninstalled: ' . $pluginstring);
}
} else {
cli_writeln('Can not be uninstalled: ' . $pluginstring);
}
}
}
}
exit(0);
}
if ($options['plugins']) {
$components = explode(',', $options['plugins']);
foreach ($components as $component) {
$plugin = $pluginman->get_plugin_info($component);
if (is_null($plugin)) {
cli_writeln('Unknown plugin: ' . $component);
} else {
$pluginstring = $plugin->component . "\t" . $plugin->displayname;
if ($pluginman->can_uninstall_plugin($plugin->component)) {
if ($options['run']) {
cli_writeln('Uninstalling: ' . $pluginstring);
$progress = new progress_trace_buffer(new text_progress_trace(), true);
$pluginman->uninstall_plugin($plugin->component, $progress);
$progress->finished();
cli_write($progress->get_buffer());
} else {
cli_writeln('Will be uninstalled: ' . $pluginstring);
}
} else {
cli_writeln('Can not be uninstalled: ' . $pluginstring);
}
}
}
exit(0);
}
cli_writeln($help);
exit(0);
+23 -161
View File
@@ -38,36 +38,24 @@ if (function_exists('opcache_reset') and !isset($_SERVER['REMOTE_ADDR'])) {
define('CLI_SCRIPT', true);
define('CACHE_DISABLE_ALL', true);
require(__DIR__.'/../../config.php');
require(dirname(dirname(dirname(__FILE__))).'/config.php');
require_once($CFG->libdir.'/adminlib.php'); // various admin-only functions
require_once($CFG->libdir.'/upgradelib.php'); // general upgrade/install related functions
require_once($CFG->libdir.'/clilib.php'); // cli only functions
require_once($CFG->libdir.'/environmentlib.php');
// now get cli options
$lang = isset($SESSION->lang) ? $SESSION->lang : $CFG->lang;
list($options, $unrecognized) = cli_get_params(
array(
'allow-unstable' => false,
'help' => false,
'is-maintenance-required' => false,
'is-pending' => false,
'lang' => $lang,
'maintenance' => true,
'non-interactive' => false,
'set-ui-upgrade-lock' => false,
'unset-ui-upgrade-lock' => false,
'verbose-settings' => false,
'non-interactive' => false,
'allow-unstable' => false,
'help' => false
),
array(
'h' => 'help'
)
);
if ($options['lang']) {
$SESSION->lang = $options['lang'];
}
$interactive = empty($options['non-interactive']);
if ($unrecognized) {
@@ -83,35 +71,10 @@ Please note you must execute this script with the same uid as apache!
Site defaults may be changed via local/defaults.php.
Options:
--allow-unstable Upgrade even if the version is not marked as stable yet,
required in non-interactive mode.
-h, --help Print out this help.
--is-maintenance-required Returns exit code 2 if the upgrade requires maintenance mode.
Returns exit code 3 if no maintenance is required for the upgrade.
--is-pending Exit with error code 2 if an upgrade is required.
--lang=CODE Set preferred language for CLI output. Defaults to the
site language if not set. Defaults to 'en' if the lang
parameter is invalid or if the language pack is not
installed.
--maintenance Sets whether this upgrade will use maintenance mode.
If not possible, the upgrade will not happen and the script will exit.
WARNING: Caches (except theme) will be STALE and MUST be purged after upgrading.
DO NOT USE if the upgrade contains known breaking changes to the way data
and the database interact.
RECOMMENDED for lightweight deployments, to allow for a graceful purge and
rebuild of the cache.
--non-interactive No interactive questions or confirmations.
--set-ui-upgrade-lock Sets the upgrade to CLI only and unable to be triggered from the frontend.
If called with --maintenance=false, the lock WILL NOT be released when the
upgrade finishes, and MUST be manually removed.
If called with --is-maintenance-required before an upgrade,
The lock WILL be released when the upgrade finishes.
--unset-ui-upgrade-lock Removes the frontend upgrade lock, if the lock exists.
Useful when an error during the upgrade leaves the upgrade locked,
or there is need to control the time where the unlock happens.
--verbose-settings Show new settings values. By default only the name of
new core or plugin settings are displayed. This option
outputs the new values as well as the setting name.
--non-interactive No interactive questions or confirmations
--allow-unstable Upgrade even if the version is not marked as stable yet,
required in non-interactive mode.
-h, --help Print out this help
Example:
\$sudo -u www-data /usr/bin/php admin/cli/upgrade.php
@@ -135,60 +98,10 @@ if ($version < $CFG->version) {
$oldversion = "$CFG->release ($CFG->version)";
$newversion = "$release ($version)";
if ($options['unset-ui-upgrade-lock']) {
// Unconditionally unset this config if requested.
set_config('outagelessupgrade', false);
cli_writeln(get_string('cliupgradeunsetlock', 'admin'));
}
$allhash = core_component::get_all_component_hash();
// Initialise allcomponent hash if not set. It will be correctly set after upgrade.
$CFG->allcomponenthash = $CFG->allcomponenthash ?? '';
if (!$options['maintenance']) {
if ($allhash !== $CFG->allcomponenthash) {
// Throw an error here, we can't proceed, this needs to set maintenance.
cli_error(get_string('cliupgrademaintenancerequired', 'core_admin'), 2);
}
// Set a constant to stop any upgrade var from being set during processing.
// This protects against the upgrade setting timeouts and maintenance during the upgrade.
define('CLI_UPGRADE_RUNNING', true);
// This database control is the control to block the GUI from doing upgrade related actions.
set_config('outagelessupgrade', true);
}
// We should ignore all upgrade locks here.
if (!moodle_needs_upgrading(false)) {
if (!moodle_needs_upgrading()) {
cli_error(get_string('cliupgradenoneed', 'core_admin', $newversion), 0);
}
// Handle exit based options for outputting upgrade state.
if ($options['is-pending'] || $options['is-maintenance-required']) {
// If we aren't doing a maintenance check, plain pending check.
if (!$options['is-maintenance-required']) {
cli_error(get_string('cliupgradepending', 'core_admin'), 2);
}
// Can we do this safely with no maintenance/outage? Detect if there is a schema or other application state change.
if ($allhash !== $CFG->allcomponenthash) {
// State change here, we need to do this in maintenance.
cli_writeln(get_string('cliupgradepending', 'core_admin'));
cli_error(get_string('cliupgrademaintenancerequired', 'core_admin'), 2);
}
// If requested, we should always set the upgrade lock here, so this cannot be run from frontend.
if ($options['set-ui-upgrade-lock']) {
set_config('outagelessupgrade', true);
cli_writeln(get_string('cliupgradesetlock', 'admin'));
}
// We can do an upgrade without maintenance!
cli_writeln(get_string('cliupgradepending', 'core_admin'));
cli_error(get_string('cliupgrademaintenancenotrequired', 'core_admin'), 3);
}
// Test environment first.
list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
if (!$envstatus) {
@@ -201,27 +114,17 @@ if (!$envstatus) {
exit(1);
}
// Make sure there are no files left over from previous versions.
if (upgrade_stale_php_files_present()) {
cli_problem(get_string('upgradestalefiles', 'admin'));
// Stale file info contains HTML elements which aren't suitable for CLI.
$upgradestalefilesinfo = get_string('upgradestalefilesinfo', 'admin', get_docs_url('Upgrading'));
cli_error(strip_tags($upgradestalefilesinfo));
}
// Test plugin dependencies.
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
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'));
}
$a = new stdClass();
$a->oldversion = $oldversion;
$a->newversion = $newversion;
if ($interactive) {
$a = new stdClass();
$a->oldversion = $oldversion;
$a->newversion = $newversion;
echo cli_heading(get_string('databasechecking', '', $a)) . PHP_EOL;
}
@@ -253,18 +156,12 @@ if ($interactive) {
}
if ($version > $CFG->version) {
// Only purge caches if this is a plain upgrade.
// In the case of a no-outage upgrade, we will gracefully roll caches after upgrade.
if ($options['maintenance']) {
// We purge all of MUC's caches here.
// Caches are disabled for upgrade by CACHE_DISABLE_ALL so we must set the first arg to true.
// This ensures a real config object is loaded and the stores will be purged.
// This is the only way we can purge custom caches such as memcache or APC.
// Note: all other calls to caches will still used the disabled API.
cache_helper::purge_all(true);
}
// We purge all of MUC's caches here.
// Caches are disabled for upgrade by CACHE_DISABLE_ALL so we must set the first arg to true.
// This ensures a real config object is loaded and the stores will be purged.
// This is the only way we can purge custom caches such as memcache or APC.
// Note: all other calls to caches will still used the disabled API.
cache_helper::purge_all(true);
upgrade_core($version, true);
}
set_config('release', $release);
@@ -276,44 +173,9 @@ upgrade_noncore(true);
// log in as admin - we need doanything permission when applying defaults
\core\session\manager::set_user(get_admin());
// Apply default settings and output those that have changed.
cli_heading(get_string('cliupgradedefaultheading', 'admin'));
$settingsoutput = admin_apply_default_settings(null, false);
foreach ($settingsoutput as $setting => $value) {
if ($options['verbose-settings']) {
$stringvlaues = array(
'name' => $setting,
'defaultsetting' => var_export($value, true) // Expand objects.
);
echo get_string('cliupgradedefaultverbose', 'admin', $stringvlaues) . PHP_EOL;
} else {
echo get_string('cliupgradedefault', 'admin', $setting) . PHP_EOL;
}
}
// This needs to happen at the end to ensure it occurs after all caches
// have been purged for the last time.
// This will build a cached version of the current theme for the user
// to immediately start browsing the site.
upgrade_themes();
echo get_string('cliupgradefinished', 'admin', $a)."\n";
if (!$options['maintenance']) {
cli_writeln(get_string('cliupgradecompletenomaintenanceupgrade', 'admin'));
// Here we check if upgrade lock has not been specifically set during this upgrade run.
// This supports wider server orchestration actions happening, which should call with no-maintenance AND set-ui-upgrade-lock,
// such as a new docker container deployment, of which the moodle upgrade is only a component.
if (!$options['set-ui-upgrade-lock']) {
// In this case we should release the lock now, as the upgrade is finished.
// We weren't told to keep the lock with set-ui-upgrade-lock, so release.
set_config('outagelessupgrade', false);
}
}
// apply all default settings, just in case do it twice to fill all defaults
admin_apply_default_settings(NULL, false);
admin_apply_default_settings(NULL, false);
echo get_string('cliupgradefinished', 'admin')."\n";
exit(0); // 0 means success
-65
View File
@@ -1,65 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Communication and its plugins settings.
*
* @package core
* @subpackage communication
* @copyright 2023 Huong Nguyen <huongnv13@gmail.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/communication.php');
$PAGE->set_context($syscontext);
require_admin();
require_sesskey();
$return = new moodle_url('/admin/settings.php', ['section' => 'managecommunicationproviders']);
$plugins = core_plugin_manager::instance()->get_plugins_of_type('communication');
$sortorder = array_flip(array_keys($plugins));
if (!isset($plugins[$name])) {
throw new moodle_exception('communicationprovidernotfound', 'core_communication', $return, $name);
}
$plugintypename = $plugins[$name]->type . '_' . $plugins[$name]->name;
switch ($action) {
case 'disable':
if ($plugins[$name]->is_enabled()) {
$class = core_plugin_manager::resolve_plugininfo_class('communication');
$class::enable_plugin($name, false);
}
break;
case 'enable':
if (!$plugins[$name]->is_enabled()) {
$class = core_plugin_manager::resolve_plugininfo_class('communication');
$class::enable_plugin($name, true);
}
break;
}
redirect($return);
-87
View File
@@ -1,87 +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])) {
throw new \moodle_exception('contenttypenotfound', 'error', $return, $name);
}
switch ($action) {
case 'disable':
if ($plugins[$name]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('contenttype');
$class::enable_plugin($name, false);
}
break;
case 'enable':
if (!$plugins[$name]->is_enabled()) {
$class = \core_plugin_manager::resolve_plugininfo_class('contenttype');
$class::enable_plugin($name, true);
}
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));
core_plugin_manager::reset_caches();
}
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));
core_plugin_manager::reset_caches();
}
break;
}
$cache = cache::make('core', 'contentbank_enabled_extensions');
$cache->purge();
$cache = cache::make('core', 'contentbank_context_extensions');
$cache->purge();
redirect($return);

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