Compare commits

..

541 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) 70fa678586 Moodle release 3.2.2 2017-03-11 22:16:10 +01:00
AMOS bot 0c6de97371 Automatically generated installer lang files 2017-03-12 00:04:17 +08:00
AMOS bot 63981e5a82 Automatically generated installer lang files 2017-03-12 00:04:17 +08:00
Eloy Lafuente (stronk7) 6a0dfc60d6 weekly release 3.2.1+ 2017-03-10 20:59:59 +01:00
Eloy Lafuente (stronk7) 38c4435a37 Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2017-03-10 20:59:55 +01:00
Damyon Wiese 3cc4e2f725 MDL-57596 forms: CLEANHTML in persistent forms
Add special handling for text fields with the CLEANHTML type. This should
be used when students and teachers can edit the same field (you can't trust those students).

Applies cleaning on submitted data, and on data stored in the DB before it is put back in an editing form.
2017-03-10 18:07:55 +00:00
Marina Glancy ca3cbbc233 MDL-58010 user: allow to update only whitelisted user preferences 2017-03-10 18:07:54 +00:00
Andrew Nicols 7d196ef3b3 Merge branch 'wip-mdl-57940-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-03-10 18:07:53 +00:00
Eloy Lafuente (stronk7) 069b9d5820 Merge branch 'MDL-58123-32' of git://github.com/junpataleta/moodle into MOODLE_32_STABLE 2017-03-10 18:07:53 +00:00
Dan Poltawski 454a3d34d5 Merge branch 'MDL-58035_32' of git://github.com/timhunt/moodle into MOODLE_32_STABLE 2017-03-10 18:07:52 +00:00
Ankit Agarwal db3a985faf MDL-56526 userlib: Do not allow not loggedin users if forceloginforprofile is set 2017-03-10 18:07:52 +00:00
Ankit Agarwal c535520966 MDL-56526 globalsearch: Fix bug in phpdocs 2017-03-10 18:07:51 +00:00
David Mudrák e35ad40de1 MDL-57597 competency: Fix serving of prior learning evidence files
For security reasons, all files submitted by students must be disposed
as attachments, not inline contents.
2017-03-10 18:07:51 +00:00
AMOS bot 436acc27fe Automatically generated installer lang files 2017-03-10 00:04:27 +08:00
Dan Poltawski 73fd6f2928 Merge branch 'MDL-57990-32' of git://github.com/crazyserver/moodle into MOODLE_32_STABLE 2017-03-07 13:59:15 -03:00
AMOS bot 84e17f59c5 Automatically generated installer lang files 2017-03-08 00:05:55 +08:00
Eloy Lafuente (stronk7) 63464df041 Merge branch 'MDL-58064-32-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_32_STABLE 2017-03-07 16:37:36 +01:00
Dan Poltawski 17c82085fc Merge branch 'wip-mdl-58056-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-03-07 11:08:23 -03:00
Dan Poltawski 5e3ce67f37 Merge branch 'MDL-57361-32' of git://github.com/jleyva/moodle into MOODLE_32_STABLE 2017-03-07 11:07:46 -03:00
Tim Hunt ec02a34e1f MDL-58035 tool_templatelibrary: fix unit test using removed base theme 2017-03-07 13:35:34 +00:00
Tim Hunt 1e1e1b8229 MDL-58035 lib: log when the expected theme cannot be initialised 2017-03-07 13:35:32 +00:00
David Monllao f7af2c5fc7 Merge branch 'MDL-58106_32' of git://github.com/timhunt/moodle into MOODLE_32_STABLE 2017-03-07 13:38:18 +01:00
David Monllao 92194c1c8d Merge branch 'wip-mdl-58091-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-03-07 13:16:03 +01:00
David Mudrák 7bbe8a1c76 MDL-58064 lang: Clarify the PHP 7.x limitations
These are related to SQL*Server support only and affect all PHP 7
versions, not just 7.0.x. Credit goes to Eloy Lafuente for spotting
this.
2017-03-07 13:00:46 +01:00
Dan Poltawski 22ee65c275 MDL-58040 blocks: add upgrade.txt note 2017-03-07 08:34:54 -03:00
Dan Poltawski 9354f9de64 Merge branch 'MDL-58040_32' of git://github.com/timhunt/moodle into MOODLE_32_STABLE 2017-03-07 08:34:48 -03:00
David Monllao 04d2305788 Merge branch 'wip-MDL-57485-32' of git://github.com/abgreeve/moodle into MOODLE_32_STABLE 2017-03-07 12:16:48 +01:00
David Monllao e21e294072 Merge branch 'MDL-58057-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2017-03-07 12:09:35 +01:00
Dan Poltawski 19b7ac05ad Merge branch 'MDL-55859-32' of git://github.com/ankitagarwal/moodle into MOODLE_32_STABLE 2017-03-07 07:02:31 -03:00
Dan Poltawski 4294bbd50f Merge branch 'MDL-58052_behat_get_session_user_MOODLE_32_STABLE' of https://github.com/gthomas2/moodle into MOODLE_32_STABLE 2017-03-07 06:54:34 -03:00
Adrian Greeve b1ffb73177 MDL-57485 themes: Set images to default display type.
Imported images in atto would no longer hold a URL
tag around it. display: block was the culprit.
2017-03-07 17:33:23 +08:00
Ankit Agarwal cde1ac3eea MDL-57362 assign: Fix permission checks 2017-03-07 13:04:01 +05:30
Jake Dallimore 059759aab9 MDL-58057 core_files: properly trim curl whitelist config when fetching 2017-03-07 09:49:50 +08:00
Dan Poltawski 188d41ccc9 Merge branch 'MDL-57362-32' of git://github.com/ankitagarwal/moodle into MOODLE_32_STABLE 2017-03-06 10:18:30 -03:00
gthomas2 0b5f9f6e60 MDL-58052 behat: user session function - use to edit current profile 2017-03-03 12:29:47 +00:00
Pau Ferrer Ocaña fa60a11522 MDL-57990 course: Add sortorder as public field 2017-03-03 11:52:10 +01:00
Eloy Lafuente (stronk7) 29cdf58116 weekly release 3.2.1+ 2017-03-03 10:33:52 +01:00
Eloy Lafuente (stronk7) 3db24b8015 Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2017-03-03 10:33:47 +01:00
Tim Hunt b21b210f41 MDL-58106 random Q restore: avoid MySQL performance issues 2017-03-02 19:40:53 +00:00
Ankit Agarwal 79482e3fe8 MDL-55859 assign_editpdf: cleanup htmlfile in case of errors 2017-03-02 21:16:37 +05:30
Cameron Ball 3935371599 MDL-57321 theme_boost: Remove extra quotation mark 2017-03-02 16:05:55 +08:00
Jun Pataleta 14026572ae MDL-58123 mod_lesson: Fix lesson table name in refresh_events DB query 2017-03-02 10:55:42 +08:00
Eloy Lafuente (stronk7) ee66d63054 Merge branch 'MDL-57321-32' of git://github.com/cameron1729/moodle into MOODLE_32_STABLE 2017-03-02 00:01:47 +01:00
Juan Leyva af2d6085cd MDL-57361 auth_email: Force policy agreed on sign-up 2017-03-01 18:20:59 +01:00
Cameron Ball e615d70923 MDL-57321 theme_boost: Remove duplicate aria-labelledby attribute 2017-03-01 11:37:29 +08:00
Cameron Ball ae8388d51c MDL-57321 theme_boost: Fix improperly nested ul elements in footer 2017-03-01 11:37:28 +08:00
Cameron Ball 962e3eb662 MDL-57321 theme_boost: Use div instead of span for dropdown items 2017-03-01 11:37:28 +08:00
Cameron Ball 4c586b025e MDL-57321 theme_boost: Consistently apply attributes on elements 2017-03-01 11:37:28 +08:00
Andrew Nicols 8612c8aa3e Merge branch 'MDL-58072_32_tabtree_mustache' of https://github.com/mchurchward/moodle into MOODLE_32_STABLE 2017-03-01 11:10:18 +08:00
Eloy Lafuente (stronk7) a7db91030b Merge branch 'wip-MDL-48228-32' of git://github.com/abgreeve/moodle into MOODLE_32_STABLE 2017-03-01 02:57:16 +01:00
Adrian Greeve d807d3c603 MDL-48228 database: Unit test addition and update. 2017-03-01 09:05:40 +08:00
Adrian Greeve 8f61b909e8 MDL-48228 database: Make utf8mb4 the default character set for mysql.
Thanks to Jetha Chan for providing the initial patch that this is
based on.
2017-03-01 09:05:40 +08:00
Eloy Lafuente (stronk7) e44ce23c9f Merge branch 'MDL-58071-32' of git://github.com/jleyva/moodle into MOODLE_32_STABLE 2017-02-28 23:00:42 +01:00
Eloy Lafuente (stronk7) 6c87b08240 Merge branch 'MDL-55762-32' of git://github.com/ankitagarwal/moodle into MOODLE_32_STABLE 2017-02-28 20:40:51 +01:00
David Monllao 9afdc8fc12 MDL-51833 docs: Move upgrade note under 3.2.2 2017-02-28 11:32:39 +01:00
David Monllao e30a500fb9 Merge branch 'wip-MDL-51833-32' of git://github.com/abgreeve/moodle into MOODLE_32_STABLE 2017-02-28 11:31:09 +01:00
Ankit Agarwal 121d3e0d29 MDL-57362 assignlib: Fix minor bug in phpdocs 2017-02-28 10:34:41 +05:30
Ankit Agarwal 5b7356cdde MDL-57362 assignlib: Check for sep groups edge case 2017-02-28 10:34:41 +05:30
Andrew Nicols 169d972bf6 Merge branch 'MDL-58038-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2017-02-28 12:25:43 +08:00
Rajesh Taneja 4fef0dadf0 MDL-58091 behat: Added missing @_file_upload tag 2017-02-28 11:22:38 +08:00
Andrew Nicols 96a0d1bc7a Merge branch 'MDL-35980-32' of git://github.com/snake/moodle into MOODLE_32_STABLE 2017-02-28 10:34:00 +08:00
Jake Dallimore 01c2ca76c0 MDL-35980 behat: fix link text in submission_comments feature 2017-02-28 10:24:53 +08:00
Andrew Nicols 46c68c1b42 MDL-55547 tool_monitor: Coding style fixes 2017-02-28 09:42:44 +08:00
Andrew Nicols e65f6a7e40 Merge branch 'wip-MDL-55547-32' of git://github.com/marinaglancy/moodle into MOODLE_32_STABLE 2017-02-28 09:42:39 +08:00
Eloy Lafuente (stronk7) 800da1b13d Merge branch 'MDL-58041_32' of https://github.com/sam-moodle/moodle into MOODLE_32_STABLE 2017-02-28 02:35:20 +01:00
Eloy Lafuente (stronk7) a53008f1f0 Merge branch 'MDL-57524_M32' of https://github.com/nadavkav/moodle into MOODLE_32_STABLE 2017-02-28 01:40:54 +01:00
Eloy Lafuente (stronk7) f1a117b86b Merge branch 'MDL-58030_32' of git://github.com/aolley/moodle into MOODLE_32_STABLE 2017-02-27 22:47:22 +01:00
Helen Foster bcbd4140a1 MDL-58064 lang: Merge English strings from the en_fix language pack 2017-02-27 10:20:17 +01:00
Rajesh Taneja c99c5a436e MDL-57940 behat: Allow behat parallel run to start with delay
Behat parallel run if executed together
then selenium might fail to launch browser
and timeout. It would be nice to have a
custom delay between the start of each process
2017-02-27 16:16:06 +08:00
Andrew Nicols b7d36bdbaf Merge branch 'MDL-50719-fast-locks-MOODLE_32_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_32_STABLE 2017-02-27 13:47:02 +08:00
Andrew Nicols c21f12e786 Merge branch 'MDL-35980-32' of git://github.com/snake/moodle into MOODLE_32_STABLE 2017-02-27 12:20:02 +08:00
Ankit Agarwal 2dd1bb44c2 MDL-55762 assignpdf: Handle errored pages better 2017-02-27 09:27:23 +05:30
Ankit Agarwal 63de9b5cdb MDL-55762 assignpdf: Fix bug in phpdocs 2017-02-27 09:27:23 +05:30
Andrew Nicols 24a00cadec Merge branch 'MDL-58032-32' of git://github.com/ankitagarwal/moodle into MOODLE_32_STABLE 2017-02-27 11:51:13 +08:00
Adrian Greeve 3f709d3272 MDL-51833 tool_monitor: Improve access check for monitor. 2017-02-27 09:00:54 +08:00
Nadav Kavalerchik def32a798d MDL-57524 theme_boost: Fix ignored input size on admin pages 2017-02-24 21:51:43 +02:00
Juan Leyva b63524492f MDL-58071 user: Return usernotfullysetup exception in WS
If there is an empty required custom user profile field, Web Services
should return the usernotfullysetup exception instead ignoring it.
The mobile app already handles this exception for core fields
redirecting the user to web in order to fill the missing field.
2017-02-24 20:17:19 +01:00
Mike Churchward 46f0136a5a MDL-58072 theme_boost: Added quotes to title; removed extra spaces. 2017-02-24 11:10:56 -05:00
Brendan Heywood 83dbc72f38 MDL-50719 cron: Fixed parallel task lock contention issues 2017-02-24 13:19:12 +11:00
Jake Dallimore c6911cefb4 MDL-56364 javascript: Prevent bad prototype chains in core dialogue
The DIALOGUE object was using Y.clone to copy the input config, messing
up the prototype chains for any objects in the config param. Really,
this doesn't need to clone the config, so I've refactored to avoid doing
so. Also moved some of the other attribute init and setup calls to the
appropriate places (initializer and modifyAttrs).
2017-02-24 08:27:44 +08:00
Jake Dallimore dfbdf40af9 MDL-35980 comment: add comment info to delete button for screen readers
For each delete button in the comments widget, make the spoken text a
string containing the name of the poster and the datetime.
2017-02-24 08:16:38 +08:00
Jake Dallimore 3e0fb6862e MDL-58038 email: make sure all allowedemaildomain entries are respected
Fixes a bug with exploding the config var, in which trailing carriage
returns were causing string matches to fail.
2017-02-24 08:07:59 +08:00
AMOS bot 0e8eba7e1f Automatically generated installer lang files 2017-02-24 00:07:41 +08:00
David Monllao d0209e611f weekly release 3.2.1+ 2017-02-23 08:07:49 +01:00
David Monllao ec9ed6d067 Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2017-02-23 08:07:48 +01:00
Rajesh Taneja 3e340aba45 MDL-58056 behat: Ensure form element exists
Before getting form field, ensure node is
visible. Else it may fail to get form
field
2017-02-23 14:45:43 +08:00
Rajesh Taneja de80be59bb MDL-58056 behat: Catch webdriver exception if element removed
While checking for element visibility, ensure
that element is there in dom
2017-02-23 14:45:43 +08:00
AMOS bot 310172571b Automatically generated installer lang files 2017-02-23 00:05:42 +08:00
David Monllao a550b70a94 MDL-58014 messaging: Note about behavioural change in message_count_unread_messages 2017-02-22 09:47:12 +01:00
Ankit Agarwal 3cd6842501 MDL-58032 core_user: Fix case when acting user is a visitor 2017-02-22 09:55:58 +05:30
Rajesh Taneja f17c1aadb3 MDL-57765 behat: Allow exact selectors to be used
In Blocks with boost theme selector to
find block with name is partial match
it might fail in some cases. It would
be nice to use exact match to avoid
unexpected failures
2017-02-21 23:57:37 +01:00
Sam Chaffee 043dffdd34 MDL-58041 tool_monitor: Fix event monitor subscription behat failures 2017-02-21 11:24:17 -07:00
Tim Hunt 6fef2ab3db MDL-58040 blocklib: never use global in block manager class
This switches everything to ->page, including coverting static method to real one.
2017-02-21 15:19:55 +00:00
Adam Olley 9ffcf8a3e9 MDL-58030 gradingform_guide: Init $commentchooser before use
The initialisation of $commentschooser was moved into an IF condition,
whilst still using it outside of that IF conditions scope. As such, if
there are no comments to choose from, the variable is never init'd but
it still goes to use it, emitting a PHP notice.
2017-02-21 14:36:49 +10:30
Eloy Lafuente (stronk7) 56b8f8c8be Merge branch 'wip-MDL-57113-MOODLE_32_STABLE' of https://github.com/kwiliarty/moodle into MOODLE_32_STABLE 2017-02-21 01:00:53 +01:00
Eloy Lafuente (stronk7) fede68a0ac Merge branch 'wip-mdl-56616-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-02-21 00:58:13 +01:00
Eloy Lafuente (stronk7) 6588079c5d Merge branch 'MDL-55867_m32v1' of https://github.com/sbourget/moodle into MOODLE_32_STABLE 2017-02-21 00:53:21 +01:00
Eloy Lafuente (stronk7) f7e4c3627c Merge branch 'MDL-56206_32-text-enrolled-users-page-aligned' of https://github.com/lucaboesch/moodle into MOODLE_32_STABLE 2017-02-20 19:26:35 +01:00
David Monllao 6c3f7e0ae6 Merge branch 'MDL-57576-32-updatefeedbackfile' of git://github.com/roperto/moodle into MOODLE_32_STABLE 2017-02-20 12:27:33 +01:00
Dan Poltawski 89d948d86b Merge branch 'MDL-57962-32' of git://github.com/dpalou/moodle into MOODLE_32_STABLE 2017-02-20 11:19:17 +00:00
David Monllao e1dcad3d13 Merge branch 'MDL-57795-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2017-02-20 10:28:23 +01:00
David Monllao 07d000c51e Merge branch 'MDL-57801-32' of https://github.com/lucisgit/moodle into MOODLE_32_STABLE 2017-02-20 10:10:15 +01:00
David Monllao 636e7a13b6 Merge branch 'MDL-58014_32' of git://github.com/markn86/moodle into MOODLE_32_STABLE 2017-02-20 09:34:43 +01:00
David Monllao a57bdfa055 Merge branch 'MDL-56679-32' of git://github.com/junpataleta/moodle into MOODLE_32_STABLE 2017-02-20 09:20:26 +01:00
David Monllao 80a57cf924 Merge branch 'MDL-57274-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2017-02-20 09:07:25 +01:00
David Monllao 059d6ffd9f Merge branch 'MDL-50729-32' of git://github.com/ankitagarwal/moodle into MOODLE_32_STABLE 2017-02-20 08:27:07 +01:00
Mark Nelson fd13953a8a MDL-58014 core_message: fixed unread message count 2017-02-20 13:59:33 +08:00
Marina Glancy 488e115027 MDL-55547 tool_monitor: fix exceptions when course was deleted
Delete subscriptions when course is deleted
2017-02-20 12:16:27 +08:00
Jake Dallimore 72e3ff3c15 MDL-57274 upgrade: fix curl security notices during upgrade/install
Handles the case where $CFG->curlsecurityxxx vars don't yet exist
during install or upgrade by treating not set the same as empty.
2017-02-20 08:56:47 +08:00
Jake Dallimore bd4f6ce186 MDL-57795 mod_assign: fix for filters killing review pane when grading
Fixes a bug in which the review pane was destroyed if the user selected
a combination of filters resulting in no matched users. Now, the pane
is just hidden in such cases, and displayed again if subsequent filter
changes return one or more users.
2017-02-20 08:53:00 +08:00
Dan Poltawski 5416d932d7 Merge branch 'MDL-57967_32' of git://github.com/markn86/moodle into MOODLE_32_STABLE 2017-02-19 19:44:51 +00:00
Matteo Scaramuccia 27e719e709 MDL-57379 Files: Improved file argument evaluation.
get_file_argument() is responsible to extract the relative path
of the file to be served by a specific Moodle component
like a theme or a module.
Some modules like scorm and imscp require slasharguments support
and they force it when creating the URLs to serve their files.
It should honor the slasharguments setting but this could break
those instances where existing hard-coded links still make usage of
the "old" format, the one when slasharguments is set to No i.e. '?file='.

Its logic has been improved by looking at when the URL is related to
serving a plug-in file in a "forced" slasharguments way of serving it
i.e. using '/pluginfile.php/' and not '/pluginfile.php?'.
2017-02-19 18:44:48 +00:00
Tony Butler b577d34861 MDL-57801 core_filestorage: Delete temp file if disk space runs out 2017-02-16 12:46:46 +00:00
Tony Butler dcd27d9cee MDL-57801 core_filestorage: Verify hash of temp file before committing
This addresses an edge scenario on NFS filesystems with no space
remaining, where subsequent uploads fail silently while zero byte files
are saved to the pool (and for some reason the filesize check passes).
2017-02-16 12:46:46 +00:00
Gergely Kún 863dcb14a8 MDL-56679 core: Initialise $SESSION if necessary 2017-02-16 16:19:42 +08:00
Dan Poltawski 1a754e8446 weekly release 3.2.1+ 2017-02-16 08:14:54 +00:00
Dan Poltawski 95e9f4cc02 Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2017-02-16 08:14:48 +00:00
Mark Nelson bac13609ca MDL-57967 core_message: do not process conversations from deleted users 2017-02-16 13:03:02 +08:00
Rajesh Taneja df90a44f3f MDL-57030 behat: Save run status after execution 2017-02-15 10:38:43 +01:00
Eloy Lafuente (stronk7) 23fd4f3afc Merge branch 'MDL-53991_m32v4' of https://github.com/sbourget/moodle into MOODLE_32_STABLE 2017-02-14 18:16:24 +01:00
Eloy Lafuente (stronk7) 9b39a92170 Merge branch 'wip-mdl-57030-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-02-14 16:53:59 +01:00
David Monllao 69c5e60f8c MDL-56122 editpdf: Fix ghostscript checking 2017-02-14 13:45:39 +01:00
Brendan Heywood cc36a37ea4 MDL-57810 lib: Disable nginx buffers when not required 2017-02-14 11:36:01 +00:00
Dani Palou 2678ee4e81 MDL-57962 forum: Allow creating new discussions with groupid -1 2017-02-14 10:44:00 +01:00
David Monllao 5a9f3039a7 Merge branch 'MDL-56122-32' of https://github.com/lucisgit/moodle into MOODLE_32_STABLE 2017-02-14 09:53:39 +01:00
Ankit Agarwal 667784420f MDL-50729 gradelib: Regrade event should be assigned to system 2017-02-14 11:40:54 +05:30
Ankit Agarwal f628e0ecf6 MDL-50729 events: Add user constants to events base class 2017-02-14 11:40:54 +05:30
Damyon Wiese 9ae3b89cc5 MDL-57766 assign: Put back the manual marker filter
I removed too much from gradingtable.php in the last patch.
2017-02-14 10:19:15 +08:00
Eloy Lafuente (stronk7) 098a875e4e Merge branch 'MDL-57868-32' of git://github.com/jleyva/moodle into MOODLE_32_STABLE 2017-02-13 23:42:46 +01:00
Eloy Lafuente (stronk7) 9d64f4f078 Merge branch 'MDL-57708-32' of git://github.com/merrill-oakland/moodle into MOODLE_32_STABLE 2017-02-13 23:33:00 +01:00
Tony Butler 5fac573391 MDL-56122 assignfeedback_editpdf: Add test assertions for pdf generation 2017-02-13 17:30:15 +00:00
Tony Butler def9c15904 MDL-56122 assignfeedback_editpdf: Regenerate PDF & page images if blank 2017-02-13 17:30:15 +00:00
Dan Poltawski d4e9fe521e Merge branch 'MDL-56841_32' of https://github.com/andrewhancox/moodle into MOODLE_32_STABLE 2017-02-13 16:39:39 +00:00
B Krishnan Iyer 343cdba46b MDL-57354 output: Render continue button as a primary button. 2017-02-13 15:50:43 +00:00
Davo Smith aca74d0d74 MDL-57752 session: fix check_security() session termination 2017-02-13 13:54:43 +00:00
Dan Poltawski ce01dbab40 Merge branch 'MDL-57768-webservice-config-error-MOODLE_32_STABLE' of https://github.com/ilya-catalyst/moodle into MOODLE_32_STABLE 2017-02-13 13:31:04 +00:00
David Monllao 21cf201536 Merge branch 'MDL-57766-32' of git://github.com/damyon/moodle into MOODLE_32_STABLE 2017-02-13 09:44:25 +01:00
David Monllao dfefe26665 Merge branch 'wip-MDL-50770-32' of git://github.com/marinaglancy/moodle into MOODLE_32_STABLE 2017-02-13 09:15:08 +01:00
Rajesh Taneja de70bc556c MDL-56616 theme_boost: Fix style for performance info 2017-02-13 14:39:23 +08:00
AMOS bot 7b06a12ef3 Automatically generated installer lang files 2017-02-11 00:11:46 +08:00
Ilya Tregubov a415eb505e MDL-57768 webservice: Delete manual setting of config in test 2017-02-10 11:48:44 +11:00
Damyon Wiese 54a20ea8fc MDL-57766 mod_assign: Marker allocation fixes
Marking allocation was only ever applied in the view for the grading table. It should
have been added to the list_participants function because that is used by webservices and
the new grading UI.
2017-02-09 17:15:10 +08:00
David Monllao a1740aad65 weekly release 3.2.1+ 2017-02-09 08:00:10 +01:00
David Monllao 3680b1efa0 Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2017-02-09 08:00:09 +01:00
Ryan Wyllie b90c2e2627 MDL-57370 message: add unread count to conversation tests 2017-02-09 13:46:31 +08:00
Ryan Wyllie 5c53893f97 MDL-57370 message: improve message union sql 2017-02-09 13:46:30 +08:00
Rajesh Taneja 3049c086a3 MDL-57030 behat: Added option to automatically rerun failures 2017-02-09 07:16:00 +08:00
Eric Merrill c644b03f02 MDL-57708 assign: Fix display of overridden submissions 2017-02-08 14:54:11 -05:00
David Monllao 7693409caa Merge branch 'wip-MDL-57316-32' of git://github.com/marinaglancy/moodle into MOODLE_32_STABLE 2017-02-08 13:11:40 +01:00
Dan Poltawski eac59c38f8 Merge branch 'MDL-57370-32-int-fix-1' of git://github.com/ryanwyllie/moodle into MOODLE_32_STABLE 2017-02-08 09:14:22 +00:00
Dan Poltawski cd6612b079 MDL-57370 messaging: fix mesed up versions
(Again, I didn't have a good day yesterday...)
2017-02-08 09:08:02 +00:00
Ryan Wyllie 7d88829470 MDL-57370 message: fix duplicate ids 2017-02-08 07:43:14 +00:00
Rajesh Taneja 9fde80dfa0 MDL-56954 behat: Fixed string to pass behat
colon is not concatenated to Search courses string
2017-02-08 12:19:26 +08:00
Damyon Wiese e787fa6ab4 MDL-57009 javascript: Fix "failed to prefetch"
The scanForPartials in amd/src/templates.js function is not handling
nested sections (the list of tokens is a tree not a flat list).
2017-02-08 11:17:39 +08:00
Marina Glancy 24cfd4c7d8 MDL-57316 media: create different instances for different pages 2017-02-08 10:17:18 +08:00
AMOS bot de33f85405 Automatically generated installer lang files 2017-02-08 00:09:21 +08:00
Damyon Wiese 57e38e1d12 MDL-57009 javascript: Reject on all errors
Not all error paths were resulting in a reject() call to fail a promise.
2017-02-07 12:37:10 +00:00
Damyon Wiese ddbf8c29ae MDL-57009 javascript: Always use when.apply
Or it does not really wait for the promises.
2017-02-07 12:37:02 +00:00
Dan Poltawski f265312fcf Merge branch 'MDL-57009-32' of git://github.com/damyon/moodle into MOODLE_32_STABLE 2017-02-07 12:36:27 +00:00
Dan Poltawski 7dc6674cc4 MDL-57370 upgrade: fix versions 2017-02-07 10:49:49 +00:00
Dan Poltawski c1b9c51914 Merge branch 'MDL-57370-32' of git://github.com/ryanwyllie/moodle into MOODLE_32_STABLE 2017-02-07 10:25:27 +00:00
Luca Bösch 14da7f58a4 MDL-56206 themes: Text on Enrolled users page well aligned
Helps to align the table row content.
2017-02-07 07:19:37 +01:00
Eloy Lafuente (stronk7) 18221902bc Merge branch 'MDL-56954-32' of git://github.com/lameze/moodle into MOODLE_32_STABLE 2017-02-07 06:35:08 +01:00
Ryan Wyllie 7d9ee66a2f MDL-57370 message: change indexes on message tables 2017-02-07 01:44:39 +00:00
John Okely de60425a16 MDL-57316 media: Setup media plugins in media_manager::instance() 2017-02-07 09:43:49 +08:00
John Okely 4eb3f8d9b7 MDL-57316 videojs: Add behat tests for lesson, url and resource 2017-02-07 09:43:48 +08:00
Ryan Wyllie 994e94bf76 MDL-57370 message: unit tests for get_conversations 2017-02-07 01:43:33 +00:00
Ryan Wyllie 2f9f8b5903 MDL-57370 message: remove joins from get_conversations
I have broken up the single query that was doing multiple joins on the
messaging and user tables. It no longer does any joins and will instead
query each data set individually.

This may cost more in terms of PHP processing but it will mean that
standard database tunings should be able to handle larger data sets.

For example this function was taking a long time to run on moodle.org
and was causing the MySQL join buffer to overflow.
2017-02-07 01:43:32 +00:00
Eloy Lafuente (stronk7) 3923610e6c Merge branch 'wip-mdl-57851-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-02-07 01:26:21 +01:00
Eloy Lafuente (stronk7) 0913eb3c2a Merge branch 'wip-mdl-57853-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-02-06 21:55:05 +01:00
AMOS bot f5b50e0472 Automatically generated installer lang files 2017-02-07 00:05:29 +08:00
Eloy Lafuente (stronk7) 09261027b6 Merge branch 'MDL-53349-32' of https://github.com/xow/moodle into MOODLE_32_STABLE 2017-02-06 16:09:46 +01:00
Dan Poltawski e0c4e6496f Merge branch 'MDL-57660-32' of git://github.com/junpataleta/moodle into MOODLE_32_STABLE 2017-02-06 13:47:29 +00:00
Dan Poltawski 672ce4c6cd Merge branch 'MDL-57587_32' of git://github.com/timhunt/moodle into MOODLE_32_STABLE 2017-02-06 11:04:00 +00:00
Juan Leyva 13a2a8344c MDL-57868 mod_feedback: Fix incorrect query parameters order
get_records_menu call get_records using the same params ordering, it is
causing a duplicated value error for the first column
2017-02-06 11:32:33 +01:00
David Monllao 8184f47d6c Merge branch 'MDL-57777-m32' of https://github.com/micaherne/moodle into MOODLE_32_STABLE 2017-02-06 09:41:52 +01:00
Rajesh Taneja 7a7320af90 MDL-57853 phpunit: Remove use of setExpectedException 2017-02-06 11:45:45 +08:00
Stephen Bourget 70fd9fbb39 MDL-55867 block_activity_results: Sort activities alphabetically. 2017-02-05 21:30:01 -05:00
Rajesh Taneja e16448d3f1 MDL-57851 behat: Add some more wait for scenario to pass
On slow machine with phnatomjs profile
this scenario keeps failing. Add some more
wait to ensure the page is stable and next
step can be executed
2017-02-03 12:54:45 +08:00
AMOS bot 2b4eb2cb71 Automatically generated installer lang files 2017-02-03 00:04:16 +08:00
Andrew Hancox ed798679bb MDL-56841 mod_folder: Display edit and download buttons inline 2017-02-02 15:17:00 +00:00
Simey Lameze 299dcca1b1 MDL-56954 theme_boost: apply bs4 styles to course management page 2017-02-02 15:52:51 +08:00
Andrew Nicols c16c53d137 weekly release 3.2.1+ 2017-02-02 11:32:16 +08:00
Andrew Nicols 52723e1e3f Merge branch 'MDL-57630-m32' of https://github.com/micaherne/moodle into MOODLE_32_STABLE 2017-02-02 09:19:08 +08:00
Rajesh Taneja 0bcbd5b205 MDL-54628 behat: Rerun command now include replace option passed 2017-02-02 08:21:31 +08:00
Nadav Kavalerchik ec319d13df MDL-53349 Autocomplete: Support multi lingual COMMA keycode (44) 2017-02-01 16:30:23 +08:00
Ankit Agarwal 0c4422af0b MDL-57300 lti: Make tool provider page more readable 2017-02-01 11:51:32 +05:30
Ankit Agarwal 40dcbac3d6 MDL-57027 accesslib: Improve perf of sql 2017-02-01 13:06:03 +08:00
Petr Skoda 62eb5ef8eb MDL-57027 fix get_users_by_capability()
Change-Id: I98dc88784dfa0293f88a19c3d36e7a46a3f52672
2017-02-01 13:06:02 +08:00
Eloy Lafuente (stronk7) 434e8abac8 Merge branch 'MDL-57592-32' of https://github.com/mwehr/moodle into MOODLE_32_STABLE 2017-02-01 13:06:01 +08:00
Dan Poltawski 28add18d9b Merge branch 'MDL-57588_32' of git://github.com/timhunt/moodle into MOODLE_32_STABLE 2017-02-01 13:06:01 +08:00
Dan Poltawski f9220d8138 Merge branch 'wip-mdl-54628-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-02-01 13:06:00 +08:00
Dan Poltawski 32237b8308 Merge branch 'MDL-57300-32' of git://github.com/ankitagarwal/moodle into MOODLE_32_STABLE 2017-02-01 13:06:00 +08:00
Dan Poltawski c2ae90c553 Merge branch 'MDL-57728_m32v1' of https://github.com/sbourget/moodle into MOODLE_32_STABLE 2017-02-01 13:05:59 +08:00
Michael Aherne 7035e0f5b5 MDL-57777 rss: Return 404 when context not found. 2017-01-31 09:31:31 +00:00
Andrew Nicols 6a3777f90c Merge branch 'wip-MDL-57785-32' of git://github.com/amygroshek/moodle into MOODLE_32_STABLE 2017-01-31 12:21:37 +08:00
Andrew Nicols de7a6ff47e Merge branch 'MDL-35978-32-blockfix' of https://github.com/snake/moodle into MOODLE_32_STABLE 2017-01-31 11:51:17 +08:00
Jake Dallimore 46e26a1b69 MDL-35978 comments: fix for comments block which has no toggler 2017-01-31 11:33:02 +08:00
Andrew Nicols 0db0a63e50 Merge branch 'MDL-57296-32' of git://github.com/ankitagarwal/moodle into MOODLE_32_STABLE 2017-01-31 08:54:47 +08:00
wehr 120798e85f MDL-57592 assignment: Adds filtering of assignment name in grader view 2017-01-30 18:25:17 +01:00
Tim Hunt 4679634e36 MDL-57588 questions: regrading should not lose flags 2017-01-30 14:32:16 +00:00
Dan Poltawski 1c0462deb3 Merge branch 'wip-MDL-57782-32' of git://github.com/marinaglancy/moodle into MOODLE_32_STABLE 2017-01-30 10:08:28 +00:00
Dan Poltawski 7dc8cc1ab6 Merge branch 'MDL-35978-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2017-01-30 09:54:13 +00:00
Dan Poltawski 170cd579ff Merge branch 'MDL-36233-32' of git://github.com/lameze/moodle into MOODLE_32_STABLE 2017-01-30 09:34:54 +00:00
Ankit Agarwal 6c83de1d51 MDL-57296 gradelib: Fix get_hidding_effect for grade_type_none items 2017-01-30 13:49:57 +05:30
Ankit Agarwal 0ef42d5f6d MDL-57296 gradebook: Fix issue with gradebook while collapsing grades 2017-01-30 13:49:57 +05:30
Mike Churchward ffc60d23b4 MDL-36233 mod_assign: fixed submission time comparison sql and test. 2017-01-30 09:26:39 +08:00
Rajesh Taneja 4f5a6ca40e MDL-54628 behat: Set behat dir for each run under behat_dataroot
Before this patch behat_dataroot for parallel runs
were created at same level as ->behat_dataroot
After this patch, it will be created 1 level under
->behat_dataroot with BEHAT_PARALLEL_SITE_NAME
prefix and run number as suffix. This will allow
common files as test enabled and parallel run info
to be saved in parent directory and access it easily.
2017-01-30 09:23:58 +08:00
Rajesh Taneja a669c6b21e MDL-54628 behat: Show parallel run command with proper rerun option 2017-01-30 09:23:58 +08:00
Kevin Wiliarty e7734513b8 MDL-57113 boost: min-width for region-main in grade views 2017-01-28 11:47:13 -05:00
Amy Groshek 44b4f83298 MDL-57785 scorm: Prevents SCORM nav refresh when nav not shown.
This improvement prevents refresh of SCORM 1.2 navigation menu
when the navigation menu is not displayed.
2017-01-27 09:12:45 -06:00
Marina Glancy 49053808a2 MDL-57782 enrol_self: fix check when email needs to be sent
Thanks to Leandro for providing a fix
2017-01-27 14:25:17 +08:00
Helson Castro 8ea5d72218 MDL-57568 forms: Added missing include for button element. 2017-01-27 14:01:16 +08:00
Jake Dallimore e33b7b342a MDL-35978 comments: expandable comments announce change when toggled
Added role and aria-expanded attributes to the toggler link and added
a key handler for the space and enter keys.
2017-01-27 13:07:12 +08:00
Jun Pataleta f33a8d4eee MDL-57660 mod_forum: Preserve forum ID selection after form submission 2017-01-27 10:09:54 +08:00
Eloy Lafuente (stronk7) 6a4a1d812c weekly release 3.2.1+ 2017-01-27 00:28:06 +01:00
Eloy Lafuente (stronk7) c94dce9c89 Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2017-01-27 00:28:01 +01:00
Tim Hunt a551ea0210 MDL-57587 question file access: fix regression caused by MDL-53744 2017-01-26 18:54:28 +00:00
Michael Aherne 72b489ef65 MDL-57777 rss: Return 404 when context not found. 2017-01-26 10:51:47 +00:00
Eloy Lafuente (stronk7) 827d93f88a Merge branch 'MDL-55915_32' of https://github.com/rezaies/moodle into MOODLE_32_STABLE 2017-01-24 22:11:41 +01:00
AMOS bot 884f4d3ec3 Automatically generated installer lang files 2017-01-25 00:04:42 +08:00
Ankit Agarwal a072271853 MDL-57300 lti: Rename lti2 as registration url
AMOS BEGIN
CPY [registrationurl,mod_lti],[registrationurl,enrol_lti]
AMOS END
2017-01-24 16:41:04 +05:30
Ankit Agarwal 95c794075a MDL-57300 lti: Fix incorrect variable types in docs 2017-01-24 16:41:04 +05:30
Dan Poltawski 890f84cdb2 Merge branch 'MDL-57639-32' of git://github.com/andrewnicols/moodle into MOODLE_32_STABLE 2017-01-24 10:11:29 +00:00
Dan Poltawski b4e1bbef47 Merge branch 'MDL-57667-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2017-01-24 09:40:57 +00:00
Andrew Nicols 678d051bee Merge branch 'm32_MDL-46782' of git://github.com/danmarsden/moodle into MOODLE_32_STABLE 2017-01-24 10:44:03 +08:00
Dan Marsden c83ef7e25b MDL-46782 mod_scorm: fix completion test, remove redundant test. 2017-01-24 13:06:57 +13:00
Dan Poltawski 1ee447d3a4 Merge branch 'wip_32_mdl-50625_ldap_better_check_paged_results_support' of https://github.com/iarenaza/moodle into MOODLE_32_STABLE 2017-01-23 16:21:02 +00:00
Dan Poltawski 217d523d43 Merge branch 'wip-MDL-57511-32' of git://github.com/Beedell/moodle into MOODLE_32_STABLE 2017-01-23 15:39:57 +00:00
Dan Poltawski 76cebe50cb Merge branch 'MDL-57415_m32v1' of https://github.com/sbourget/moodle into MOODLE_32_STABLE 2017-01-23 12:24:11 +00:00
Dan Poltawski 7dfc04ff98 Merge branch 'MDL-57287-32' of git://github.com/snake/moodle into MOODLE_32_STABLE 2017-01-23 12:19:23 +00:00
Dan Poltawski ff037d9698 Merge branch 'mdl57668-moodle32' of https://github.com/tlock/moodle into MOODLE_32_STABLE 2017-01-23 12:05:33 +00:00
Dan Poltawski 39dc183d9f Merge branch 'wip-mdl-57700-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-01-23 11:59:11 +00:00
Dan Poltawski f7ddcd23f8 Merge branch 'MDL-57677-32-usermodified' of git://github.com/mudrd8mz/moodle into MOODLE_32_STABLE 2017-01-23 09:48:12 +00:00
Dan Poltawski 92f57f8397 Merge branch 'm32_MDL-46782' of git://github.com/danmarsden/moodle into MOODLE_32_STABLE 2017-01-23 09:28:31 +00:00
Dan Poltawski 98f246ae97 Merge branch 'MDL-57737-32' of git://github.com/crazyserver/moodle into MOODLE_32_STABLE 2017-01-23 09:26:56 +00:00
Pau Ferrer Ocaña f9e7ee4534 MDL-57737 glossary: Add entry description accepts HTML 2017-01-20 13:26:02 +01:00
Shamim Rezaie b14507a31f MDL-55915 enrol_manual: let fullname()know if user has viewfullnames cap
fullname() relies on its second parameter to determine wheter it should use fullnamedisplay or alternativefullnameformat.
We need to check for moodle/site:viewfullnames capability and pass true as the second parameter to fullname() whereever
the user has this capability.
2017-01-20 19:31:08 +11:00
Shamim Rezaie 4436b9e9dd MDL-55915 core_user: let fullname() know if user has viewfullnames cap
Added $viewfullnames property to the user_selector_base class so anyone using a child class of this class can
let it know if user has viewfullnames capability or not.
2017-01-20 19:30:21 +11:00
Shamim Rezaie 2568183232 MDL-55915 Gradebook: let fullname() know if user has viewfullnames cap
Instruct fullname() to format names on the gradebook grader report with alternativefullnameformat when user
has moodle/site:viewfullnames capability.
2017-01-20 19:28:36 +11:00
Shamim Rezaie bcca23f9c5 MDL-55915 mod_assign: let fullname() know if user has viewfullnames cap
Instruct fullname() to format names on the assignment grading page with alternativefullnameformat when user
has moodle/site:viewfullnames capability.
2017-01-20 19:26:33 +11:00
Rajesh Taneja bab24efe70 MDL-57700 behat: Fixed undefined RuntimeException 2017-01-20 11:05:10 +08:00
Jake Dallimore 45a46ecbd8 MDL-57667 theme: change base layout for boost to columns2
Ensures capability errors are displayed on a page with full navigation.
2017-01-20 08:48:38 +08:00
Stephen Bourget 64cfe467f8 MDL-57728 theme: Fix text display when using tabs 2017-01-19 11:32:52 -05:00
AMOS bot 48f0ebcd49 Automatically generated installer lang files 2017-01-20 00:07:16 +08:00
John Beedell 6537c557b5 MDL-57511 Quiz: Attempts report shows non-unique debugging 2017-01-19 14:44:16 +00:00
Iñaki Arenaza 225e039e73 MDL-50625 auth_ldap: Better check for paged results support
There is at least one LDAP server (Sun Directory Server) that doesn't
support Paged Results extension, even if it supports LDAP version 3. So
checking just for LDAP version is not enough.

If possible, we check the supportedControl attribute of the LDAP rootDSE
and see if the paged results control is available. This needs an LDAP
connection, which might not be possible to establish before we configure
some essential LDAP settings (server, bind user, password, etc.). Thus
we try to establish the connection and check the supportedControl
attribute. But if we fail, we perform only basic checks that are less
accurate and err on the side of cautiousness.
2017-01-19 10:58:13 +01:00
Andrew Nicols c8dddb5ccb MDL-57639 mod_forum: Update to use correct variable name
This addresses a regression where unnecessary attributes were removed
from the old variable. This one was missed.
2017-01-19 13:47:45 +08:00
Andrew Nicols 3e276d6efa weekly release 3.2.1+ 2017-01-19 12:17:57 +08:00
Andrew Nicols adf2ea6166 Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2017-01-19 12:17:56 +08:00
Andrew Nicols fd90d0e925 MDL-57613 enrol_lti: Correct location of upgrade step 2017-01-19 07:56:17 +08:00
Tim Lock 58a4ce4774 MDL-57668 mod_assign: Fix optional_param() form processing 2017-01-19 08:08:07 +10:30
Stephen Bourget b44972cc8b MDL-57415 user: Add missing bootstrap classes to participants page 2017-01-18 10:38:33 -05:00
Dan Poltawski 655570df00 MDL-57604 mod_assign: fix empty case in user selector
Sadly the js arguments object gives an arguments.length of 1 when
no arguments are passed, so we have to explicitly check for it.
2017-01-18 09:59:33 +01:00
Dan Marsden dbf70dec42 MDL-46782 mod_scorm: Load first incomplete sco on re-entry. 2017-01-18 21:03:52 +13:00
Rajesh Taneja c40ed5f6ff MDL-45821 behat: navigate back to scorm to avoid scroll
On Exiting scrom activity, it goes back to course
and scrolls to section. On slow machines next step
fails. To avoid such case navigate to home screen
and then follow next step.
2017-01-18 13:03:07 +08:00
Andrew Nicols 2827c7f997 Merge branch 'MDL-57634-m32' of https://github.com/micaherne/moodle into MOODLE_32_STABLE 2017-01-18 12:38:14 +08:00
Andrew Nicols 2259fb5f36 Merge branch 'wip_MDL-57590_32_forum_search' of https://github.com/mchurchward/moodle into MOODLE_32_STABLE 2017-01-18 08:38:10 +08:00
Dan Poltawski 6dc7039af9 MDL-57604 mod_assign: Adding some missing stuff in 32_STABLE
In order to keep 31, 32 and master the same.
2017-01-18 01:04:48 +01:00
Eloy Lafuente (stronk7) ee7b977a8b Merge branch 'MDL-57604-32' of git://github.com/danpoltawski/moodle into MOODLE_32_STABLE 2017-01-18 00:17:11 +01:00
Eloy Lafuente (stronk7) f4841f394c Merge branch 'wip-MDL-57608-32-3' of git://github.com/marinaglancy/moodle into MOODLE_32_STABLE 2017-01-17 20:46:19 +01:00
David Mudrák 6973e38a91 MDL-57677 mod_forum: Fix wrong user displayed as the last post's author
In the recent issue MDL-56225, we started to record the current user as
the usermodified in the forum_discussions table when updating a forum
post. It made sense but it was a mistake.

Even if the current user really modifies the discussion by updating the
post, the field usermodified has actually been always interpreted and
displayed as the last post' author. Not as the last user who touched the
discussion.

This patch reverts that particular change to the previous behaviour and
adds explicit unit test for it.
2017-01-17 19:39:40 +01:00
AMOS bot c1b158b569 Automatically generated installer lang files 2017-01-18 00:07:24 +08:00
Dan Poltawski 21a8a95869 Merge branch 'wip-mdl-57669-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-01-17 10:28:52 +00:00
sam marshall 359914c8f6 MDL-57515 Resource: 'not very efficient' with a large number of files
Fixes bug where the resource module loads metadata for all files while
building course modinfo, even though it only needs the first file.
(This causes problems if you have ~10k files.)
2017-01-17 10:22:13 +00:00
Jake Dallimore 95208fe135 MDL-57287 themes: fix buttons in default dashboard page header
This fix modifies styling for pages having no navbar, such as the
dashboard, site home and default dashboard pages and fixes an overlap
problem with the buttons and context header.
2017-01-17 15:55:39 +08:00
Rajesh Taneja df428648ee MDL-57669 behat: Exit with error code if step undefined 2017-01-17 10:32:47 +08:00
Dan Poltawski 9148905e9a Merge branch 'MDL-57368-32-2' of https://github.com/snake/moodle into MOODLE_32_STABLE 2017-01-16 16:19:57 +00:00
Dan Poltawski 64df3fed13 Merge branch 'MDL-57613-32' of https://github.com/xow/moodle into MOODLE_32_STABLE 2017-01-16 16:17:16 +00:00
Mike Churchward ed4aaea57b MDL-57590 mod_forum: fixed search form with forumid and actionurl. 2017-01-16 11:16:27 -05:00
AMOS bot 163fc8588d Automatically generated installer lang files 2017-01-17 00:08:10 +08:00
Dan Poltawski 39e34b9586 Merge branch 'MDL-57452_behat_completion_fix_master_MOODLE_32_STABLE' of https://github.com/gthomas2/moodle into MOODLE_32_STABLE 2017-01-16 13:34:09 +00:00
Dan Poltawski 5c63ab7ee8 Merge branch 'MDL-57601-m32' of https://github.com/sammarshallou/moodle into MOODLE_32_STABLE 2017-01-16 12:23:06 +00:00
Dan Poltawski 3e3068cd11 Merge branch 'MDL-57374_m32' of https://github.com/dasistwas/moodle into MOODLE_32_STABLE 2017-01-16 12:10:51 +00:00
Dan Poltawski a27dde0ba7 Merge branch 'MDL-57554-32' of git://github.com/crazyserver/moodle into MOODLE_32_STABLE 2017-01-16 11:17:59 +00:00
Dan Poltawski b92400a49f Merge branch 'm32_MDL-45821' of git://github.com/danmarsden/moodle into MOODLE_32_STABLE 2017-01-16 09:17:50 +00:00
Dan Poltawski a477c8b752 Merge branch 'wip-MDL-56271-32' of git://github.com/marinaglancy/moodle into MOODLE_32_STABLE 2017-01-16 08:01:23 +00:00
Pau Ferrer Ocaña 7f52d5c740 MDL-57554 forum: Mark as read on view_forum_discussion calls 2017-01-13 09:27:06 +01:00
John Okely f52bdbb885 MDL-57613 enrol_lti: Allow longer nonces 2017-01-13 11:22:19 +08:00
David Bogner 7c519588f1 MDL-57374 editor: Pasting plain text in Atto removes all styles/classes 2017-01-12 18:00:37 +01:00
AMOS bot 7345917de4 Automatically generated installer lang files 2017-01-13 00:05:19 +08:00
Stephen Bourget 8a71b10a68 MDL-53991 calendar: fix repeating events on course import 2017-01-12 09:40:38 -05:00
Michael Aherne 18907a51d5 MDL-57634 messaging: Ensure test uses a configured plugin 2017-01-12 12:31:56 +00:00
gthomas2 11d04ffe8a MDL-57452 behat: Make completion check work with manual completion input 2017-01-12 11:38:59 +00:00
Dan Poltawski 5e1014a76e weekly release 3.2.1+ 2017-01-12 07:42:37 +00:00
Dan Poltawski 6e497e6e7d Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2017-01-12 07:42:36 +00:00
Jake Dallimore 66a4a376ee MDL-57368 mod_feeback: fix drag and drop question reordering in boost 2017-01-12 11:37:43 +08:00
Jake Dallimore 3563244314 MDL-57368 templates: add example context to core_form/element-template 2017-01-12 11:37:34 +08:00
Dan Poltawski bf02dc9819 MDL-57608 media_videojs: lazily load videojs on demand
The videojs javascript is over 1MB of javascript which we don't need to
load on every page, now that we only require it demand, the js can be
lazily loaded when its needed, which keeps the first.js smaller and more
likely to stay in browser cache.
2017-01-12 10:56:06 +08:00
Dan Poltawski 8e8c066448 MDL-57608 media_videojs: fix third party locations 2017-01-12 10:56:06 +08:00
Marina Glancy 67f83d9279 MDL-57608 media_videojs: load youtube module only when requested 2017-01-12 10:56:06 +08:00
Michael Aherne bcd1915dd0 MDL-57630 messaging: Pass unit test with third-party plugins 2017-01-11 16:39:31 +00:00
Eloy Lafuente (stronk7) 992ffccfd2 Merge branch 'wip-mdl-57595-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-01-11 02:29:56 +01:00
Dan Poltawski 97fd5a9841 Merge branch 'MDL-57480-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2017-01-10 08:40:12 +00:00
Marina Glancy 6b47a070e7 MDL-56271 mod_feedback: recaptcha was not working 2017-01-10 14:08:26 +08:00
David Monllao b4cfb7d733 Merge branch 'MDL-57385-32-2' of git://github.com/junpataleta/moodle into MOODLE_32_STABLE 2017-01-10 05:27:11 +01:00
Marina Glancy a9fa51024f MDL-50770 blocks: copy sitewide blocks positions when cloning dashboards 2017-01-10 11:40:27 +08:00
Jun Pataleta 2eec6ffc6c MDL-57385 core: Set page layouts of non-mydashboard pages to standard
The following pages are using the "mydashboard" page layout:
* User preferences > Badges > Manage badges
* User preferences > Badges > Backpack settings
* User preferences > Repositories > Manage instances
* Private files
However, the "mydashboard" page layout should only be used for the user's
dashboard page. Changing these to use the "standard" page layout.
2017-01-10 09:46:18 +08:00
Rajesh Taneja 3f1574f849 MDL-57595 behat: Added redirect and wait to ensure next step pass 2017-01-10 08:45:43 +08:00
Jake Dallimore 40b78a23e9 MDL-57480 core_course: make drag and drop fire a dom updated event
When adding media via drag and drop, the notifyFilterContentUpdated
event should be called after the item is added to the DOM. This allows
things like videojs for example, to process the new content.
2017-01-10 07:47:18 +08:00
Dan Poltawski fb5655b5c2 MDL-57604 mod_assign: fix incorrect user being selector from chooser
Previously there was a logic bug where by if some students were filtered
from the list, the label for another student could be attached to the
'filered' student.

This fix reworks the promises a bit so we render the student summary and
then build an row with the explict user id, rather than itterating through
the array later.

I also remove the storing of the initial promise in a varible because
this is an easy way to introduce a bug (not waiting for the .then()
chained promise)
2017-01-09 20:28:01 +00:00
sam marshall 405dcba6f3 MDL-57601 Grade report: Error for ungraded quiz without view hidden
If a course contains an ungraded quiz (max grade set to 0), and there
is a user account which can view the grader reports but does not have
permission to view hidden grades, they will get errors.
2017-01-09 17:14:44 +00:00
Dan Poltawski 7f32c5a447 Merge branch 'MDL-57427_m32' of https://github.com/jrchamp/moodle into MOODLE_32_STABLE 2017-01-09 16:26:18 +00:00
AMOS bot ec3eeb7ace Automatically generated installer lang files 2017-01-10 00:04:55 +08:00
Jonathan Champ 1af3d13bf3 MDL-57427 cache: Use perfdebug only when enabled 2017-01-09 10:18:41 -05:00
David Monllao 84122523ba Merge branch 'wip-mdl-55042-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-01-09 12:56:12 +01:00
godric 382c069e52 MDL-40132 lib: Using compare rule results in fatal error.
In getValidationScript function variable $element can be an array or object.
Function attempt get non-existing attributes.
To avoid this we should check before accessing.
2017-01-09 10:30:03 +00:00
Dan Poltawski 3f58a36504 Merge branch 'wip-mdl-56211-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-01-09 09:58:42 +00:00
Dan Poltawski 9e41e4e8ea Merge branch 'MDL-57373-32' of git://github.com/ankitagarwal/moodle into MOODLE_32_STABLE 2017-01-09 09:42:17 +00:00
Dan Poltawski 7523d99558 Merge branch 'MDL-53367_32' of https://github.com/juancs/moodle into MOODLE_32_STABLE 2017-01-09 08:27:56 +00:00
Dan Marsden 9a375bdf6c MDL-45821 mod_scorm: Check lesson_status correctly for multi-sco. 2017-01-09 20:08:10 +13:00
Eloy Lafuente (stronk7) 07f6358b03 Moodle release 3.2.1 2017-01-08 11:04:37 +01:00
AMOS bot 7ffb98d0f5 Automatically generated installer lang files 2017-01-08 00:04:57 +08:00
Dan Poltawski dda99bb3f2 weekly release 3.2+ 2017-01-06 01:30:59 +00:00
Dan Poltawski 9cff26295b Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2017-01-06 01:30:57 +00:00
Rajesh Taneja 2fd5ceadb5 MDL-56211 behat: Add suite name to faildump path
If suite is not default then add suite name
to end of faildump file name
2017-01-06 09:20:10 +08:00
David Mudrák 5865a6875b MDL-57580 mod_assign: Fix the incorrect type of some input parameters
The PARAM_TEXT has been misused in certain cases here. The 'action'
parameter seems to always be alphabetic, with values like
savesubmission, editsubmission and others as handled in assign::view().

Fixing the action handling fixes the reported XSS issue. While working
on it, I spotted two more places where PARAM_TEXT does not seem
appropriate. I include changes for them too, even if they are no
strictly related to the reported bug and there are no known ways to
abuse it.

* The 'plugin' looks like PARAM_PLUGIN and is even declared as such in
  some other parts of the assignment code (such as feedback forms).

* The 'workflowstate' is one of the ASSIGN_MARKING_WORKFLOW_STATE
  constants and is supposed to be alpha in external function input
  parameters handling, too.
2017-01-05 17:39:51 +01:00
Dan Poltawski ef2eed1b3c Merge branch 'MDL-57563-32-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_32_STABLE 2017-01-05 10:11:40 +00:00
Rajesh Taneja 6601017d02 MDL-57531 behat: Set noreplyaddress to valid address
noreplyaddress should be a valid address, else
it will not be saved. For behat we don't send
email, so set it to noreply@example.com, to
avoid failing validation on localhost
2017-01-05 06:52:06 +00:00
Daniel Thee Roperto a204d7d921 MDL-57576 assignment: Overwrite feedback file if it has the same name. 2017-01-05 15:32:51 +11:00
Damyon Wiese bf345fc4ca MDL-57009 javascript: cibot nagging 2017-01-05 09:36:09 +08:00
Damyon Wiese 2722404791 MDL-57009 javascript: Dont rely on async ajax
Recursively pre-scan mustache templates to extract the list of blocks and partials. Then
we can pre-fetch them all and don't have to rely on jquery async ajax (which is deprecated).

This is part of a refactoring of the promises code in the templates module to prevent duplicate requests.
2017-01-05 09:36:09 +08:00
Damyon Wiese 256f820dfd MDL-57009 js: Do not fetch the same template twice
Also clean up promises use of done vs then.
2017-01-05 09:36:09 +08:00
Damyon Wiese 173f5515e3 MDL-57009 js: Skip ajax request for same string
This is done by caching the first promise generated to fetch a string.
2017-01-05 09:36:09 +08:00
David Mudrák 7ed6f330c6 MDL-57563 lang: Use the new newsitemsnumber wording in behat 2017-01-04 22:19:32 +01:00
Helen Foster 418d01aaf4 MDL-57563 lang: Merge English strings from the en_fix language pack 2017-01-04 22:18:31 +01:00
AMOS bot 11f9ff55e1 Automatically generated installer lang files 2017-01-05 00:05:20 +08:00
Dan Poltawski 04d4796089 Merge branch 'MDL-57531-32-phpmailer' of git://github.com/mudrd8mz/moodle into MOODLE_32_STABLE 2017-01-04 13:28:39 +00:00
David Mudrák e889aee562 MDL-57531 mail: Validate the sender's email address
The patch adds validation for the noreplyaddress setting variable, for
the explicit $replyto parameter and for the sender's email. In case of
misconfigured noreplyaddress setting, it falls back to the default
noreply address value. In case of invalid email in the user's record,
the email is not sent.

The patch also adds unit test for the value returned by the function
generate_email_processing_address() so that it can be considered as a
valid email, too.

This is supposed to significantly minimise the risk of exploiting the
vulnerability in PHPMailer's Sender field.
2017-01-04 12:37:36 +01:00
David Mudrák 228157ebf5 MDL-57531 mail: Do not let admins set invalid email addresses
The noreply and support emails should always be valid.
2017-01-04 12:37:36 +01:00
Eloy Lafuente (stronk7) c77ae4e017 Merge branch 'MDL-57192-32' of git://github.com/ankitagarwal/moodle into MOODLE_32_STABLE 2017-01-04 11:34:23 +00:00
David Mudrák 1da3022e50 MDL-56225 mod_forum: Fix inability to edit attachments
The 'attachments' is not a real DB field here. It comes from the form's
filepicker and holds the id of the attachments filearea. The function
forum_add_attachment() expects it as a property of the first argument.

There were two possible approaches here. Either to pass the raw $newpost
to forum_add_attachment(), or add the attachments into the list
modifiable fields. The second approach is safer.
2017-01-04 11:34:22 +00:00
David Monllao f6507b8e35 Merge branch 'm32_MDL-49557' of git://github.com/danmarsden/moodle into MOODLE_32_STABLE 2017-01-04 11:34:22 +00:00
David Monllao d52b937932 MDL-57338 templates: Fix modal_cancel template name 2017-01-04 11:34:21 +00:00
Rajesh Taneja ce36e3626f MDL-57536 availability: Fixed css for clean theme 2017-01-04 11:34:21 +00:00
Ankit Agarwal 063f7c198b MDL-56992 core_scss: Don't allow invalid files to be included
We allow only .scss files so allow files to be included only and only if they end in .scss and they exist on server under theme directory.
2017-01-04 11:34:20 +00:00
Andrew Nicols 83dedbcd33 MDL-56225 mod_forum: Remove unnecessary attributes from update 2017-01-04 11:34:20 +00:00
Dan Marsden 0ad466926d MDL-49557 mod_scorm: optionally strip quotes. 2017-01-04 15:45:08 +13:00
Ankit Agarwal ced9a33352 MDL-57192 dml: Temporarily disable query logging during setup 2017-01-03 17:27:08 +05:30
Ankit Agarwal 3b4fba5588 MDL-57192 dml: Support temporarily disabling query logs during setup 2017-01-03 17:27:08 +05:30
Rajesh Taneja 926d5a53ff MDL-55042 phpunit: Get sorted sections
Sometimes db doesn't return records in order
So enusre it is in order so that last record
doesn't have section equal 0. As section 0
can't be deleted.
2017-01-03 10:00:05 +08:00
Eloy Lafuente (stronk7) 9cc9dabf17 Merge branch 'wip-mdl-57494-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2017-01-03 02:35:10 +01:00
Eloy Lafuente (stronk7) cb8be0b6b8 Merge branch 'MDL-57536-32' of git://github.com/jleyva/moodle into MOODLE_32_STABLE 2017-01-02 18:59:55 +01:00
Juan Leyva c6bd4c1a45 MDL-57536 availability: Document required selectors changes
MDL-55839 Introduced some changes in CSS selectors used by the form.js
file.

This caused contributed plugins to not work (javascript stop working)
when editing a module.
2017-01-02 18:52:22 +01:00
Davo Smith 31e4c05002 MDL-47198 filelib: fix curl handling headers with no value 2017-01-02 16:43:52 +01:00
Dan Poltawski c5f11c0f3c Merge branch 'm32_MDL-49557' of git://github.com/danmarsden/moodle into MOODLE_32_STABLE 2017-01-02 12:35:10 +00:00
Dan Poltawski 6158379f75 Merge branch 'MDL-57080-m32' of https://github.com/micaherne/moodle into MOODLE_32_STABLE 2017-01-02 12:15:02 +00:00
Dan Poltawski bc076bf1b8 Merge branch 'wip-MDL-57464-32' of git://github.com/abgreeve/moodle into MOODLE_32_STABLE 2017-01-02 11:16:24 +00:00
Dan Poltawski 27a3a42efd MDL-57532 calendar: tidy up button grouping 2017-01-02 10:45:24 +00:00
Dan Poltawski b0c2ea4640 Merge branch 'MDL-57532_m32v1' of https://github.com/sbourget/moodle into MOODLE_32_STABLE 2017-01-02 10:45:20 +00:00
David Monllao 00ef7b1caa Merge branch 'MDL-56926_32' of git://github.com/dmonllao/moodle into MOODLE_32_STABLE 2016-12-30 10:00:08 +01:00
David Monllao 7914b0035f MDL-56926 theme_boost: Restore filepicker's filename and icons original spacing 2016-12-30 09:57:41 +01:00
Nadav Kavalerchik cb358279b7 MDL-56926 Theme/Boost: Fix filepicker folder tree YUI guides 2016-12-30 09:57:35 +01:00
AMOS bot 339edb47e2 Automatically generated installer lang files 2016-12-30 00:05:21 +08:00
Dan Poltawski bd6bc508df Merge branch 'MDL-57512-32' of git://github.com/crazyserver/moodle into MOODLE_32_STABLE 2016-12-29 11:50:58 +00:00
Dan Poltawski c53194f3f9 Merge branch 'm32_MDL-50643' of git://github.com/danmarsden/moodle into MOODLE_32_STABLE 2016-12-29 11:46:48 +00:00
Pau Ferrer Ocaña c477dc23c0 MDL-57512 categories: Use maxcategorydepth only when getting all cats 2016-12-29 12:05:27 +01:00
David Monllao 8cd421e941 Merge branch 'MDL-57338-32' of git://github.com/danpoltawski/moodle into MOODLE_32_STABLE 2016-12-29 10:52:30 +01:00
Dan Poltawski f18c2a9d15 MDL-57338 templates: fix missing example variables
From Davids review, thanks
2016-12-29 08:05:04 +00:00
David Monllao 403e0d96e5 Merge branch 'MDL-57331-32' of https://github.com/xow/moodle into MOODLE_32_STABLE 2016-12-28 22:32:33 +01:00
Dan Poltawski 5984ffded4 Merge branch 'MDL-57451-32' of https://github.com/lucisgit/moodle into MOODLE_32_STABLE 2016-12-28 21:17:48 +00:00
Dan Poltawski cd9a925e6a Merge branch 'MDL-55955_32' of git://github.com/markn86/moodle into MOODLE_32_STABLE 2016-12-28 21:17:47 +00:00
Dan Poltawski 40471ed54c Merge branch 'wip-MDL-57366-32' of git://github.com/abgreeve/moodle into MOODLE_32_STABLE 2016-12-28 21:17:46 +00:00
David Monllao 000b0949e6 Merge branch 'MDL-57491_m32v3' of https://github.com/sbourget/moodle into MOODLE_32_STABLE 2016-12-28 21:17:46 +00:00
Dan Poltawski 6c7f60dbc0 Merge branch 'MDL-57417-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2016-12-28 21:17:45 +00:00
David Monllao 3b37e372f2 Merge branch 'MDL-52366-32-mustachethemedir' of git://github.com/mudrd8mz/moodle into MOODLE_32_STABLE 2016-12-28 12:23:49 +01:00
David Monllao 44b94d9324 Merge branch 'MDL-57450-32' of git://github.com/danpoltawski/moodle into MOODLE_32_STABLE 2016-12-28 11:48:05 +01:00
Dan Poltawski e5bc84f84f MDL-57251 upgrade: bump versions
and remove uncessary ->mark_dirty()
2016-12-28 10:28:37 +00:00
Dan Poltawski a38d0650d4 Merge branch 'wip-MDL-57251-32' of git://github.com/abgreeve/moodle into MOODLE_32_STABLE 2016-12-28 10:28:31 +00:00
David Monllao 8d9edc0e7c Merge branch 'MDL-57357-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2016-12-28 11:17:11 +01:00
David Monllao 4e0357c1e3 Merge branch 'MDL-56488-32' of git://github.com/danpoltawski/moodle into MOODLE_32_STABLE 2016-12-28 10:58:22 +01:00
Dan Poltawski 9efd73abec Merge branch 'wip-MDL-57292-32' of git://github.com/abgreeve/moodle into MOODLE_32_STABLE 2016-12-28 09:13:37 +00:00
Dan Poltawski c31b5bbf9d Merge branch 'MDL-57474-32-messageid' of git://github.com/mudrd8mz/moodle into MOODLE_32_STABLE 2016-12-28 08:56:06 +00:00
Dan Marsden 7606ba2133 MDL-49557 mod_scorm: fix AICC pre-requisite handling. 2016-12-28 10:09:00 +13:00
Ankit Agarwal 88c0fcb03f MDL-57373 navigation: Fix course names in flat nav 2016-12-27 12:21:02 +05:30
Stephen Bourget 51b7f8f0a4 MDL-57532 calendar: Add missing bootstrap classes 2016-12-26 11:41:50 -05:00
AMOS bot 40fdf0f84f Automatically generated installer lang files 2016-12-27 00:08:58 +08:00
AMOS bot 3e99f4f642 Automatically generated installer lang files 2016-12-26 00:05:52 +08:00
AMOS bot 324e613b48 Automatically generated installer lang files 2016-12-25 00:04:37 +08:00
Adrian Greeve 502397dcbc MDL-57464 mod_lesson: fix notice with sub-clusters. 2016-12-23 11:12:27 +08:00
Jake Dallimore f1f83c3ba1 MDL-57357 auth: add behat coverage for remember username login feature 2016-12-23 11:04:19 +08:00
Jake Dallimore 2c3f09ccf7 MDL-57357 auth: fix the remember username feature on login page 2016-12-23 10:45:06 +08:00
Adrian Greeve e2f5592b8f MDL-57366 mod_lesson: Zero now acceptable numeric answer.
When creating a numerical question. If the answer to the
question is 0 then the answer will not save.
2016-12-23 10:36:12 +08:00
Mark Nelson 522fcf2ffc MDL-55955 mod_quiz: ensure duplicated override events are removed 2016-12-23 10:02:47 +08:00
Jake Dallimore 96e743ff78 MDL-57417 navigation: fix legacy_activity_onclick_handler callback scope 2016-12-23 08:43:37 +08:00
Dan Marsden e514ae345e MDL-50643 mod_scorm: redirect using current window instead of parent. 2016-12-23 10:18:52 +13:00
Stephen Bourget 2659b808ab MDL-57491 report_log: Improve filtering code by using static entries 2016-12-22 16:12:34 -05:00
AMOS bot 54037cf3e2 Automatically generated installer lang files 2016-12-23 00:04:18 +08:00
Dan Poltawski b0773d70c6 MDL-57338 message: fix template component 2016-12-22 12:57:11 +00:00
Dan Poltawski 4348fffe0c MDL-57338 templates: add missing example context 2016-12-22 12:57:11 +00:00
Dan Poltawski 216c68b834 MDL-57338 chart: add example context
And fix aria roles
2016-12-22 12:57:11 +00:00
Dan Poltawski a3c1bd86ed MDL-57338 mustache: fix admin_setting_tabs
* Add example context
* Fix validation issue (need role="tablist" to contain the tabs)
2016-12-22 12:57:11 +00:00
Michael Aherne e0006399ff MDL-57080 completion: Update completion expected date on reset 2016-12-22 11:43:39 +00:00
Tony Butler 2084c59b82 MDL-57451 theme_boost: Add checkboxgroup class to checkbox input element 2016-12-22 11:30:24 +00:00
Dan Poltawski a09a9879e5 weekly release 3.2+ 2016-12-22 08:15:17 +00:00
Dan Poltawski a3a095b6eb Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2016-12-22 08:15:15 +00:00
Adrian Greeve 0edf724367 MDL-57292 tool_lpimportcsv: Fix for unit tests. 2016-12-22 14:41:32 +08:00
Simey Lameze a953ac5942 MDL-57292 tool_lpimportcsv: display progress bar for large imports 2016-12-22 14:41:17 +08:00
Rajesh Taneja 5627b0b1a1 MDL-57494 behat: Fixed tags and removed reset in after_scenario
1. Added missing switch_window tags
2. Fixed switch_frame tags to use switch_iframe
3. Removed reset from after_scenario.
2016-12-22 12:44:38 +08:00
David Monllao 5d3a7be453 Merge branch 'MDL-55575_B_32' of https://github.com/bostelm/moodle into MOODLE_32_STABLE 2016-12-21 05:50:17 +01:00
David Mudrák 8f27fdf1ab MDL-57474 mailer: Make sure that our exlicit MessageID is trimmed
The new version of phpmailer shipped with Moodle 3.2 has added check
that the explicitly provided MessageID matches /^<.*@.*>$/.

Values coming from our overridden moodle_phpmailer::addCustomHeader()
had a whitespace at the start. So the requested value was not used as
the Message-ID header and the default phpmailer value was used.

As a result, forum posts threading was broken in email clients.
2016-12-21 01:11:32 +01:00
AMOS bot 1d5c2c6560 Automatically generated installer lang files 2016-12-21 00:04:00 +08:00
Simey Lameze 18317c7c1c MDL-57114 filemanager: apply btn-sm class to buttons
This commit also creates a new css rule to fix the file picker icons misalignment.
2016-12-20 10:34:08 +00:00
Dan Poltawski b83fd5b1fe Merge branch 'MDL-54996_m32v1' of https://github.com/sbourget/moodle into MOODLE_32_STABLE 2016-12-20 09:19:27 +00:00
Juan Segarra Montesinos 972304f4cb MDL-53367 mod_forum: Subscribe current users when importing a forum
Subscribes currently enrolled users when importing a forum with
automatic subscription enabled.
2016-12-20 08:55:34 +01:00
Adrian Greeve 11eeb2e347 MDL-57251 navigation: Correct permission shows site admin
If the user does not have the moodle/site:configview
capability then do not show them the site administration
link.
2016-12-20 14:54:34 +08:00
Adrian Greeve 0aa8b11f5c MDL-57251 administration: Updated coursecreator role.
The coursecreator role now has the moodle/site:configview
capability so that they have access to the required admin
pages.
2016-12-20 14:54:34 +08:00
John Okely 829cafc050 MDL-57331 messaging: Fix sent messages appearing twice. 2016-12-20 10:48:01 +08:00
John Okely 25474b5e84 MDL-57268 auth_db: Unit tests for deletion from a large user set 2016-12-20 02:27:05 +01:00
Rafal Domagalski b7f902b5b3 MDL-52366 themes: check for templates in themedir 2016-12-19 18:08:37 +01:00
Dan Poltawski 11488775eb Merge branch 'MDL-57386-32' of git://github.com/damyon/moodle into MOODLE_32_STABLE 2016-12-19 15:46:59 +00:00
Dan Poltawski 32ec7e3d30 Merge branch 'MDL-55568_m32v2' of https://github.com/sbourget/moodle into MOODLE_32_STABLE 2016-12-19 14:33:06 +00:00
Dan Poltawski 1a1eef4345 Merge branch 'wip-MDL-56912-32' of git://github.com/marinaglancy/moodle into MOODLE_32_STABLE 2016-12-19 12:21:23 +00:00
Eloy Lafuente (stronk7) 4942dfc7cd Merge branch 'MDL-57270_32' of git://github.com/markn86/moodle into MOODLE_32_STABLE 2016-12-19 13:04:25 +01:00
Eloy Lafuente (stronk7) d469fb2181 Merge branch 'MDL-57293-32' of git://github.com/danpoltawski/moodle into MOODLE_32_STABLE 2016-12-19 13:02:16 +01:00
Dan Poltawski 0213ce081c Merge branch 'MDL-52098_32_STABLE' of git://github.com/Chocolate-lightning/moodle into MOODLE_32_STABLE 2016-12-19 11:25:49 +00:00
David Monllao 70b6a6618a Merge branch 'MDL-57402_32' of git://github.com/timhunt/moodle into MOODLE_32_STABLE 2016-12-19 12:23:45 +01:00
Dan Poltawski 089cf944f3 MDL-57450 enviroment: remove tls library check
Unfortunately it has come to light that the version sniffing is just not
reliable at all, operating system vendors backport security patches to
older versions - so in many cases we reporting a problem which is not a
problem. False positives and the solution to self-compile or something
like php will be causing more harm than good.
2016-12-19 10:53:59 +00:00
Dan Poltawski 68d9adcba8 Merge branch 'MDL-53044-m32' of https://github.com/ak4t0sh/moodle into MOODLE_32_STABLE 2016-12-19 08:47:23 +00:00
Dan Poltawski 32636d1757 Merge branch 'MDL-55715_m32v1' of https://github.com/sbourget/moodle into MOODLE_32_STABLE 2016-12-19 08:35:43 +00:00
Stephen Bourget 48ff43d3bd MDL-54996 Calendar: Fix dates for future multi-day events
Thanks to Martin Cunliffe for providing the fix
2016-12-17 10:53:00 -05:00
Mathew May 725863abe4 MDL-52098 enrol: cohort now looks at instance status 2016-12-16 11:22:06 +13:00
Arnaud Trouve 9de4bbf8a8 MDL-53044 auth : force change on expired password 2016-12-15 15:11:30 +01:00
Dan Poltawski cd7ca81fdd MDL-57293 lang/email: Improve emailvia string
* Strip the https? part of url for existing strings
* Switch the string to (via shortname)
2016-12-15 09:54:34 +00:00
Andrew Nicols 1ca30f2503 weekly release 3.2+ 2016-12-15 11:34:25 +08:00
Andrew Nicols c47a9439d3 Merge branch 'install_32_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_32_STABLE 2016-12-15 11:34:21 +08:00
Damyon Wiese 2ce5b1d637 MDL-57386 blocklib: wrong variable in is_block_present
This isn't reachable code in core moodle, but themes/plugins could call is_block_present to trigger it.
2016-12-15 10:51:31 +08:00
Tim Hunt c4ade76ee5 MDL-57402 quiz editing: fix add heading after remove page break 2016-12-14 16:35:17 +00:00
AMOS bot 62fc665ff6 Automatically generated installer lang files 2016-12-15 00:04:14 +08:00
Dan Poltawski 263865899e MDL-56488 boost: validate scss settings for parsable scss
* Parses the scss and fails validation if a parse error is found

* Does not detect the situation when variables are not present - this
  would involve us parsing the entire tree and would be slow. It could
  also change over time, depending on whats defined in the scss
  from themes.

* Introduces a new admin_setting_scsscode to do this
2016-12-14 11:34:25 +00:00
Mark Nelson f927f3e196 MDL-57270 core_message: trim message before it is sent 2016-12-14 12:19:24 +08:00
Stephen Bourget 70f5e9ba61 MDL-55715 calendar: Only update events from the current subscription
The iCal import should only update calendar events from the current
subscription not any subscription that contains the same event.
2016-12-13 22:06:44 -05:00
Andrew Nicols 3b7bf2cee0 Merge branch 'wip-mdl-57380-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2016-12-14 09:56:57 +08:00
Mark Nelson a57a9053d7 MDL-55062 tool_uploaduser: prevent defaults when not selected 2016-12-14 09:49:04 +08:00
Rajesh Taneja 0292245755 MDL-57380 behat: Check for list tags and text
after list tag span can be added on few browsers
like chrome 51.0, so test if text starts with
list tag and contains text
2016-12-14 09:38:35 +08:00
Stephen Bourget dd7aa695b2 MDL-55568 chat: chat_refresh_events should only create published events 2016-12-13 18:53:40 -05:00
Eloy Lafuente (stronk7) 2626dce64c Merge branch 'MDL-55809-32' of https://github.com/xow/moodle into MOODLE_32_STABLE 2016-12-13 20:05:23 +01:00
Dan Poltawski 7e2e135943 Merge branch 'MDL-57125-32' of git://github.com/lameze/moodle into MOODLE_32_STABLE 2016-12-13 16:34:58 +00:00
Matt Davidson cc15b9d46f MDL-56810 unoconv: task fails if user removed
If the user is removed from a course after a submission has been made,
the task will crash and never continue.  This removes submissions from
the cron task if the user isn't enrolled in the course.
2016-12-13 14:56:52 +00:00
Eloy Lafuente (stronk7) ce47bacfe9 Merge branch 'MOODLE_32_STABLE' of https://github.com/fwsl/moodle into MOODLE_32_STABLE 2016-12-13 12:00:58 +01:00
ak4t0sh 7c89091995 MDL-55720 course: fix potential undefined variable and cleaning
This commit replace $e usage by $returnfromfunc.
Indeed $returnfromfunc always exists in the scope and take $e value in case of moodle_exception.

This commit also remove useless $modcontext affectation.
2016-12-13 11:49:32 +01:00
Henning Bostelmann 7766ffc618 MDL-55575 mod_glossary: Allow viewing all entries on one page 2016-12-13 11:46:03 +01:00
Mark Nelson 75efa0860c MDL-57250 core: show admin settings when only one category exists 2016-12-13 10:25:19 +00:00
Dan Poltawski d31412392c Merge branch 'MDL-56859-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2016-12-13 09:45:19 +00:00
Dan Poltawski da694c75ff Merge branch 'MDL-57074-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2016-12-13 09:26:08 +00:00
Adrian Greeve 76f5d7b9ab MDL-57216 navigation: Updated parent behat test. 2016-12-13 09:04:40 +00:00
Adrian Greeve e7d8926583 MDL-57216 navigation: Added missing grade overview link.
For theme_boost the grade overview link has been added
to the user profile page.
2016-12-13 09:04:36 +00:00
Dan Poltawski c87f1ac4c7 Merge branch 'MDL-57182-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2016-12-13 08:47:35 +00:00
Dan Poltawski 75c4f5b0ca Merge branch 'wip-MDL-57257-32' of git://github.com/abgreeve/moodle into MOODLE_32_STABLE 2016-12-13 08:46:03 +00:00
Marina Glancy f7b3774380 MDL-56912 feedback: empty multichoice questions do not submit 2016-12-13 15:01:04 +08:00
Andrew Nicols 78293c74bf Merge branch 'MDL-57213-32-2' of git://github.com/junpataleta/moodle into MOODLE_32_STABLE 2016-12-13 13:06:25 +08:00
Simey Lameze 406fc019c1 MDL-57125 comment: prevent js execution if there are no comments 2016-12-13 11:55:05 +08:00
Jun Pataleta 903cd37434 MDL-57213 navigation: Load all my course categories into navigation tree
* Load all of the relevant course categories of the courses that a user
  is enrolled in.
2016-12-13 11:43:22 +08:00
Nadav Kavalerchik 6fd8b0098a MDL-57056 Theme/Boost: Fix "Skip to" link when Tab key pressed 2016-12-13 10:47:50 +08:00
Jan Dageförde 34954a6050 MDL-57257 lesson: Validate type of numerical answer 2016-12-13 10:34:36 +08:00
Mark Nelson 949d8ae04e MDL-57222 mod_assign: show validation message on visible element 2016-12-13 10:30:38 +08:00
Eloy Lafuente (stronk7) 1c7cbed23c Merge branch 'wip-mdl-57328-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2016-12-13 02:30:06 +01:00
Eloy Lafuente (stronk7) 9156498826 Merge branch 'mdl32_MDL-57324' of git://github.com/danmarsden/moodle into MOODLE_32_STABLE 2016-12-13 02:02:02 +01:00
Jake Dallimore 71adc9a9a3 MDL-57182 navigation: fix login failures display in page footer.
A bug introduced with MDL-45893 meant that the failure count was being
reset, causing the footer code to be skipped. This patch fixes that
bug and adds behat tests covering the displayloginfailures feature.
2016-12-13 07:20:58 +08:00
Eloy Lafuente (stronk7) 49612b733f Merge branch 'MDL-57319-32' of git://github.com/danpoltawski/moodle into MOODLE_32_STABLE 2016-12-12 16:23:20 +01:00
Arnaud Trouve bc0721c7d9 MDL-56525 forum: remove targeted user enrolment check
By removing the check on the targeted user's enrolment we allow to show his forum posts even if he is unenrol from a course (obviouly we need to have access to this course to view them)
2016-12-12 14:10:21 +00:00
Ryan Wyllie c5452484ee MDL-55782 groups: wrap long group names (theme: boost)
In the groups UI if a group name is very long it now no longer underlaps
the user column on its right hand side.
2016-12-12 13:19:18 +00:00
= 74eecb6078 MDL-55782 groups: wrap long group names
In the groups UI if a group name is very long it now no longer underlaps the user
column on its right hand side.
2016-12-12 13:19:15 +00:00
Dan Poltawski 725be51c11 Merge branch 'wip-mdl-52796-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2016-12-12 13:00:56 +00:00
Philipp Hager d0d8a7f984 MDL-57198 course: add css-classes to restrictbygroup-button 2016-12-12 12:46:52 +00:00
Adrian Greeve 4a50811ae3 MDL-57299 Atto: Theme boost fix for manage files.
Theme boost removed a selector that was being used
to remove used files and so the page wasn't loading
properly.
2016-12-12 12:40:09 +00:00
Dan Poltawski b82ddcbcac Merge branch 'wip-mdl-57325-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2016-12-12 12:23:25 +00:00
Dan Poltawski 6e4cc6caf4 Merge branch 'wip-mdl-57314-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2016-12-12 12:21:31 +00:00
Dan Poltawski fe8e9b1b4e Merge branch 'wip-mdl-57343-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2016-12-12 12:21:13 +00:00
Dan Poltawski 72770e9a60 Merge branch 'MDL-57171-32-2' of git://github.com/junpataleta/moodle into MOODLE_32_STABLE 2016-12-12 10:31:13 +00:00
Dan Poltawski a847efc70b Merge branch 'MDL-56566_32' of https://github.com/bostelm/moodle into MOODLE_32_STABLE 2016-12-12 09:20:13 +00:00
Ilya Tregubov 9e99327888 MDL-55906 table: Update user preferences table when reset preferences 2016-12-12 09:07:30 +00:00
Andrew Nicols 9973eebb91 Merge branch 'MDL-46714-32-nadav' of git://github.com/FMCorz/moodle into MOODLE_32_STABLE 2016-12-12 13:26:58 +08:00
Nadav Kavalerchik a162f636d8 MDL-46714 Calendar: Properly order Date & Time fields in RTL mode 2016-12-12 12:38:45 +08:00
Rajesh Taneja 8ff8d598fe MDL-57343 behat: Ensure we wait enough for page to be fully loaded 2016-12-12 10:38:32 +08:00
Ramindu Deshapriya 8704d2e5fc MDL-52796 behat: Behat feature to test reset wiki page, tags & comments 2016-12-12 10:27:44 +08:00
Bram Tassyns f9dd21a17a MDL-56859 SCORM: player shouldn't display TOC while loading 2016-12-12 09:11:50 +08:00
Jake Dallimore eb349bdfc4 MDL-57074 Filepicker: Fix alias and link icons in RTL mode
Fixed alignment of the images in RTL mode. Also fixed a z-index problem
in which the icons were displayed above the open drawer on narrow
screens.
2016-12-12 08:48:15 +08:00
AMOS bot 89d186af72 Automatically generated installer lang files 2016-12-10 00:04:00 +08:00
Dan Poltawski 65de977483 MDL-57319 outputlib: raise timeout for scss/less compilation 2016-12-09 08:47:05 +00:00
Rajesh Taneja e167481759 MDL-57328 core: Remove xdebug extension, so test run faster 2016-12-09 10:24:01 +08:00
Rajesh Taneja 457c913461 MDL-57325 behat: Fixed backup/restore steps to use proper api 2016-12-09 09:31:13 +08:00
Rajesh Taneja 422449dca8 MDL-57328 core: Run tests with php 7.1 2016-12-09 08:49:21 +08:00
Dan Marsden 53c8f0ca3c MDL-57324 scorm: exclude objective raw.score from grade update 2016-12-09 10:13:20 +13:00
Henning Bostelmann b094b88a9a MDL-56566 mod_assign: ignore "doanything" in course overview
Do not count site admin "doanything" capability for determining
what should be shown in the course overview for assignments.
2016-12-08 20:28:10 +00:00
AMOS bot 49e5d04a8d Merge branch 'MOODLE_32_STABLE' into install_32_STABLE 2016-12-09 00:04:15 +08:00
AMOS bot 38e28dfbcd Automatically generated installer lang files 2016-12-08 18:11:21 +08:00
Dan Poltawski 44047dc78d weekly release 3.2+ 2016-12-08 08:43:05 +00:00
Marina Glancy c06b8145b1 MDL-56614 behat: add missing wait for page is ready 2016-12-08 13:51:53 +08:00
Franziska Hübler 79da2c5bfa MDL-55809 glossary: Keep file author and license across import/export 2016-12-08 12:28:22 +08:00
Andrew Nicols a5800adaf0 Merge branch 'MDL-57278-32-5' of https://github.com/xow/moodle into MOODLE_32_STABLE 2016-12-08 10:53:37 +08:00
John Okely c1c3f50965 MDL-57278 signup: Fix double encoding of confirmation links 2016-12-08 10:17:50 +08:00
John Okely cff14cf0d1 MDL-57278 signup: Unit tests covering confirmation link generation 2016-12-08 10:17:50 +08:00
Rajesh Taneja c95ea731bc MDL-57314 behat: Press enter after setting password unmask 2016-12-08 09:24:37 +08:00
Rajesh Taneja b98f14632b MDL-56642 dataformat: Fixed method_exits parameters 2016-12-08 00:37:03 +01:00
Mark Nelson a1e1b45ae7 MDL-57283 core: fixed function call on null 2016-12-07 10:17:36 +00:00
Kenneth Hendricks 2d44bb544b MDL-56674 core: Fix test_get_all_observers 2016-12-07 08:46:04 +00:00
Marina Glancy c60d333578 MDL-56614 behat: corrections to new steps 2016-12-07 14:58:39 +08:00
Andrew Nicols 182690b018 Merge branch 'wip-mdl-56353-m32' of https://github.com/rajeshtaneja/moodle into MOODLE_32_STABLE 2016-12-07 12:03:36 +08:00
Rajesh Taneja b36b54179d MDL-56353 behat: Added test for multi select dependency 2016-12-07 11:19:01 +08:00
Andrew Nicols fc4b768e25 Merge branch 'wip-MDL-56642-32' of git://github.com/marinaglancy/moodle into MOODLE_32_STABLE 2016-12-07 10:00:59 +08:00
Andrew Nicols 7e0f1972f1 Merge branch 'MDL-57266_32' of git://github.com/stronk7/moodle into MOODLE_32_STABLE 2016-12-07 09:54:33 +08:00
Andrew Nicols 93e64c823c Merge branch 'MDL-56240_32' of git://github.com/stronk7/moodle into MOODLE_32_STABLE 2016-12-07 09:51:07 +08:00
Rajesh Taneja 20d598f094 MDL-56614 behat: Fixed steps to use new definition 2016-12-07 09:43:06 +08:00
Marina Glancy e376549179 MDL-56642 dataformat: set temp dir
Thanks to Chien Wen-Chang for proposing a patch
2016-12-07 09:30:25 +08:00
Rajesh Taneja 163a317bcc MDL-57137 behat: Subcategory has black space before name 2016-12-07 09:13:26 +08:00
Dan Poltawski 7ecf13ac1d Merge branch 'MDL-45873_32' of https://github.com/bostelm/moodle into MOODLE_32_STABLE 2016-12-06 15:56:28 +00:00
Ankit Agarwal 2fbe4fca87 MDL-57284 boost: Fix booktool_print icons 2016-12-06 15:50:57 +00:00
Jun Pataleta d07a8ebd7e MDL-57171 admin: Make environment check table look better
* Use Bootstrap label classes for the text under the status column.
* theme_bootstrapbase:
  - Cleanup unnecessary classes and make .error styles consistent
    with .warn styles
* theme_boost:
  - Set font color appropriate for success, warning and error strings.
* Enclose report text in div so that the feedback texts will be
  displayed right below it.
2016-12-06 22:18:55 +08:00
SSRF d4feb70e17 MDL-53677 tool_spamcleaner: CSRF Fix
Resolves minor CSRF within Moodle spamcleaner.
2016-12-06 12:48:31 +00:00
Dan Poltawski f477809e38 Merge branch 'MDL-56836-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2016-12-06 12:46:19 +00:00
Daniel Thee Roperto 94caed45db MDL-56233 forms library: Fixed form identifier when mocking a form.
If the plugin is using namespaces instead of frankenstyle class name,
get_called_class() will return 'type\name' instead of 'type_name'.

Added code to replace backslashes to underscores and fix that issue.
2016-12-06 12:42:17 +00:00
Dan Poltawski 8c4fdb1073 MDL-56778 enrol: add note about legacy css 2016-12-06 12:32:30 +00:00
Nadav Kavalerchik e5bbe44230 MDL-56778 Enrollment: Fix enroll users dialog in RTL mode (theme:Boost) 2016-12-06 12:32:23 +00:00
Tim Hunt d0a58fe035 MDL-57199 question preview: make HTML ids unique 2016-12-06 12:25:45 +00:00
Michael Aherne 9c68157292 MDL-56971 enrol: Use autoloading in enrol_get_plugin() 2016-12-06 11:08:17 +00:00
Grzegorz Ziółek 44f71599df MDL-56830 config_log: Add block plugin visibility changes to config_log. 2016-12-06 11:51:48 +01:00
Alexander Melihov 1fac7b914b MDL-57137 quiz: Create question category with specified parent category
Fix question category generator bug. Now it is possible to specify parent category of subcategory, supply only name of parent category
2016-12-06 15:34:13 +08:00
Tony Butler cede73411f MDL-56346 assignfeedback_editpdf: Correct typo in property name 2016-12-06 14:38:01 +08:00
Andrew Nicols 47deb83b5c Merge branch 'MDL-56301-32' of https://github.com/snake/moodle into MOODLE_32_STABLE 2016-12-06 14:27:03 +08:00
Andrew Nicols 4ea56c1c80 Merge branch 'wip-MDL-56614-m32-2' of https://github.com/marinaglancy/moodle into MOODLE_32_STABLE 2016-12-06 13:38:08 +08:00
Marina Glancy 311121b16c MDL-56614 behat: add navigation block when required
Most of these hacks have links to corresponding MDL issues
2016-12-06 13:35:40 +08:00
Marina Glancy 5863f1b073 MDL-56614 behat: rename step for navigating in the gradebook 2016-12-06 13:35:40 +08:00
Marina Glancy 2bb195f64f MDL-56614 behat: navigate without navigation and admin blocks 2016-12-06 13:35:40 +08:00
Marina Glancy f6b50d9901 MDL-56614 block_navigation: Add block in behat tests 2016-12-06 13:35:39 +08:00
Marina Glancy a0b0234a18 MDL-56614 behat: new steps for navigation without blocks 2016-12-06 13:35:39 +08:00
Andrew Nicols f8b8a363ae Merge branch 'MDL-57161-32' of git://github.com/lameze/moodle into MOODLE_32_STABLE 2016-12-06 13:10:40 +08:00
Donald Barrett b197272987 MDL-56301 course: Use value for intro field if set in a mods function
Respects a module that has set a value for the db field intro in it's lib function modulename_add_instance.
2016-12-06 10:40:49 +08:00
Juan Leyva e4976aefc5 MDL-57255 gradereport_user: Fix default value for graderaw
graderaw is a PARAM_FLOAT, the default to empty string was incorrect
2016-12-06 10:18:53 +08:00
David Monllao dcd408b81f MDL-57161 search: Set the correct HTTP header
All credit goes to Test Valley School
2016-12-06 10:00:07 +08:00
Simey Lameze 4a564ca40b MDL-56759 themes: fix badge list alignment issues 2016-12-06 09:24:31 +08:00
Eloy Lafuente (stronk7) 5da06d632a MDL-57266 upgrade: add 3.2.0 separation line to all upgrade scripts 2016-12-05 17:17:54 +01:00
Eloy Lafuente (stronk7) d797e57255 MDL-56240 upgrade: delete incorrect lines, manually added
Note that, with MDL-57266, we are changine the comment to be:

// Automatically generated Moodle v3.2.0 release upgrade line

in order to make to make to make it clearer that it's an
automatic (part of the release process) comment and should not
be added manually ever.
2016-12-05 16:52:31 +01:00
Frederic Massart 55d2042f0a MDL-56459 competency: Invalid use of indirect property key
This change ensures that PHP7 and earlier work the same way. Before
the patch PHP < 7 would not expand the property as we expected it.

More information here:
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.variable-handling.indirect
2016-12-05 15:48:47 +00:00
David Mudrák 8cd6972966 MDL-57256 course: Fix display of the Legacy course files link
The patch fixes the classical operator precedence bug.
2016-12-05 15:45:38 +00:00
Henning Bostelmann 9cbc0a0cdb MDL-45873 mode_data: Allow "0" entries in menu field 2016-12-05 09:21:07 +00:00
John Okely 931d12b589 MDL-54921 signup: Only clear wanturl when necessary
Thanks to Juho Jaakkola for original patch idea.
2016-12-05 15:35:25 +08:00
Shamim Rezaie 0beeb95a8a MDL-52840 assignsubmission_file: Change default setting file size
The default value of the assignsubmission_file/maxbytes setting is changed to $CFG->maxbytes.
2016-12-05 13:02:20 +08:00
Mark Nelson 617f8bb911 MDL-57084 core_message: prevent duplication of day separator 2016-12-05 12:28:56 +08:00
Michael Spall 75dd21a002 MDL-56893 grades: Fix edit grade item when grade_report_showmin is false
Check to make sure $data['grademin'] exists. When grade_report_showmin
is false $data['grademin'] doesn't exist.
2016-12-05 12:05:19 +08:00
Bram Tassyns a0c13477ab MDL-56836 SCORM: player doesn't remember display mode when not logged in 2016-12-05 09:25:31 +08:00
13842 changed files with 440341 additions and 1344484 deletions
+23 -36
View File
@@ -3,30 +3,29 @@
*/**/build/
node_modules/
vendor/
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
admin/tool/usertours/amd/src/tour.js
admin/tool/usertours/amd/src/popper.js
auth/cas/CAS/
cache/stores/mongodb/MongoDB/
auth/fc/fcFPP.php
enrol/lti/ims-blti/
filter/algebra/AlgParser.pm
filter/tex/mimetex.*
h5p/h5plib/v124/joubel/core/
h5p/h5plib/v124/joubel/editor/
lib/editor/atto/plugins/html/yui/src/codemirror/
lib/editor/atto/plugins/html/yui/src/beautify/
lib/editor/atto/yui/src/rangy/js/*.*
lib/editor/tinymce/plugins/pdw/tinymce/
lib/editor/tinymce/plugins/spellchecker/rpc.php
lib/editor/tinymce/tiny_mce/
lib/mlbackend/php/phpml/
lib/adodb/
lib/bennu/
lib/evalmath/
lib/phpspreadsheet/
lib/lessphp/
lib/phpexcel/
lib/google/
lib/htmlpurifier/
lib/jabber/
lib/minify/matthiasmullie-minify/
lib/minify/matthiasmullie-pathconverter/
lib/pear/Auth/RADIUS.php
lib/pear/Crypt/CHAP.php
lib/pear/HTML/Common.php
lib/pear/HTML/QuickForm.php
lib/pear/HTML/QuickForm/
@@ -40,7 +39,9 @@ lib/yuilib/gallery/
lib/jquery/
lib/html2text/
lib/markdown/
lib/recaptchalib.php
lib/xhprof/
lib/xmlize.php
lib/horde/
lib/requirejs/
lib/amd/src/loglevel.js
@@ -55,38 +56,24 @@ lib/amd/src/chartjs-lazy.js
lib/maxmind/GeoIp2/
lib/maxmind/MaxMind/
lib/ltiprovider/
lib/amd/src/truncate.js
lib/fonts/
lib/amd/src/adapter.js
lib/validateurlsyntax.php
lib/amd/src/popper.js
lib/geopattern-php/
lib/php-jwt/
lib/babel-polyfill/
lib/polyfills/
lib/emoji-data/
lib/plist/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
media/player/videojs/amd/src/videojs-flash-lazy.js
media/player/videojs/videojs/video-js.swf
mod/assign/feedback/editpdf/fpdi/
repository/s3/S3.php
theme/boost/scss/bootstrap/
theme/boost/amd/src/bootstrap/alert.js
theme/boost/amd/src/bootstrap/button.js
theme/boost/amd/src/bootstrap/carousel.js
theme/boost/amd/src/bootstrap/collapse.js
theme/boost/amd/src/bootstrap/dropdown.js
theme/boost/amd/src/bootstrap/index.js
theme/boost/amd/src/bootstrap/modal.js
theme/boost/amd/src/bootstrap/popover.js
theme/boost/amd/src/bootstrap/tools/sanitizer.js
theme/boost/amd/src/bootstrap/scrollspy.js
theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/amd/src/alert.js
theme/boost/amd/src/button.js
theme/boost/amd/src/carousel.js
theme/boost/amd/src/collapse.js
theme/boost/amd/src/dropdown.js
theme/boost/amd/src/modal.js
theme/boost/amd/src/popover.js
theme/boost/amd/src/scrollspy.js
theme/boost/amd/src/tab.js
theme/boost/amd/src/tooltip.js
theme/boost/amd/src/util.js
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
theme/bootstrapbase/less/bootstrap/
theme/bootstrapbase/javascript/html5shiv.js
theme/bootstrapbase/amd/src/bootstrap.js
+2 -71
View File
@@ -1,8 +1,4 @@
{
'plugins': [
'babel',
'promise',
],
'env': {
'browser': true,
'amd': true
@@ -17,7 +13,6 @@
// === Possible Errors ===
'comma-dangle': 'off',
'no-compare-neg-zero': 'error',
'no-cond-assign': 'error',
'no-console': 'error',
'no-constant-condition': 'error',
@@ -69,6 +64,7 @@
'no-fallthrough': 'error',
'no-floating-decimal': 'warn',
'no-global-assign': 'warn',
// Enabled by grunt for AMD modules: 'no-implicit-globals': 'error',
'no-implied-eval': 'error',
'no-invalid-this': 'error',
'no-iterator': 'error',
@@ -107,7 +103,6 @@
'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',
@@ -175,75 +170,11 @@
'unicode-bom': 'error',
'wrap-regex': 'off',
// === Promises ===
'promise/always-return': 'warn',
'promise/no-return-wrap': 'warn',
'promise/param-names': 'warn',
'promise/catch-or-return': ['warn', {terminationMethod: ['catch', 'fail']}],
'promise/no-native': 'warn',
'promise/no-promise-in-callback': 'warn',
'promise/no-callback-in-promise': 'warn',
'promise/avoid-new': 'warn',
// === Deprecations ===
"no-restricted-properties": ['warn', {
'object': 'M',
'property': 'str',
'message': 'Use AMD module "core/str" or M.util.get_string()'
}],
},
overrides: [
{
files: ["**/yui/src/**/*.js"],
// Disable some rules which we can't safely define for YUI rollups.
rules: {
'no-undef': 'off',
'no-unused-vars': 'off',
'no-unused-expressions': 'off'
}
},
{
files: ["**/amd/src/*.js", "**/amd/src/**/*.js", "Gruntfile*.js", "babel-plugin-add-module-to-define.js"],
// We support es6 now. Woot!
env: {
es6: true
},
// We're using babel transpiling so use their parser
// for linting.
parser: 'babel-eslint',
// Check AMD with some slightly stricter rules.
rules: {
'no-unused-vars': 'error',
'no-implicit-globals': 'error',
// Disable all of the rules that have babel versions.
'new-cap': 'off',
// 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',
// This is off in the original style int.
'babel/quotes': 'off',
'babel/semi': 'error',
'babel/no-unused-expressions': 'error',
// === Promises ===
// We have Promise now that we're using ES6.
'promise/no-native': 'off',
'promise/avoid-new': 'off'
},
parserOptions: {
'ecmaVersion': 9,
'sourceType': 'module'
}
}
]
}
}
-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"]
}
+2 -1
View File
@@ -1,3 +1,4 @@
**/yui/build/** -diff
**/amd/build/** -diff
lib/dml/oci_native_moodle_package.sql text eol=lf
theme/bootstrapbase/style/editor.css -diff
theme/bootstrapbase/style/moodle.css -diff
-2
View File
@@ -1,2 +0,0 @@
# Primary donations pages.
custom: ["https://moodle.com/donations/", moodle.org]
-71
View File
@@ -1,71 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Template configuraton file for github actions CI/CD.
*
* @package core
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com}
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// This cannot be used out from a github actions workflow, so just exit.
getenv('GITHUB_WORKFLOW') || die; // phpcs:ignore moodle.Files.MoodleInternal.MoodleInternalGlobalState
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->dbtype = getenv('dbtype');
$CFG->dblibrary = 'native';
$CFG->dbhost = '127.0.0.1';
$CFG->dbname = 'test';
$CFG->dbuser = 'test';
$CFG->dbpass = 'test';
$CFG->prefix = 'm_';
$CFG->dboptions = ['dbcollation' => 'utf8mb4_bin'];
$host = 'localhost';
$CFG->wwwroot = "http://{$host}";
$CFG->dataroot = realpath(dirname(__DIR__)) . '/moodledata';
$CFG->admin = 'admin';
$CFG->directorypermissions = 0777;
// Debug options - possible to be controlled by flag in future.
$CFG->debug = (E_ALL | E_STRICT); // DEBUG_DEVELOPER.
$CFG->debugdisplay = 1;
$CFG->debugstringids = 1; // Add strings=1 to url to get string ids.
$CFG->perfdebug = 15;
$CFG->debugpageinfo = 1;
$CFG->allowthemechangeonurl = 1;
$CFG->passwordpolicy = 0;
$CFG->cronclionly = 0;
$CFG->pathtophp = getenv('pathtophp');
$CFG->phpunit_dataroot = realpath(dirname(__DIR__)) . '/phpunitdata';
$CFG->phpunit_prefix = 't_';
define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://localhost:8080');
define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://localhost:8080');
define('TEST_SESSION_REDIS_HOST', 'localhost');
define('TEST_CACHESTORE_REDIS_TESTSERVERS', 'localhost');
// TODO: add others (solr, mongodb, memcached, ldap...).
// Too much for now: define('PHPUNIT_LONGTEST', true); // Only leaves a few tests out and they are run later by CI.
require_once(__DIR__ . '/lib/setup.php');
-103
View File
@@ -1,103 +0,0 @@
name: Core
on: [push]
env:
php: 7.4
jobs:
Grunt:
runs-on: ubuntu-18.04
steps:
- name: Checking out code
uses: actions/checkout@v2
- name: Configuring node & npm
shell: bash -l {0}
run: nvm install
- name: Installing node stuff
run: npm install
- name: Running grunt
run: npx grunt
- name: Looking for uncommitted changes
# Add all files to the git index and then run diff --cached to see all changes.
# This ensures that we get the status of all files, including new files.
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
run: |
git add .
git reset -- npm-shrinkwrap.json
git diff --cached --exit-code
PHPUnit:
runs-on: ${{ matrix.os }}
services:
exttests:
image: moodlehq/moodle-exttests
ports:
- 8080:80
redis:
image: redis
ports:
- 6379:6379
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
php: 7.2
db: mysqli
- os: ubuntu-18.04
php: 7.4
db: pgsql
steps:
- name: Setting up DB mysql
if: ${{ matrix.db == 'mysqli' }}
uses: johanmeiring/mysql-action@tmpfs-patch
with:
collation server: utf8mb4_bin
mysql version: 5.7
mysql database: test
mysql user: test
mysql password: test
use tmpfs: true
- name: Setting up DB pgsql
if: ${{ matrix.db == 'pgsql' }}
uses: m4nu56/postgresql-action@v1
with:
postgresql version: 9.6
postgresql db: test
postgresql user: test
postgresql password: test
- name: Configuring git vars
uses: rlespinasse/github-slug-action@v3.x
- name: Setting up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- name: Checking out code from ${{ env.GITHUB_REF_SLUG }}
uses: actions/checkout@v2
- name: Setting up PHPUnit
env:
dbtype: ${{ matrix.db }}
run: |
echo "pathtophp=$(which php)" >> $GITHUB_ENV # Inject installed pathtophp to env. The template config needs it.
cp .github/workflows/config-template.php config.php
mkdir ../moodledata
sudo locale-gen en_AU.UTF-8
php admin/tool/phpunit/cli/init.php --no-composer-self-update
- name: Running PHPUnit tests
env:
dbtype: ${{ matrix.db }}
run: vendor/bin/phpunit -v
+2 -10
View File
@@ -9,18 +9,10 @@
#
# 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.*
-2
View File
@@ -1,2 +0,0 @@
**/amd/**
/*.js
-1
View File
@@ -1 +0,0 @@
v14.15.0
+26 -39
View File
@@ -1,33 +1,32 @@
# Generated by "grunt ignorefiles"
**/yui/build/*
theme/boost/style/moodle.css
theme/classic/style/moodle.css
theme/bootstrapbase/style/
theme/clean/style/custom.css
theme/more/style/custom.css
node_modules/
vendor/
admin/tool/policy/amd/src/jquery-eu-cookie-law-popup.js
admin/tool/usertours/amd/src/tour.js
admin/tool/usertours/amd/src/popper.js
auth/cas/CAS/
cache/stores/mongodb/MongoDB/
auth/fc/fcFPP.php
enrol/lti/ims-blti/
filter/algebra/AlgParser.pm
filter/tex/mimetex.*
h5p/h5plib/v124/joubel/core/
h5p/h5plib/v124/joubel/editor/
lib/editor/atto/plugins/html/yui/src/codemirror/
lib/editor/atto/plugins/html/yui/src/beautify/
lib/editor/atto/yui/src/rangy/js/*.*
lib/editor/tinymce/plugins/pdw/tinymce/
lib/editor/tinymce/plugins/spellchecker/rpc.php
lib/editor/tinymce/tiny_mce/
lib/mlbackend/php/phpml/
lib/adodb/
lib/bennu/
lib/evalmath/
lib/phpspreadsheet/
lib/lessphp/
lib/phpexcel/
lib/google/
lib/htmlpurifier/
lib/jabber/
lib/minify/matthiasmullie-minify/
lib/minify/matthiasmullie-pathconverter/
lib/pear/Auth/RADIUS.php
lib/pear/Crypt/CHAP.php
lib/pear/HTML/Common.php
lib/pear/HTML/QuickForm.php
lib/pear/HTML/QuickForm/
@@ -41,7 +40,9 @@ lib/yuilib/gallery/
lib/jquery/
lib/html2text/
lib/markdown/
lib/recaptchalib.php
lib/xhprof/
lib/xmlize.php
lib/horde/
lib/requirejs/
lib/amd/src/loglevel.js
@@ -56,38 +57,24 @@ lib/amd/src/chartjs-lazy.js
lib/maxmind/GeoIp2/
lib/maxmind/MaxMind/
lib/ltiprovider/
lib/amd/src/truncate.js
lib/fonts/
lib/amd/src/adapter.js
lib/validateurlsyntax.php
lib/amd/src/popper.js
lib/geopattern-php/
lib/php-jwt/
lib/babel-polyfill/
lib/polyfills/
lib/emoji-data/
lib/plist/
media/player/videojs/amd/src/video-lazy.js
media/player/videojs/amd/src/Youtube-lazy.js
media/player/videojs/videojs/
media/player/videojs/amd/src/videojs-flash-lazy.js
media/player/videojs/videojs/video-js.swf
mod/assign/feedback/editpdf/fpdi/
repository/s3/S3.php
theme/boost/scss/bootstrap/
theme/boost/amd/src/bootstrap/alert.js
theme/boost/amd/src/bootstrap/button.js
theme/boost/amd/src/bootstrap/carousel.js
theme/boost/amd/src/bootstrap/collapse.js
theme/boost/amd/src/bootstrap/dropdown.js
theme/boost/amd/src/bootstrap/index.js
theme/boost/amd/src/bootstrap/modal.js
theme/boost/amd/src/bootstrap/popover.js
theme/boost/amd/src/bootstrap/tools/sanitizer.js
theme/boost/amd/src/bootstrap/scrollspy.js
theme/boost/amd/src/bootstrap/tab.js
theme/boost/amd/src/bootstrap/toast.js
theme/boost/amd/src/bootstrap/tooltip.js
theme/boost/amd/src/bootstrap/util.js
theme/boost/amd/src/alert.js
theme/boost/amd/src/button.js
theme/boost/amd/src/carousel.js
theme/boost/amd/src/collapse.js
theme/boost/amd/src/dropdown.js
theme/boost/amd/src/modal.js
theme/boost/amd/src/popover.js
theme/boost/amd/src/scrollspy.js
theme/boost/amd/src/tab.js
theme/boost/amd/src/tooltip.js
theme/boost/amd/src/util.js
theme/boost/amd/src/tether.js
theme/boost/scss/fontawesome/
theme/bootstrapbase/less/bootstrap/
theme/bootstrapbase/javascript/html5shiv.js
theme/bootstrapbase/amd/src/bootstrap.js
+10 -11
View File
@@ -1,22 +1,18 @@
{
"plugins": [
"stylelint-csstree-validator"
],
"rules": {
"csstree/validator": true,
"at-rule-empty-line-before": [ "always",
{"except": [ "blockless-after-blockless"], ignore: ["after-comment", "inside-block"]}
{"except": [ "blockless-group"], ignore: ["after-comment", "all-nested"]}
],
"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-newline-before": "always-multi-line",
"block-closing-brace-space-before": "always-single-line",
"block-no-empty": true,
"block-opening-brace-newline-after": "always",
"block-no-single-line": true,
"block-opening-brace-newline-after": "always-multi-line",
"block-opening-brace-space-after": "always-single-line",
"block-opening-brace-space-before": "always",
"color-hex-case": ["lower", { "severity": "warning" }],
@@ -25,6 +21,7 @@
"declaration-bang-space-after": "never",
"declaration-bang-space-before": "always",
"declaration-block-no-duplicate-properties": true,
"declaration-block-no-ignored-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",
@@ -35,7 +32,6 @@
"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",
@@ -45,7 +41,7 @@
"function-name-case": "lower",
"function-parentheses-newline-inside": "always-multi-line",
"function-parentheses-space-inside": "never-single-line",
"function-url-scheme-blacklist": ["data"],
"function-url-data-uris": never,
"function-whitespace-after": "always",
"indentation": 4,
"keyframe-declaration-no-important": true,
@@ -54,12 +50,14 @@
"max-line-length": [132, { "severity": "warning" }],
"media-feature-colon-space-after": "always",
"media-feature-colon-space-before": "never",
"media-feature-no-missing-punctuation": true,
"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-browser-hacks": null, # Enabled for non-scss in grunt.
"no-empty-source": true,
"no-eol-whitespace": true,
"no-extra-semicolons": [true, { "severity": "warning" }],
@@ -80,10 +78,11 @@
"selector-pseudo-class-parentheses-space-inside": "never",
"selector-pseudo-element-case": "lower",
"selector-pseudo-element-no-unknown": true,
"selector-root-no-composition": true,
"selector-type-case": "lower",
"selector-type-no-unknown": true,
"string-no-newline": true,
"time-min-milliseconds": 100,
"time-no-imperceptible": true,
"unit-blacklist": ["pt"],
"unit-case": "lower",
"unit-no-unknown": true,
+89 -86
View File
@@ -2,91 +2,74 @@
# process (which uses our internal CI system) this file is here for the benefit
# of community developers git clones - see MDL-51458.
sudo: false
# We currently disable Travis notifications entirely until https://github.com/travis-ci/travis-ci/issues/4976
# is fixed.
notifications:
email:
if: env(MOODLE_EMAIL) != no
email: false
language: php
os: linux
dist: xenial
php:
# We only run the highest and lowest supported versions to reduce the load on travis-ci.org.
- 7.1
- 5.6
services:
- mysql
- docker
- redis-server
addons:
postgresql: "9.6"
env:
# Although we want to run these jobs and see failures as quickly as possible, we also want to get the slowest job to
# start first so that the total run time is not too high.
#
# We only run MySQL on PHP 7.1, so run that first.
# CI Tests should be second-highest in priority as these only take <= 60 seconds to run under normal circumstances.
# Postgres is significantly is pretty reasonable in its run-time.
jobs:
# Run unit tests on MySQL
- DB=mysqli TASK=PHPUNIT
# Run CI Tests without running PHPUnit.
- DB=none TASK=CITEST
# Run unit tests on Postgres
- DB=pgsql TASK=PHPUNIT
# Perform an upgrade test too.
- DB=pgsql TASK=UPGRADE
matrix:
# Enable fast finish.
# This will fail the build if a single job fails (except those in allow_failures).
# It will not stop the jobs from running.
fast_finish: true
include:
# First all the lowest php ones (7.2)
- php: 7.2
env: DB=none TASK=CITEST
- php: 7.2
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
# Run grunt/npm install on lowest supported npm version
- php: 7.1
env: DB=none TASK=GRUNT NVM_VERSION='4'
# Run grunt/npm install on highest version ('node' is an alias for the latest node.js version.)
- php: 7.1
env: DB=none TASK=GRUNT NVM_VERSION='node'
- if: env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present
php: 7.2
env: DB=pgsql TASK=PHPUNIT
exclude:
# MySQL - it's just too slow.
# Exclude it on all versions except for 7.1
- if: env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all"
php: 7.2
env: DB=mysqli TASK=PHPUNIT
- env: DB=mysqli TASK=PHPUNIT
php: 5.6
# Then, conditionally, all the highest php ones (7.4)
- if: env(MOODLE_PHP) = "all"
php: 7.4
env: DB=none TASK=CITEST
- if: env(MOODLE_PHP) = "all"
php: 7.4
env: DB=none TASK=GRUNT NVM_VERSION='lts/carbon'
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "pgsql" OR env(MOODLE_DATABASE) = "all" OR env(MOODLE_DATABASE) IS NOT present)
php: 7.4
env: DB=pgsql TASK=PHPUNIT
- if: env(MOODLE_PHP) = "all" AND (env(MOODLE_DATABASE) = "mysqli" OR env(MOODLE_DATABASE) = "all")
php: 7.4
env: DB=mysqli TASK=PHPUNIT
# Moodle 2.7 is not compatible with PHP 7 for the upgrade test.
- env: DB=pgsql TASK=UPGRADE
php: 7.1
cache:
directories:
- $HOME/.composer/cache
- $HOME/.npm
before_install:
- docker run -d -p 127.0.0.1:8080:80 --name exttests moodlehq/moodle-exttests
# Avoid IPv6 default binding as service (causes redis not to start).
- sudo service redis-server start --bind 127.0.0.1
install:
- >
if [ "$DB" = 'mysqli' ];
then
sudo mkdir /mnt/ramdisk
sudo mount -t tmpfs -o size=1024m tmpfs /mnt/ramdisk
sudo service mysql stop
sudo mv /var/lib/mysql /mnt/ramdisk
sudo ln -s /mnt/ramdisk/mysql /var/lib/mysql
sudo service mysql restart
fi
- >
if [ "$DB" = 'pgsql' ];
then
sudo mkdir /mnt/ramdisk
sudo mount -t tmpfs -o size=1024m tmpfs /mnt/ramdisk
sudo service postgresql stop
sudo mv /var/lib/postgresql /mnt/ramdisk
sudo ln -s /mnt/ramdisk/postgresql /var/lib/postgresql
sudo service postgresql start 9.6
fi
- >
if [ "$TASK" = 'PHPUNIT' ];
then
@@ -95,6 +78,7 @@ install:
echo 'auth.json' >> .git/info/exclude
fi
# Enable Redis.
echo 'extension="redis.so"' > /tmp/redis.ini
phpenv config-add /tmp/redis.ini
@@ -114,7 +98,7 @@ install:
before_script:
- phpenv config-rm xdebug.ini
- >
if [ "$TASK" = 'PHPUNIT' ];
if [ "$TASK" = 'PHPUNIT' -o "$TASK" = 'UPGRADE' ];
then
# Copy generic configuration in place.
cp config-dist.php config.php ;
@@ -130,7 +114,7 @@ before_script:
# The wwwroot and dataroot.
sed -i \
-e "s%http://example.com/moodle%https://localhost%" \
-e "s%http://example.com/moodle%http://localhost%" \
-e "s%/home/example/moodledata%/home/travis/roots/base%" \
config.php ;
@@ -170,21 +154,7 @@ before_script:
sed -i \
-e "/require_once/i \\\$CFG->phpunit_dataroot = '\/home\/travis\/roots\/phpunit';" \
-e "/require_once/i \\\$CFG->phpunit_prefix = 'p_';" \
config.php ;
# Enable test external resources
sed -i \
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTP_URL', 'http://127.0.0.1:8080');" \
-e "/require_once/i \\define('TEST_EXTERNAL_FILES_HTTPS_URL', 'http://127.0.0.1:8080');" \
config.php ;
# Redis cache store tests
sed -i \
-e "/require_once/i \\define('TEST_CACHESTORE_REDIS_TESTSERVERS', '127.0.0.1');" \
config.php ;
# Redis session tests, but not for PHP 7.2 and up. See MDL-60978 for more info.
redissession="define('TEST_SESSION_REDIS_HOST', '127.0.0.1');"
sed -i \
-e "/require_once/i \\${redissession}" \
-e "/require_once/i \\define('TEST_SESSION_REDIS_HOST', '127.0.0.1');" \
config.php ;
# Initialise PHPUnit for Moodle.
@@ -214,7 +184,7 @@ before_script:
# We need the official upstream for comparison
git remote add upstream https://github.com/moodle/moodle.git;
git fetch upstream MOODLE_39_STABLE;
git fetch upstream MOODLE_32_STABLE;
export GIT_PREVIOUS_COMMIT="`git merge-base FETCH_HEAD $TRAVIS_COMMIT`";
export GIT_COMMIT="$TRAVIS_COMMIT";
export UPSTREAM_FETCH_HEAD=`git rev-parse FETCH_HEAD`
@@ -225,11 +195,37 @@ before_script:
export phpcmd=`which php`;
fi
########################################################################
# Upgrade test
########################################################################
- >
if [ "$TASK" = 'UPGRADE' ];
then
# We need the official upstream.
git remote add upstream https://github.com/moodle/moodle.git;
# Checkout 27 STABLE branch.
git fetch upstream MOODLE_27_STABLE;
git checkout MOODLE_27_STABLE;
# Perform the upgrade
php admin/cli/install_database.php --agree-license --adminpass=Password --adminemail=admin@example.com --fullname="Upgrade test" --shortname=Upgrade;
# Return to the previous commit
git checkout -;
# Perform the upgrade
php admin/cli/upgrade.php --non-interactive --allow-unstable ;
# The local_ci repository can be used to check upgrade savepoints.
git clone https://github.com/moodlehq/moodle-local_ci.git local/ci ;
fi
script:
- >
if [ "$TASK" = 'PHPUNIT' ];
then
vendor/bin/phpunit --fail-on-risky --disallow-test-output --verbose;
vendor/bin/phpunit;
fi
- >
@@ -244,16 +240,23 @@ script:
grunt ;
# Add all files to the git index and then run diff --cached to see all changes.
# This ensures that we get the status of all files, including new files.
# We ignore npm-shrinkwrap.json to make the tasks immune to npm changes.
git add . ;
git reset -- npm-shrinkwrap.json ;
git diff --cached --exit-code ;
fi
after_script:
########################################################################
# Upgrade test
########################################################################
- >
if [ "$TASK" = 'PHPUNIT' ];
if [ "$TASK" = 'UPGRADE' ];
then
EXTTESTS_HITS=$(docker logs exttests 2>&1 | grep -Fv -e 'AH00558' -e '[pid 1]' | wc -l)
echo -e "\nTest local resources number of hits: ${EXTTESTS_HITS}.\n"
cp local/ci/check_upgrade_savepoints/check_upgrade_savepoints.php ./check_upgrade_savepoints.php
result=`php check_upgrade_savepoints.php`;
# Check if there are problems
count=`echo "$result" | grep -P "ERROR|WARN" | wc -l` ;
if (($count > 0));
then
echo "$result"
exit 1 ;
fi
fi
+133 -616
View File
@@ -20,203 +20,42 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/* eslint-env node */
/**
* Calculate the cwd, taking into consideration the `root` option (for Windows).
*
* @param {Object} grunt
* @returns {String} The current directory as best we can determine
* Grunt configuration
*/
const getCwd = grunt => {
const fs = require('fs');
const path = require('path');
let cwd = fs.realpathSync(process.env.PWD || process.cwd());
module.exports = function(grunt) {
var path = require('path'),
tasks = {},
cwd = process.env.PWD || process.cwd(),
async = require('async'),
DOMParser = require('xmldom').DOMParser,
xpath = require('xpath'),
semver = require('semver');
// 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 too old. Require ' + expected + ', version installed: ' + actual);
}
// 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');
var root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) {
cwd = fs.realpathSync(path.join(__dirname, root));
cwd = path.join(__dirname, root);
grunt.log.ok('Setting root to ' + cwd);
} else {
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
return cwd;
};
/**
* Register any stylelint tasks.
*
* @param {Object} grunt
* @param {Array} files
* @param {String} fullRunDir
*/
const registerStyleLintTasks = (grunt, files, fullRunDir) => {
const getCssConfigForFiles = files => {
return {
stylelint: {
css: {
// Use a fully-qualified path.
src: files,
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
}
}
}
},
},
};
};
const getScssConfigForFiles = files => {
return {
stylelint: {
scss: {
options: {syntax: 'scss'},
src: files,
},
},
};
};
let hasCss = true;
let hasScss = true;
if (files) {
// Specific files were passed. Just set them up.
grunt.config.merge(getCssConfigForFiles(files));
grunt.config.merge(getScssConfigForFiles(files));
} else {
// The stylelint system does not handle the case where there was no file to lint.
// Check whether there are any files to lint in the current directory.
const glob = require('glob');
const scssSrc = [];
glob.sync(`${fullRunDir}/**/*.scss`).forEach(path => scssSrc.push(path));
if (scssSrc.length) {
grunt.config.merge(getScssConfigForFiles(scssSrc));
} else {
hasScss = false;
}
const cssSrc = [];
glob.sync(`${fullRunDir}/**/*.css`).forEach(path => cssSrc.push(path));
if (cssSrc.length) {
grunt.config.merge(getCssConfigForFiles(cssSrc));
} else {
hasCss = false;
}
}
const scssTasks = ['sass'];
if (hasScss) {
scssTasks.unshift('stylelint:scss');
}
grunt.registerTask('scss', scssTasks);
const cssTasks = [];
if (hasCss) {
cssTasks.push('stylelint:css');
}
grunt.registerTask('rawcss', cssTasks);
grunt.registerTask('css', ['scss', 'rawcss']);
};
/**
* Grunt configuration.
*
* @param {Object} grunt
*/
module.exports = function(grunt) {
const path = require('path');
const tasks = {};
const async = require('async');
const DOMParser = require('xmldom').DOMParser;
const xpath = require('xpath');
const semver = require('semver');
const watchman = require('fb-watchman');
const watchmanClient = new watchman.Client();
const fs = require('fs');
const ComponentList = require(path.resolve('GruntfileComponents.js'));
const sass = require('node-sass');
// Verify the node version is new enough.
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
var actual = semver.valid(process.version);
if (!semver.satisfies(actual, expected)) {
grunt.fail.fatal('Node version not satisfied. Require ' + expected + ', version installed: ' + actual);
}
// Detect directories:
// * gruntFilePath The real path on disk to this Gruntfile.js
// * cwd The current working directory, which can be overridden by the `root` option
// * relativeCwd The cwd, relative to the Gruntfile.js
// * componentDirectory The root directory of the component if the cwd is in a valid component
// * inComponent Whether the cwd is in a valid component
// * runDir The componentDirectory or cwd if not in a component, relative to Gruntfile.js
// * fullRunDir The full path to the runDir
const gruntFilePath = fs.realpathSync(process.cwd());
const cwd = getCwd(grunt);
const relativeCwd = path.relative(gruntFilePath, cwd);
const componentDirectory = ComponentList.getOwningComponentDirectory(relativeCwd);
const inComponent = !!componentDirectory;
const runDir = inComponent ? componentDirectory : relativeCwd;
const fullRunDir = fs.realpathSync(gruntFilePath + path.sep + runDir);
grunt.log.debug('============================================================================');
grunt.log.debug(`= Node version: ${process.versions.node}`);
grunt.log.debug(`= grunt version: ${grunt.package.version}`);
grunt.log.debug(`= process.cwd: '` + process.cwd() + `'`);
grunt.log.debug(`= process.env.PWD: '${process.env.PWD}'`);
grunt.log.debug(`= path.sep '${path.sep}'`);
grunt.log.debug('============================================================================');
grunt.log.debug(`= gruntFilePath: '${gruntFilePath}'`);
grunt.log.debug(`= relativeCwd: '${relativeCwd}'`);
grunt.log.debug(`= componentDirectory: '${componentDirectory}'`);
grunt.log.debug(`= inComponent: '${inComponent}'`);
grunt.log.debug(`= runDir: '${runDir}'`);
grunt.log.debug(`= fullRunDir: '${fullRunDir}'`);
grunt.log.debug('============================================================================');
if (inComponent) {
grunt.log.ok(`Running tasks for component directory ${componentDirectory}`);
}
let files = null;
if (grunt.option('files')) {
// Accept a comma separated list of files to process.
files = grunt.option('files').split(',');
}
// If the cwd is the amd directory in the current component then it will be empty.
// If the cwd is a child of the component's AMD directory, the relative directory will not start with ..
const inAMD = !path.relative(`${componentDirectory}/amd`, cwd).startsWith('..');
var inAMD = path.basename(cwd) == 'amd';
// Globbing pattern for matching all AMD JS source files.
let amdSrc = [];
if (inComponent) {
amdSrc.push(componentDirectory + "/amd/src/*.js");
amdSrc.push(componentDirectory + "/amd/src/**/*.js");
} else {
amdSrc = ComponentList.getAmdSrcGlobList();
}
let yuiSrc = [];
if (inComponent) {
yuiSrc.push(componentDirectory + "/yui/src/**/*.js");
} else {
yuiSrc = ComponentList.getYuiSrcGlobList(gruntFilePath + '/');
}
var amdSrc = [inAMD ? cwd + '/src/*.js' : '**/amd/src/*.js'];
/**
* Function to generate the destination for the uglify task
@@ -228,9 +67,10 @@ module.exports = function(grunt) {
* @param {String} srcPath the matched src path
* @return {String} The rewritten destination path.
*/
var babelRename = function(destPath, srcPath) {
var uglifyRename = function(destPath, srcPath) {
destPath = srcPath.replace('src', 'build');
destPath = destPath.replace('.js', '.min.js');
destPath = path.resolve(cwd, destPath);
return destPath;
};
@@ -241,199 +81,153 @@ module.exports = function(grunt) {
* @return {array} The list of thirdparty paths.
*/
var getThirdPartyPathsFromXML = function() {
const thirdpartyfiles = ComponentList.getThirdPartyLibsList(gruntFilePath + '/');
const libs = ['node_modules/', 'vendor/'];
var thirdpartyfiles = grunt.file.expand('*/**/thirdpartylibs.xml');
var libs = ['node_modules/', 'vendor/'];
thirdpartyfiles.forEach(function(file) {
const dirname = path.dirname(file);
var dirname = path.dirname(file);
const doc = new DOMParser().parseFromString(grunt.file.read(file));
const nodes = xpath.select("/libraries/library/location/text()", doc);
var doc = new DOMParser().parseFromString(grunt.file.read(file));
var nodes = xpath.select("/libraries/library/location/text()", doc);
nodes.forEach(function(node) {
let lib = path.posix.join(dirname, node.toString());
if (grunt.file.isDir(lib)) {
// Ensure trailing slash on dirs.
lib = lib.replace(/\/?$/, '/');
}
nodes.forEach(function(node) {
var lib = path.join(dirname, node.toString());
if (grunt.file.isDir(lib)) {
// Ensure trailing slash on dirs.
lib = lib.replace(/\/?$/, '/');
}
// Look for duplicate paths before adding to array.
if (libs.indexOf(lib) === -1) {
libs.push(lib);
}
});
// Look for duplicate paths before adding to array.
if (libs.indexOf(lib) === -1) {
libs.push(lib);
}
});
});
return libs;
};
/**
* Get the list of feature files to pass to the gherkin linter.
*
* @returns {Array}
*/
const getGherkinLintTargets = () => {
if (files) {
// Specific files were requested. Only check these.
return files;
}
if (inComponent) {
return [`${runDir}/tests/behat/*.feature`];
}
return ['**/tests/behat/*.feature'];
};
// Project configuration.
grunt.initConfig({
eslint: {
// Even though warnings dont stop the build we don't display warnings by default because
// at this moment we've got too many core warnings.
// To display warnings call: grunt eslint --show-lint-warnings
// To fail on warnings call: grunt eslint --max-lint-warnings=0
// Also --max-lint-warnings=-1 can be used to display warnings but not fail.
options: {
quiet: (!grunt.option('show-lint-warnings')) && (typeof grunt.option('max-lint-warnings') === 'undefined'),
maxWarnings: ((typeof grunt.option('max-lint-warnings') !== 'undefined') ? grunt.option('max-lint-warnings') : -1)
options: {quiet: !grunt.option('show-lint-warnings')},
amd: {
src: amdSrc,
// Check AMD with some slightly stricter rules.
rules: {
'no-unused-vars': 'error',
'no-implicit-globals': 'error'
}
},
amd: {src: files ? files : amdSrc},
// Check YUI module source files.
yui: {src: files ? files : yuiSrc},
yui: {
src: ['**/yui/src/**/*.js', '!*/**/yui/src/*/meta/*.js'],
options: {
// Disable some rules which we can't safely define for YUI rollups.
rules: {
'no-undef': 'off',
'no-unused-vars': 'off',
'no-unused-expressions': 'off'
}
}
}
},
babel: {
options: {
sourceMaps: true,
comments: false,
plugins: [
'transform-es2015-modules-amd-lazy',
'system-import-transformer',
// This plugin modifies the Babel transpiling for "export default"
// so that if it's used then only the exported value is returned
// by the generated AMD module.
//
// It also adds the Moodle plugin name to the AMD module definition
// so that it can be imported as expected in other modules.
path.resolve('babel-plugin-add-module-to-define.js'),
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-syntax-import-meta',
['@babel/plugin-proposal-class-properties', {'loose': false}],
'@babel/plugin-proposal-json-strings'
],
presets: [
['minify', {
// This minification plugin needs to be disabled because it breaks the
// source map generation and causes invalid source maps to be output.
simplify: false,
builtIns: false
}],
['@babel/preset-env', {
targets: {
browsers: [
">0.25%",
"last 2 versions",
"not ie <= 10",
"not op_mini all",
"not Opera > 0",
"not dead"
]
},
modules: false,
useBuiltIns: false
}]
]
},
dist: {
uglify: {
amd: {
files: [{
expand: true,
src: files ? files : amdSrc,
rename: babelRename
}]
src: amdSrc,
rename: uglifyRename
}],
options: {report: 'none'}
}
},
sass: {
dist: {
less: {
bootstrapbase: {
files: {
"theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss",
"theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss"
"theme/bootstrapbase/style/moodle.css": "theme/bootstrapbase/less/moodle.less",
"theme/bootstrapbase/style/editor.css": "theme/bootstrapbase/less/editor.less",
},
options: {
compress: false // We must not compress to keep the comments.
}
},
options: {
implementation: sass,
includePaths: ["theme/boost/scss/", "theme/classic/scss/"]
}
}
},
watch: {
options: {
nospawn: true // We need not to spawn so config can be changed dynamically.
},
amd: {
files: inComponent
? ['amd/src/*.js', 'amd/src/**/*.js']
: ['**/amd/src/**/*.js'],
files: ['**/amd/src/**/*.js'],
tasks: ['amd']
},
boost: {
files: [inComponent ? 'scss/**/*.scss' : 'theme/boost/scss/**/*.scss'],
tasks: ['scss']
},
rawcss: {
files: [
'**/*.css',
],
excludes: [
'**/moodle.css',
'**/editor.css',
],
tasks: ['rawcss']
bootstrapbase: {
files: ["theme/bootstrapbase/less/**/*.less"],
tasks: ["css"]
},
yui: {
files: inComponent
? ['yui/src/*.json', 'yui/src/**/*.js']
: ['**/yui/src/**/*.js'],
files: ['**/yui/src/**/*.js'],
tasks: ['yui']
},
gherkinlint: {
files: [inComponent ? 'tests/behat/*.feature' : '**/tests/behat/*.feature'],
tasks: ['gherkinlint']
}
},
shifter: {
options: {
recursive: true,
// Shifter takes a relative path.
paths: files ? files : [runDir]
paths: [cwd]
}
},
gherkinlint: {
options: {
files: getGherkinLintTargets(),
stylelint: {
less: {
options: {
syntax: 'less',
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
"no-browser-hacks": [true, {"severity": "warning"}]
}
}
},
src: ['theme/**/*.less']
},
scss: {
options: {syntax: 'scss'},
src: ['*/**/*.scss']
},
css: {
src: ['*/**/*.css'],
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
"no-browser-hacks": [true, {"severity": "warning"}]
}
}
}
}
},
}
});
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
tasks.ignorefiles = function() {
// An array of paths to third party directories.
const thirdPartyPaths = getThirdPartyPathsFromXML();
// Generate .eslintignore.
const eslintIgnores = [
'# Generated by "grunt ignorefiles"',
'*/**/yui/src/*/meta/',
'*/**/build/',
].concat(thirdPartyPaths);
grunt.file.write('.eslintignore', eslintIgnores.join('\n'));
// Generate .stylelintignore.
const stylelintIgnores = [
'# Generated by "grunt ignorefiles"',
'**/yui/build/*',
'theme/boost/style/moodle.css',
'theme/classic/style/moodle.css',
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
// An array of paths to third party directories.
var thirdPartyPaths = getThirdPartyPathsFromXML();
// Generate .eslintignore.
var eslintIgnores = ['# Generated by "grunt ignorefiles"', '*/**/yui/src/*/meta/', '*/**/build/'].concat(thirdPartyPaths);
grunt.file.write('.eslintignore', eslintIgnores.join('\n'));
// Generate .stylelintignore.
var stylelintIgnores = [
'# Generated by "grunt ignorefiles"',
'theme/bootstrapbase/style/',
'theme/clean/style/custom.css',
'theme/more/style/custom.css'
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
};
/**
@@ -524,35 +318,6 @@ module.exports = function(grunt) {
}, done);
};
tasks.gherkinlint = function() {
const done = this.async();
const options = grunt.config('gherkinlint.options');
// Grab the gherkin-lint linter and required scaffolding.
const linter = require('gherkin-lint/dist/linter.js');
const featureFinder = require('gherkin-lint/dist/feature-finder.js');
const configParser = require('gherkin-lint/dist/config-parser.js');
const formatter = require('gherkin-lint/dist/formatters/stylish.js');
// Run the linter.
return linter.lint(
featureFinder.getFeatureFiles(grunt.file.expand(options.files)),
configParser.getConfiguration(configParser.defaultConfigFileName)
)
.then(results => {
// Print the results out uncondtionally.
formatter.printResults(results);
return results;
})
.then(results => {
// Report on the results.
// The done function takes a bool whereby a falsey statement causes the task to fail.
return results.every(result => result.errors.length === 0);
})
.then(done); // eslint-disable-line promise/no-callback-in-promise
};
tasks.startup = function() {
// Are we in a YUI directory?
if (path.basename(path.resolve(cwd, '../../')) == 'yui') {
@@ -564,292 +329,44 @@ module.exports = function(grunt) {
// Run them all!.
grunt.task.run('css');
grunt.task.run('js');
grunt.task.run('gherkinlint');
}
};
/**
* This is a wrapper task to handle the grunt watch command. It attempts to use
* Watchman to monitor for file changes, if it's installed, because it's much faster.
*
* If Watchman isn't installed then it falls back to the grunt-contrib-watch file
* watcher for backwards compatibility.
*/
tasks.watch = function() {
var watchTaskDone = this.async();
var watchInitialised = false;
var watchTaskQueue = {};
var processingQueue = false;
// Grab the tasks and files that have been queued up and execute them.
var processWatchTaskQueue = function() {
if (!Object.keys(watchTaskQueue).length || processingQueue) {
// If there is nothing in the queue or we're already processing then wait.
return;
}
processingQueue = true;
// Grab all tasks currently in the queue.
var queueToProcess = watchTaskQueue;
// Reset the queue.
watchTaskQueue = {};
async.forEachSeries(
Object.keys(queueToProcess),
function(task, next) {
var files = queueToProcess[task];
var filesOption = '--files=' + files.join(',');
grunt.log.ok('Running task ' + task + ' for files ' + filesOption);
// Spawn the task in a child process so that it doesn't kill this one
// if it failed.
grunt.util.spawn(
{
// Spawn with the grunt bin.
grunt: true,
// Run from current working dir and inherit stdio from process.
opts: {
cwd: fullRunDir,
stdio: 'inherit'
},
args: [task, filesOption]
},
function(err, res, code) {
if (code !== 0) {
// The grunt task failed.
grunt.log.error(err);
}
// Move on to the next task.
next();
}
);
},
function() {
// No longer processing.
processingQueue = false;
// Once all of the tasks are done then recurse just in case more tasks
// were queued while we were processing.
processWatchTaskQueue();
}
);
};
const originalWatchConfig = grunt.config.get(['watch']);
const watchConfig = Object.keys(originalWatchConfig).reduce(function(carry, key) {
if (key == 'options') {
return carry;
}
const value = originalWatchConfig[key];
const taskNames = value.tasks;
const files = value.files;
let excludes = [];
if (value.excludes) {
excludes = value.excludes;
}
taskNames.forEach(function(taskName) {
carry[taskName] = {
files,
excludes,
};
});
return carry;
}, {});
watchmanClient.on('error', function(error) {
// We have to add an error handler here and parse the error string because the
// example way from the docs to check if Watchman is installed doesn't actually work!!
// See: https://github.com/facebook/watchman/issues/509
if (error.message.match('Watchman was not found')) {
// If watchman isn't installed then we should fallback to the other watch task.
grunt.log.ok('It is recommended that you install Watchman for better performance using the "watch" command.');
// Fallback to the old grunt-contrib-watch task.
grunt.renameTask('watch-grunt', 'watch');
grunt.task.run(['watch']);
// This task is finished.
watchTaskDone(0);
} else {
grunt.log.error(error);
// Fatal error.
watchTaskDone(1);
}
});
watchmanClient.on('subscription', function(resp) {
if (resp.subscription !== 'grunt-watch') {
return;
}
resp.files.forEach(function(file) {
grunt.log.ok('File changed: ' + file.name);
var fullPath = fullRunDir + '/' + file.name;
Object.keys(watchConfig).forEach(function(task) {
const fileGlobs = watchConfig[task].files;
var match = fileGlobs.some(function(fileGlob) {
return grunt.file.isMatch(`**/${fileGlob}`, fullPath);
});
if (match) {
// If we are watching a subdirectory then the file.name will be relative
// to that directory. However the grunt tasks expect the file paths to be
// relative to the Gruntfile.js location so let's normalise them before
// adding them to the queue.
var relativePath = fullPath.replace(gruntFilePath + '/', '');
if (task in watchTaskQueue) {
if (!watchTaskQueue[task].includes(relativePath)) {
watchTaskQueue[task] = watchTaskQueue[task].concat(relativePath);
}
} else {
watchTaskQueue[task] = [relativePath];
}
}
});
});
processWatchTaskQueue();
});
process.on('SIGINT', function() {
// Let the user know that they may need to manually stop the Watchman daemon if they
// no longer want it running.
if (watchInitialised) {
grunt.log.ok('The Watchman daemon may still be running and may need to be stopped manually.');
}
process.exit();
});
// Initiate the watch on the current directory.
watchmanClient.command(['watch-project', fullRunDir], function(watchError, watchResponse) {
if (watchError) {
grunt.log.error('Error initiating watch:', watchError);
watchTaskDone(1);
return;
}
if ('warning' in watchResponse) {
grunt.log.error('warning: ', watchResponse.warning);
}
var watch = watchResponse.watch;
var relativePath = watchResponse.relative_path;
watchInitialised = true;
watchmanClient.command(['clock', watch], function(clockError, clockResponse) {
if (clockError) {
grunt.log.error('Failed to query clock:', clockError);
watchTaskDone(1);
return;
}
// Generate the expression query used by watchman.
// Documentation is limited, but see https://facebook.github.io/watchman/docs/expr/allof.html for examples.
// We generate an expression to match any value in the files list of all of our tasks, but excluding
// all value in the excludes list of that task.
//
// [anyof, [
// [allof, [
// [anyof, [
// ['match', validPath, 'wholename'],
// ['match', validPath, 'wholename'],
// ],
// [not,
// [anyof, [
// ['match', invalidPath, 'wholename'],
// ['match', invalidPath, 'wholename'],
// ],
// ],
// ],
var matchWholeName = fileGlob => ['match', fileGlob, 'wholename'];
var matches = Object.keys(watchConfig).map(function(task) {
const matchAll = [];
matchAll.push(['anyof'].concat(watchConfig[task].files.map(matchWholeName)));
if (watchConfig[task].excludes.length) {
matchAll.push(['not', ['anyof'].concat(watchConfig[task].excludes.map(matchWholeName))]);
}
return ['allof'].concat(matchAll);
});
matches = ['anyof'].concat(matches);
var sub = {
expression: matches,
// Which fields we're interested in.
fields: ["name", "size", "type"],
// Add our time constraint.
since: clockResponse.clock
};
if (relativePath) {
/* eslint-disable camelcase */
sub.relative_root = relativePath;
}
watchmanClient.command(['subscribe', watch, 'grunt-watch', sub], function(subscribeError) {
if (subscribeError) {
// Probably an error in the subscription criteria.
grunt.log.error('failed to subscribe: ', subscribeError);
watchTaskDone(1);
return;
}
grunt.log.ok('Listening for changes to files in ' + fullRunDir);
});
});
});
};
// On watch, we dynamically modify config to build only affected files. This
// method is slightly complicated to deal with multiple changed files at once (copied
// from the grunt-contrib-watch readme).
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
var files = Object.keys(changedFiles);
grunt.config('eslint.amd.src', files);
grunt.config('eslint.yui.src', files);
grunt.config('shifter.options.paths', files);
grunt.config('gherkinlint.options.files', files);
grunt.config('babel.dist.files', [{expand: true, src: files, rename: babelRename}]);
changedFiles = Object.create(null);
var files = Object.keys(changedFiles);
grunt.config('eslint.amd.src', files);
grunt.config('eslint.yui.src', files);
grunt.config('uglify.amd.files', [{expand: true, src: files, rename: uglifyRename}]);
grunt.config('shifter.options.paths', files);
grunt.config('stylelint.less.src', files);
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
changedFiles[filepath] = action;
onChange();
});
// Register NPM tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('grunt-stylelint');
grunt.loadNpmTasks('grunt-babel');
// Rename the grunt-contrib-watch "watch" task because we're going to wrap it.
grunt.renameTask('watch', 'watch-grunt');
// Register JS tasks.
grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter);
grunt.registerTask('gherkinlint', 'Run gherkinlint against the current directory', tasks.gherkinlint);
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles);
grunt.registerTask('watch', 'Run tasks on file changes', tasks.watch);
grunt.registerTask('yui', ['eslint:yui', 'shifter']);
grunt.registerTask('amd', ['eslint:amd', 'babel']);
grunt.registerTask('amd', ['eslint:amd', 'uglify']);
grunt.registerTask('js', ['amd', 'yui']);
// Register CSS tasks.
registerStyleLintTasks(grunt, files, fullRunDir);
// Register CSS taks.
grunt.registerTask('css', ['stylelint:scss', 'stylelint:less', 'less:bootstrapbase', 'stylelint:css']);
// Register the startup task.
grunt.registerTask('startup', 'Run the correct tasks for the current directory', tasks.startup);
-188
View File
@@ -1,188 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Helper functions for working with Moodle component names, directories, and sources.
*
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
/* eslint-env node */
/** @var {Object} A list of subsystems in Moodle */
const componentData = {};
/**
* Load details of all moodle modules.
*
* @returns {object}
*/
const fetchComponentData = () => {
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const gruntFilePath = process.cwd();
if (!Object.entries(componentData).length) {
componentData.subsystems = {};
componentData.pathList = [];
// Fetch the component definiitions from the distributed JSON file.
const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`));
// Build the list of moodle subsystems.
componentData.subsystems.lib = 'core';
componentData.pathList.push(process.cwd() + path.sep + 'lib');
for (const [component, thisPath] of Object.entries(components.subsystems)) {
if (thisPath) {
// Prefix "core_" to the front of the subsystems.
componentData.subsystems[thisPath] = `core_${component}`;
componentData.pathList.push(process.cwd() + path.sep + thisPath);
}
}
// The list of components incldues the list of subsystems.
componentData.components = componentData.subsystems;
// Go through each of the plugintypes.
Object.entries(components.plugintypes).forEach(([pluginType, pluginTypePath]) => {
// We don't allow any code in this place..?
glob.sync(`${pluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${pluginType}_${componentName}`;
componentData.components[`${pluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
// Look for any subplugins.
const subPluginConfigurationFile = `${componentPath}/db/subplugins.json`;
if (fs.existsSync(subPluginConfigurationFile)) {
const subpluginList = JSON.parse(fs.readFileSync(fs.realpathSync(subPluginConfigurationFile)));
Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => {
glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => {
const componentPath = fs.realpathSync(path.dirname(versionPath));
const componentName = path.basename(componentPath);
const frankenstyleName = `${subpluginType}_${componentName}`;
componentData.components[`${subpluginTypePath}/${componentName}`] = frankenstyleName;
componentData.pathList.push(componentPath);
});
});
}
});
});
}
return componentData;
};
/**
* Get the list of paths to build AMD sources.
*
* @returns {Array}
*/
const getAmdSrcGlobList = () => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
globList.push(`${componentPath}/amd/src/*.js`);
globList.push(`${componentPath}/amd/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to build YUI sources.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getYuiSrcGlobList = relativeTo => {
const globList = [];
fetchComponentData().pathList.forEach(componentPath => {
const relativeComponentPath = componentPath.replace(relativeTo, '');
globList.push(`${relativeComponentPath}/yui/src/**/*.js`);
});
return globList;
};
/**
* Get the list of paths to thirdpartylibs.xml.
*
* @param {String} relativeTo
* @returns {Array}
*/
const getThirdPartyLibsList = relativeTo => {
const fs = require('fs');
const path = require('path');
return fetchComponentData().pathList
.map(componentPath => path.relative(relativeTo, componentPath) + '/thirdpartylibs.xml')
.map(componentPath => componentPath.replace(/\\/g, '/'))
.filter(path => fs.existsSync(path))
.sort();
};
/**
* Find the name of the component matching the specified path.
*
* @param {String} path
* @returns {String|null} Name of matching component.
*/
const getComponentFromPath = path => {
const componentList = fetchComponentData().components;
if (componentList.hasOwnProperty(path)) {
return componentList[path];
}
return null;
};
/**
* Check whether the supplied path, relative to the Gruntfile.js, is in a known component.
*
* @param {String} checkPath The path to check. This can be with either Windows, or Linux directory separators.
* @returns {String|null}
*/
const getOwningComponentDirectory = checkPath => {
const path = require('path');
// Fetch all components into a reverse sorted array.
// This ensures that components which are within the directory of another component match first.
const pathList = Object.keys(fetchComponentData().components).sort().reverse();
for (const componentPath of pathList) {
// If the componentPath is the directory being checked, it will be empty.
// If the componentPath is a parent of the directory being checked, the relative directory will not start with ..
if (!path.relative(componentPath, checkPath).startsWith('..')) {
return componentPath;
}
}
return null;
};
module.exports = {
getAmdSrcGlobList,
getComponentFromPath,
getOwningComponentDirectory,
getYuiSrcGlobList,
getThirdPartyLibsList,
};
+4 -5
View File
@@ -33,7 +33,8 @@ $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();
require_login();
require_capability('moodle/site:config', context_system::instance());
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageantiviruses";
@@ -98,10 +99,8 @@ switch ($action) {
default:
break;
}
$new = implode(',', $activeantiviruses);
add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core');
set_config('antiviruses', $new);
set_config('antiviruses', implode(',', $activeantiviruses));
core_plugin_manager::reset_caches();
redirect ($returnurl);
redirect ($returnurl);
+2 -1
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'));
+4 -29
View File
@@ -16,9 +16,6 @@ $err = array();
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageauths";
debugging("Use of config.html files in authentication plugins have been deprecated. " .
" Please migrate your plugin to use the admin settings API", DEBUG_DEVELOPER);
// save configuration changes
if ($frm = data_submitted() and confirm_sesskey()) {
@@ -89,28 +86,12 @@ exit;
/// Functions /////////////////////////////////////////////////////////////////
/**
* auth field locking
* Good enough for most auth plugins
* but some may want a custom one if they are offering
* other options
* Note: lockconfig_ fields have special handling.
*
* @param string $auth authentication plugin shortname
* @param array $user_fields user profile fields
* @param string $helptext help text to be displayed at top of form
* @param boolean $retrieveopts Map fields or lock only.
* @param boolean $updateopts Allow remote updates
* @param array $customfields list of custom profile fields
* @deprecated since Moodle 3.3
*/
// 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;
debugging("The function 'print_auth_lock_options' has been deprecated, " .
"Please migrate your code to use the admin settings API and use the function 'display_auth_lock_options' instead. ",
DEBUG_DEVELOPER);
echo '<tr><td colspan="3">';
if ($retrieveopts) {
echo $OUTPUT->heading(get_string('auth_data_mapping', 'auth'));
@@ -165,12 +146,6 @@ function print_auth_lock_options($auth, $user_fields, $helptext, $retrieveopts,
// If custom field then pick name from database.
$fieldshortname = str_replace('profile_field_', '', $fieldname);
$fieldname = $customfieldname[$fieldshortname]->name;
if (core_text::strlen($fieldshortname) > 67) {
// If custom profile field name is longer than 67 characters we will not be able to store the setting
// such as 'field_updateremote_profile_field_NOTSOSHORTSHORTNAME' in the database because the character
// limit for the setting name is 100.
continue;
}
} elseif ($fieldname == 'url') {
$fieldname = get_string('webpage');
} else {
+4 -4
View File
@@ -168,10 +168,10 @@
$visible = '';
} else if ($blocks[$blockid]->visible) {
$visible = '<a href="blocks.php?hide='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strhide.'">'.
$OUTPUT->pix_icon('t/hide', $strhide) . '</a>';
'<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.'">'.
$OUTPUT->pix_icon('t/show', $strshow) . '</a>';
'<img src="'.$OUTPUT->pix_url('t/show') . '" class="iconsmall" alt="'.$strshow.'" /></a>';
$class = 'dimmed_text';
}
@@ -186,10 +186,10 @@
$undeletable = '';
} else if (in_array($blockname, $undeletableblocktypes)) {
$undeletable = '<a href="blocks.php?unprotect='.$blockid.'&amp;sesskey='.sesskey().'" title="'.$strunprotect.'">'.
$OUTPUT->pix_icon('t/unlock', $strunprotect) . '</a>';
'<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.'">'.
$OUTPUT->pix_icon('t/lock', $strprotect) . '</a>';
'<img src="'.$OUTPUT->pix_url('t/lock') . '" class="iconsmall" alt="'.$strprotect.'" /></a>';
}
$row = array(
+11 -14
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));
@@ -53,16 +54,14 @@ $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');
@@ -74,7 +73,7 @@ if ($data = data_submitted() and confirm_sesskey()) {
if ($PAGE->user_allowed_editing() && $adminediting != -1) {
$USER->editing = $adminediting;
}
$buttons = null;
if ($PAGE->user_allowed_editing()) {
$url = clone($PAGE->url);
if ($PAGE->user_is_editing()) {
@@ -90,7 +89,7 @@ if ($PAGE->user_allowed_editing()) {
$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) {
@@ -128,9 +127,7 @@ if ($savebutton) {
$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();
-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,59 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* 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'];
$mform->addElement('text', 'recipient', get_string('testoutgoingmailconf_toemail', 'admin'), $options);
$mform->setType('recipient', PARAM_EMAIL);
$mform->addRule('recipient', get_string('required'), 'required');
$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');
}
}
-195
View File
@@ -1,195 +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);
}
/**
* 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;
}
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');
}
$bytes = $data['v'] * $data['u'];
$result = $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);
}
}
-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';
}
}
-289
View File
@@ -1,289 +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 log table.
*
* @package core_admin
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_admin;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/tablelib.php');
/**
* Table to display list of task logs.
*
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class task_log_table extends \table_sql {
/**
* Constructor for the task_log table.
*
* @param string $filter
* @param int $resultfilter
*/
public function __construct(string $filter = '', int $resultfilter = null) {
global $DB;
if (-1 === $resultfilter) {
$resultfilter = null;
}
parent::__construct('tasklogs');
$columnheaders = [
'classname' => get_string('name'),
'type' => get_string('tasktype', 'admin'),
'userid' => get_string('user', 'admin'),
'timestart' => get_string('task_starttime', 'admin'),
'duration' => get_string('task_duration', 'admin'),
'db' => get_string('task_dbstats', 'admin'),
'result' => get_string('task_result', 'admin'),
'actions' => '',
];
$this->define_columns(array_keys($columnheaders));
$this->define_headers(array_values($columnheaders));
// The name column is a header.
$this->define_header_column('classname');
// This table is not collapsible.
$this->collapsible(false);
// The actions class should not wrap. Use the BS text utility class.
$this->column_class('actions', 'text-nowrap');
// Allow pagination.
$this->pageable(true);
// Allow sorting. Default to sort by timestarted DESC.
$this->sortable(true, 'timestart', SORT_DESC);
// Add filtering.
$where = [];
$params = [];
if (!empty($filter)) {
$orwhere = [];
$filter = str_replace('\\', '\\\\', $filter);
// Check the class name.
$orwhere[] = $DB->sql_like('classname', ':classfilter', false, false);
$params['classfilter'] = '%' . $DB->sql_like_escape($filter) . '%';
$orwhere[] = $DB->sql_like('output', ':outputfilter', false, false);
$params['outputfilter'] = '%' . $DB->sql_like_escape($filter) . '%';
$where[] = "(" . implode(' OR ', $orwhere) . ")";
}
if (null !== $resultfilter) {
$where[] = 'tl.result = :result';
$params['result'] = $resultfilter;
}
$where = implode(' AND ', $where);
$this->set_sql('', '', $where, $params);
}
/**
* Query the db. Store results in the table object for use by build_table.
*
* @param int $pagesize size of page for paginated displayed table.
* @param bool $useinitialsbar do you want to use the initials bar. Bar
* will only be used if there is a fullname column defined for the table.
*/
public function query_db($pagesize, $useinitialsbar = true) {
global $DB;
// Fetch the attempts.
$sort = $this->get_sql_sort();
if ($sort) {
$sort = "ORDER BY $sort";
}
$extrafields = get_extra_user_fields(\context_system::instance());
$userfields = \user_picture::fields('u', $extrafields, 'userid2', 'user');
$where = '';
if (!empty($this->sql->where)) {
$where = "WHERE {$this->sql->where}";
}
$sql = "SELECT
tl.id, tl.type, tl.component, tl.classname, tl.userid, tl.timestart, tl.timeend,
tl.dbreads, tl.dbwrites, tl.result,
tl.dbreads + tl.dbwrites AS db,
tl.timeend - tl.timestart AS duration,
{$userfields}
FROM {task_log} tl
LEFT JOIN {user} u ON u.id = tl.userid
{$where}
{$sort}";
$this->pagesize($pagesize, $DB->count_records_sql("SELECT COUNT('x') FROM {task_log} tl {$where}", $this->sql->params));
if (!$this->is_downloading()) {
$this->rawdata = $DB->get_records_sql($sql, $this->sql->params, $this->get_page_start(), $this->get_page_size());
} else {
$this->rawdata = $DB->get_records_sql($sql, $this->sql->params);
}
}
/**
* Format the name cell.
*
* @param \stdClass $row
* @return string
*/
public function col_classname($row) : string {
$output = '';
if (class_exists($row->classname)) {
$task = new $row->classname;
if ($task instanceof \core\task\scheduled_task) {
$output = $task->get_name();
}
}
$output .= \html_writer::tag('div', "\\{$row->classname}", [
'class' => 'task-class',
]);
return $output;
}
/**
* Format the type cell.
*
* @param \stdClass $row
* @return string
*/
public function col_type($row) : string {
if (\core\task\database_logger::TYPE_SCHEDULED == $row->type) {
return get_string('task_type:scheduled', 'admin');
} else {
return get_string('task_type:adhoc', 'admin');
}
}
/**
* Format the timestart cell.
*
* @param \stdClass $row
* @return string
*/
public function col_result($row) : string {
if ($row->result) {
return get_string('task_result:failed', 'admin');
} else {
return get_string('success');
}
}
/**
* Format the timestart cell.
*
* @param \stdClass $row
* @return string
*/
public function col_timestart($row) : string {
return userdate($row->timestart, get_string('strftimedatetimeshort', 'langconfig'));
}
/**
* Format the duration cell.
*
* @param \stdClass $row
* @return string
*/
public function col_duration($row) : string {
$duration = round($row->timeend - $row->timestart, 2);
if (empty($duration)) {
// The format_time function returns 'now' when the difference is exactly 0.
// Note: format_time performs concatenation in exactly this fashion so we should do this for consistency.
return '0 ' . get_string('secs', 'moodle');
}
return format_time($duration);
}
/**
* Format the DB details cell.
*
* @param \stdClass $row
* @return string
*/
public function col_db($row) : string {
$output = '';
$output .= \html_writer::div(get_string('task_stats:dbreads', 'admin', $row->dbreads));
$output .= \html_writer::div(get_string('task_stats:dbwrites', 'admin', $row->dbwrites));
return $output;
}
/**
* Format the actions cell.
*
* @param \stdClass $row
* @return string
*/
public function col_actions($row) : string {
global $OUTPUT;
$actions = [];
$url = new \moodle_url('/admin/tasklogs.php', ['logid' => $row->id]);
// Quick view.
$actions[] = $OUTPUT->action_icon(
$url,
new \pix_icon('e/search', get_string('view')),
new \popup_action('click', $url)
);
// Download.
$actions[] = $OUTPUT->action_icon(
new \moodle_url($url, ['download' => true]),
new \pix_icon('t/download', get_string('download'))
);
return implode('&nbsp;', $actions);
}
/**
* Format the user cell.
*
* @param \stdClass $row
* @return string
*/
public function col_userid($row) : string {
if (empty($row->userid)) {
return '';
}
$user = (object) [];
username_load_fields_from_object($user, $row, 'user');
return fullname($user);
}
}
-122
View File
@@ -1,122 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Task executor for adhoc tasks.
*
* @package core
* @subpackage cli
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../config.php');
require_once("{$CFG->libdir}/clilib.php");
require_once("{$CFG->libdir}/cronlib.php");
list($options, $unrecognized) = cli_get_params(
[
'execute' => false,
'help' => false,
'keep-alive' => 0,
'showsql' => false,
'showdebugging' => false,
'ignorelimits' => false,
], [
'h' => 'help',
'e' => 'execute',
'k' => 'keep-alive',
'i' => 'ignorelimits',
]
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help'] or empty($options['execute'])) {
$help = <<<EOT
Ad hoc cron tasks.
Options:
-h, --help Print out this help
--showsql Show sql queries before they are executed
--showdebugging Show developer level debugging information
-e, --execute Run all queued adhoc tasks
-k, --keep-alive=N Keep this script alive for N seconds and poll for new adhoc tasks
-i --ignorelimits Ignore task_adhoc_concurrency_limit and task_adhoc_max_runtime limits
Example:
\$sudo -u www-data /usr/bin/php admin/cli/adhoc_task.php --execute
EOT;
echo $help;
die;
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql']) {
$DB->set_debug(true);
}
if (CLI_MAINTENANCE) {
echo "CLI maintenance mode active, cron execution suspended.\n";
exit(1);
}
if (moodle_needs_upgrading()) {
echo "Moodle upgrade pending, cron execution suspended.\n";
exit(1);
}
if (empty($options['execute'])) {
exit(0);
}
if (empty($options['keep-alive'])) {
$options['keep-alive'] = 0;
}
if (!empty($CFG->showcronsql)) {
$DB->set_debug(true);
}
if (!empty($CFG->showcrondebugging)) {
set_debugging(DEBUG_DEVELOPER, true);
}
$checklimits = empty($options['ignorelimits']);
core_php_time_limit::raise();
// Increase memory limit.
raise_memory_limit(MEMORY_EXTRA);
// Emulate normal session - we use admin account by default.
cron_setup_user();
$humantimenow = date('r', time());
$keepalive = (int)$options['keep-alive'];
\core\local\cli\shutdown::script_supports_graceful_exit();
mtrace("Server Time: {$humantimenow}\n");
cron_run_adhoc_tasks(time(), $keepalive, $checklimits);
-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);
-178
View File
@@ -1,178 +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.
if (array_key_exists($options['name'], $CFG->config_php_settings)) {
cli_error('The configuration variable is hard-set in the config.php, unable to change.', 4);
}
$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);
}
-171
View File
@@ -1,171 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI tool for system checks
*
* @package core
* @category check
* @copyright 2020 Brendan Heywood (brendan@catalyst-au.net)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../config.php');
require_once($CFG->libdir.'/clilib.php');
use core\check\result;
list($options, $unrecognized) = cli_get_params([
'help' => false,
'filter' => '',
'type' => 'status',
'verbose' => false,
], [
'h' => 'help',
'f' => 'filter',
'v' => 'verbose',
't' => 'type',
]);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
$checks = \core\check\manager::get_checks($options['type']);
$types = join(', ', \core\check\manager::TYPES);
$help = "Run Moodle system checks
Options:
-h, --help Print out this help
-f, --filter Filter to a subset of checks
-t, --type Which set of checks? Defaults to 'status'
One of $types
-v, --verbose Show details of all checks, not just failed checks
Example:
sudo -u www-data php admin/cli/checks.php
sudo -u www-data php admin/cli/checks.php -v
sudo -u www-data php admin/cli/checks.php -v --filter=environment
";
if ($options['help']) {
echo $help;
die();
}
$filter = $options['filter'];
if ($filter) {
$checks = array_filter($checks, function($check, $key) use ($filter) {
$ref = $check->get_ref();
return (strpos($ref, $filter) !== false);
}, 1);
}
// These shell exit codes and labels align with the NRPE standard.
$exitcodes = [
result::NA => 0,
result::OK => 0,
result::INFO => 0,
result::UNKNOWN => 3,
result::WARNING => 1,
result::ERROR => 2,
result::CRITICAL => 2,
];
$exitlabel = [
result::NA => 'OK',
result::OK => 'OK',
result::INFO => 'OK',
result::UNKNOWN => 'UNKNOWN',
result::WARNING => 'WARNING',
result::ERROR => 'CRITICAL',
result::CRITICAL => 'CRITICAL',
];
$format = "% 10s| % -60s\n";
$spacer = "----------+--------------------------------------------------------------------\n";
$prefix = ' |';
$output = '';
$header = $exitlabel[result::OK] . ': ' . get_string('checksok', '', $options['type']) . "\n";
$exitcode = $exitcodes[result::OK];
foreach ($checks as $check) {
$ref = $check->get_ref();
$result = $check->get_result();
$status = $result->get_status();
$checkexitcode = $exitcodes[$status];
// Summary is treated as html.
$summary = $result->get_summary();
$summary = html_to_text($summary, 60, false);
if ($checkexitcode > $exitcode) {
$exitcode = $checkexitcode;
$header = $exitlabel[$status] . ': ' . $check->get_name() . " (" . $check->get_ref() . ")\n";
}
if (empty($messages[$status])) {
$messages[$status] = $result;
}
$len = strlen(get_string('status' . $status));
if ($options['verbose'] ||
$status == result::WARNING ||
$status == result::CRITICAL ||
$status == result::ERROR) {
$output .= sprintf(
$format,
$OUTPUT->check_result($result),
sprintf('%s (%s)', $check->get_name(), $ref)
);
$summary = str_replace("\n", "\n" . $prefix . ' ', $summary);
$output .= sprintf( $format, '', ' ' . $summary);
if ($options['verbose']) {
$actionlink = $check->get_action_link();
if ($actionlink) {
$output .= sprintf( $format, '', ' ' . $actionlink->url);
}
$output .= sprintf( $format, '', '');
}
}
}
// Print NRPE header.
print $header;
// Only show the table header if there is anything to show.
if ($output) {
print sprintf($format,
get_string('status'). ' ',
get_string('check')
) . $spacer;
print $output;
}
// NRPE shell exit code.
exit($exitcode);
+2 -20
View File
@@ -35,16 +35,8 @@ require_once($CFG->libdir.'/clilib.php'); // cli only functions
require_once($CFG->libdir.'/cronlib.php');
// now get cli options
list($options, $unrecognized) = cli_get_params(
array(
'help' => false,
'stop' => false,
),
array(
'h' => 'help',
's' => 'stop',
)
);
list($options, $unrecognized) = cli_get_params(array('help'=>false),
array('h'=>'help'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
@@ -57,7 +49,6 @@ if ($options['help']) {
Options:
-h, --help Print out this help
-s, --stop Notify all other running cron processes to stop after the current task
Example:
\$sudo -u www-data /usr/bin/php admin/cli/cron.php
@@ -67,13 +58,4 @@ Example:
die;
}
if ($options['stop']) {
// By clearing the caches this signals to other running processes
// to exit after finishing the current task.
\core\task\manager::clear_static_caches();
die;
}
\core\local\cli\shutdown::script_supports_graceful_exit();
cron_run();
-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');
+195 -214
View File
@@ -146,9 +146,14 @@ 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.6.5") < 0) {
$phpversion = phpversion();
// do NOT localise - lang strings would not work here and we CAN NOT move it after installib
fwrite(STDERR, "Moodle 3.2 or later requires at least PHP 5.6.5 (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;
@@ -215,11 +220,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) {
@@ -267,7 +272,6 @@ list($options, $unrecognized) = cli_get_params(
);
$interactive = empty($options['non-interactive']);
$skipdatabase = $options['skip-database'];
// set up language
$lang = clean_param($options['lang'], PARAM_SAFEDIR);
@@ -393,6 +397,7 @@ if ($interactive) {
$CFG->wwwroot = $wwwroot;
$CFG->httpswwwroot = $CFG->wwwroot;
//We need dataroot before lang download
$CFG->dataroot = $options['dataroot'];
if ($interactive) {
@@ -443,7 +448,6 @@ if ($interactive) {
}
}
$CFG->tempdir = $CFG->dataroot.'/temp';
$CFG->backuptempdir = $CFG->tempdir.'/backup';
$CFG->cachedir = $CFG->dataroot.'/cache';
$CFG->localcachedir = $CFG->dataroot.'/localcache';
@@ -515,105 +519,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 {
@@ -621,118 +620,110 @@ 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'));
}
} 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'));
}
} while ($hintdatabase !== '');
}
// If --skip-database option is provided, we do not need to ask for site fullname, shortname, adminuser, adminpass, adminemail.
// These fields will be requested during the database install part.
if (!$skipdatabase) {
// Ask for fullname.
if ($interactive) {
cli_separator();
cli_heading(get_string('fullsitename', 'moodle'));
// ask for fullname
if ($interactive) {
cli_separator();
cli_heading(get_string('fullsitename', 'moodle'));
if ($options['fullname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['fullname'] = cli_input($prompt, $options['fullname']);
} while (empty($options['fullname']));
if ($options['fullname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['fullname']);
} else {
if (empty($options['fullname'])) {
$a = (object)['option' => 'fullname', 'value' => $options['fullname']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for shortname.
if ($interactive) {
cli_separator();
cli_heading(get_string('shortsitename', 'moodle'));
if ($options['shortname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['shortname'] = cli_input($prompt, $options['shortname']);
} while (empty($options['shortname']));
} else {
if (empty($options['shortname'])) {
$a = (object)['option' => 'shortname', 'value' => $options['shortname']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for admin user name.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminusername', 'install'));
if (!empty($options['adminuser'])) {
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
} else {
if ((empty($options['adminuser']) || $options['adminuser'] === 'guest')) {
$a = (object)['option' => 'adminuser', 'value' => $options['adminuser']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for admin user password.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminpassword', 'install'));
$prompt = get_string('clitypevalue', 'admin');
do {
$options['adminpass'] = cli_input($prompt);
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
} else {
if ((empty($options['adminpass']) or $options['adminpass'] === 'admin')) {
$a = (object)['option' => 'adminpass', 'value' => $options['adminpass']];
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for the admin email address.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
$options['adminemail'] = cli_input($prompt, $options['adminemail']);
}
// Validate that the address provided was an e-mail address.
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
$a = (object)['option' => 'adminemail', 'value' => $options['adminemail']];
do {
$options['fullname'] = cli_input($prompt, $options['fullname']);
} while (empty($options['fullname']));
} else {
if (empty($options['fullname'])) {
$a = (object)array('option'=>'fullname', 'value'=>$options['fullname']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// ask for shortname
if ($interactive) {
cli_separator();
cli_heading(get_string('shortsitename', 'moodle'));
if ($options['shortname'] !== '') {
$prompt = get_string('clitypevaluedefault', 'admin', $options['shortname']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['shortname'] = cli_input($prompt, $options['shortname']);
} while (empty($options['shortname']));
} else {
if (empty($options['shortname'])) {
$a = (object)array('option'=>'shortname', 'value'=>$options['shortname']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// ask for admin user name
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminusername', 'install'));
if (!empty($options['adminuser'])) {
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminuser']);
} else {
$prompt = get_string('clitypevalue', 'admin');
}
do {
$options['adminuser'] = cli_input($prompt, $options['adminuser']);
} while (empty($options['adminuser']) or $options['adminuser'] === 'guest');
} else {
if (empty($options['adminuser']) or $options['adminuser'] === 'guest') {
$a = (object)array('option'=>'adminuser', 'value'=>$options['adminuser']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// ask for admin user password
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminpassword', 'install'));
$prompt = get_string('clitypevalue', 'admin');
do {
$options['adminpass'] = cli_input($prompt);
} while (empty($options['adminpass']) or $options['adminpass'] === 'admin');
} else {
if (empty($options['adminpass']) or $options['adminpass'] === 'admin') {
$a = (object)array('option'=>'adminpass', 'value'=>$options['adminpass']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
}
// Ask for the admin email address.
if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
$options['adminemail'] = cli_input($prompt);
}
// Validate that the address provided was an e-mail address.
if (!empty($options['adminemail']) && !validate_email($options['adminemail'])) {
$a = (object) array('option' => 'adminemail', 'value' => $options['adminemail']);
cli_error(get_string('cliincorrectvalueerror', 'admin', $a));
}
// Ask for the upgrade key.
if ($interactive) {
cli_separator();
@@ -751,27 +742,23 @@ if ($options['upgradekey'] !== '') {
$CFG->upgradekey = $options['upgradekey'];
}
// The user does not also need to pass agree-license when --skip-database is provided as the user will need to accept
// the license again in the database install part.
if (!$skipdatabase) {
if ($interactive) {
if (!$options['agree-license']) {
cli_separator();
cli_heading(get_string('copyrightnotice'));
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
echo get_string('gpl3')."\n\n";
echo get_string('doyouagree')."\n";
$prompt = get_string('cliyesnoprompt', 'admin');
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
if ($input == get_string('clianswerno', 'admin')) {
exit(1);
}
}
} else {
if (!$options['agree-license'] && !$skipdatabase) {
cli_error(get_string('climustagreelicense', 'install'));
if ($interactive) {
if (!$options['agree-license']) {
cli_separator();
cli_heading(get_string('copyrightnotice'));
echo "Moodle - Modular Object-Oriented Dynamic Learning Environment\n";
echo get_string('gpl3')."\n\n";
echo get_string('doyouagree')."\n";
$prompt = get_string('cliyesnoprompt', 'admin');
$input = cli_input($prompt, '', array(get_string('clianswerno', 'admin'), get_string('cliansweryes', 'admin')));
if ($input == get_string('clianswerno', 'admin')) {
exit(1);
}
}
} else {
if (!$options['agree-license']) {
cli_error(get_string('climustagreelicense', 'install'));
}
}
// Finally we have all info needed for config.php
@@ -819,14 +806,8 @@ if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
cli_error(get_string('pluginschecktodo', 'admin'));
}
if (!$skipdatabase) {
if (!$options['skip-database']) {
install_cli_database($options, $interactive);
// This needs to happen at the end to ensure it occurs after all caches
// have been purged for the last time.
// 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";
}
+14 -16
View File
@@ -62,9 +62,14 @@ 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.6.5") < 0) {
$phpversion = phpversion();
// do NOT localise - lang strings would not work here and we CAN NOT move it after installib
fwrite(STDERR, "Moodle 3.2 or later requires at least PHP 5.6.5 (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';
@@ -82,6 +87,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);
@@ -104,17 +114,12 @@ list($options, $unrecognized) = cli_get_params(
)
);
// 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
}
@@ -178,12 +183,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);
+5 -41
View File
@@ -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'])) {
@@ -145,22 +145,9 @@ 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 CHARACTER SET $charset DEFAULT COLLATE = $collation");
echo "CONVERTED\n";
$converted++;
}
$sql = "SHOW FULL COLUMNS FROM $table->name WHERE collation IS NOT NULL";
@@ -203,7 +190,7 @@ if (!empty($options['collation'])) {
$DB->change_database_structure($sql);
} else {
echo "ERROR (unknown column type: $column->type)\n";
$errors++;
$error++;
continue;
}
echo "CONVERTED\n";
@@ -303,26 +290,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;
}
+7 -30
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>
@@ -28,16 +26,7 @@ define('CLI_SCRIPT', true);
require(__DIR__.'/../../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);
+1 -1
View File
@@ -94,7 +94,7 @@ if ($options['password'] == '' ) {
$errmsg = '';//prevent eclipse warning
if (!$options['ignore-password-policy'] ) {
if (!check_password_policy($password, $errmsg, $user)) {
if (!check_password_policy($password, $errmsg)) {
cli_error(html_to_text($errmsg, 0));
}
}
-151
View File
@@ -1,151 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* CLI task execution.
*
* @package core
* @subpackage cli
* @copyright 2014 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../config.php');
require_once("$CFG->libdir/clilib.php");
require_once("$CFG->libdir/cronlib.php");
list($options, $unrecognized) = cli_get_params(
array('help' => false, 'list' => false, 'execute' => false, 'showsql' => false, 'showdebugging' => false),
array('h' => 'help')
);
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help'] or (!$options['list'] and !$options['execute'])) {
$help =
"Scheduled cron tasks.
Options:
--execute=\\some\\task Execute scheduled task manually
--list List all scheduled tasks
--showsql Show sql queries before they are executed
--showdebugging Show developer level debugging information
-h, --help Print out this help
Example:
\$sudo -u www-data /usr/bin/php admin/cli/scheduled_task.php --execute=\\core\\task\\session_cleanup_task
";
echo $help;
die;
}
if ($options['showdebugging']) {
set_debugging(DEBUG_DEVELOPER, true);
}
if ($options['showsql']) {
$DB->set_debug(true);
}
if ($options['list']) {
cli_heading("List of scheduled tasks ($CFG->wwwroot)");
$shorttime = get_string('strftimedatetimeshort');
$tasks = \core\task\manager::get_all_scheduled_tasks();
echo str_pad(get_string('scheduledtasks', 'tool_task'), 50, ' ') . ' ' . str_pad(get_string('runpattern', 'tool_task'), 17, ' ')
. ' ' . str_pad(get_string('lastruntime', 'tool_task'), 40, ' ') . get_string('nextruntime', 'tool_task') . "\n";
foreach ($tasks as $task) {
$class = '\\' . get_class($task);
$schedule = $task->get_minute() . ' '
. $task->get_hour() . ' '
. $task->get_day() . ' '
. $task->get_day_of_week() . ' '
. $task->get_month() . ' '
. $task->get_day_of_week();
$nextrun = $task->get_next_run_time();
$lastrun = $task->get_last_run_time();
$plugininfo = core_plugin_manager::instance()->get_plugin_info($task->get_component());
$plugindisabled = $plugininfo && $plugininfo->is_enabled() === false && !$task->get_run_if_component_disabled();
if ($plugindisabled) {
$nextrun = get_string('plugindisabled', 'tool_task');
} else if ($task->get_disabled()) {
$nextrun = get_string('taskdisabled', 'tool_task');
} else if ($nextrun > time()) {
$nextrun = userdate($nextrun);
} else {
$nextrun = get_string('asap', 'tool_task');
}
if ($lastrun) {
$lastrun = userdate($lastrun);
} else {
$lastrun = get_string('never');
}
echo str_pad($class, 50, ' ') . ' ' . str_pad($schedule, 17, ' ') .
' ' . str_pad($lastrun, 40, ' ') . ' ' . $nextrun . "\n";
}
exit(0);
}
if ($execute = $options['execute']) {
if (!$task = \core\task\manager::get_scheduled_task($execute)) {
mtrace("Task '$execute' not found");
exit(1);
}
if (moodle_needs_upgrading()) {
mtrace("Moodle upgrade pending, cannot execute tasks.");
exit(1);
}
// Increase memory limit.
raise_memory_limit(MEMORY_EXTRA);
// Emulate normal session - we use admin account by default.
cron_setup_user();
// Execute the task.
\core\local\cli\shutdown::script_supports_graceful_exit();
$cronlockfactory = \core\lock\lock_config::get_lock_factory('cron');
if (!$cronlock = $cronlockfactory->get_lock('core_cron', 10)) {
mtrace('Cannot obtain cron lock');
exit(129);
}
if (!$lock = $cronlockfactory->get_lock('\\' . get_class($task), 10)) {
$cronlock->release();
mtrace('Cannot obtain task lock');
exit(130);
}
$task->set_lock($lock);
if (!$task->is_blocking()) {
$cronlock->release();
} else {
$task->set_cron_lock($cronlock);
}
cron_run_inner_scheduled_task($task);
}
-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 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.
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,
], [
'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);
}
$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);
+9 -42
View File
@@ -51,9 +51,7 @@ list($options, $unrecognized) = cli_get_params(
'non-interactive' => false,
'allow-unstable' => false,
'help' => false,
'lang' => $lang,
'verbose-settings' => false,
'is-pending' => false,
'lang' => $lang
),
array(
'h' => 'help'
@@ -86,11 +84,6 @@ Options:
site language if not set. Defaults to 'en' if the lang
parameter is invalid or if the language pack is not
installed.
--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.
--is-pending If an upgrade is needed it exits with an error code of
2 so it distinct from other types of errors.
-h, --help Print out this help
Example:
@@ -119,10 +112,6 @@ if (!moodle_needs_upgrading()) {
cli_error(get_string('cliupgradenoneed', 'core_admin', $newversion), 0);
}
if ($options['is-pending']) {
cli_error(get_string('cliupgradepending', 'core_admin'), 2);
}
// Test environment first.
list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
if (!$envstatus) {
@@ -137,16 +126,15 @@ if (!$envstatus) {
// Test plugin dependencies.
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed)))));
cli_error(get_string('pluginschecktodo', 'admin'));
}
$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;
}
@@ -195,30 +183,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);
// 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);
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";
echo get_string('cliupgradefinished', 'admin')."\n";
exit(0); // 0 means success
-84
View File
@@ -1,84 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Content bank and its plugins settings.
*
* @package core
* @subpackage contentbank
* @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
$action = required_param('action', PARAM_ALPHANUMEXT);
$name = required_param('name', PARAM_PLUGIN);
$syscontext = context_system::instance();
$PAGE->set_url('/admin/contentbank.php');
$PAGE->set_context($syscontext);
require_admin();
require_sesskey();
$return = new moodle_url('/admin/settings.php', array('section' => 'managecontentbanktypes'));
$plugins = core_plugin_manager::instance()->get_plugins_of_type('contenttype');
$sortorder = array_flip(array_keys($plugins));
if (!isset($plugins[$name])) {
print_error('contenttypenotfound', 'error', $return, $name);
}
switch ($action) {
case 'disable':
if ($plugins[$name]->is_enabled()) {
set_config('disabled', 1, 'contentbank_'. $name);
}
break;
case 'enable':
if (!$plugins[$name]->is_enabled()) {
unset_config('disabled', 'contentbank_'. $name);
}
break;
case 'up':
if ($sortorder[$name]) {
$currentindex = $sortorder[$name];
$seq = array_keys($plugins);
$seq[$currentindex] = $seq[$currentindex - 1];
$seq[$currentindex - 1] = $name;
set_config('contentbank_plugins_sortorder', implode(',', $seq));
}
break;
case 'down':
if ($sortorder[$name] < count($sortorder) - 1) {
$currentindex = $sortorder[$name];
$seq = array_keys($plugins);
$seq[$currentindex] = $seq[$currentindex + 1];
$seq[$currentindex + 1] = $name;
set_config('contentbank_plugins_sortorder', implode(',', $seq));
}
break;
}
core_plugin_manager::reset_caches();
$cache = cache::make('core', 'contentbank_enabled_extensions');
$cache->purge();
$cache = cache::make('core', 'contentbank_context_extensions');
$cache->purge();
redirect($return);
+2 -1
View File
@@ -32,7 +32,8 @@ $syscontext = context_system::instance();
$PAGE->set_url('/admin/courseformats.php');
$PAGE->set_context($syscontext);
require_admin();
require_login();
require_capability('moodle/site:config', $syscontext);
require_sesskey();
$return = new moodle_url('/admin/settings.php', array('section' => 'manageformats'));
-61
View File
@@ -1,61 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Allows the admin to enable, disable and uninstall custom fields
*
* @package core_admin
* @copyright 2018 Daniel Neis Araujo
* @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);
$customfieldname = required_param('field', PARAM_PLUGIN);
$syscontext = context_system::instance();
$PAGE->set_url('/admin/customfields.php');
$PAGE->set_context($syscontext);
require_admin();
require_sesskey();
$return = new moodle_url('/admin/settings.php', array('section' => 'managecustomfields'));
$customfieldplugins = core_plugin_manager::instance()->get_plugins_of_type('customfield');
$sortorder = array_flip(array_keys($customfieldplugins));
if (!isset($customfieldplugins[$customfieldname])) {
print_error('customfieldnotfound', 'error', $return, $customfieldname);
}
switch ($action) {
case 'disable':
if ($customfieldplugins[$customfieldname]->is_enabled()) {
set_config('disabled', 1, 'customfield_'. $customfieldname);
core_plugin_manager::reset_caches();
}
break;
case 'enable':
if (!$customfieldplugins[$customfieldname]->is_enabled()) {
unset_config('disabled', 'customfield_'. $customfieldname);
core_plugin_manager::reset_caches();
}
break;
}
redirect($return);
+2 -1
View File
@@ -33,7 +33,8 @@ $syscontext = context_system::instance();
$PAGE->set_url('/admin/dataformats.php');
$PAGE->set_context($syscontext);
require_admin();
require_login();
require_capability('moodle/site:config', $syscontext);
require_sesskey();
$return = new moodle_url('/admin/settings.php', array('section' => 'managedataformats'));
+2 -5
View File
@@ -15,7 +15,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
$PAGE->set_url('/admin/editors.php', array('action'=>$action, 'editor'=>$editor));
$PAGE->set_context(context_system::instance());
require_admin();
require_login();
require_capability('moodle/site:config', context_system::instance());
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageeditors";
@@ -46,7 +47,6 @@ switch ($action) {
// remove from enabled list
$key = array_search($editor, $active_editors);
unset($active_editors[$key]);
add_to_config_log('editor_visibility', '1', '0', $editor);
break;
case 'enable':
@@ -54,7 +54,6 @@ switch ($action) {
if (!in_array($editor, $active_editors)) {
$active_editors[] = $editor;
$active_editors = array_unique($active_editors);
add_to_config_log('editor_visibility', '0', '1', $editor);
}
break;
@@ -67,7 +66,6 @@ switch ($action) {
$fsave = $active_editors[$key];
$active_editors[$key] = $active_editors[$key + 1];
$active_editors[$key + 1] = $fsave;
add_to_config_log('editor_position', $key, $key + 1, $editor);
}
}
break;
@@ -81,7 +79,6 @@ switch ($action) {
$fsave = $active_editors[$key];
$active_editors[$key] = $active_editors[$key - 1];
$active_editors[$key - 1] = $fsave;
add_to_config_log('editor_position', $key, $key - 1, $editor);
}
}
break;
+2 -1
View File
@@ -35,7 +35,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
$PAGE->set_url('/admin/enrol.php');
$PAGE->set_context(context_system::instance());
require_admin();
require_login();
require_capability('moodle/site:config', context_system::instance());
require_sesskey();
$enabled = enrol_get_plugins(true);
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -28,6 +28,10 @@ require_once($CFG->libdir . '/adminlib.php');
$action = optional_param('action', '', PARAM_ALPHA);
$filterpath = optional_param('filterpath', '', PARAM_PLUGIN);
require_login();
$systemcontext = context_system::instance();
require_capability('moodle/site:config', $systemcontext);
admin_externalpage_setup('managefilters');
// Clean up bogus filter states first.
@@ -214,7 +218,7 @@ function get_table_row(\core\plugininfo\filter $plugininfo, $state, $isfirstrow,
// Re-order.
$updown = '';
$spacer = $OUTPUT->spacer();
$spacer = '<img src="' . $OUTPUT->pix_url('spacer') . '" class="iconsmall" alt="" />';
if ($state->active != TEXTFILTER_DISABLED) {
if (!$isfirstrow) {
$updown .= $OUTPUT->action_icon(filters_action_url($filter, 'up'), new pix_icon('t/up', get_string('up'), '', array('class' => 'iconsmall')));
+25 -71
View File
@@ -29,9 +29,14 @@ if (!file_exists('../config.php')) {
die();
}
// 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 as soon as possible
if (version_compare(phpversion(), '5.6.5') < 0) {
$phpversion = phpversion();
// do NOT localise - lang strings would not work here and we CAN NOT move it to later place
echo "Moodle 3.2 or later requires at least PHP 5.6.5 (currently using version $phpversion).<br />";
echo "Please upgrade your server software or install older Moodle version.";
die();
}
// make sure iconv is available and actually works
if (!function_exists('iconv')) {
@@ -96,12 +101,6 @@ if (function_exists('opcache_invalidate')) {
// indirectly calls the protected init() method is good here.
core_component::get_core_subsystems();
if (is_major_upgrade_required() && isloggedin()) {
// A major upgrade is required.
// Terminate the session and redirect back here before anything DB-related happens.
redirect_if_major_upgrade_required();
}
require_once($CFG->libdir.'/adminlib.php'); // various admin-only functions
require_once($CFG->libdir.'/upgradelib.php'); // general upgrade/install related functions
@@ -226,7 +225,7 @@ if (!core_tables_exist()) {
}
if (empty($confirmrelease)) {
require_once($CFG->libdir.'/environmentlib.php');
list($envstatus, $environmentresults) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
list($envstatus, $environment_results) = check_moodle_environment(normalize_version($release), ENV_SELECT_RELEASE);
$strcurrentrelease = get_string('currentrelease');
$PAGE->navbar->add($strcurrentrelease);
@@ -235,13 +234,13 @@ if (!core_tables_exist()) {
$PAGE->set_cacheable(false);
$output = $PAGE->get_renderer('core', 'admin');
echo $output->install_environment_page($maturity, $envstatus, $environmentresults, $release);
echo $output->install_environment_page($maturity, $envstatus, $environment_results, $release);
die();
}
// check plugin dependencies
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
$PAGE->navbar->add(get_string('pluginscheck', 'admin'));
$PAGE->set_title($strinstallation);
$PAGE->set_heading($strinstallation . ' - Moodle ' . $CFG->target_release);
@@ -358,9 +357,9 @@ if (!$cache and $version > $CFG->version) { // upgrade
echo $output->upgrade_confirm_page($a->newversion, $maturity, $testsite);
die();
} else if (empty($confirmrelease)) {
} else if (empty($confirmrelease)){
require_once($CFG->libdir.'/environmentlib.php');
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
list($envstatus, $environment_results) = check_moodle_environment($release, ENV_SELECT_RELEASE);
$strcurrentrelease = get_string('currentrelease');
$PAGE->navbar->add($strcurrentrelease);
@@ -368,7 +367,7 @@ if (!$cache and $version > $CFG->version) { // upgrade
$PAGE->set_heading($strcurrentrelease);
$PAGE->set_cacheable(false);
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
echo $output->upgrade_environment_page($release, $envstatus, $environment_results);
die();
} else if (empty($confirmplugins)) {
@@ -508,9 +507,8 @@ if (!$cache and $version > $CFG->version) { // upgrade
} else {
// Always verify plugin dependencies!
$failed = array();
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed, $CFG->branch)) {
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
array('confirmplugincheck' => 0)));
if (!core_plugin_manager::instance()->all_plugins_ok($version, $failed)) {
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
die();
}
unset($failed);
@@ -534,10 +532,7 @@ if (!$cache and $branch <> $CFG->branch) { // Update the branch
if (!$cache and moodle_needs_upgrading()) {
$PAGE->set_url(new moodle_url($PAGE->url, array(
'confirmrelease' => $confirmrelease,
'confirmplugincheck' => $confirmplugins,
)));
$PAGE->set_url(new moodle_url($PAGE->url, array('confirmplugincheck' => $confirmplugins)));
check_upgrade_key($upgradekeyhash);
@@ -547,21 +542,7 @@ if (!$cache and moodle_needs_upgrading()) {
$pluginman = core_plugin_manager::instance();
$output = $PAGE->get_renderer('core', 'admin');
if (empty($confirmrelease)) {
require_once($CFG->libdir . '/environmentlib.php');
list($envstatus, $environmentresults) = check_moodle_environment($release, ENV_SELECT_RELEASE);
$strcurrentrelease = get_string('currentrelease');
$PAGE->navbar->add($strcurrentrelease);
$PAGE->set_title($strcurrentrelease);
$PAGE->set_heading($strcurrentrelease);
$PAGE->set_cacheable(false);
echo $output->upgrade_environment_page($release, $envstatus, $environmentresults);
die();
} else if (!$confirmplugins) {
if (!$confirmplugins) {
$strplugincheck = get_string('plugincheck');
$PAGE->navbar->add($strplugincheck);
@@ -700,10 +681,9 @@ if (!$cache and moodle_needs_upgrading()) {
// Make sure plugin dependencies are always checked.
$failed = array();
if (!$pluginman->all_plugins_ok($version, $failed, $CFG->branch)) {
if (!$pluginman->all_plugins_ok($version, $failed)) {
$output = $PAGE->get_renderer('core', 'admin');
echo $output->unsatisfied_dependencies_page($version, $failed, new moodle_url($PAGE->url,
array('confirmplugincheck' => 0)));
echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url);
die();
}
unset($failed);
@@ -718,7 +698,6 @@ if (!$cache and moodle_needs_upgrading()) {
if (during_initial_install()) {
set_config('rolesactive', 1); // after this, during_initial_install will return false.
set_config('adminsetuppending', 1);
set_config('registrationpending', 1); // Remind to register site after all other setup is finished.
// we need this redirect to setup proper session
upgrade_finished("index.php?sessionstarted=1&amp;lang=$CFG->lang");
}
@@ -821,7 +800,7 @@ $SESSION->admin_critical_warning = ($insecuredataroot==INSECURE_DATAROOT_ERROR);
$adminroot = admin_get_root();
// Check if there are any new admin settings which have still yet to be set
if (any_new_admin_settings($adminroot)) {
if (any_new_admin_settings($adminroot)){
redirect('upgradesettings.php');
}
@@ -834,20 +813,14 @@ if (isset($SESSION->pluginuninstallreturn)) {
}
}
// If site registration needs updating, redirect.
\core\hub\registration::registration_reminder('/admin/index.php');
// Everything should now be set up, and the user is an admin
// Print default admin page with notifications.
$errorsdisplayed = defined('WARN_DISPLAY_ERRORS_ENABLED');
$lastcron = get_config('tool_task', 'lastcronstart');
// We make the assumption that at least one schedule task should run once per day.
$lastcron = $DB->get_field_sql('SELECT MAX(lastruntime) FROM {task_scheduled}');
$cronoverdue = ($lastcron < time() - 3600 * 24);
$lastcroninterval = get_config('tool_task', 'lastcroninterval');
$expectedfrequency = $CFG->expectedcronfrequency ?? MINSECS;
$croninfrequent = !$cronoverdue && ($lastcroninterval > ($expectedfrequency + MINSECS) || $lastcron < time() - $expectedfrequency);
$dbproblems = $DB->diagnose();
$maintenancemode = !empty($CFG->maintenance_enabled);
@@ -883,29 +856,12 @@ if ($updateschecker->enabled()) {
$buggyiconvnomb = (!function_exists('mb_convert_encoding') and @iconv('UTF-8', 'UTF-8//IGNORE', '100'.chr(130).'€') !== '100€');
//check if the site is registered on Moodle.org
$registered = \core\hub\registration::is_registered();
$registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
// Check if there are any cache warnings.
$cachewarnings = cache_helper::warnings();
// Check if there are events 1 API handlers.
$eventshandlers = $DB->get_records_sql('SELECT DISTINCT component FROM {events_handlers}');
$themedesignermode = !empty($CFG->themedesignermode);
$mobileconfigured = !empty($CFG->enablemobilewebservice);
$invalidforgottenpasswordurl = !empty($CFG->forgottenpasswordurl) && empty(clean_param($CFG->forgottenpasswordurl, PARAM_URL));
// Check if a directory with development libraries exists.
if (empty($CFG->disabledevlibdirscheck) && (is_dir($CFG->dirroot.'/vendor') || is_dir($CFG->dirroot.'/node_modules'))) {
$devlibdir = true;
} else {
$devlibdir = false;
}
// Check if the site is being foced onto ssl.
$overridetossl = !empty($CFG->overridetossl);
// Check if moodle campaign content setting is enabled or not.
$showcampaigncontent = !isset($CFG->showcampaigncontent) || $CFG->showcampaigncontent;
// Encourage admins to enable the user feedback feature if it is not enabled already.
$showfeedbackencouragement = empty($CFG->enableuserfeedback);
admin_externalpage_setup('adminnotifications');
@@ -913,6 +869,4 @@ $output = $PAGE->get_renderer('core', 'admin');
echo $output->admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed, $cronoverdue, $dbproblems,
$maintenancemode, $availableupdates, $availableupdatesfetch, $buggyiconvnomb,
$registered, $cachewarnings, $eventshandlers, $themedesignermode, $devlibdir,
$mobileconfigured, $overridetossl, $invalidforgottenpasswordurl, $croninfrequent,
$showcampaigncontent, $showfeedbackencouragement);
$registered, $cachewarnings, $eventshandlers, $themedesignermode);
+57
View File
@@ -0,0 +1,57 @@
<?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 licenses.
*/
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->libdir.'/licenselib.php');
require_login();
require_capability('moodle/site:config', context_system::instance());
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=managelicenses";
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
$license = optional_param('license', '', PARAM_SAFEDIR);
////////////////////////////////////////////////////////////////////////////////
// process actions
if (!confirm_sesskey()) {
redirect($returnurl);
}
$return = true;
switch ($action) {
case 'disable':
license_manager::disable($license);
break;
case 'enable':
license_manager::enable($license);
break;
default:
break;
}
if ($return) {
redirect ($returnurl);
}
-96
View File
@@ -1,96 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file is used to display a categories sub categories, external pages, and settings.
*
* @package admin
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once("{$CFG->libdir}/adminlib.php");
$contextid = required_param('id', PARAM_INT);
$confirm = optional_param('confirm', null, PARAM_INT);
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
$PAGE->set_url('/admin/lock.php', ['id' => $contextid]);
list($context, $course, $cm) = get_context_info_array($contextid);
$parentcontext = $context->get_parent_context();
if ($parentcontext && !empty($parentcontext->locked)) {
// Can't make changes to a context whose parent is locked.
throw new \coding_exception('Not sure how you got here');
}
if ($course) {
$isfrontpage = ($course->id == SITEID);
} else {
$isfrontpage = false;
$course = $SITE;
}
require_login($course, false, $cm);
require_capability('moodle/site:managecontextlocks', $context);
$PAGE->set_pagelayout('admin');
$PAGE->navigation->clear_cache();
$a = (object) [
'contextname' => $context->get_context_name(),
];
if (null !== $confirm && confirm_sesskey()) {
$context->set_locked(!empty($confirm));
if ($context->locked) {
$lockmessage = get_string('managecontextlocklocked', 'admin', $a);
} else {
$lockmessage = get_string('managecontextlockunlocked', 'admin', $a);
}
if (empty($returnurl)) {
$returnurl = $context->get_url();
} else {
$returnurl = new moodle_url($returnurl);
}
redirect($returnurl, $lockmessage);
}
$heading = get_string('managecontextlock', 'admin');
$PAGE->set_title($heading);
$PAGE->set_heading($heading);
echo $OUTPUT->header();
if ($context->locked) {
$confirmstring = get_string('confirmcontextunlock', 'admin', $a);
$target = 0;
} else {
$confirmstring = get_string('confirmcontextlock', 'admin', $a);
$target = 1;
}
$confirmurl = new \moodle_url($PAGE->url, ['confirm' => $target]);
if (!empty($returnurl)) {
$confirmurl->param('returnurl', $returnurl);
}
echo $OUTPUT->confirm($confirmstring, $confirmurl, $context->get_url());
echo $OUTPUT->footer();
+2 -1
View File
@@ -35,7 +35,8 @@ $confirm = optional_param('confirm', 0, PARAM_BOOL);
$PAGE->set_url('/admin/media.php');
$PAGE->set_context(context_system::instance());
require_admin();
require_login();
require_capability('moodle/site:config', context_system::instance());
require_sesskey();
$plugins = core_plugin_manager::instance()->get_plugins_of_type('media');
+29 -100
View File
@@ -25,121 +25,50 @@ require_once(__DIR__ . '/../config.php');
require_once($CFG->dirroot . '/message/lib.php');
require_once($CFG->libdir.'/adminlib.php');
// This is an admin page.
// This is an admin page
admin_externalpage_setup('managemessageoutputs');
// Fetch processors.
$allprocessors = get_message_processors();
$processors = array_filter($allprocessors, function($processor) {
return $processor->enabled;
});
$disabledprocessors = array_filter($allprocessors, function($processor) {
return !$processor->enabled;
});
// Require site configuration capability
require_capability('moodle/site:config', context_system::instance());
// Fetch message providers.
$providers = get_message_providers();
// Fetch the manage message outputs interface.
$preferences = get_message_output_default_preferences();
// Get the submitted params
$disable = optional_param('disable', 0, PARAM_INT);
$enable = optional_param('enable', 0, PARAM_INT);
if (($form = data_submitted()) && confirm_sesskey()) {
$newpreferences = array();
// Prepare default message outputs settings.
foreach ($providers as $provider) {
$componentproviderbase = $provider->component.'_'.$provider->name;
$disableprovidersetting = $componentproviderbase.'_disable';
$providerdisabled = false;
if (!isset($form->$disableprovidersetting)) {
$providerdisabled = true;
$newpreferences[$disableprovidersetting] = 1;
} else {
$newpreferences[$disableprovidersetting] = 0;
}
$headingtitle = get_string('managemessageoutputs', 'message');
foreach (array('permitted', 'loggedin', 'loggedoff') as $setting) {
$value = null;
$componentprovidersetting = $componentproviderbase.'_'.$setting;
if ($setting == 'permitted') {
// If we deal with permitted select element, we need to create individual
// setting for each possible processor. Note that this block will
// always be processed first after entring parental foreach iteration
// so we can change form values on this stage.
foreach ($processors as $processor) {
$value = '';
if (isset($form->{$componentprovidersetting}[$processor->name])) {
$value = $form->{$componentprovidersetting}[$processor->name];
}
// Ensure that loggedin loggedoff options are set correctly for this permission.
if (($value == 'disallowed') || $providerdisabled) {
// It might be better to unset them, but I can't figure out why that cause error.
$form->{$componentproviderbase.'_loggedin'}[$processor->name] = 0;
$form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 0;
} else if ($value == 'forced') {
$form->{$componentproviderbase.'_loggedin'}[$processor->name] = 1;
$form->{$componentproviderbase.'_loggedoff'}[$processor->name] = 1;
}
// Record the site preference.
$newpreferences[$processor->name.'_provider_'.$componentprovidersetting] = $value;
}
} else {
$newsettings = array();
if (property_exists($form, $componentprovidersetting)) {
// We must be processing loggedin or loggedoff checkboxes.
// Store defained comma-separated processors as setting value.
// Using array_filter eliminates elements set to 0 above.
$newsettings = array_keys(array_filter($form->{$componentprovidersetting}));
}
// Let's join existing setting values for disabled processors.
$property = 'message_provider_'.$componentprovidersetting;
if (property_exists($preferences, $property)) {
$existingsetting = $preferences->$property;
foreach ($disabledprocessors as $disable) {
if (strpos($existingsetting, $disable->name) > -1) {
$newsettings[] = $disable->name;
}
}
}
$value = join(',', $newsettings);
if (empty($value)) {
$value = null;
}
}
if ($setting != 'permitted') {
// We have already recoded site preferences for 'permitted' type.
$newpreferences['message_provider_'.$componentprovidersetting] = $value;
}
}
if (!empty($disable) && confirm_sesskey()) {
if (!$processor = $DB->get_record('message_processors', array('id'=>$disable))) {
print_error('outputdoesnotexist', 'message');
}
// Update database.
$transaction = $DB->start_delegated_transaction();
// Save processors enabled/disabled status.
foreach ($allprocessors as $processor) {
$enabled = isset($form->{$processor->name});
\core_message\api::update_processor_status($processor, $enabled);
}
foreach ($newpreferences as $name => $value) {
set_config($name, $value, 'message');
}
$transaction->allow_commit();
\core_message\api::update_processor_status($processor, 0); // Disable output.
core_plugin_manager::reset_caches();
}
if (!empty($enable) && confirm_sesskey()) {
if (!$processor = $DB->get_record('message_processors', array('id'=>$enable))) {
print_error('outputdoesnotexist', 'message');
}
\core_message\api::update_processor_status($processor, 1); // Enable output.
core_plugin_manager::reset_caches();
}
if ($disable || $enable) {
$url = new moodle_url('message.php');
redirect($url);
}
// Page settings
$PAGE->set_context(context_system::instance());
$PAGE->requires->js_init_call('M.core_message.init_defaultoutputs');
// Grab the renderer
$renderer = $PAGE->get_renderer('core', 'message');
// Display the page.
// Display the manage message outputs interface
$processors = get_message_processors();
$messageoutputs = $renderer->manage_messageoutputs($processors);
// Display the page
echo $OUTPUT->header();
echo $renderer->manage_messageoutput_settings($allprocessors, $processors, $providers, $preferences);
echo $OUTPUT->heading($headingtitle);
echo $messageoutputs;
echo $OUTPUT->footer();
+3 -1
View File
@@ -12,6 +12,8 @@ $page = optional_param('page', 0, PARAM_INT);
$perpage = optional_param('perpage', 30, PARAM_INT);
$action = trim(strtolower(optional_param('action', '', PARAM_ALPHA)));
require_login();
admin_externalpage_setup('ssoaccesscontrol');
if (!extension_loaded('openssl')) {
@@ -148,7 +150,7 @@ foreach ($columns as $column) {
} else {
$columndir = $dir == "ASC" ? "DESC" : "ASC";
$columnicon = $dir == "ASC" ? "down" : "up";
$columnicon = " " . $OUTPUT->pix_icon('t/' . $columnicon, get_string('sort'));
$columnicon = " <img src=\"" . $OUTPUT->pix_url('t/' . $columnicon) . "\" alt=\"\" />";
}
$headings[$column] = "<a href=\"?sort=$column&amp;dir=$columndir&amp;\">".$string[$column]."</a>$columnicon";
}
+5
View File
@@ -34,6 +34,11 @@ $step = optional_param('step', 'verify', PARAM_ALPHA);
$hostid = required_param('hostid', PARAM_INT);
require_login();
$context = context_system::instance();
require_capability('moodle/site:config', $context, $USER->id, true, "nopermissions");
$mnet = get_mnet_environment();
$PAGE->set_url('/admin/mnet/delete.php');
+2
View File
@@ -6,10 +6,12 @@
require_once($CFG->libdir.'/adminlib.php');
include_once($CFG->dirroot.'/mnet/lib.php');
require_login();
admin_externalpage_setup('net');
$context = context_system::instance();
require_capability('moodle/site:config', $context, $USER->id, true, "nopermissions");
$site = get_site();
$mnet = get_mnet_environment();
+1 -1
View File
@@ -156,7 +156,7 @@ class mnet_review_host_form extends moodleform {
if ($mnet_peer && !empty($mnet_peer->deleted)) {
$radioarray = array();
$radioarray[] = $mform->createElement('static', 'deletedinfo', '',
$OUTPUT->container(get_string('deletedhostinfo', 'mnet'), 'alert alert-warning'));
$OUTPUT->container(get_string('deletedhostinfo', 'mnet'), 'deletedhostinfo'));
$radioarray[] = $mform->createElement('radio', 'deleted', '', get_string('yes'), 1);
$radioarray[] = $mform->createElement('radio', 'deleted', '', get_string('no'), 0);
$mform->addGroup($radioarray, 'radioar', get_string('deleted'), array(' ', ' '), false);
+4
View File
@@ -32,6 +32,10 @@ require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot.'/mnet/lib.php');
require_once($CFG->dirroot.'/'.$CFG->admin.'/mnet/peer_forms.php');
require_login();
$context = context_system::instance();
require_capability('moodle/site:config', $context, $USER->id, true, 'nopermissions');
/// Initialize variables.
$hostid = optional_param('hostid', 0, PARAM_INT);
+4
View File
@@ -29,10 +29,14 @@ require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot . '/' . $CFG->admin .'/mnet/profilefields_form.php');
$mnet = get_mnet_environment();
require_login();
$hostid = required_param('hostid', PARAM_INT);
$mnet_peer = new mnet_peer();
$mnet_peer->set_id($hostid);
$context = context_system::instance();
require_capability('moodle/site:config', $context, $USER->id, true, 'nopermissions');
admin_externalpage_setup('mnetpeers');
$form = new mnet_profile_form(null, array('hostid' => $hostid));
+3
View File
@@ -30,8 +30,11 @@ require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/mnet/services_form.php');
$mnet = get_mnet_environment();
require_login();
admin_externalpage_setup('mnetpeers');
$context = context_system::instance();
require_capability('moodle/site:config', $context, $USER->id, true, "nopermissions");
$hostid = required_param('hostid', PARAM_INT);
+4
View File
@@ -21,8 +21,12 @@ if ($CFG->mnet_dispatcher_mode === 'off') {
print_error('mnetdisabled', 'mnet');
}
require_login();
admin_externalpage_setup('mnettestclient');
$context = context_system::instance();
require_capability('moodle/site:config', $context);
error_reporting(DEBUG_ALL);
echo $OUTPUT->header();
+4
View File
@@ -5,8 +5,12 @@
require_once($CFG->libdir.'/adminlib.php');
include_once($CFG->dirroot.'/mnet/lib.php');
require_login();
admin_externalpage_setup('trustedhosts');
$context = context_system::instance();
require_capability('moodle/site:config', $context, $USER->id, true, "nopermissions");
if (!extension_loaded('openssl')) {
echo $OUTPUT->header();
+6 -12
View File
@@ -49,7 +49,6 @@
array($module->id));
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
redirect(new moodle_url('/admin/modules.php'));
}
if (!empty($show) and confirm_sesskey()) {
@@ -67,7 +66,6 @@
array($module->id));
core_plugin_manager::reset_caches();
admin_get_root(true, false); // settings not required - only pages
redirect(new moodle_url('/admin/modules.php'));
}
echo $OUTPUT->header();
@@ -89,18 +87,14 @@
$table->set_attribute('class', 'admintable generaltable');
$table->setup();
$pluginmanager = core_plugin_manager::instance();
foreach ($modules as $module) {
$plugininfo = $pluginmanager->get_plugin_info('mod_'.$module->name);
$status = $plugininfo->get_status();
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
if (!file_exists("$CFG->dirroot/mod/$module->name/lib.php")) {
$strmodulename = '<span class="notifyproblem">'.$module->name.' ('.get_string('missingfromdisk').')</span>';
$missing = true;
} else {
// took out hspace="\10\", because it does not validate. don't know what to replace with.
$icon = "<img src=\"" . $OUTPUT->image_url('icon', $module->name) . "\" class=\"icon\" alt=\"\" />";
$icon = "<img src=\"" . $OUTPUT->pix_url('icon', $module->name) . "\" class=\"icon\" alt=\"\" />";
$strmodulename = $icon.' '.get_string('modulename', $module->name);
$missing = false;
}
@@ -123,8 +117,8 @@
$count = -1;
}
if ($count>0) {
$countlink = $OUTPUT->action_link(new moodle_url('/course/search.php', ['modulelist' => $module->name]),
$count, null, ['title' => $strshowmodulecourse]);
$countlink = "<a href=\"{$CFG->wwwroot}/course/search.php?modulelist=$module->name" .
"&amp;sesskey=".sesskey()."\" title=\"$strshowmodulecourse\">$count</a>";
} else if ($count < 0) {
$countlink = get_string('error');
} else {
@@ -136,11 +130,11 @@
$class = '';
} else if ($module->visible) {
$visible = "<a href=\"modules.php?hide=$module->name&amp;sesskey=".sesskey()."\" title=\"$strhide\">".
$OUTPUT->pix_icon('t/hide', $strhide) . '</a>';
"<img src=\"" . $OUTPUT->pix_url('t/hide') . "\" class=\"iconsmall\" alt=\"$strhide\" /></a>";
$class = '';
} else {
$visible = "<a href=\"modules.php?show=$module->name&amp;sesskey=".sesskey()."\" title=\"$strshow\">".
$OUTPUT->pix_icon('t/show', $strshow) . '</a>';
"<img src=\"" . $OUTPUT->pix_url('t/show') . "\" class=\"iconsmall\" alt=\"$strshow\" /></a>";
$class = 'dimmed_text';
}
if ($module->name == "forum") {
-11
View File
@@ -30,17 +30,6 @@
require_once(__DIR__ . '/../config.php');
$error = optional_param('error', '', PARAM_RAW);
if ($error) {
$message = optional_param('error_description', '', PARAM_RAW);
if ($message) {
print_error($message);
} else {
print_error($error);
}
die();
}
// The authorization code generated by the authorization server.
$code = required_param('code', PARAM_RAW);
// The state parameter we've given (used in moodle as a redirect url).
+3 -2
View File
@@ -43,8 +43,9 @@ $confirminstallupdate = optional_param('confirminstallupdate', false, PARAM_BOOL
// NOTE: do not use admin_externalpage_setup() here because it loads
// full admin tree which is not possible during uninstallation.
require_admin();
require_login();
$syscontext = context_system::instance();
require_capability('moodle/site:config', $syscontext);
// URL params we want to maintain on redirects.
$pageparams = array('updatesonly' => $updatesonly, 'contribonly' => $contribonly);
@@ -53,6 +54,7 @@ $pageurl = new moodle_url('/admin/plugins.php', $pageparams);
$pluginman = core_plugin_manager::instance();
if ($uninstall) {
require_sesskey();
if (!$confirmed) {
admin_externalpage_setup('pluginsoverview', '', $pageparams);
@@ -91,7 +93,6 @@ if ($uninstall) {
exit();
} else {
require_sesskey();
$SESSION->pluginuninstallreturn = $pluginfo->get_return_url_after_uninstall($return);
$progress = new progress_trace_buffer(new text_progress_trace(), false);
$pluginman->uninstall_plugin($pluginfo->component, $progress);
+2
View File
@@ -35,6 +35,8 @@ if ($action == 'newon') {
admin_externalpage_setup($pagename);
require_capability('moodle/site:config', context_system::instance());
$baseurl = "$CFG->wwwroot/$CFG->admin/portfolio.php";
$sesskeyurl = "$CFG->wwwroot/$CFG->admin/portfolio.php?sesskey=" . sesskey();
$configstr = get_string('manageportfolios', 'portfolio');
+16 -22
View File
@@ -27,43 +27,37 @@ require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$returnurl = optional_param('returnurl', '/admin/purgecaches.php', PARAM_LOCALURL);
$returnurl = new moodle_url($returnurl);
admin_externalpage_setup('purgecaches');
$form = new core_admin\form\purge_caches(null, ['returnurl' => $returnurl]);
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
// If we have got here as a confirmed aciton, do it.
if ($data = $form->get_data()) {
if ($confirm && isloggedin() && confirm_sesskey()) {
require_capability('moodle/site:config', context_system::instance());
// Valid request. Purge, and redirect the user back to where they came from.
$selected = $data->purgeselectedoptions;
purge_caches($selected);
purge_all_caches();
if (isset($data->all)) {
$message = get_string('purgecachesfinished', 'admin');
if ($returnurl) {
$returnurl = $CFG->wwwroot . $returnurl;
} else {
$message = get_string('purgeselectedcachesfinished', 'admin');
$returnurl = new moodle_url('/admin/purgecaches.php');
}
} else if ($confirm && confirm_sesskey()) {
purge_caches();
$message = get_string('purgecachesfinished', 'admin');
redirect($returnurl, get_string('purgecachesfinished', 'admin'));
}
if (isset($message)) {
redirect($returnurl, $message);
}
// Otherwise, show a button to actually purge the caches.
admin_externalpage_setup('purgecaches');
// Otherwise, show a form to actually purge the caches.
$actionurl = new moodle_url('/admin/purgecaches.php', array('sesskey'=>sesskey(), 'confirm'=>1));
if ($returnurl) {
$actionurl->param('returnurl', $returnurl);
}
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('purgecachespage', 'admin'));
echo $OUTPUT->heading(get_string('purgecaches', 'admin'));
echo $OUTPUT->box_start('generalbox', 'notice');
echo html_writer::tag('p', get_string('purgecachesconfirm', 'admin'));
echo $form->render();
echo $OUTPUT->single_button($actionurl, get_string('purgecaches', 'admin'), 'post');
echo $OUTPUT->box_end();
echo $OUTPUT->footer();
+2 -2
View File
@@ -31,7 +31,7 @@ require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/tablelib.php');
// Check permissions.
require_login(null, false);
require_login();
$systemcontext = context_system::instance();
require_capability('moodle/question:config', $systemcontext);
@@ -170,7 +170,7 @@ foreach ($sortedbehaviours as $behaviour => $behaviourname) {
if ($version) {
$row[] = $version;
} else {
$row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'text-muted'));
$row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'disabled'));
}
// Other question types required by this one.
+4 -3
View File
@@ -30,12 +30,13 @@ require_once($CFG->libdir . '/questionlib.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->libdir . '/tablelib.php');
admin_externalpage_setup('manageqtypes');
// Check permissions.
require_login();
$systemcontext = context_system::instance();
require_capability('moodle/question:config', $systemcontext);
$canviewreports = has_capability('report/questioninstances:view', $systemcontext);
admin_externalpage_setup('manageqtypes');
$thispageurl = new moodle_url('/admin/qtypes.php');
$qtypes = question_bank::get_all_qtypes();
@@ -172,7 +173,7 @@ foreach ($sortedqtypes as $qtypename => $localname) {
if ($version) {
$row[] = $version;
} else {
$row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'text-muted'));
$row[] = html_writer::tag('span', get_string('nodatabase', 'admin'), array('class' => 'disabled'));
}
// Other question types required by this one.
+32 -27
View File
@@ -20,7 +20,7 @@
// //
///////////////////////////////////////////////////////////////////////////
/**
/*
* @package moodle
* @subpackage registration
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
@@ -36,6 +36,7 @@
require('../../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
$newtoken = optional_param('newtoken', '', PARAM_ALPHANUM);
$url = optional_param('url', '', PARAM_URL);
@@ -43,19 +44,7 @@ $hubname = optional_param('hubname', '', PARAM_TEXT);
$token = optional_param('token', '', PARAM_TEXT);
$error = optional_param('error', '', PARAM_ALPHANUM);
admin_externalpage_setup('registrationmoodleorg');
if (parse_url($url, PHP_URL_HOST) !== parse_url(HUB_MOODLEORGHUBURL, PHP_URL_HOST)) {
// Allow other plugins to confirm registration on custom hubs. Plugins implementing this
// callback need to redirect or exit. See https://docs.moodle.org/en/Hub_registration .
$callbacks = get_plugins_with_function('hub_registration');
foreach ($callbacks as $plugintype => $plugins) {
foreach ($plugins as $plugin => $callback) {
$callback('confirm');
}
}
throw new moodle_exception('errorotherhubsnotsupported', 'hub');
}
admin_externalpage_setup('registrationhubs');
if (!empty($error) and $error == 'urlalreadyexist') {
throw new moodle_exception('urlalreadyregistered', 'hub',
@@ -63,22 +52,38 @@ if (!empty($error) and $error == 'urlalreadyexist') {
}
//check that we are waiting a confirmation from this hub, and check that the token is correct
core\hub\registration::confirm_registration($token, $newtoken, $hubname);
$registrationmanager = new registration_manager();
$registeredhub = $registrationmanager->get_unconfirmedhub($url);
if (!empty($registeredhub) and $registeredhub->token == $token) {
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('registrationconfirmed', 'hub'), 3, 'main');
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('registrationconfirmed', 'hub'), 3, 'main');
// Display notification message.
echo $OUTPUT->notification(get_string('registrationconfirmedon', 'hub'), 'notifysuccess');
$registeredhub->token = $newtoken;
$registeredhub->confirmed = 1;
$registeredhub->hubname = $hubname;
$registrationmanager->update_registeredhub($registeredhub);
// Display continue button.
$returnurl = !empty($SESSION->registrationredirect) ? clean_param($SESSION->registrationredirect, PARAM_LOCALURL) : null;
unset($SESSION->registrationredirect);
$continueurl = new moodle_url($returnurl ?: '/admin/registration/index.php');
$continuebutton = $OUTPUT->render(new single_button($continueurl, get_string('continue')));
$continuebutton = html_writer::tag('div', $continuebutton, array('class' => 'mdl-align'));
echo $continuebutton;
// Display notification message.
echo $OUTPUT->notification(get_string('registrationconfirmedon', 'hub'), 'notifysuccess');
echo $OUTPUT->footer();
//display continue button
$registrationpage = new moodle_url('/admin/registration/index.php');
$continuebutton = $OUTPUT->render(new single_button($registrationpage, get_string('continue', 'hub')));
$continuebutton = html_writer::tag('div', $continuebutton, array('class' => 'mdl-align'));
echo $continuebutton;
if (!extension_loaded('xmlrpc')) {
//display notice about xmlrpc
$xmlrpcnotification = $OUTPUT->doc_link('admin/environment/php_extension/xmlrpc', '');
$xmlrpcnotification .= get_string('xmlrpcdisabledregistration', 'hub');
echo $OUTPUT->notification($xmlrpcnotification);
}
echo $OUTPUT->footer();
} else {
throw new moodle_exception('wrongtoken', 'hub',
$CFG->wwwroot . '/' . $CFG->admin . '/registration/index.php');
}
+479 -3
View File
@@ -20,7 +20,7 @@
// //
///////////////////////////////////////////////////////////////////////////
/**
/*
* @package moodle
* @subpackage registration
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
@@ -30,6 +30,482 @@
* The forms needed by registration pages.
*/
defined('MOODLE_INTERNAL') || die();
debugging('Support for alternative hubs has been removed from Moodle in 3.4.', DEBUG_DEVELOPER);
require_once($CFG->libdir . '/formslib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
/**
* This form display a unregistration form.
*/
class site_unregistration_form extends moodleform {
public function definition() {
$mform = & $this->_form;
$mform->addElement('header', 'site', get_string('unregister', 'hub'));
$huburl = $this->_customdata['huburl'];
$hubname = $this->_customdata['hubname'];
$unregisterlabel = get_string('unregister', 'hub');
$mform->addElement('checkbox', 'unpublishalladvertisedcourses', '',
' ' . get_string('unpublishalladvertisedcourses', 'hub'));
$mform->setType('unpublishalladvertisedcourses', PARAM_INT);
$mform->addElement('checkbox', 'unpublishalluploadedcourses', '',
' ' . get_string('unpublishalluploadedcourses', 'hub'));
$mform->setType('unpublishalluploadedcourses', PARAM_INT);
$mform->addElement('hidden', 'confirm', 1);
$mform->setType('confirm', PARAM_INT);
$mform->addElement('hidden', 'unregistration', 1);
$mform->setType('unregistration', PARAM_INT);
$mform->addElement('hidden', 'huburl', $huburl);
$mform->setType('huburl', PARAM_URL);
$mform->addElement('hidden', 'hubname', $hubname);
$mform->setType('hubname', PARAM_TEXT);
$this->add_action_buttons(true, $unregisterlabel);
}
}
/**
* This form display a clean registration data form.
*/
class site_clean_registration_data_form extends moodleform {
public function definition() {
$mform = & $this->_form;
$mform->addElement('header', 'site', get_string('unregister', 'hub'));
$huburl = $this->_customdata['huburl'];
$hubname = $this->_customdata['hubname'];
$unregisterlabel = get_string('forceunregister', 'hub');
$mform->addElement('static', '', get_string('warning', 'hub'), get_string('forceunregisterconfirmation', 'hub', $hubname));
$mform->addElement('hidden', 'confirm', 1);
$mform->setType('confirm', PARAM_INT);
$mform->addElement('hidden', 'unregistration', 1);
$mform->setType('unregistration', PARAM_INT);
$mform->addElement('hidden', 'cleanregdata', 1);
$mform->setType('cleanregdata', PARAM_INT);
$mform->addElement('hidden', 'huburl', $huburl);
$mform->setType('huburl', PARAM_URL);
$mform->addElement('hidden', 'hubname', $hubname);
$mform->setType('hubname', PARAM_TEXT);
$this->add_action_buttons(true, $unregisterlabel);
}
}
/**
* This form display a hub selector.
* The hub list is retrieved from Moodle.org hub directory.
* Also displayed, a text field to enter private hub url + its password
*/
class hub_selector_form extends moodleform {
public function definition() {
global $CFG, $OUTPUT;
$mform = & $this->_form;
$mform->addElement('header', 'site', get_string('selecthub', 'hub'));
//retrieve the hub list on the hub directory by web service
$function = 'hubdirectory_get_hubs';
$params = array();
$serverurl = HUB_HUBDIRECTORYURL . "/local/hubdirectory/webservice/webservices.php";
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, 'publichubdirectory');
try {
$hubs = $xmlrpcclient->call($function, $params);
} catch (Exception $e) {
$error = $OUTPUT->notification(get_string('errorhublisting', 'hub', $e->getMessage()));
$mform->addElement('static', 'errorhub', '', $error);
$hubs = array();
}
//remove moodle.org from the hub list
foreach ($hubs as $key => $hub) {
if ($hub['url'] == HUB_MOODLEORGHUBURL) {
unset($hubs[$key]);
}
}
//Public hub list
$options = array();
foreach ($hubs as $hub) {
//to not display a name longer than 100 character (too big)
if (core_text::strlen($hub['name']) > 100) {
$hubname = core_text::substr($hub['name'], 0, 100);
$hubname = $hubname . "...";
} else {
$hubname = $hub['name'];
}
$options[$hub['url']] = $hubname;
$mform->addElement('hidden', clean_param($hub['url'], PARAM_ALPHANUMEXT), $hubname);
$mform->setType(clean_param($hub['url'], PARAM_ALPHANUMEXT), PARAM_ALPHANUMEXT);
}
if (!empty($hubs)) {
$mform->addElement('select', 'publichub', get_string('publichub', 'hub'),
$options, array("size" => 15));
$mform->setType('publichub', PARAM_URL);
}
$mform->addElement('static', 'or', '', get_string('orenterprivatehub', 'hub'));
//Private hub
$mform->addElement('text', 'unlistedurl', get_string('privatehuburl', 'hub'),
array('class' => 'registration_textfield'));
$mform->setType('unlistedurl', PARAM_URL);
$mform->addElement('text', 'password', get_string('password'),
array('class' => 'registration_textfield'));
$mform->setType('password', PARAM_RAW);
$this->add_action_buttons(false, get_string('selecthub', 'hub'));
}
/**
* Check the unlisted URL is a URL
*/
function validation($data, $files) {
global $CFG;
$errors = parent::validation($data, $files);
$unlistedurl = $this->_form->_submitValues['unlistedurl'];
if (empty($unlistedurl)) {
$errors['unlistedurl'] = get_string('badurlformat', 'hub');
}
return $errors;
}
}
/**
* The site registration form. Information will be sent to a given hub.
*/
class site_registration_form extends moodleform {
public function definition() {
global $CFG, $DB;
$strrequired = get_string('required');
$mform = & $this->_form;
$huburl = $this->_customdata['huburl'];
$hubname = $this->_customdata['hubname'];
$password = $this->_customdata['password'];
$admin = get_admin();
$site = get_site();
//retrieve config for this hub and set default if they don't exist
$cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
$sitename = get_config('hub', 'site_name_' . $cleanhuburl);
if ($sitename === false) {
$sitename = format_string($site->fullname, true, array('context' => context_course::instance(SITEID)));
}
$sitedescription = get_config('hub', 'site_description_' . $cleanhuburl);
if ($sitedescription === false) {
$sitedescription = $site->summary;
}
$contactname = get_config('hub', 'site_contactname_' . $cleanhuburl);
if ($contactname === false) {
$contactname = fullname($admin, true);
}
$contactemail = get_config('hub', 'site_contactemail_' . $cleanhuburl);
if ($contactemail === false) {
$contactemail = $admin->email;
}
$contactphone = get_config('hub', 'site_contactphone_' . $cleanhuburl);
if ($contactphone === false) {
$contactphone = $admin->phone1;
}
$imageurl = get_config('hub', 'site_imageurl_' . $cleanhuburl);
$privacy = get_config('hub', 'site_privacy_' . $cleanhuburl);
$address = get_config('hub', 'site_address_' . $cleanhuburl);
$region = get_config('hub', 'site_region_' . $cleanhuburl);
$country = get_config('hub', 'site_country_' . $cleanhuburl);
if ($country === false) {
$country = $admin->country;
}
$language = get_config('hub', 'site_language_' . $cleanhuburl);
if ($language === false) {
$language = current_language();
}
$geolocation = get_config('hub', 'site_geolocation_' . $cleanhuburl);
$contactable = get_config('hub', 'site_contactable_' . $cleanhuburl);
$emailalert = get_config('hub', 'site_emailalert_' . $cleanhuburl);
$emailalert = ($emailalert === 0) ? 0 : 1;
$coursesnumber = get_config('hub', 'site_coursesnumber_' . $cleanhuburl);
$usersnumber = get_config('hub', 'site_usersnumber_' . $cleanhuburl);
$roleassignmentsnumber = get_config('hub', 'site_roleassignmentsnumber_' . $cleanhuburl);
$postsnumber = get_config('hub', 'site_postsnumber_' . $cleanhuburl);
$questionsnumber = get_config('hub', 'site_questionsnumber_' . $cleanhuburl);
$resourcesnumber = get_config('hub', 'site_resourcesnumber_' . $cleanhuburl);
$badgesnumber = get_config('hub', 'site_badges_' . $cleanhuburl);
$issuedbadgesnumber = get_config('hub', 'site_issuedbadges_' . $cleanhuburl);
$mediancoursesize = get_config('hub', 'site_mediancoursesize_' . $cleanhuburl);
$participantnumberaveragecfg = get_config('hub', 'site_participantnumberaverage_' . $cleanhuburl);
$modulenumberaveragecfg = get_config('hub', 'site_modulenumberaverage_' . $cleanhuburl);
//hidden parameters
$mform->addElement('hidden', 'huburl', $huburl);
$mform->setType('huburl', PARAM_URL);
$mform->addElement('hidden', 'hubname', $hubname);
$mform->setType('hubname', PARAM_TEXT);
$mform->addElement('hidden', 'password', $password);
$mform->setType('password', PARAM_RAW);
//the input parameters
$mform->addElement('header', 'moodle', get_string('registrationinfo', 'hub'));
$mform->addElement('text', 'name', get_string('sitename', 'hub'),
array('class' => 'registration_textfield'));
$mform->addRule('name', $strrequired, 'required', null, 'client');
$mform->setType('name', PARAM_TEXT);
$mform->setDefault('name', $sitename);
$mform->addHelpButton('name', 'sitename', 'hub');
$options = array();
$registrationmanager = new registration_manager();
$options[HUB_SITENOTPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITENOTPUBLISHED);
$options[HUB_SITENAMEPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITENAMEPUBLISHED);
$options[HUB_SITELINKPUBLISHED] = $registrationmanager->get_site_privacy_string(HUB_SITELINKPUBLISHED);
$mform->addElement('select', 'privacy', get_string('siteprivacy', 'hub'), $options);
$mform->setDefault('privacy', $privacy);
$mform->setType('privacy', PARAM_ALPHA);
$mform->addHelpButton('privacy', 'privacy', 'hub');
unset($options);
$mform->addElement('textarea', 'description', get_string('sitedesc', 'hub'),
array('rows' => 8, 'cols' => 41));
$mform->addRule('description', $strrequired, 'required', null, 'client');
$mform->setDefault('description', $sitedescription);
$mform->setType('description', PARAM_TEXT);
$mform->addHelpButton('description', 'sitedesc', 'hub');
$languages = get_string_manager()->get_list_of_languages();
core_collator::asort($languages);
$mform->addElement('select', 'language', get_string('sitelang', 'hub'),
$languages);
$mform->setType('language', PARAM_ALPHANUMEXT);
$mform->addHelpButton('language', 'sitelang', 'hub');
$mform->setDefault('language', $language);
$mform->addElement('textarea', 'address', get_string('postaladdress', 'hub'),
array('rows' => 4, 'cols' => 41));
$mform->setType('address', PARAM_TEXT);
$mform->setDefault('address', $address);
$mform->addHelpButton('address', 'postaladdress', 'hub');
//TODO: use the region array I generated
// $mform->addElement('select', 'region', get_string('selectaregion'), array('-' => '-'));
// $mform->setDefault('region', $region);
$mform->addElement('hidden', 'regioncode', '-');
$mform->setType('regioncode', PARAM_ALPHANUMEXT);
$countries = get_string_manager()->get_list_of_countries();
$mform->addElement('select', 'countrycode', get_string('sitecountry', 'hub'), $countries);
$mform->setDefault('countrycode', $country);
$mform->setType('countrycode', PARAM_ALPHANUMEXT);
$mform->addHelpButton('countrycode', 'sitecountry', 'hub');
$mform->addElement('text', 'geolocation', get_string('sitegeolocation', 'hub'),
array('class' => 'registration_textfield'));
$mform->setDefault('geolocation', $geolocation);
$mform->setType('geolocation', PARAM_RAW);
$mform->addHelpButton('geolocation', 'sitegeolocation', 'hub');
$mform->addElement('text', 'contactname', get_string('siteadmin', 'hub'),
array('class' => 'registration_textfield'));
$mform->addRule('contactname', $strrequired, 'required', null, 'client');
$mform->setType('contactname', PARAM_TEXT);
$mform->setDefault('contactname', $contactname);
$mform->addHelpButton('contactname', 'siteadmin', 'hub');
$mform->addElement('text', 'contactphone', get_string('sitephone', 'hub'),
array('class' => 'registration_textfield'));
$mform->setType('contactphone', PARAM_TEXT);
$mform->addHelpButton('contactphone', 'sitephone', 'hub');
$mform->setForceLtr('contactphone');
$mform->addElement('text', 'contactemail', get_string('siteemail', 'hub'),
array('class' => 'registration_textfield'));
$mform->addRule('contactemail', $strrequired, 'required', null, 'client');
$mform->setType('contactemail', PARAM_EMAIL);
$mform->setDefault('contactemail', $contactemail);
$mform->addHelpButton('contactemail', 'siteemail', 'hub');
$options = array();
$options[0] = get_string("registrationcontactno");
$options[1] = get_string("registrationcontactyes");
$mform->addElement('select', 'contactable', get_string('siteregistrationcontact', 'hub'), $options);
$mform->setDefault('contactable', $contactable);
$mform->setType('contactable', PARAM_INT);
$mform->addHelpButton('contactable', 'siteregistrationcontact', 'hub');
unset($options);
$options = array();
$options[0] = get_string("registrationno");
$options[1] = get_string("registrationyes");
$mform->addElement('select', 'emailalert', get_string('siteregistrationemail', 'hub'), $options);
$mform->setDefault('emailalert', $emailalert);
$mform->setType('emailalert', PARAM_INT);
$mform->addHelpButton('emailalert', 'siteregistrationemail', 'hub');
unset($options);
//TODO site logo
$mform->addElement('hidden', 'imageurl', ''); //TODO: temporary
$mform->setType('imageurl', PARAM_URL);
$mform->addElement('static', 'urlstring', get_string('siteurl', 'hub'), $CFG->wwwroot);
$mform->addHelpButton('urlstring', 'siteurl', 'hub');
$mform->addElement('static', 'versionstring', get_string('siteversion', 'hub'), $CFG->version);
$mform->addElement('hidden', 'moodleversion', $CFG->version);
$mform->setType('moodleversion', PARAM_INT);
$mform->addHelpButton('versionstring', 'siteversion', 'hub');
$mform->addElement('static', 'releasestring', get_string('siterelease', 'hub'), $CFG->release);
$mform->addElement('hidden', 'moodlerelease', $CFG->release);
$mform->setType('moodlerelease', PARAM_TEXT);
$mform->addHelpButton('releasestring', 'siterelease', 'hub');
/// Display statistic that are going to be retrieve by the hub
$coursecount = $DB->count_records('course') - 1;
$usercount = $DB->count_records('user', array('deleted' => 0));
$roleassigncount = $DB->count_records('role_assignments');
$postcount = $DB->count_records('forum_posts');
$questioncount = $DB->count_records('question');
$resourcecount = $DB->count_records('resource');
require_once($CFG->dirroot . "/course/lib.php");
$participantnumberaverage = number_format(average_number_of_participants(), 2);
$modulenumberaverage = number_format(average_number_of_courses_modules(), 2);
require_once($CFG->libdir . '/badgeslib.php');
$badges = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
$issuedbadges = $DB->count_records('badge_issued');
if (HUB_MOODLEORGHUBURL != $huburl) {
$mform->addElement('checkbox', 'courses', get_string('sendfollowinginfo', 'hub'),
" " . get_string('coursesnumber', 'hub', $coursecount));
$mform->setDefault('courses', $coursesnumber != -1);
$mform->setType('courses', PARAM_INT);
$mform->addHelpButton('courses', 'sendfollowinginfo', 'hub');
$mform->addElement('checkbox', 'users', '',
" " . get_string('usersnumber', 'hub', $usercount));
$mform->setDefault('users', $usersnumber != -1);
$mform->setType('users', PARAM_INT);
$mform->addElement('checkbox', 'roleassignments', '',
" " . get_string('roleassignmentsnumber', 'hub', $roleassigncount));
$mform->setDefault('roleassignments', $roleassignmentsnumber != -1);
$mform->setType('roleassignments', PARAM_INT);
$mform->addElement('checkbox', 'posts', '',
" " . get_string('postsnumber', 'hub', $postcount));
$mform->setDefault('posts', $postsnumber != -1);
$mform->setType('posts', PARAM_INT);
$mform->addElement('checkbox', 'questions', '',
" " . get_string('questionsnumber', 'hub', $questioncount));
$mform->setDefault('questions', $questionsnumber != -1);
$mform->setType('questions', PARAM_INT);
$mform->addElement('checkbox', 'resources', '',
" " . get_string('resourcesnumber', 'hub', $resourcecount));
$mform->setDefault('resources', $resourcesnumber != -1);
$mform->setType('resources', PARAM_INT);
$mform->addElement('checkbox', 'badges', '',
" " . get_string('badgesnumber', 'hub', $badges));
$mform->setDefault('badges', $badgesnumber != -1);
$mform->setType('resources', PARAM_INT);
$mform->addElement('checkbox', 'issuedbadges', '',
" " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
$mform->setDefault('issuedbadges', $issuedbadgesnumber != -1);
$mform->setType('resources', PARAM_INT);
$mform->addElement('checkbox', 'participantnumberaverage', '',
" " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
$mform->setDefault('participantnumberaverage', $participantnumberaveragecfg != -1);
$mform->setType('participantnumberaverage', PARAM_FLOAT);
$mform->addElement('checkbox', 'modulenumberaverage', '',
" " . get_string('modulenumberaverage', 'hub', $modulenumberaverage));
$mform->setDefault('modulenumberaverage', $modulenumberaveragecfg != -1);
$mform->setType('modulenumberaverage', PARAM_FLOAT);
} else {
$mform->addElement('static', 'courseslabel', get_string('sendfollowinginfo', 'hub'),
" " . get_string('coursesnumber', 'hub', $coursecount));
$mform->addElement('hidden', 'courses', 1);
$mform->setType('courses', PARAM_INT);
$mform->addHelpButton('courseslabel', 'sendfollowinginfo', 'hub');
$mform->addElement('static', 'userslabel', '',
" " . get_string('usersnumber', 'hub', $usercount));
$mform->addElement('hidden', 'users', 1);
$mform->setType('users', PARAM_INT);
$mform->addElement('static', 'roleassignmentslabel', '',
" " . get_string('roleassignmentsnumber', 'hub', $roleassigncount));
$mform->addElement('hidden', 'roleassignments', 1);
$mform->setType('roleassignments', PARAM_INT);
$mform->addElement('static', 'postslabel', '',
" " . get_string('postsnumber', 'hub', $postcount));
$mform->addElement('hidden', 'posts', 1);
$mform->setType('posts', PARAM_INT);
$mform->addElement('static', 'questionslabel', '',
" " . get_string('questionsnumber', 'hub', $questioncount));
$mform->addElement('hidden', 'questions', 1);
$mform->setType('questions', PARAM_INT);
$mform->addElement('static', 'resourceslabel', '',
" " . get_string('resourcesnumber', 'hub', $resourcecount));
$mform->addElement('hidden', 'resources', 1);
$mform->setType('resources', PARAM_INT);
$mform->addElement('static', 'badgeslabel', '',
" " . get_string('badgesnumber', 'hub', $badges));
$mform->addElement('hidden', 'badges', 1);
$mform->setType('badges', PARAM_INT);
$mform->addElement('static', 'issuedbadgeslabel', '',
" " . get_string('issuedbadgesnumber', 'hub', $issuedbadges));
$mform->addElement('hidden', 'issuedbadges', true);
$mform->setType('issuedbadges', PARAM_INT);
$mform->addElement('static', 'participantnumberaveragelabel', '',
" " . get_string('participantnumberaverage', 'hub', $participantnumberaverage));
$mform->addElement('hidden', 'participantnumberaverage', 1);
$mform->setType('participantnumberaverage', PARAM_FLOAT);
$mform->addElement('static', 'modulenumberaveragelabel', '',
" " . get_string('modulenumberaverage', 'hub', $modulenumberaverage));
$mform->addElement('hidden', 'modulenumberaverage', 1);
$mform->setType('modulenumberaverage', PARAM_FLOAT);
}
//check if it's a first registration or update
$hubregistered = $registrationmanager->get_registeredhub($huburl);
if (!empty($hubregistered)) {
$buttonlabel = get_string('updatesite', 'hub',
!empty($hubname) ? $hubname : $huburl);
$mform->addElement('hidden', 'update', true);
$mform->setType('update', PARAM_BOOL);
} else {
$buttonlabel = get_string('registersite', 'hub',
!empty($hubname) ? $hubname : $huburl);
}
$this->add_action_buttons(false, $buttonlabel);
}
}
+171 -86
View File
@@ -15,114 +15,199 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
/*
* @package moodle
* @subpackage registration
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com
*
* This page displays the site registration form.
* It handles redirection to the hub to continue the registration workflow process.
* It also handles update operation by web service.
* On this page the administrator selects which hub he wants to register (except for moodle.net)
* Admins can register with moodle.net via the site admin menu "Registration" link.
* On this page the administrator can also unregister from any hubs including moodle.net.
*/
require_once('../../config.php');
require('../../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/forms.php');
require_once($CFG->dirroot . '/course/publish/lib.php');
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
admin_externalpage_setup('registrationmoodleorg');
admin_externalpage_setup('registrationhubs');
$unregistration = optional_param('unregistration', false, PARAM_BOOL);
$confirm = optional_param('confirm', false, PARAM_BOOL);
$renderer = $PAGE->get_renderer('core', 'register');
if ($unregistration && \core\hub\registration::is_registered()) {
if ($confirm) {
require_sesskey();
\core\hub\registration::unregister(false, false);
$unregistration = optional_param('unregistration', 0, PARAM_INT);
$cleanregdata = optional_param('cleanregdata', 0, PARAM_BOOL);
$confirm = optional_param('confirm', 0, PARAM_INT);
$huburl = optional_param('huburl', '', PARAM_URL);
$cancel = optional_param('cancel', null, PARAM_ALPHA);
if (!\core\hub\registration::is_registered()) {
redirect(new moodle_url('/admin/registration/index.php'));
$registrationmanager = new registration_manager();
$publicationmanager = new course_publish_manager();
$errormessage = '';
if (empty($cancel) and $unregistration and $confirm and confirm_sesskey()) {
$hub = $registrationmanager->get_registeredhub($huburl);
//unpublish course and unregister the site by web service
if (!$cleanregdata) {
//check if we need to unpublish courses
//enrollable courses
$unpublishalladvertisedcourses = optional_param('unpublishalladvertisedcourses', 0, PARAM_INT);
$hubcourseids = array();
if ($unpublishalladvertisedcourses) {
$enrollablecourses = $publicationmanager->get_publications($huburl, null, 1);
if (!empty($enrollablecourses)) {
foreach ($enrollablecourses as $enrollablecourse) {
$hubcourseids[] = $enrollablecourse->hubcourseid;
}
}
}
//downloadable courses
$unpublishalluploadedcourses = optional_param('unpublishalluploadedcourses', 0, PARAM_INT);
if ($unpublishalluploadedcourses) {
$downloadablecourses = $publicationmanager->get_publications($huburl, null, 0);
if (!empty($downloadablecourses)) {
foreach ($downloadablecourses as $downloadablecourse) {
$hubcourseids[] = $downloadablecourse->hubcourseid;
}
}
}
//unpublish the courses by web service
if (!empty($hubcourseids)) {
$function = 'hub_unregister_courses';
$params = array('courseids' => $hubcourseids);
$serverurl = $huburl . "/local/hub/webservice/webservices.php";
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
try {
$result = $xmlrpcclient->call($function, $params);
//delete the published courses
if (!empty($enrollablecourses)) {
$publicationmanager->delete_hub_publications($huburl, 1);
}
if (!empty($downloadablecourses)) {
$publicationmanager->delete_hub_publications($huburl, 0);
}
} catch (Exception $e) {
$errormessage = $e->getMessage();
$errormessage .= html_writer::empty_tag('br') .
get_string('errorunpublishcourses', 'hub');
$confirm = false;
$cleanregdata = 1;
}
}
}
//course unpublish went ok, unregister the site now
if ($confirm) {
$function = 'hub_unregister_site';
$params = array();
$serverurl = $huburl . "/local/hub/webservice/webservices.php";
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
try {
$result = $xmlrpcclient->call($function, $params);
} catch (Exception $e) {
if (!$cleanregdata) {
$errormessage = $e->getMessage();
$confirm = false;
$cleanregdata = 1;
}
}
}
//check that we are still processing the unregistration,
//it could have been unset if an exception were previsouly catched
if ($confirm) {
$registrationmanager->delete_registeredhub($huburl);
}
}
if (empty($cancel) and $unregistration and !$confirm) {
echo $OUTPUT->header();
//do not check sesskey if confirm = false because this script is linked into email message
if (!empty($errormessage)) {
echo $OUTPUT->notification(get_string('unregistrationerror', 'hub', $errormessage));
}
$hub = $registrationmanager->get_registeredhub($huburl);
echo $OUTPUT->heading(get_string('unregisterfrom', 'hub', $hub->hubname), 3, 'main');
if ($cleanregdata) {
$siteunregistrationform = new site_clean_registration_data_form('',
array('huburl' => $huburl, 'hubname' => $hub->hubname));
} else {
$siteunregistrationform = new site_unregistration_form('',
array('huburl' => $huburl, 'hubname' => $hub->hubname));
}
$siteunregistrationform->display();
} else {
$registeredonmoodleorg = false;
$moodleorghub = $registrationmanager->get_registeredhub(HUB_MOODLEORGHUBURL);
if (!empty($moodleorghub)) {
$registeredonmoodleorg = true;
}
// load the hub selector form
$hubselectorform = new hub_selector_form();
$fromform = $hubselectorform->get_data();
$selectedhuburl = optional_param('publichub', false, PARAM_URL);
$unlistedhuburl = optional_param('unlistedurl', false, PARAM_TEXT);
$password = optional_param('password', '', PARAM_RAW);
$registeringhuburl = null;
if (!empty($unlistedhuburl)) {
if (clean_param($unlistedhuburl, PARAM_URL) !== '') {
$registeringhuburl = $unlistedhuburl;
}
} else if (!empty($selectedhuburl)) {
$registeringhuburl = $selectedhuburl;
}
// a hub has been selected, redirect to the hub registration page
if (empty($cancel) and !empty($registeringhuburl) and confirm_sesskey()) {
$hubname = optional_param(clean_param($registeringhuburl, PARAM_ALPHANUMEXT), '', PARAM_TEXT);
$params = array('sesskey' => sesskey(), 'huburl' => $registeringhuburl,
'password' => $password, 'hubname' => $hubname);
redirect(new moodle_url($CFG->wwwroot . "/" . $CFG->admin . "/registration/register.php",
$params));
}
echo $OUTPUT->header();
echo $OUTPUT->confirm(
get_string('registerwithmoodleorgremove', 'core_hub'),
new moodle_url(new moodle_url('/admin/registration/index.php', ['unregistration' => 1, 'confirm' => 1])),
new moodle_url(new moodle_url('/admin/registration/index.php'))
);
echo $OUTPUT->footer();
exit;
}
$isinitialregistration = \core\hub\registration::show_after_install(true);
if (!$returnurl = optional_param('returnurl', null, PARAM_LOCALURL)) {
$returnurl = $isinitialregistration ? '/admin/index.php' : '/admin/registration/index.php';
}
//check if the site is registered on Moodle.org and display a message about registering on MOOCH
$registered = $DB->count_records('registration_hubs', array('huburl' => HUB_MOODLEORGHUBURL, 'confirmed' => 1));
if (empty($registered)) {
$warningmsg = get_string('registermoochtips', 'hub');
$warningmsg .= $renderer->single_button(new moodle_url('register.php', array('huburl' => HUB_MOODLEORGHUBURL
, 'hubname' => 'Moodle.org')), get_string('register', 'admin'));
echo $renderer->box($warningmsg, 'buttons mdl-align generalbox adminwarning');
}
$siteregistrationform = new \core\hub\site_registration_form();
$siteregistrationform->set_data(['returnurl' => $returnurl]);
if ($fromform = $siteregistrationform->get_data()) {
//do not check sesskey if confirm = false because this script is linked into email message
if (!empty($errormessage)) {
echo $OUTPUT->notification(get_string('unregistrationerror', 'hub', $errormessage));
}
// Save the settings.
\core\hub\registration::save_site_info($fromform);
echo $OUTPUT->heading(get_string('registerwith', 'hub'));
if (\core\hub\registration::is_registered()) {
if (\core\hub\registration::update_manual()) {
redirect(new moodle_url($returnurl));
$hubselectorform->display();
if (extension_loaded('xmlrpc')) {
$hubs = $registrationmanager->get_registered_on_hubs();
if (!empty($hubs)) {
echo $OUTPUT->heading(get_string('registeredon', 'hub'), 3, 'main');
echo $renderer->registeredonhublisting($hubs);
}
redirect(new moodle_url('/admin/registration/index.php', ['returnurl' => $returnurl]));
} else {
\core\hub\registration::register($returnurl);
// This method will redirect away.
} else { //display notice about xmlrpc
$xmlrpcnotification = $OUTPUT->doc_link('admin/environment/php_extension/xmlrpc', '');
$xmlrpcnotification .= get_string('xmlrpcdisabledregistration', 'hub');
echo $OUTPUT->notification($xmlrpcnotification);
}
}
// OUTPUT SECTION.
echo $OUTPUT->header();
// Current status of registration.
$notificationtype = \core\output\notification::NOTIFY_ERROR;
if (\core\hub\registration::is_registered()) {
$lastupdated = \core\hub\registration::get_last_updated();
if ($lastupdated == 0) {
$registrationmessage = get_string('pleaserefreshregistrationunknown', 'admin');
} else if (\core\hub\registration::get_new_registration_fields()) {
$registrationmessage = get_string('pleaserefreshregistrationnewdata', 'admin');
} else {
$lastupdated = userdate($lastupdated, get_string('strftimedate', 'langconfig'));
$registrationmessage = get_string('pleaserefreshregistration', 'admin', $lastupdated);
$notificationtype = \core\output\notification::NOTIFY_INFO;
}
echo $OUTPUT->notification($registrationmessage, $notificationtype);
} else if (!$isinitialregistration) {
$registrationmessage = get_string('registrationwarning', 'admin');
echo $OUTPUT->notification($registrationmessage, $notificationtype);
}
// Heading.
if (\core\hub\registration::is_registered()) {
echo $OUTPUT->heading(get_string('registerwithmoodleorgupdate', 'core_hub'));
} else if ($isinitialregistration) {
echo $OUTPUT->heading(get_string('registerwithmoodleorgcomplete', 'core_hub'));
} else {
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'core_hub'));
}
$renderer = $PAGE->get_renderer('core', 'admin');
echo $renderer->moodleorg_registration_message();
$siteregistrationform->display();
if (\core\hub\registration::is_registered()) {
// Unregister link.
$unregisterhuburl = new moodle_url("/admin/registration/index.php", ['unregistration' => 1]);
echo html_writer::div(html_writer::link($unregisterhuburl, get_string('unregister', 'hub')), 'unregister mt-2');
} else if ($isinitialregistration) {
echo html_writer::div(html_writer::link(new moodle_url($returnurl), get_string('skipregistration', 'hub')),
'skipregistration mt-2');
}
echo $OUTPUT->footer();
+295 -1
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
@@ -14,4 +15,297 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
defined('MOODLE_INTERNAL') || die();
//// SITE PRIVACY /////
/**
* Site privacy: private
*/
define('HUB_SITENOTPUBLISHED', 'notdisplayed');
/**
* Site privacy: public
*/
define('HUB_SITENAMEPUBLISHED', 'named');
/**
* Site privacy: public and global
*/
define('HUB_SITELINKPUBLISHED', 'linked');
/**
*
* Site registration library
*
* @package course
* @copyright 2010 Moodle Pty Ltd (http://moodle.com)
* @author Jerome Mouneyrac
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class registration_manager {
/**
* Automatically update the registration on all hubs
*/
public function cron() {
global $CFG;
if (extension_loaded('xmlrpc')) {
$function = 'hub_update_site_info';
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
// Update all hubs where the site is registered.
$hubs = $this->get_registered_on_hubs();
if (empty($hubs)) {
mtrace(get_string('registrationwarning', 'admin'));
}
foreach ($hubs as $hub) {
// Update the registration.
$siteinfo = $this->get_site_info($hub->huburl);
$params = array('siteinfo' => $siteinfo);
$serverurl = $hub->huburl . "/local/hub/webservice/webservices.php";
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $hub->token);
try {
$result = $xmlrpcclient->call($function, $params);
$this->update_registeredhub($hub); // To update timemodified.
mtrace(get_string('siteupdatedcron', 'hub', $hub->hubname));
} catch (Exception $e) {
$errorparam = new stdClass();
$errorparam->errormessage = $e->getMessage();
$errorparam->hubname = $hub->hubname;
mtrace(get_string('errorcron', 'hub', $errorparam));
}
}
} else {
mtrace(get_string('errorcronnoxmlrpc', 'hub'));
}
}
/**
* Return the site secret for a given hub
* site identifier is assigned to Mooch
* each hub has a unique and personal site secret.
* @param string $huburl
* @return string site secret
*/
public function get_site_secret_for_hub($huburl) {
global $DB;
$existingregistration = $DB->get_record('registration_hubs',
array('huburl' => $huburl));
if (!empty($existingregistration)) {
return $existingregistration->secret;
}
if ($huburl == HUB_MOODLEORGHUBURL) {
$siteidentifier = get_site_identifier();
} else {
$siteidentifier = random_string(32) . $_SERVER['HTTP_HOST'];
}
return $siteidentifier;
}
/**
* When the site register on a hub, he must call this function
* @param object $hub where the site is registered on
* @return integer id of the record
*/
public function add_registeredhub($hub) {
global $DB;
$hub->timemodified = time();
$id = $DB->insert_record('registration_hubs', $hub);
return $id;
}
/**
* When a site unregister from a hub, he must call this function
* @param string $huburl the huburl to delete
*/
public function delete_registeredhub($huburl) {
global $DB;
$DB->delete_records('registration_hubs', array('huburl' => $huburl));
}
/**
* Get a hub on which the site is registered for a given url or token
* Mostly use to check if the site is registered on a specific hub
* @param string $huburl
* @param string $token
* @return object the hub
*/
public function get_registeredhub($huburl = null, $token = null) {
global $DB;
$params = array();
if (!empty($huburl)) {
$params['huburl'] = $huburl;
}
if (!empty($token)) {
$params['token'] = $token;
}
$params['confirmed'] = 1;
$token = $DB->get_record('registration_hubs', $params);
return $token;
}
/**
* Get the hub which has not confirmed that the site is registered on,
* but for which a request has been sent
* @param string $huburl
* @return object the hub
*/
public function get_unconfirmedhub($huburl) {
global $DB;
$params = array();
$params['huburl'] = $huburl;
$params['confirmed'] = 0;
$token = $DB->get_record('registration_hubs', $params);
return $token;
}
/**
* Update a registered hub (mostly use to update the confirmation status)
* @param object $hub the hub
*/
public function update_registeredhub($hub) {
global $DB;
$hub->timemodified = time();
$DB->update_record('registration_hubs', $hub);
}
/**
* Return all hubs where the site is registered
*/
public function get_registered_on_hubs() {
global $DB;
$hubs = $DB->get_records('registration_hubs', array('confirmed' => 1));
return $hubs;
}
/**
* Return site information for a specific hub
* @param string $huburl
* @return array site info
*/
public function get_site_info($huburl) {
global $CFG, $DB;
$siteinfo = array();
$cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
$siteinfo['name'] = get_config('hub', 'site_name_' . $cleanhuburl);
$siteinfo['description'] = get_config('hub', 'site_description_' . $cleanhuburl);
$siteinfo['contactname'] = get_config('hub', 'site_contactname_' . $cleanhuburl);
$siteinfo['contactemail'] = get_config('hub', 'site_contactemail_' . $cleanhuburl);
$siteinfo['contactphone'] = get_config('hub', 'site_contactphone_' . $cleanhuburl);
$siteinfo['imageurl'] = get_config('hub', 'site_imageurl_' . $cleanhuburl);
$siteinfo['privacy'] = get_config('hub', 'site_privacy_' . $cleanhuburl);
$siteinfo['street'] = get_config('hub', 'site_address_' . $cleanhuburl);
$siteinfo['regioncode'] = get_config('hub', 'site_region_' . $cleanhuburl);
$siteinfo['countrycode'] = get_config('hub', 'site_country_' . $cleanhuburl);
$siteinfo['geolocation'] = get_config('hub', 'site_geolocation_' . $cleanhuburl);
$siteinfo['contactable'] = get_config('hub', 'site_contactable_' . $cleanhuburl);
$siteinfo['emailalert'] = get_config('hub', 'site_emailalert_' . $cleanhuburl);
if (get_config('hub', 'site_coursesnumber_' . $cleanhuburl) == -1) {
$coursecount = -1;
} else {
$coursecount = $DB->count_records('course') - 1;
}
$siteinfo['courses'] = $coursecount;
if (get_config('hub', 'site_usersnumber_' . $cleanhuburl) == -1) {
$usercount = -1;
} else {
$usercount = $DB->count_records('user', array('deleted' => 0));
}
$siteinfo['users'] = $usercount;
if (get_config('hub', 'site_roleassignmentsnumber_' . $cleanhuburl) == -1) {
$roleassigncount = -1;
} else {
$roleassigncount = $DB->count_records('role_assignments');
}
$siteinfo['enrolments'] = $roleassigncount;
if (get_config('hub', 'site_postsnumber_' . $cleanhuburl) == -1) {
$postcount = -1;
} else {
$postcount = $DB->count_records('forum_posts');
}
$siteinfo['posts'] = $postcount;
if (get_config('hub', 'site_questionsnumber_' . $cleanhuburl) == -1) {
$questioncount = -1;
} else {
$questioncount = $DB->count_records('question');
}
$siteinfo['questions'] = $questioncount;
if (get_config('hub', 'site_resourcesnumber_' . $cleanhuburl) == -1) {
$resourcecount = -1;
} else {
$resourcecount = $DB->count_records('resource');
}
$siteinfo['resources'] = $resourcecount;
// Badge statistics.
require_once($CFG->libdir . '/badgeslib.php');
if (get_config('hub', 'site_badges_' . $cleanhuburl) == -1) {
$badges = -1;
} else {
$badges = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
}
$siteinfo['badges'] = $badges;
if (get_config('hub', 'site_issuedbadges_' . $cleanhuburl) == -1) {
$issuedbadges = -1;
} else {
$issuedbadges = $DB->count_records('badge_issued');
}
$siteinfo['issuedbadges'] = $issuedbadges;
//TODO
require_once($CFG->dirroot . "/course/lib.php");
if (get_config('hub', 'site_participantnumberaverage_' . $cleanhuburl) == -1) {
$participantnumberaverage = -1;
} else {
$participantnumberaverage = average_number_of_participants();
}
$siteinfo['participantnumberaverage'] = $participantnumberaverage;
if (get_config('hub', 'site_modulenumberaverage_' . $cleanhuburl) == -1) {
$modulenumberaverage = -1;
} else {
$modulenumberaverage = average_number_of_courses_modules();
}
$siteinfo['modulenumberaverage'] = $modulenumberaverage;
$siteinfo['language'] = get_config('hub', 'site_language_' . $cleanhuburl);
$siteinfo['moodleversion'] = $CFG->version;
$siteinfo['moodlerelease'] = $CFG->release;
$siteinfo['url'] = $CFG->wwwroot;
return $siteinfo;
}
/**
* Retrieve the site privacy string matching the define value
* @param string $privacy must match the define into moodlelib.php
* @return string
*/
public function get_site_privacy_string($privacy) {
switch ($privacy) {
case HUB_SITENOTPUBLISHED:
$privacystring = get_string('siteprivacynotpublished', 'hub');
break;
case HUB_SITENAMEPUBLISHED:
$privacystring = get_string('siteprivacypublished', 'hub');
break;
case HUB_SITELINKPUBLISHED:
$privacystring = get_string('siteprivacylinked', 'hub');
break;
}
if (empty($privacystring)) {
throw new moodle_exception('unknownprivacy');
}
return $privacystring;
}
}
?>
+165 -2
View File
@@ -20,7 +20,7 @@
// //
///////////////////////////////////////////////////////////////////////////
/**
/*
* @package moodle
* @subpackage registration
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
@@ -34,5 +34,168 @@
require_once('../../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/forms.php');
require_once($CFG->dirroot . '/webservice/lib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
redirect(new moodle_url('/admin/registration/index.php'));
require_sesskey();
$huburl = required_param('huburl', PARAM_URL);
$huburl = rtrim($huburl, "/");
if ($huburl == HUB_MOODLEORGHUBURL) { // register to Moodle.org
admin_externalpage_setup('registrationmoodleorg');
} else { //register to a hub
admin_externalpage_setup('registrationhub');
}
$password = optional_param('password', '', PARAM_TEXT);
$hubname = optional_param('hubname', '', PARAM_TEXT);
$registrationmanager = new registration_manager();
$registeredhub = $registrationmanager->get_registeredhub($huburl);
$siteregistrationform = new site_registration_form('',
array('alreadyregistered' => !empty($registeredhub->token),
'huburl' => $huburl, 'hubname' => $hubname,
'password' => $password));
$fromform = $siteregistrationform->get_data();
if (!empty($fromform) and confirm_sesskey()) {
// Set to -1 all optional data marked as "don't send" by the admin.
// The function get_site_info() will not calculate the optional data if config is set to -1.
$inputnames = array('courses', 'users', 'roleassignments', 'posts', 'questions', 'resources',
'badges', 'issuedbadges', 'modulenumberaverage', 'participantnumberaverage');
foreach ($inputnames as $inputname) {
if (empty($fromform->{$inputname})) {
$fromform->{$inputname} = -1;
}
}
// Save the settings.
$cleanhuburl = clean_param($huburl, PARAM_ALPHANUMEXT);
set_config('site_name_' . $cleanhuburl, $fromform->name, 'hub');
set_config('site_description_' . $cleanhuburl, $fromform->description, 'hub');
set_config('site_contactname_' . $cleanhuburl, $fromform->contactname, 'hub');
set_config('site_contactemail_' . $cleanhuburl, $fromform->contactemail, 'hub');
set_config('site_contactphone_' . $cleanhuburl, $fromform->contactphone, 'hub');
set_config('site_imageurl_' . $cleanhuburl, $fromform->imageurl, 'hub');
set_config('site_privacy_' . $cleanhuburl, $fromform->privacy, 'hub');
set_config('site_address_' . $cleanhuburl, $fromform->address, 'hub');
set_config('site_region_' . $cleanhuburl, $fromform->regioncode, 'hub');
set_config('site_country_' . $cleanhuburl, $fromform->countrycode, 'hub');
set_config('site_language_' . $cleanhuburl, $fromform->language, 'hub');
set_config('site_geolocation_' . $cleanhuburl, $fromform->geolocation, 'hub');
set_config('site_contactable_' . $cleanhuburl, $fromform->contactable, 'hub');
set_config('site_emailalert_' . $cleanhuburl, $fromform->emailalert, 'hub');
set_config('site_coursesnumber_' . $cleanhuburl, $fromform->courses, 'hub');
set_config('site_usersnumber_' . $cleanhuburl, $fromform->users, 'hub');
set_config('site_roleassignmentsnumber_' . $cleanhuburl, $fromform->roleassignments, 'hub');
set_config('site_postsnumber_' . $cleanhuburl, $fromform->posts, 'hub');
set_config('site_questionsnumber_' . $cleanhuburl, $fromform->questions, 'hub');
set_config('site_resourcesnumber_' . $cleanhuburl, $fromform->resources, 'hub');
set_config('site_badges_' . $cleanhuburl, $fromform->badges, 'hub');
set_config('site_issuedbadges_' . $cleanhuburl, $fromform->issuedbadges, 'hub');
set_config('site_modulenumberaverage_' . $cleanhuburl, $fromform->modulenumberaverage, 'hub');
set_config('site_participantnumberaverage_' . $cleanhuburl, $fromform->participantnumberaverage, 'hub');
}
/////// UPDATE ACTION ////////
// update the hub registration
$update = optional_param('update', 0, PARAM_INT);
if ($update and confirm_sesskey()) {
//update the registration
$function = 'hub_update_site_info';
$siteinfo = $registrationmanager->get_site_info($huburl);
$params = array('siteinfo' => $siteinfo);
$serverurl = $huburl . "/local/hub/webservice/webservices.php";
require_once($CFG->dirroot . "/webservice/xmlrpc/lib.php");
$xmlrpcclient = new webservice_xmlrpc_client($serverurl, $registeredhub->token);
try {
$result = $xmlrpcclient->call($function, $params);
$registrationmanager->update_registeredhub($registeredhub); // To update timemodified.
} catch (Exception $e) {
$error = $OUTPUT->notification(get_string('errorregistration', 'hub', $e->getMessage()));
}
}
/////// FORM REGISTRATION ACTION //////
if (!empty($fromform) and empty($update) and confirm_sesskey()) {
if (!empty($fromform) and confirm_sesskey()) { // if the register button has been clicked
// Retrieve the optional info (specially course number, user number, module number average...).
$siteinfo = $registrationmanager->get_site_info($huburl);
$fromform->courses = $siteinfo['courses'];
$fromform->users = $siteinfo['users'];
$fromform->enrolments = $siteinfo['enrolments'];
$fromform->posts = $siteinfo['posts'];
$fromform->questions = $siteinfo['questions'];
$fromform->resources = $siteinfo['resources'];
$fromform->badges = $siteinfo['badges'];
$fromform->issuedbadges = $siteinfo['issuedbadges'];
$fromform->modulenumberaverage = $siteinfo['modulenumberaverage'];
$fromform->participantnumberaverage = $siteinfo['participantnumberaverage'];
$fromform->street = $siteinfo['street'];
$params = (array) $fromform; //we are using the form input as the redirection parameters (token, url and name)
$unconfirmedhub = $registrationmanager->get_unconfirmedhub($huburl);
if (empty($unconfirmedhub)) {
//we save the token into the communication table in order to have a reference
$unconfirmedhub = new stdClass();
$unconfirmedhub->token = $registrationmanager->get_site_secret_for_hub($huburl);
$unconfirmedhub->secret = $unconfirmedhub->token;
$unconfirmedhub->huburl = $huburl;
$unconfirmedhub->hubname = $hubname;
$unconfirmedhub->confirmed = 0;
$unconfirmedhub->id = $registrationmanager->add_registeredhub($unconfirmedhub);
}
$params['token'] = $unconfirmedhub->token;
$params['url'] = $CFG->wwwroot;
redirect(new moodle_url($huburl . '/local/hub/siteregistration.php', $params));
}
}
/////// OUTPUT SECTION /////////////
echo $OUTPUT->header();
//Display update notification result
if (!empty($registeredhub->confirmed)) {
if (!empty($result)) {
echo $OUTPUT->notification(get_string('siteregistrationupdated', 'hub'), 'notifysuccess');
}
}
if (!empty($error)) {
echo $error;
}
// Some Moodle.org registration explanation.
if ($huburl == HUB_MOODLEORGHUBURL) {
if (!empty($registeredhub->token)) {
if ($registeredhub->timemodified == 0) {
$registrationmessage = get_string('pleaserefreshregistrationunknown', 'admin');
} else {
$lastupdated = userdate($registeredhub->timemodified, get_string('strftimedate', 'langconfig'));
$registrationmessage = get_string('pleaserefreshregistration', 'admin', $lastupdated);
}
} else {
$registrationmessage = get_string('registrationwarning', 'admin');
}
echo $OUTPUT->notification($registrationmessage);
echo $OUTPUT->heading(get_string('registerwithmoodleorg', 'admin'));
$renderer = $PAGE->get_renderer('core', 'register');
echo $renderer->moodleorg_registration_message();
}
$siteregistrationform->display();
echo $OUTPUT->footer();
+95
View File
@@ -0,0 +1,95 @@
<?php
///////////////////////////////////////////////////////////////////////////
// //
// This file is part of Moodle - http://moodle.org/ //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// //
// 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/>. //
// //
///////////////////////////////////////////////////////////////////////////
/**
* Registration renderer.
* @package moodle
* @subpackage registration
* @copyright 2010 Moodle Pty Ltd (http://moodle.com)
* @author Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_register_renderer extends plugin_renderer_base {
/**
* Display message about the benefits of registering on Moodle.org
*
* @return string
*/
public function moodleorg_registration_message() {
$moodleorgstatslink = html_writer::link('http://moodle.net/stats',
get_string('statsmoodleorg', 'admin'),
array('target' => '_blank'));
$moodleorgregmsg = get_string('registermoodleorg', 'admin');
$items = array(get_string('registermoodleorgli1', 'admin'),
get_string('registermoodleorgli2', 'admin', $moodleorgstatslink));
$moodleorgregmsg .= html_writer::alist($items);
return $moodleorgregmsg;
}
/**
* Display a box message confirming a site registration (add or update)
* @param string $confirmationmessage
* @return string
*/
public function registration_confirmation($confirmationmessage) {
$linktositelist = html_writer::tag('a', get_string('sitelist', 'hub'),
array('href' => new moodle_url('/local/hub/index.php')));
$message = $confirmationmessage . html_writer::empty_tag('br') . $linktositelist;
return $this->output->box($message);
}
/**
* Display the listing of registered on hub
*/
public function registeredonhublisting($hubs) {
global $CFG;
$table = new html_table();
$table->head = array(get_string('hub', 'hub'), get_string('operation', 'hub'));
$table->size = array('80%', '20%');
foreach ($hubs as $hub) {
if ($hub->huburl == HUB_MOODLEORGHUBURL) {
$hub->hubname = get_string('registeredmoodleorg', 'hub', $hub->hubname);
}
$hublink = html_writer::tag('a', $hub->hubname, array('href' => $hub->huburl));
$hublinkcell = html_writer::tag('div', $hublink, array('class' => 'registeredhubrow'));
$unregisterhuburl = new moodle_url("/" . $CFG->admin . "/registration/index.php",
array('sesskey' => sesskey(), 'huburl' => $hub->huburl,
'unregistration' => 1));
$unregisterbutton = new single_button($unregisterhuburl,
get_string('unregister', 'hub'));
$unregisterbutton->class = 'centeredbutton';
$unregisterbuttonhtml = $this->output->render($unregisterbutton);
//add button cells
$cells = array($hublinkcell, $unregisterbuttonhtml);
$row = new html_table_row($cells);
$table->data[] = $row;
}
return html_writer::table($table);
}
}
+33 -29
View File
@@ -20,7 +20,7 @@
// //
///////////////////////////////////////////////////////////////////////////
/**
/*
* @package moodle
* @subpackage registration
* @author Jerome Mouneyrac <jerome@mouneyrac.com>
@@ -33,40 +33,44 @@
require('../../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php');
$url = optional_param('url', '', PARAM_URL);
$hubname = optional_param('hubname', '', PARAM_TEXT);
$token = optional_param('token', '', PARAM_TEXT);
admin_externalpage_setup('registrationmoodleorg');
admin_externalpage_setup('registrationhubs');
if (parse_url($url, PHP_URL_HOST) !== parse_url(HUB_MOODLEORGHUBURL, PHP_URL_HOST)) {
// Allow other plugins to renew registration on custom hubs. Plugins implementing this
// callback need to redirect or exit. See https://docs.moodle.org/en/Hub_registration .
$callbacks = get_plugins_with_function('hub_registration');
foreach ($callbacks as $plugintype => $plugins) {
foreach ($plugins as $plugin => $callback) {
$callback('renew');
}
//check that we are waiting a confirmation from this hub, and check that the token is correct
$registrationmanager = new registration_manager();
$registeredhub = $registrationmanager->get_unconfirmedhub($url);
if (!empty($registeredhub) and $registeredhub->token == $token) {
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('renewregistration', 'hub'), 3, 'main');
$hublink = html_writer::tag('a', $hubname, array('href' => $url));
$registrationmanager->delete_registeredhub($url);
//Mooch case, need to recreate the siteidentifier
if ($url == HUB_MOODLEORGHUBURL) {
$CFG->siteidentifier = null;
get_site_identifier();
}
throw new moodle_exception('errorotherhubsnotsupported', 'hub');
$deletedregmsg = get_string('previousregistrationdeleted', 'hub', $hublink);
$button = new single_button(new moodle_url('/admin/registration/index.php'),
get_string('restartregistration', 'hub'));
$button->class = 'restartregbutton';
echo html_writer::tag('div', $deletedregmsg . $OUTPUT->render($button),
array('class' => 'mdl-align'));
echo $OUTPUT->footer();
} else {
throw new moodle_exception('wrongtoken', 'hub',
$CFG->wwwroot . '/' . $CFG->admin . '/registration/index.php');
}
// Check that we are waiting a confirmation from this hub, and check that the token is correct.
\core\hub\registration::reset_site_identifier($token);
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('renewregistration', 'hub'), 3, 'main');
$hublink = html_writer::tag('a', HUB_MOODLEORGHUBURL, array('href' => HUB_MOODLEORGHUBURL));
$deletedregmsg = get_string('previousregistrationdeleted', 'hub', $hublink);
$button = new single_button(new moodle_url('/admin/registration/index.php'),
get_string('restartregistration', 'hub'));
$button->class = 'restartregbutton';
echo html_writer::tag('div', $deletedregmsg . $OUTPUT->render($button),
array('class' => 'mdl-align'));
echo $OUTPUT->footer();
+105 -311
View File
@@ -253,7 +253,7 @@ class core_admin_renderer extends plugin_renderer_base {
$out .= $this->output->container(get_string('cancelinstallinfodir', 'core_plugin', $pluginfo->rootdir));
if ($repotype = $pluginman->plugin_external_source($pluginfo->component)) {
$out .= $this->output->container(get_string('uninstalldeleteconfirmexternal', 'core_plugin', $repotype),
'alert alert-warning mt-2');
'uninstalldeleteconfirmexternal');
}
}
@@ -276,24 +276,12 @@ class core_admin_renderer extends plugin_renderer_base {
* @param int|null $availableupdatesfetch timestamp of the most recent updates fetch or null (unknown)
* @param string[] $cachewarnings An array containing warnings from the Cache API.
* @param array $eventshandlers Events 1 API handlers.
* @param bool $themedesignermode Warn about the theme designer mode.
* @param bool $devlibdir Warn about development libs directory presence.
* @param bool $mobileconfigured Whether the mobile web services have been enabled
* @param bool $overridetossl Whether or not ssl is being forced.
* @param bool $invalidforgottenpasswordurl Whether the forgotten password URL does not link to a valid URL.
* @param bool $croninfrequent If true, warn that cron hasn't run in the past few minutes
* @param bool $showcampaigncontent Whether the campaign content should be visible or not.
* @param bool $showfeedbackencouragement Whether the feedback encouragement content should be displayed or not.
*
* @return string HTML to output.
*/
public function admin_notifications_page($maturity, $insecuredataroot, $errorsdisplayed,
$cronoverdue, $dbproblems, $maintenancemode, $availableupdates, $availableupdatesfetch,
$buggyiconvnomb, $registered, array $cachewarnings = array(), $eventshandlers = 0,
$themedesignermode = false, $devlibdir = false, $mobileconfigured = false,
$overridetossl = false, $invalidforgottenpasswordurl = false, $croninfrequent = false,
$showcampaigncontent = false, bool $showfeedbackencouragement = false) {
$buggyiconvnomb, $registered, array $cachewarnings = array(), $eventshandlers = 0, $themedesignermode = false) {
global $CFG;
$output = '';
@@ -302,22 +290,15 @@ class core_admin_renderer extends plugin_renderer_base {
$output .= $this->legacy_log_store_writing_error();
$output .= empty($CFG->disableupdatenotifications) ? $this->available_updates($availableupdates, $availableupdatesfetch) : '';
$output .= $this->insecure_dataroot_warning($insecuredataroot);
$output .= $this->development_libs_directories_warning($devlibdir);
$output .= $this->themedesignermode_warning($themedesignermode);
$output .= $this->display_errors_warning($errorsdisplayed);
$output .= $this->buggy_iconv_warning($buggyiconvnomb);
$output .= $this->cron_overdue_warning($cronoverdue);
$output .= $this->cron_infrequent_warning($croninfrequent);
$output .= $this->db_problems($dbproblems);
$output .= $this->maintenance_mode_warning($maintenancemode);
$output .= $this->overridetossl_warning($overridetossl);
$output .= $this->cache_warnings($cachewarnings);
$output .= $this->events_handlers($eventshandlers);
$output .= $this->registration_warning($registered);
$output .= $this->mobile_configuration_warning($mobileconfigured);
$output .= $this->forgotten_password_url_warning($invalidforgottenpasswordurl);
$output .= $this->userfeedback_encouragement($showfeedbackencouragement);
$output .= $this->campaign_content($showcampaigncontent);
//////////////////////////////////////////////////////////////////////////////////////////////////
//// IT IS ILLEGAL AND A VIOLATION OF THE GPL TO HIDE, REMOVE OR MODIFY THIS COPYRIGHT NOTICE ///
@@ -367,15 +348,14 @@ class core_admin_renderer extends plugin_renderer_base {
$output = '';
if ($checker->enabled()) {
$output .= $this->container_start('checkforupdates mb-4');
$output .= $this->container_start('checkforupdates');
$output .= $this->single_button(
new moodle_url($reloadurl, array('fetchupdates' => 1)),
get_string('checkforupdates', 'core_plugin')
);
if ($timefetched = $checker->get_last_timefetched()) {
$timefetched = userdate($timefetched, get_string('strftimedatetime', 'core_langconfig'));
$output .= $this->container(get_string('checkforupdateslast', 'core_plugin', $timefetched),
'lasttimefetched small text-muted mt-1');
$output .= $this->container(get_string('checkforupdateslast', 'core_plugin', $timefetched), 'lasttimefetched');
}
$output .= $this->container_end();
}
@@ -439,7 +419,7 @@ class core_admin_renderer extends plugin_renderer_base {
if ($repotype = $pluginman->plugin_external_source($pluginfo->component)) {
$confirm .= $this->output->container(get_string('uninstalldeleteconfirmexternal', 'core_plugin', $repotype),
'alert alert-warning mt-2');
'uninstalldeleteconfirmexternal');
}
// After any uninstall we must execute full upgrade to finish the cleanup!
@@ -518,7 +498,7 @@ class core_admin_renderer extends plugin_renderer_base {
* @return string HTML to output.
*/
protected function warning($message, $type = 'warning') {
return $this->box($message, 'generalbox alert alert-' . $type);
return $this->box($message, 'generalbox admin' . $type);
}
/**
@@ -533,25 +513,7 @@ class core_admin_renderer extends plugin_renderer_base {
return $this->warning(get_string('datarootsecuritywarning', 'admin', $CFG->dataroot));
} else if ($insecuredataroot == INSECURE_DATAROOT_ERROR) {
return $this->warning(get_string('datarootsecurityerror', 'admin', $CFG->dataroot), 'danger');
} else {
return '';
}
}
/**
* Render a warning that a directory with development libs is present.
*
* @param bool $devlibdir True if the warning should be displayed.
* @return string
*/
protected function development_libs_directories_warning($devlibdir) {
if ($devlibdir) {
$moreinfo = new moodle_url('/report/security/index.php');
$warning = get_string('devlibdirpresent', 'core_admin', ['moreinfourl' => $moreinfo->out()]);
return $this->warning($warning, 'danger');
return $this->warning(get_string('datarootsecurityerror', 'admin', $CFG->dataroot), 'error');
} else {
return '';
@@ -608,27 +570,19 @@ class core_admin_renderer extends plugin_renderer_base {
return '';
}
$check = new \tool_task\check\cronrunning();
$result = $check->get_result();
return $this->warning($result->get_summary() . '&nbsp;' . $this->help_icon('cron', 'admin'));
}
if (empty($CFG->cronclionly)) {
$url = new moodle_url('/admin/cron.php');
if (!empty($CFG->cronremotepassword)) {
$url = new moodle_url('/admin/cron.php', array('password' => $CFG->cronremotepassword));
}
/**
* Render an appropriate message if cron is not being run frequently (recommended every minute).
*
* @param bool $croninfrequent
* @return string HTML to output.
*/
public function cron_infrequent_warning(bool $croninfrequent) : string {
global $CFG;
if (!$croninfrequent) {
return '';
return $this->warning(get_string('cronwarning', 'admin', $url->out()) . '&nbsp;' .
$this->help_icon('cron', 'admin'));
}
$check = new \tool_task\check\cronrunning();
$result = $check->get_result();
return $this->warning($result->get_summary() . '&nbsp;' . $this->help_icon('cron', 'admin'));
// $CFG->cronclionly is not empty: cron can run only from CLI.
return $this->warning(get_string('cronwarningcli', 'admin') . '&nbsp;' .
$this->help_icon('cron', 'admin'));
}
/**
@@ -690,20 +644,6 @@ class core_admin_renderer extends plugin_renderer_base {
return $this->warning(get_string('sitemaintenancewarning2', 'admin', $url));
}
/**
* Render a warning that ssl is forced because the site was on loginhttps.
*
* @param bool $overridetossl Whether or not ssl is being forced.
* @return string
*/
protected function overridetossl_warning($overridetossl) {
if (!$overridetossl) {
return '';
}
$warning = get_string('overridetossl', 'core_admin');
return $this->warning($warning, 'warning');
}
/**
* Display a warning about installing development code if necesary.
* @param int $maturity
@@ -718,7 +658,7 @@ class core_admin_renderer extends plugin_renderer_base {
return $this->warning(
$this->container(get_string('maturitycorewarning', 'admin', $maturitylevel)) .
$this->container($this->doc_link('admin/versions', get_string('morehelp'))),
'danger');
'error');
}
/*
@@ -734,7 +674,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
$warning = (get_string('testsiteupgradewarning', 'admin', $testsite));
return $this->warning($warning, 'danger');
return $this->warning($warning, 'error');
}
/**
@@ -769,7 +709,7 @@ class core_admin_renderer extends plugin_renderer_base {
$level = 'warning';
if ($maturity == MATURITY_ALPHA) {
$level = 'danger';
$level = 'error';
}
$maturitylevel = get_string('maturity' . $maturity, 'admin');
@@ -820,7 +760,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
}
$updateinfo .= $this->container_start('checkforupdates mt-1');
$updateinfo .= $this->container_start('checkforupdates');
$fetchurl = new moodle_url('/admin/index.php', array('fetchupdates' => 1, 'sesskey' => sesskey(), 'cache' => 0));
$updateinfo .= $this->single_button($fetchurl, get_string('checkforupdates', 'core_plugin'));
if ($fetch) {
@@ -840,82 +780,19 @@ class core_admin_renderer extends plugin_renderer_base {
*/
protected function registration_warning($registered) {
if (!$registered && site_is_public()) {
if (has_capability('moodle/site:config', context_system::instance())) {
$registerbutton = $this->single_button(new moodle_url('/admin/registration/index.php'),
get_string('register', 'admin'));
$str = 'registrationwarning';
} else {
$registerbutton = '';
$str = 'registrationwarningcontactadmin';
}
if (!$registered) {
return $this->warning( get_string($str, 'admin')
. '&nbsp;' . $this->help_icon('registration', 'admin') . $registerbutton ,
'error alert alert-danger');
$registerbutton = $this->single_button(new moodle_url('/admin/registration/register.php',
array('huburl' => HUB_MOODLEORGHUBURL, 'hubname' => 'Moodle.org')),
get_string('register', 'admin'));
return $this->warning( get_string('registrationwarning', 'admin')
. '&nbsp;' . $this->help_icon('registration', 'admin') . $registerbutton );
}
return '';
}
/**
* Return an admin page warning if site is not registered with moodle.org
*
* @return string
*/
public function warn_if_not_registered() {
return $this->registration_warning(\core\hub\registration::is_registered());
}
/**
* Display a warning about the Mobile Web Services being disabled.
*
* @param boolean $mobileconfigured true if mobile web services are enabled
* @return string HTML to output.
*/
protected function mobile_configuration_warning($mobileconfigured) {
$output = '';
if (!$mobileconfigured) {
$settingslink = new moodle_url('/admin/settings.php', ['section' => 'mobilesettings']);
$configurebutton = $this->single_button($settingslink, get_string('enablemobilewebservice', 'admin'));
$output .= $this->warning(get_string('mobilenotconfiguredwarning', 'admin') . '&nbsp;' . $configurebutton);
}
return $output;
}
/**
* Display campaign content.
*
* @param bool $showcampaigncontent Whether the campaign content should be visible or not.
* @return string the campaign content raw html.
*/
protected function campaign_content(bool $showcampaigncontent): string {
if (!$showcampaigncontent) {
return '';
}
return $this->render_from_template('core/campaign_content', ['lang' => current_language()]);
}
/**
* Display a warning about the forgotten password URL not linking to a valid URL.
*
* @param boolean $invalidforgottenpasswordurl true if the forgotten password URL is not valid
* @return string HTML to output.
*/
protected function forgotten_password_url_warning($invalidforgottenpasswordurl) {
$output = '';
if ($invalidforgottenpasswordurl) {
$settingslink = new moodle_url('/admin/settings.php', ['section' => 'manageauths']);
$configurebutton = $this->single_button($settingslink, get_string('check', 'moodle'));
$output .= $this->warning(get_string('invalidforgottenpasswordurl', 'admin') . '&nbsp;' . $configurebutton,
'error alert alert-danger');
}
return $output;
}
/**
* Helper method to render the information about the available Moodle update
*
@@ -923,7 +800,7 @@ class core_admin_renderer extends plugin_renderer_base {
*/
protected function moodle_available_update_info(\core\update\info $updateinfo) {
$boxclasses = 'moodleupdateinfo mb-2';
$boxclasses = 'moodleupdateinfo';
$info = array();
if (isset($updateinfo->release)) {
@@ -943,8 +820,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
if (isset($updateinfo->download)) {
$info[] = html_writer::link($updateinfo->download, get_string('download'),
array('class' => 'info download btn btn-secondary'));
$info[] = html_writer::link($updateinfo->download, get_string('download'), array('class' => 'info download'));
}
if (isset($updateinfo->url)) {
@@ -952,9 +828,9 @@ class core_admin_renderer extends plugin_renderer_base {
array('class' => 'info more'));
}
$box = $this->output->container_start($boxclasses);
$box .= $this->output->container(implode(html_writer::tag('span', ' | ', array('class' => 'separator')), $info), '');
$box .= $this->output->container_end();
$box = $this->output->box_start($boxclasses);
$box .= $this->output->box(implode(html_writer::tag('span', ' ', array('class' => 'separator')), $info), '');
$box .= $this->output->box_end();
return $box;
}
@@ -966,7 +842,7 @@ class core_admin_renderer extends plugin_renderer_base {
protected function release_notes_link() {
$releasenoteslink = get_string('releasenoteslink', 'admin', 'http://docs.moodle.org/dev/Releases');
$releasenoteslink = str_replace('target="_blank"', 'onclick="this.target=\'_blank\'"', $releasenoteslink); // extremely ugly validation hack
return $this->box($releasenoteslink, 'generalbox alert alert-info');
return $this->box($releasenoteslink, 'generalbox releasenoteslink');
}
/**
@@ -995,7 +871,7 @@ class core_admin_renderer extends plugin_renderer_base {
* @return string HTML code
*/
public function plugins_check_table(core_plugin_manager $pluginman, $version, array $options = array()) {
global $CFG;
$plugininfo = $pluginman->get_plugins();
if (empty($plugininfo)) {
@@ -1066,7 +942,7 @@ class core_admin_renderer extends plugin_renderer_base {
$displayname = new html_table_cell(
$icon.
html_writer::span($plugin->displayname, 'pluginname').
html_writer::div($plugin->get_dir(), 'plugindir text-muted small')
html_writer::div($plugin->get_dir(), 'plugindir')
);
$versiondb = new html_table_cell($plugin->versiondb);
@@ -1074,46 +950,44 @@ class core_admin_renderer extends plugin_renderer_base {
if ($isstandard = $plugin->is_standard()) {
$row->attributes['class'] .= ' standard';
$sourcelabel = html_writer::span(get_string('sourcestd', 'core_plugin'), 'sourcetext badge badge-secondary');
$sourcelabel = html_writer::span(get_string('sourcestd', 'core_plugin'), 'sourcetext label');
} else {
$row->attributes['class'] .= ' extension';
$sourcelabel = html_writer::span(get_string('sourceext', 'core_plugin'), 'sourcetext badge badge-info');
$sourcelabel = html_writer::span(get_string('sourceext', 'core_plugin'), 'sourcetext label label-info');
}
$coredependency = $plugin->is_core_dependency_satisfied($version);
$incompatibledependency = $plugin->is_core_compatible_satisfied($CFG->branch);
$otherpluginsdependencies = $pluginman->are_dependencies_satisfied($plugin->get_other_required_plugins());
$dependenciesok = $coredependency && $otherpluginsdependencies && $incompatibledependency;
$dependenciesok = $coredependency && $otherpluginsdependencies;
$statuscode = $plugin->get_status();
$row->attributes['class'] .= ' status-' . $statuscode;
$statusclass = 'statustext badge ';
$statusclass = 'statustext label ';
switch ($statuscode) {
case core_plugin_manager::PLUGIN_STATUS_NEW:
$statusclass .= $dependenciesok ? 'badge-success' : 'badge-warning';
$statusclass .= $dependenciesok ? 'label-success' : 'label-warning';
break;
case core_plugin_manager::PLUGIN_STATUS_UPGRADE:
$statusclass .= $dependenciesok ? 'badge-info' : 'badge-warning';
$statusclass .= $dependenciesok ? 'label-info' : 'label-warning';
break;
case core_plugin_manager::PLUGIN_STATUS_MISSING:
case core_plugin_manager::PLUGIN_STATUS_DOWNGRADE:
case core_plugin_manager::PLUGIN_STATUS_DELETE:
$statusclass .= 'badge-danger';
$statusclass .= 'label-important';
break;
case core_plugin_manager::PLUGIN_STATUS_NODB:
case core_plugin_manager::PLUGIN_STATUS_UPTODATE:
$statusclass .= $dependenciesok ? 'badge-light' : 'badge-warning';
$statusclass .= $dependenciesok ? '' : 'label-warning';
break;
}
$status = html_writer::span(get_string('status_' . $statuscode, 'core_plugin'), $statusclass);
if (!empty($installabortable[$plugin->component])) {
$status .= $this->output->single_button(
new moodle_url($this->page->url, array('abortinstall' => $plugin->component, 'confirmplugincheck' => 0)),
new moodle_url($this->page->url, array('abortinstall' => $plugin->component)),
get_string('cancelinstallone', 'core_plugin'),
'post',
array('class' => 'actionbutton cancelinstallone d-block mt-1')
array('class' => 'actionbutton cancelinstallone')
);
}
@@ -1122,7 +996,7 @@ class core_admin_renderer extends plugin_renderer_base {
new moodle_url($this->page->url, array('abortupgrade' => $plugin->component)),
get_string('cancelupgradeone', 'core_plugin'),
'post',
array('class' => 'actionbutton cancelupgradeone d-block mt-1')
array('class' => 'actionbutton cancelupgradeone')
);
}
@@ -1134,11 +1008,8 @@ class core_admin_renderer extends plugin_renderer_base {
}
$status = new html_table_cell($sourcelabel.' '.$status);
if ($plugin->pluginsupported != null) {
$requires = new html_table_cell($this->required_column($plugin, $pluginman, $version, $CFG->branch));
} else {
$requires = new html_table_cell($this->required_column($plugin, $pluginman, $version));
}
$requires = new html_table_cell($this->required_column($plugin, $pluginman, $version));
$statusisboring = in_array($statuscode, array(
core_plugin_manager::PLUGIN_STATUS_NODB, core_plugin_manager::PLUGIN_STATUS_UPTODATE));
@@ -1195,7 +1066,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
}
$out .= $this->output->container_start('actions mb-2');
$out .= $this->output->container_start('actions');
$installableupdates = $pluginman->filter_installable($pluginman->available_updates());
if ($installableupdates) {
@@ -1203,16 +1074,16 @@ class core_admin_renderer extends plugin_renderer_base {
new moodle_url($this->page->url, array('installupdatex' => 1)),
get_string('updateavailableinstallall', 'core_admin', count($installableupdates)),
'post',
array('class' => 'singlebutton updateavailableinstallall mr-1')
array('class' => 'singlebutton updateavailableinstallall')
);
}
if ($installabortable) {
$out .= $this->output->single_button(
new moodle_url($this->page->url, array('abortinstallx' => 1, 'confirmplugincheck' => 0)),
new moodle_url($this->page->url, array('abortinstallx' => 1)),
get_string('cancelinstallall', 'core_plugin', count($installabortable)),
'post',
array('class' => 'singlebutton cancelinstallall mr-1')
array('class' => 'singlebutton cancelinstallall')
);
}
@@ -1221,17 +1092,15 @@ class core_admin_renderer extends plugin_renderer_base {
new moodle_url($this->page->url, array('abortupgradex' => 1)),
get_string('cancelupgradeall', 'core_plugin', count($upgradeabortable)),
'post',
array('class' => 'singlebutton cancelupgradeall mr-1')
array('class' => 'singlebutton cancelupgradeall')
);
}
$out .= html_writer::div(html_writer::link(new moodle_url($this->page->url, array('showallplugins' => 0)),
get_string('plugincheckattention', 'core_plugin')).' '.html_writer::span($sumattention, 'badge badge-light'),
'btn btn-link mr-1');
get_string('plugincheckattention', 'core_plugin')).' '.html_writer::span($sumattention, 'badge'));
$out .= html_writer::div(html_writer::link(new moodle_url($this->page->url, array('showallplugins' => 1)),
get_string('plugincheckall', 'core_plugin')).' '.html_writer::span($sumtotal, 'badge badge-light'),
'btn btn-link mr-1');
get_string('plugincheckall', 'core_plugin')).' '.html_writer::span($sumtotal, 'badge'));
$out .= $this->output->container_end(); // End of .actions container.
$out .= $this->output->container_end(); // End of #plugins-check-info container.
@@ -1299,13 +1168,12 @@ class core_admin_renderer extends plugin_renderer_base {
}
}
$out = $this->output->container_start('plugins-check-dependencies mb-4');
$out = $this->output->container_start('plugins-check-dependencies');
if ($unavailable or $unknown) {
$out .= $this->output->heading(get_string('misdepsunavail', 'core_plugin'));
if ($unknown) {
$out .= $this->output->render((new \core\output\notification(get_string('misdepsunknownlist', 'core_plugin',
implode(', ', $unknown))))->set_show_closebutton(false));
$out .= $this->output->notification(get_string('misdepsunknownlist', 'core_plugin', implode($unknown, ', ')));
}
if ($unavailable) {
$unavailablelist = array();
@@ -1319,18 +1187,18 @@ class core_admin_renderer extends plugin_renderer_base {
}
$unavailablelist[] = $unavailablelistitem;
}
$out .= $this->output->render((new \core\output\notification(get_string('misdepsunavaillist', 'core_plugin',
implode(', ', $unavailablelist))))->set_show_closebutton(false));
$out .= $this->output->notification(get_string('misdepsunavaillist', 'core_plugin',
implode($unavailablelist, ', ')));
}
$out .= $this->output->container_start('plugins-check-dependencies-actions mb-4');
$out .= $this->output->container_start('plugins-check-dependencies-actions');
$out .= ' '.html_writer::link(new moodle_url('/admin/tool/installaddon/'),
get_string('dependencyuploadmissing', 'core_plugin'), array('class' => 'btn btn-secondary'));
get_string('dependencyuploadmissing', 'core_plugin'));
$out .= $this->output->container_end(); // End of .plugins-check-dependencies-actions container.
}
if ($available) {
$out .= $this->output->heading(get_string('misdepsavail', 'core_plugin'));
$out .= $this->output->container_start('plugins-check-dependencies-actions mb-2');
$out .= $this->output->container_start('plugins-check-dependencies-actions');
$installable = $pluginman->filter_installable($available);
if ($installable) {
@@ -1338,13 +1206,12 @@ class core_admin_renderer extends plugin_renderer_base {
new moodle_url($this->page->url, array('installdepx' => 1)),
get_string('dependencyinstallmissing', 'core_plugin', count($installable)),
'post',
array('class' => 'singlebutton dependencyinstallmissing d-inline-block mr-1')
array('class' => 'singlebutton dependencyinstallmissing')
);
}
$out .= html_writer::div(html_writer::link(new moodle_url('/admin/tool/installaddon/'),
get_string('dependencyuploadmissing', 'core_plugin'), array('class' => 'btn btn-link')),
'dependencyuploadmissing d-inline-block mr-1');
get_string('dependencyuploadmissing', 'core_plugin')), 'dependencyuploadmissing');
$out .= $this->output->container_end(); // End of .plugins-check-dependencies-actions container.
@@ -1383,9 +1250,9 @@ class core_admin_renderer extends plugin_renderer_base {
$supportedmoodles = array();
foreach ($plugin->version->supportedmoodles as $moodle) {
if ($CFG->branch == str_replace('.', '', $moodle->release)) {
$supportedmoodles[] = html_writer::span($moodle->release, 'badge badge-success');
$supportedmoodles[] = html_writer::span($moodle->release, 'label label-success');
} else {
$supportedmoodles[] = html_writer::span($moodle->release, 'badge badge-light');
$supportedmoodles[] = html_writer::span($moodle->release, 'label');
}
}
@@ -1399,7 +1266,7 @@ class core_admin_renderer extends plugin_renderer_base {
}
$info = html_writer::div(
get_string('requiredby', 'core_plugin', implode(', ', $requriedby)),
'requiredby mb-1'
'requiredby'
);
} else {
$info = '';
@@ -1410,39 +1277,38 @@ class core_admin_renderer extends plugin_renderer_base {
$info .= html_writer::div(
html_writer::link('https://moodle.org/plugins/view.php?plugin='.$plugin->component,
get_string('misdepinfoplugin', 'core_plugin')),
'misdepinfoplugin d-inline-block mr-3 mb-1'
'misdepinfoplugin'
);
$info .= html_writer::div(
html_writer::link('https://moodle.org/plugins/pluginversion.php?id='.$plugin->version->id,
get_string('misdepinfoversion', 'core_plugin')),
'misdepinfoversion d-inline-block mr-3 mb-1'
'misdepinfoversion'
);
$info .= html_writer::div(html_writer::link($plugin->version->downloadurl, get_string('download')),
'misdepdownload d-inline-block mr-3 mb-1');
$info .= html_writer::div(html_writer::link($plugin->version->downloadurl, get_string('download')), 'misdepdownload');
if ($pluginman->is_remote_plugin_installable($plugin->component, $plugin->version->version, $reason)) {
$info .= $this->output->single_button(
new moodle_url($this->page->url, array('installdep' => $plugin->component)),
get_string('dependencyinstall', 'core_plugin'),
'post',
array('class' => 'singlebutton dependencyinstall mr-3 mb-1')
array('class' => 'singlebutton dependencyinstall')
);
} else {
$reasonhelp = $this->info_remote_plugin_not_installable($reason);
if ($reasonhelp) {
$info .= html_writer::div($reasonhelp, 'reasonhelp dependencyinstall d-inline-block mr-3 mb-1');
$info .= html_writer::div($reasonhelp, 'reasonhelp dependencyinstall');
}
}
$info .= $this->output->container_end(); // End of .actions container.
$table->data[] = array(
html_writer::div($plugin->name, 'name').' '.html_writer::div($plugin->component, 'component text-muted small'),
html_writer::div($plugin->name, 'name').' '.html_writer::div($plugin->component, 'component'),
$plugin->version->release,
$plugin->version->version,
implode(' ', $supportedmoodles),
implode($supportedmoodles, ' '),
$info
);
}
@@ -1474,54 +1340,38 @@ class core_admin_renderer extends plugin_renderer_base {
* @param \core\plugininfo\base $plugin the plugin we are rendering the row for.
* @param core_plugin_manager $pluginman provides data on all the plugins.
* @param string $version
* @param int $branch the current Moodle branch
* @return string HTML code
*/
protected function required_column(\core\plugininfo\base $plugin, core_plugin_manager $pluginman, $version, $branch = null) {
protected function required_column(\core\plugininfo\base $plugin, core_plugin_manager $pluginman, $version) {
$requires = array();
$displayuploadlink = false;
$displayupdateslink = false;
$requirements = $pluginman->resolve_requirements($plugin, $version, $branch);
foreach ($requirements as $reqname => $reqinfo) {
foreach ($pluginman->resolve_requirements($plugin, $version) as $reqname => $reqinfo) {
if ($reqname === 'core') {
if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_OK) {
$class = 'requires-ok text-muted';
$class = 'requires-ok';
$label = '';
} else {
$class = 'requires-failed';
$label = html_writer::span(get_string('dependencyfails', 'core_plugin'), 'badge badge-danger');
$label = html_writer::span(get_string('dependencyfails', 'core_plugin'), 'label label-important');
}
if ($branch != null && !$plugin->is_core_compatible_satisfied($branch)) {
$requires[] = html_writer::tag('li',
html_writer::span(get_string('incompatibleversion', 'core_plugin', $branch), 'dep dep-core').
$requires[] = html_writer::tag('li',
html_writer::span(get_string('moodleversion', 'core_plugin', $plugin->versionrequires), 'dep dep-core').
' '.$label, array('class' => $class));
} else if ($branch != null && $plugin->pluginsupported != null) {
$requires[] = html_writer::tag('li',
html_writer::span(get_string('moodlebranch', 'core_plugin',
array('min' => $plugin->pluginsupported[0], 'max' => $plugin->pluginsupported[1])), 'dep dep-core').
' '.$label, array('class' => $class));
} else if ($reqinfo->reqver != ANY_VERSION) {
$requires[] = html_writer::tag('li',
html_writer::span(get_string('moodleversion', 'core_plugin', $plugin->versionrequires), 'dep dep-core').
' '.$label, array('class' => $class));
}
} else {
$actions = array();
if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_OK) {
$label = '';
$class = 'requires-ok text-muted';
$class = 'requires-ok';
} else if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_MISSING) {
if ($reqinfo->availability == $pluginman::REQUIREMENT_AVAILABLE) {
$label = html_writer::span(get_string('dependencymissing', 'core_plugin'), 'badge badge-warning');
$label .= ' '.html_writer::span(get_string('dependencyavailable', 'core_plugin'), 'badge badge-warning');
$label = html_writer::span(get_string('dependencymissing', 'core_plugin'), 'label label-warning');
$label .= ' '.html_writer::span(get_string('dependencyavailable', 'core_plugin'), 'label label-warning');
$class = 'requires-failed requires-missing requires-available';
$actions[] = html_writer::link(
new moodle_url('https://moodle.org/plugins/view.php', array('plugin' => $reqname)),
@@ -1529,24 +1379,24 @@ class core_admin_renderer extends plugin_renderer_base {
);
} else {
$label = html_writer::span(get_string('dependencymissing', 'core_plugin'), 'badge badge-danger');
$label = html_writer::span(get_string('dependencymissing', 'core_plugin'), 'label label-important');
$label .= ' '.html_writer::span(get_string('dependencyunavailable', 'core_plugin'),
'badge badge-danger');
'label label-important');
$class = 'requires-failed requires-missing requires-unavailable';
}
$displayuploadlink = true;
} else if ($reqinfo->status == $pluginman::REQUIREMENT_STATUS_OUTDATED) {
if ($reqinfo->availability == $pluginman::REQUIREMENT_AVAILABLE) {
$label = html_writer::span(get_string('dependencyfails', 'core_plugin'), 'badge badge-warning');
$label .= ' '.html_writer::span(get_string('dependencyavailable', 'core_plugin'), 'badge badge-warning');
$label = html_writer::span(get_string('dependencyfails', 'core_plugin'), 'label label-warning');
$label .= ' '.html_writer::span(get_string('dependencyavailable', 'core_plugin'), 'label label-warning');
$class = 'requires-failed requires-outdated requires-available';
$displayupdateslink = true;
} else {
$label = html_writer::span(get_string('dependencyfails', 'core_plugin'), 'badge badge-danger');
$label = html_writer::span(get_string('dependencyfails', 'core_plugin'), 'label label-important');
$label .= ' '.html_writer::span(get_string('dependencyunavailable', 'core_plugin'),
'badge badge-danger');
'label label-important');
$class = 'requires-failed requires-outdated requires-unavailable';
}
$displayuploadlink = true;
@@ -1570,14 +1420,13 @@ class core_admin_renderer extends plugin_renderer_base {
return '';
}
$out = html_writer::tag('ul', implode("\n", $requires), array('class' => 'm-0'));
$out = html_writer::tag('ul', implode("\n", $requires));
if ($displayuploadlink) {
$out .= html_writer::div(
html_writer::link(
new moodle_url('/admin/tool/installaddon/'),
get_string('dependencyuploadmissing', 'core_plugin'),
array('class' => 'btn btn-secondary btn-sm m-1')
get_string('dependencyuploadmissing', 'core_plugin')
),
'dependencyuploadmissing'
);
@@ -1587,20 +1436,12 @@ class core_admin_renderer extends plugin_renderer_base {
$out .= html_writer::div(
html_writer::link(
new moodle_url($this->page->url, array('sesskey' => sesskey(), 'fetchupdates' => 1)),
get_string('checkforupdates', 'core_plugin'),
array('class' => 'btn btn-secondary btn-sm m-1')
get_string('checkforupdates', 'core_plugin')
),
'checkforupdates'
);
}
// Check if supports is present, and $branch is not in, only if $incompatible check was ok.
if ($plugin->pluginsupported != null && $class == 'requires-ok' && $branch != null) {
if ($pluginman->check_explicitly_supported($plugin, $branch) == $pluginman::VERSION_NOT_SUPPORTED) {
$out .= html_writer::div(get_string('notsupported', 'core_plugin', $branch));
}
}
return $out;
}
@@ -1771,10 +1612,10 @@ class core_admin_renderer extends plugin_renderer_base {
$row = new html_table_row();
$row->attributes['class'] = 'type-' . $plugin->type . ' name-' . $plugin->type . '_' . $plugin->name;
if ($this->page->theme->resolve_image_location('icon', $plugin->type . '_' . $plugin->name, null)) {
if ($this->page->theme->resolve_image_location('icon', $plugin->type . '_' . $plugin->name)) {
$icon = $this->output->pix_icon('icon', '', $plugin->type . '_' . $plugin->name, array('class' => 'icon pluginicon'));
} else {
$icon = $this->output->spacer();
$icon = $this->output->pix_icon('spacer', '', 'moodle', array('class' => 'icon pluginicon noicon'));
}
$status = $plugin->get_status();
$row->attributes['class'] .= ' status-'.$status;
@@ -1819,13 +1660,13 @@ class core_admin_renderer extends plugin_renderer_base {
$source = '';
} else {
$row->attributes['class'] .= ' extension';
$source = html_writer::div(get_string('sourceext', 'core_plugin'), 'source badge badge-info');
$source = html_writer::div(get_string('sourceext', 'core_plugin'), 'source label label-info');
}
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
$msg = html_writer::div(get_string('status_missing', 'core_plugin'), 'statusmsg badge badge-danger');
$msg = html_writer::div(get_string('status_missing', 'core_plugin'), 'statusmsg label label-important');
} else if ($status === core_plugin_manager::PLUGIN_STATUS_NEW) {
$msg = html_writer::div(get_string('status_new', 'core_plugin'), 'statusmsg badge badge-success');
$msg = html_writer::div(get_string('status_new', 'core_plugin'), 'statusmsg label label-success');
} else {
$msg = '';
}
@@ -1947,7 +1788,7 @@ class core_admin_renderer extends plugin_renderer_base {
get_string('status'),
);
$servertable->colclasses = array('centeralign name', 'centeralign info', 'leftalign report', 'leftalign plugin', 'centeralign status');
$servertable->attributes['class'] = 'admintable environmenttable generaltable table-sm';
$servertable->attributes['class'] = 'admintable environmenttable generaltable';
$servertable->id = 'serverstatus';
$serverdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
@@ -1960,7 +1801,7 @@ class core_admin_renderer extends plugin_renderer_base {
get_string('status'),
);
$othertable->colclasses = array('aligncenter info', 'alignleft report', 'alignleft plugin', 'aligncenter status');
$othertable->attributes['class'] = 'admintable environmenttable generaltable table-sm';
$othertable->attributes['class'] = 'admintable environmenttable generaltable';
$othertable->id = 'otherserverstatus';
$otherdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
@@ -2056,7 +1897,7 @@ class core_admin_renderer extends plugin_renderer_base {
if (empty($CFG->docroot) or $environment_result->plugin) {
$report = get_string($stringtouse, 'admin', $rec);
} else {
$report = $this->doc_link(join('/', $linkparts), get_string($stringtouse, 'admin', $rec), true);
$report = $this->doc_link(join($linkparts, '/'), get_string($stringtouse, 'admin', $rec));
}
// Enclose report text in div so feedback text will be displayed underneath it.
$report = html_writer::div($report);
@@ -2064,15 +1905,15 @@ class core_admin_renderer extends plugin_renderer_base {
// Format error or warning line
if ($errorline) {
$messagetype = 'error';
$statusclass = 'badge-danger';
$statusclass = 'label-important';
} else if ($warningline) {
$messagetype = 'warn';
$statusclass = 'badge-warning';
$statusclass = 'label-warning';
} else {
$messagetype = 'ok';
$statusclass = 'badge-success';
$statusclass = 'label-success';
}
$status = html_writer::span($status, 'badge ' . $statusclass);
$status = html_writer::span($status, 'label ' . $statusclass);
// Here we'll store all the feedback found
$feedbacktext = '';
// Append the feedback if there is some
@@ -2150,51 +1991,4 @@ class core_admin_renderer extends plugin_renderer_base {
return $this->warning(get_string('legacylogginginuse'));
}
}
/**
* Display message about the benefits of registering on Moodle.org
*
* @return string
*/
public function moodleorg_registration_message() {
$out = format_text(get_string('registerwithmoodleorginfo', 'core_hub'), FORMAT_MARKDOWN);
$out .= html_writer::link(
new moodle_url('/admin/settings.php', ['section' => 'moodleservices']),
$this->output->pix_icon('i/info', '').' '.get_string('registerwithmoodleorginfoapp', 'core_hub'),
['class' => 'btn btn-link', 'role' => 'opener', 'target' => '_href']
);
$out .= html_writer::link(
HUB_MOODLEORGHUBURL,
$this->output->pix_icon('i/stats', '').' '.get_string('registerwithmoodleorginfostats', 'core_hub'),
['class' => 'btn btn-link', 'role' => 'opener', 'target' => '_href']
);
$out .= html_writer::link(
HUB_MOODLEORGHUBURL.'/sites',
$this->output->pix_icon('i/location', '').' '.get_string('registerwithmoodleorginfosites', 'core_hub'),
['class' => 'btn btn-link', 'role' => 'opener', 'target' => '_href']
);
return $this->output->box($out);
}
/**
* Display message about benefits of enabling the user feedback feature.
*
* @param bool $showfeedbackencouragement Whether the encouragement content should be displayed or not
* @return string
*/
protected function userfeedback_encouragement(bool $showfeedbackencouragement): string {
$output = '';
if ($showfeedbackencouragement) {
$settingslink = new moodle_url('/admin/settings.php', ['section' => 'userfeedback']);
$output .= $this->warning(get_string('userfeedbackencouragement', 'admin', $settingslink->out()), 'info');
}
return $output;
}
}
+5 -4
View File
@@ -47,6 +47,7 @@ if ($action == 'newon') {
$visible = false;
}
require_capability('moodle/site:config', context_system::instance());
admin_externalpage_setup($pagename);
$sesskeyurl = $CFG->wwwroot.'/'.$CFG->admin.'/repository.php?sesskey=' . sesskey();
@@ -123,13 +124,13 @@ if (($action == 'edit') || ($action == 'new')) {
}
$instanceoptionnames = repository::static_function($repository, 'get_instance_option_names');
if (!empty($instanceoptionnames)) {
if (property_exists($fromform, 'enablecourseinstances')) {
if (array_key_exists('enablecourseinstances', $fromform)) {
$settings['enablecourseinstances'] = $fromform->enablecourseinstances;
}
else {
$settings['enablecourseinstances'] = 0;
}
if (property_exists($fromform, 'enableuserinstances')) {
if (array_key_exists('enableuserinstances', $fromform)) {
$settings['enableuserinstances'] = $fromform->enableuserinstances;
}
else {
@@ -369,14 +370,14 @@ if (($action == 'edit') || ($action == 'new')) {
if ($updowncount > 1) {
$updown .= "<a href=\"$sesskeyurl&amp;action=moveup&amp;repos=".$typename."\">";
$updown .= $OUTPUT->pix_icon('t/up', get_string('moveup')) . "</a>&nbsp;";
$updown .= "<img src=\"" . $OUTPUT->pix_url('t/up') . "\" alt=\"up\" /></a>&nbsp;";
}
else {
$updown .= $spacer;
}
if ($updowncount < $totalrepositorytypes) {
$updown .= "<a href=\"$sesskeyurl&amp;action=movedown&amp;repos=".$typename."\">";
$updown .= $OUTPUT->pix_icon('t/down', get_string('movedown')) . "</a>&nbsp;";
$updown .= "<img src=\"" . $OUTPUT->pix_url('t/down') . "\" alt=\"down\" /></a>";
}
else {
$updown .= $spacer;
+1
View File
@@ -42,6 +42,7 @@ if ($edit){
}
admin_externalpage_setup($pagename, '', null, new moodle_url('/admin/repositoryinstance.php'));
require_capability('moodle/site:config', $context);
$baseurl = new moodle_url("/$CFG->admin/repositoryinstance.php", array('sesskey'=>sesskey()));
+5 -25
View File
@@ -36,12 +36,15 @@ if (!is_siteadmin()) {
}
$admisselector = new core_role_admins_existing_selector();
$admisselector->set_extra_fields(array('username', 'email'));
$potentialadmisselector = new core_role_admins_potential_selector();
$potentialadmisselector->set_extra_fields(array('username', 'email'));
if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
if ($userstoadd = $potentialadmisselector->get_selected_users()) {
$user = reset($userstoadd);
$username = $potentialadmisselector->output_user($user);
$username = fullname($user) . " ($user->username, $user->email)";
echo $OUTPUT->header();
$yesurl = new moodle_url('/admin/roles/admins.php', array('confirmadd'=>$user->id, 'sesskey'=>sesskey()));
echo $OUTPUT->confirm(get_string('confirmaddadmin', 'core_role', $username), $yesurl, $PAGE->url);
@@ -55,7 +58,7 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
if ($USER->id == $user->id) {
// Can not remove self.
} else {
$username = $admisselector->output_user($user);
$username = fullname($user) . " ($user->username, $user->email)";
echo $OUTPUT->header();
$yesurl = new moodle_url('/admin/roles/admins.php', array('confirmdel'=>$user->id, 'sesskey'=>sesskey()));
echo $OUTPUT->confirm(get_string('confirmdeladmin', 'core_role', $username), $yesurl, $PAGE->url);
@@ -77,16 +80,9 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
}
if (isset($admins[$newmain])) {
$logstringold = implode(', ', $admins);
unset($admins[$newmain]);
array_unshift($admins, $newmain);
$logstringnew = implode(', ', $admins);
set_config('siteadmins', implode(',', $admins));
add_to_config_log('siteadmins', $logstringold, $logstringnew, null);
redirect($PAGE->url);
}
}
@@ -99,16 +95,8 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
$admins[$admin] = $admin;
}
}
$logstringold = implode(', ', $admins);
$admins[$confirmadd] = $confirmadd;
$logstringnew = implode(', ', $admins);
set_config('siteadmins', implode(',', $admins));
add_to_config_log('siteadmins', $logstringold, $logstringnew, 'core');
redirect($PAGE->url);
} else if ($confirmdel and confirm_sesskey() and $confirmdel != $USER->id) {
@@ -119,16 +107,8 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
$admins[$admin] = $admin;
}
}
$logstringold = implode(', ', $admins);
unset($admins[$confirmdel]);
$logstringnew = implode(', ', $admins);
set_config('siteadmins', implode(',', $admins));
add_to_config_log('siteadmins', $logstringold, $logstringnew, 'core');
redirect($PAGE->url);
}
+18 -2
View File
@@ -29,8 +29,7 @@ $mode = required_param('mode', PARAM_ALPHANUMEXT);
$classformode = array(
'assign' => 'core_role_allow_assign_page',
'override' => 'core_role_allow_override_page',
'switch' => 'core_role_allow_switch_page',
'view' => 'core_role_allow_view_page'
'switch' => 'core_role_allow_switch_page'
);
if (!isset($classformode[$mode])) {
print_error('invalidmode', '', '', $mode);
@@ -46,6 +45,23 @@ $controller = new $classformode[$mode]();
if (optional_param('submit', false, PARAM_BOOL) && data_submitted() && confirm_sesskey()) {
$controller->process_submission();
$syscontext->mark_dirty();
$event = null;
// Create event depending on mode.
switch ($mode) {
case 'assign':
$event = \core\event\role_allow_assign_updated::create(array('context' => $syscontext));
break;
case 'override':
$event = \core\event\role_allow_override_updated::create(array('context' => $syscontext));
break;
case 'switch':
$event = \core\event\role_allow_switch_updated::create(array('context' => $syscontext));
break;
}
if ($event) {
$event->trigger();
}
redirect($baseurl);
}
+1 -1
View File
@@ -245,7 +245,7 @@ if ($roleid) {
$select = new single_select($PAGE->url, 'roleid', $nameswithcounts, $roleid, null);
$select->label = get_string('assignanotherrole', 'core_role');
echo $OUTPUT->render($select);
echo '<p><a href="' . $url . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
echo '<p><a href="' . $PAGE->url . '">' . get_string('backtoallroles', 'core_role') . '</a></p>';
echo '</div>';
} else if (empty($assignableroles)) {
+1 -5
View File
@@ -33,7 +33,7 @@ class core_role_allow_assign_page extends core_role_allow_role_page {
}
protected function set_allow($fromroleid, $targetroleid) {
core_role_set_assign_allowed($fromroleid, $targetroleid);
allow_assign($fromroleid, $targetroleid);
}
protected function get_cell_tooltip($fromrole, $targetrole) {
@@ -46,8 +46,4 @@ class core_role_allow_assign_page extends core_role_allow_role_page {
public function get_intro_text() {
return get_string('configallowassign', 'core_admin');
}
protected function get_eventclass() {
return \core\event\role_allow_assign_updated::class;
}
}
+1 -5
View File
@@ -33,7 +33,7 @@ class core_role_allow_override_page extends core_role_allow_role_page {
}
protected function set_allow($fromroleid, $targetroleid) {
core_role_set_override_allowed($fromroleid, $targetroleid);
allow_override($fromroleid, $targetroleid);
}
protected function get_cell_tooltip($fromrole, $targetrole) {
@@ -46,8 +46,4 @@ class core_role_allow_override_page extends core_role_allow_role_page {
public function get_intro_text() {
return get_string('configallowoverride2', 'core_admin');
}
protected function get_eventclass() {
return \core\event\role_allow_override_updated::class;
}
}
-30
View File
@@ -59,36 +59,12 @@ abstract class core_role_allow_role_page {
*/
public function process_submission() {
global $DB;
$context = context_system::instance();
$this->load_current_settings();
// Delete all records, then add back the ones that should be allowed.
$DB->delete_records($this->tablename);
foreach ($this->roles as $fromroleid => $notused) {
foreach ($this->roles as $targetroleid => $alsonotused) {
$isallowed = $this->allowed[$fromroleid][$targetroleid];
if (optional_param('s_' . $fromroleid . '_' . $targetroleid, false, PARAM_BOOL)) {
$this->set_allow($fromroleid, $targetroleid);
// Only trigger events if this role allow relationship did not exist and the checkbox element
// has been submitted.
if (!$isallowed) {
$eventclass = $this->get_eventclass();
$eventclass::create([
'context' => $context,
'objectid' => $fromroleid,
'other' => ['targetroleid' => $targetroleid, 'allow' => true]
])->trigger();
}
} else if ($isallowed) {
// When the user has deselect an existing role allow checkbox but it is in the list of roles
// allowances.
$eventclass = $this->get_eventclass();
$eventclass::create([
'context' => $context,
'objectid' => $fromroleid,
'other' => ['targetroleid' => $targetroleid, 'allow' => false]
])->trigger();
}
}
}
@@ -185,10 +161,4 @@ abstract class core_role_allow_role_page {
* @return string
*/
public abstract function get_intro_text();
/**
* Returns the allow class respective event class name.
* @return string
*/
protected abstract function get_eventclass();
}
+1 -5
View File
@@ -41,7 +41,7 @@ class core_role_allow_switch_page extends core_role_allow_role_page {
}
protected function set_allow($fromroleid, $targetroleid) {
core_role_set_switch_allowed($fromroleid, $targetroleid);
allow_switch($fromroleid, $targetroleid);
}
protected function is_allowed_target($targetroleid) {
@@ -58,8 +58,4 @@ class core_role_allow_switch_page extends core_role_allow_role_page {
public function get_intro_text() {
return get_string('configallowswitch', 'core_admin');
}
protected function get_eventclass() {
return \core\event\role_allow_switch_updated::class;
}
}
-81
View File
@@ -1,81 +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/>.
/**
* Role view matrix.
*
* @package core_role
* @copyright 2016 onwards Andrew Hancox <andrewdchancox@googlemail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Subclass of role_allow_role_page for the Allow views tab.
*
* @package core_role
* @copyright 2016 onwards Andrew Hancox <andrewdchancox@googlemail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_role_allow_view_page extends core_role_allow_role_page {
/** @var array */
protected $allowedtargetroles;
/**
* core_role_allow_view_page constructor.
*/
public function __construct() {
parent::__construct('role_allow_view', 'allowview');
}
/**
* Allow from role to view target role.
* @param int $fromroleid
* @param int $targetroleid
*/
protected function set_allow($fromroleid, $targetroleid) {
core_role_set_view_allowed($fromroleid, $targetroleid);
}
/**
* Get tool tip for cell.
* @param string $fromrole
* @param string $targetrole
* @return string
* @throws \coding_exception
*/
protected function get_cell_tooltip($fromrole, $targetrole) {
$a = new stdClass;
$a->fromrole = $fromrole->localname;
$a->targetrole = $targetrole->localname;
return get_string('allowroletoview', 'core_role', $a);
}
/**
* Get intro text for role allow view page.
* @return string
* @throws \coding_exception
*/
public function get_intro_text() {
return get_string('configallowview', 'core_admin');
}
protected function get_eventclass() {
return \core\event\role_allow_view_updated::class;
}
}
@@ -43,7 +43,7 @@ abstract class core_role_capability_table_base {
protected $id;
/** Added to the class="" attribute on output. */
protected $classes = array('rolecap table-hover');
protected $classes = array('rolecap');
/** Default number of capabilities in the table for the search UI to be shown. */
const NUM_CAPS_FOR_SEARCH = 12;
@@ -123,6 +123,9 @@ abstract class core_role_capability_table_with_risks extends core_role_capabilit
assign_capability($changedcap, $this->permissions[$changedcap],
$this->roleid, $this->context->id, true);
}
// Force accessinfo refresh for users visiting this context.
$this->context->mark_dirty();
}
public function display() {
@@ -180,14 +183,10 @@ abstract class core_role_capability_table_with_risks extends core_role_capabilit
public function get_risk_icon($type) {
global $OUTPUT;
$alt = get_string("{$type}short", "admin");
$title = get_string($type, "admin");
$text = $OUTPUT->pix_icon('i/' . str_replace('risk', 'risk_', $type), $alt, 'moodle', [
'title' => $title,
]);
$iconurl = $OUTPUT->pix_url('i/' . str_replace('risk', 'risk_', $type));
$text = '<img src="' . $iconurl . '" alt="' . get_string($type . 'short', 'admin') . '" />';
$action = new popup_action('click', $this->risksurl, 'docspopup');
$riskicon = $OUTPUT->action_link($this->risksurl, $text, $action);
$riskicon = $OUTPUT->action_link($this->risksurl, $text, $action, array('title'=>get_string($type, 'admin')));
return $riskicon;
}
@@ -50,7 +50,6 @@ class core_role_check_capability_table extends core_role_capability_table_base {
$this->contextname = $contextname;
$this->stryes = get_string('yes');
$this->strno = get_string('no');
$this->add_classes(['table-striped']);
}
protected function add_header_cells() {
+2 -5
View File
@@ -69,11 +69,8 @@ class core_role_check_users_selector extends user_selector_base {
if ($coursecontext and $coursecontext != SITEID) {
$sql1 = " FROM {user} u
JOIN (SELECT DISTINCT subu.id
FROM {user} subu
JOIN {user_enrolments} ue ON (ue.userid = subu.id)
JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid1)
) subq ON subq.id = u.id
JOIN {user_enrolments} ue ON (ue.userid = u.id)
JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid1)
WHERE $wherecondition";
$params['courseid1'] = $coursecontext->instanceid;
@@ -42,7 +42,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
protected $allowassign;
protected $allowoverride;
protected $allowswitch;
protected $allowview;
public function __construct($context, $roleid) {
$this->roleid = $roleid;
@@ -55,7 +54,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
foreach ($levels as $level => $classname) {
$this->allcontextlevels[$level] = context_helper::get_level_name($level);
}
$this->add_classes(['table-striped']);
}
protected function load_current_permissions() {
@@ -74,7 +72,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
$this->allowassign = array_keys($this->get_allow_roles_list('assign'));
$this->allowoverride = array_keys($this->get_allow_roles_list('override'));
$this->allowswitch = array_keys($this->get_allow_roles_list('switch'));
$this->allowview = array_keys($this->get_allow_roles_list('view'));
} else {
$this->role = new stdClass;
@@ -86,7 +83,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
$this->allowassign = array();
$this->allowoverride = array();
$this->allowswitch = array();
$this->allowview = array();
}
parent::load_current_permissions();
}
@@ -104,8 +100,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
$this->role->shortname = core_text::strtolower(clean_param($this->role->shortname, PARAM_ALPHANUMEXT));
if (empty($this->role->shortname)) {
$this->errors['shortname'] = get_string('errorbadroleshortname', 'core_role');
} else if (core_text::strlen($this->role->shortname) > 100) { // Check if it exceeds the max of 100 characters.
$this->errors['shortname'] = get_string('errorroleshortnametoolong', 'core_role');
}
}
if ($DB->record_exists_select('role', 'shortname = ? and id <> ?', array($this->role->shortname, $this->roleid))) {
@@ -158,19 +152,15 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
// Allowed roles.
$allow = optional_param_array('allowassign', null, PARAM_INT);
if (!is_null($allow)) {
$this->allowassign = array_filter($allow);
$this->allowassign = $allow;
}
$allow = optional_param_array('allowoverride', null, PARAM_INT);
if (!is_null($allow)) {
$this->allowoverride = array_filter($allow);
$this->allowoverride = $allow;
}
$allow = optional_param_array('allowswitch', null, PARAM_INT);
if (!is_null($allow)) {
$this->allowswitch = array_filter($allow);
}
$allow = optional_param_array('allowview', null, PARAM_INT);
if (!is_null($allow)) {
$this->allowview = array_filter($allow);
$this->allowswitch = $allow;
}
// Now read the permissions for each capability.
@@ -188,8 +178,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
* @param int $roleid role id or 0 for no role
* @param array $options array with following keys:
* 'name', 'shortname', 'description', 'permissions', 'archetype',
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch',
* 'allowview'
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch'
*/
public function force_duplicate($roleid, array $options) {
global $DB;
@@ -226,9 +215,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
if ($options['allowswitch']) {
$this->allowswitch = array();
}
if ($options['allowview']) {
$this->allowview = array();
}
if ($options['permissions']) {
foreach ($this->capabilities as $capid => $cap) {
@@ -274,9 +260,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
if ($options['allowswitch']) {
$this->allowswitch = array_keys($this->get_allow_roles_list('switch', $roleid));
}
if ($options['allowview']) {
$this->allowview = array_keys($this->get_allow_roles_list('view', $roleid));
}
if ($options['permissions']) {
$this->permissions = $DB->get_records_menu('role_capabilities',
@@ -297,8 +280,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
* @param string $archetype
* @param array $options array with following keys:
* 'name', 'shortname', 'description', 'permissions', 'archetype',
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch',
* 'allowview'
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch'
*/
public function force_archetype($archetype, array $options) {
$archetypes = get_role_archetypes();
@@ -339,9 +321,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
if ($options['allowswitch']) {
$this->allowswitch = get_default_role_archetype_allows('switch', $archetype);
}
if ($options['allowview']) {
$this->allowview = get_default_role_archetype_allows('view', $archetype);
}
if ($options['permissions']) {
$defaultpermissions = get_default_capabilities($archetype);
@@ -361,8 +340,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
* @param string $xml
* @param array $options array with following keys:
* 'name', 'shortname', 'description', 'permissions', 'archetype',
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch',
* 'allowview'
* 'contextlevels', 'allowassign', 'allowoverride', 'allowswitch'
*/
public function force_preset($xml, array $options) {
if (!$info = core_role_preset::parse_preset($xml)) {
@@ -399,7 +377,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
}
}
foreach (array('assign', 'override', 'switch', 'view') as $type) {
foreach (array('assign', 'override', 'switch') as $type) {
if ($options['allow'.$type]) {
if (isset($info['allow'.$type])) {
$this->{'allow'.$type} = $info['allow'.$type];
@@ -435,7 +413,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
}
public function save_changes() {
global $DB, $USER;
global $DB, $CFG;
if (!$this->roleid) {
// Creating role.
@@ -445,25 +423,12 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
// Updating role.
$DB->update_record('role', $this->role);
// Trigger role updated event.
\core\event\role_updated::create([
'userid' => $USER->id,
'objectid' => $this->role->id,
'context' => $this->context,
'other' => [
'name' => $this->role->name,
'shortname' => $this->role->shortname,
'description' => $this->role->description,
'archetype' => $this->role->archetype,
'contextlevels' => $this->contextlevels
]
])->trigger();
// This will ensure the course contacts cache is purged so name changes get updated in
// the UI. It would be better to do this only when we know that fields affected are
// updated. But thats getting into the weeds of the coursecat cache and role edits
// should not be that frequent, so here is the ugly brutal approach.
core_course_category::role_assignment_changed($this->role->id, context_system::instance());
require_once($CFG->libdir . '/coursecatlib.php');
coursecat::role_assignment_changed($this->role->id, context_system::instance());
}
// Assignable contexts.
@@ -473,7 +438,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
$this->save_allow('assign');
$this->save_allow('override');
$this->save_allow('switch');
$this->save_allow('view');
// Permissions.
parent::save_changes();
@@ -485,20 +449,13 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
$current = array_keys($this->get_allow_roles_list($type));
$wanted = $this->{'allow'.$type};
$addfunction = "core_role_set_{$type}_allowed";
$addfunction = 'allow_'.$type;
$deltable = 'role_allow_'.$type;
$field = 'allow'.$type;
$eventclass = "\\core\\event\\role_allow_" . $type . "_updated";
$context = context_system::instance();
foreach ($current as $roleid) {
if (!in_array($roleid, $wanted)) {
$DB->delete_records($deltable, array('roleid'=>$this->roleid, $field=>$roleid));
$eventclass::create([
'context' => $context,
'objectid' => $this->roleid,
'other' => ['targetroleid' => $roleid, 'allow' => false]
])->trigger();
continue;
}
$key = array_search($roleid, $wanted);
@@ -510,14 +467,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
$roleid = $this->roleid;
}
$addfunction($this->roleid, $roleid);
if (in_array($roleid, $wanted)) {
$eventclass::create([
'context' => $context,
'objectid' => $this->roleid,
'other' => ['targetroleid' => $roleid, 'allow' => true]
])->trigger();
}
}
}
@@ -527,7 +476,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
}
protected function get_shortname_field($id) {
return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="100" value="' . s($this->role->shortname) . '"' .
return '<input type="text" id="' . $id . '" name="' . $id . '" maxlength="254" value="' . s($this->role->shortname) . '"' .
' class="form-control"/>';
}
@@ -557,11 +506,9 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
if (!$this->disabled) {
$output .= '<input type="hidden" name="contextlevel' . $cl . '" value="0" />';
}
$output .= '<div class="form-check justify-content-start w-100">';
$output .= '<input class="form-check-input" type="checkbox" id="cl' . $cl . '" name="contextlevel' . $cl .
$output .= '<input type="checkbox" id="cl' . $cl . '" name="contextlevel' . $cl .
'" value="1" ' . $extraarguments . '/> ';
$output .= '<label class="form-check-label" for="cl' . $cl . '">' . $clname . "</label>\n";
$output .= '</div>';
$output .= '<label for="cl' . $cl . '">' . $clname . "</label><br />\n";
}
return $output;
}
@@ -576,7 +523,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
protected function get_allow_roles_list($type, $roleid = null) {
global $DB;
if ($type !== 'assign' and $type !== 'switch' and $type !== 'override' and $type !== 'view') {
if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') {
debugging('Invalid role allowed type specified', DEBUG_DEVELOPER);
return array();
}
@@ -600,11 +547,11 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
/**
* Returns an array of roles with the allowed type.
*
* @param string $type Must be one of: assign, switch, override or view.
* @param string $type Must be one of: assign, switch, or override.
* @return array Am array of role names with the allowed type
*/
protected function get_allow_role_control($type) {
if ($type !== 'assign' and $type !== 'switch' and $type !== 'override' and $type !== 'view') {
if ($type !== 'assign' and $type !== 'switch' and $type !== 'override') {
debugging('Invalid role allowed type specified', DEBUG_DEVELOPER);
return '';
}
@@ -619,9 +566,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
if ($this->roleid == 0) {
$options[-1] = get_string('thisnewrole', 'core_role');
}
return
html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'allow'.$type.'[]', 'value' => "")) .
html_writer::select($options, 'allow'.$type.'[]', $selected, false, array('multiple' => 'multiple',
return html_writer::select($options, 'allow'.$type.'[]', $selected, false, array('multiple' => 'multiple',
'size' => 10, 'class' => 'form-control'));
}
@@ -655,7 +600,7 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
echo "</label>\n";
}
if ($helpicon) {
echo '<span class="float-sm-right text-nowrap">'.$helpicon.'</span>';
echo '<span class="pull-xs-right text-nowrap">'.$helpicon.'</span>';
}
echo '</div>';
if (isset($this->errors[$name])) {
@@ -696,7 +641,6 @@ class core_role_define_role_table_advanced extends core_role_capability_table_wi
$this->print_field('menuallowassign', get_string('allowassign', 'core_role'), $this->get_allow_role_control('assign'));
$this->print_field('menuallowoverride', get_string('allowoverride', 'core_role'), $this->get_allow_role_control('override'));
$this->print_field('menuallowswitch', get_string('allowswitch', 'core_role'), $this->get_allow_role_control('switch'));
$this->print_field('menuallowview', get_string('allowview', 'core_role'), $this->get_allow_role_control('view'));
if ($risks = $this->get_role_risks_info()) {
$this->print_field('', get_string('rolerisks', 'core_role'), $risks);
}
@@ -56,24 +56,6 @@ class core_role_override_permissions_table_advanced extends core_role_capability
}
}
/**
* This method adds an additional class to a row if capability is other than inherited.
*
* @param stdClass $capability
* @return array
*/
protected function get_row_attributes($capability) {
$rowattributes = parent::get_row_attributes($capability);
if ($this->permissions[$capability->name] !== 0) {
if (empty($rowattributes['class'])) {
$rowattributes['class'] = "overriddenpermission table-warning";
} else {
$rowattributes['class'] .= " overriddenpermission table-warning";
}
}
return $rowattributes;
}
protected function load_parent_permissions() {
// Get the capabilities from the parent context, so that can be shown in the interface.
$parentcontext = $this->context->get_parent_context();
+4 -6
View File
@@ -93,10 +93,9 @@ class core_role_permissions_table extends core_role_capability_table_base {
foreach ($roles as $id => $name) {
if (isset($needed[$id])) {
$templatecontext = array("rolename" => $name, "roleid" => $id, "action" => "prevent", "spanclass" => "allowed",
"linkclass" => "preventlink", "adminurl" => $adminurl->out(), "icon" => "", "iconalt" => "");
"linkclass" => "preventlink", "adminurl" => $adminurl->out(), "imageurl" => "");
if (isset($overridableroles[$id]) and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
$templatecontext['icon'] = 't/delete';
$templatecontext['iconalt'] = get_string('deletexrole', 'core_role', $name);
$templatecontext['imageurl'] = $renderer->pix_url('t/delete');
}
$neededroles[$id] = $renderer->render_from_template('core/permissionmanager_role', $templatecontext);
}
@@ -106,10 +105,9 @@ class core_role_permissions_table extends core_role_capability_table_base {
if (isset($forbidden[$id]) and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability)))) {
$templatecontext = array("rolename" => $name, "roleid" => $id, "action" => "unprohibit",
"spanclass" => "forbidden", "linkclass" => "unprohibitlink", "adminurl" => $adminurl->out(),
"icon" => "", "iconalt" => "");
"imageurl" => "");
if (isset($overridableroles[$id]) and prohibit_is_removable($id, $context, $capability->name)) {
$templatecontext['icon'] = 't/delete';
$templatecontext['iconalt'] = get_string('deletexrole', 'core_role', $name);
$templatecontext['imageurl'] = $renderer->pix_url('t/delete');
}
$forbiddenroles[$id] = $renderer->render_from_template('core/permissionmanager_role', $templatecontext);
}
+2 -2
View File
@@ -84,7 +84,7 @@ class core_role_preset {
$contextlevels->appendChild($dom->createElement('level', $name));
}
foreach (array('assign', 'override', 'switch', 'view') as $type) {
foreach (array('assign', 'override', 'switch') as $type) {
$allows = $dom->createElement('allow'.$type);
$top->appendChild($allows);
$records = $DB->get_records('role_allow_'.$type, array('roleid'=>$roleid), "allow$type ASC");
@@ -205,7 +205,7 @@ class core_role_preset {
}
}
foreach (array('assign', 'override', 'switch', 'view') as $type) {
foreach (array('assign', 'override', 'switch') as $type) {
$values = self::get_node_children_values($dom, '/role/allow'.$type, 'shortname');
if (!isset($values)) {
$info['allow'.$type] = null;
-1
View File
@@ -79,7 +79,6 @@ class core_role_preset_form extends moodleform {
$mform->addElement('advcheckbox', 'allowassign', get_string('allowassign', 'core_role'));
$mform->addElement('advcheckbox', 'allowoverride', get_string('allowoverride', 'core_role'));
$mform->addElement('advcheckbox', 'allowswitch', get_string('allowswitch', 'core_role'));
$mform->addElement('advcheckbox', 'allowview', get_string('allowview', 'core_role'));
$mform->addElement('advcheckbox', 'permissions', get_string('permissions', 'core_role'));
}
-459
View File
@@ -1,459 +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_role.
*
* @package core_role
* @copyright 2018 Carlos Escobedo <carlos@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_role\privacy;
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\contextlist;
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\transform;
use \core_privacy\local\request\writer;
use \core_privacy\local\request\userlist;
use \core_privacy\local\request\approved_userlist;
/**
* Privacy provider for core_role.
*
* @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\provider,
\core_privacy\local\request\subsystem\provider,
\core_privacy\local\request\subsystem\plugin_provider,
\core_privacy\local\request\user_preference_provider,
\core_privacy\local\request\core_userlist_provider {
/**
* Get information about the user data stored by this plugin.
*
* @param collection $collection An object for storing metadata.
* @return collection The metadata.
*/
public static function get_metadata(collection $collection) : collection {
$rolecapabilities = [
'roleid' => 'privacy:metadata:role_capabilities:roleid',
'capability' => 'privacy:metadata:role_capabilities:capability',
'permission' => 'privacy:metadata:role_capabilities:permission',
'timemodified' => 'privacy:metadata:role_capabilities:timemodified',
'modifierid' => 'privacy:metadata:role_capabilities:modifierid'
];
$roleassignments = [
'roleid' => 'privacy:metadata:role_assignments:roleid',
'userid' => 'privacy:metadata:role_assignments:userid',
'timemodified' => 'privacy:metadata:role_assignments:timemodified',
'modifierid' => 'privacy:metadata:role_assignments:modifierid',
'component' => 'privacy:metadata:role_assignments:component',
'itemid' => 'privacy:metadata:role_assignments:itemid'
];
$collection->add_database_table('role_capabilities', $rolecapabilities,
'privacy:metadata:role_capabilities:tableexplanation');
$collection->add_database_table('role_assignments', $roleassignments,
'privacy:metadata:role_assignments:tableexplanation');
$collection->add_user_preference('definerole_showadvanced',
'privacy:metadata:preference:showadvanced');
return $collection;
}
/**
* Export all user preferences for the plugin.
*
* @param int $userid The userid of the user whose data is to be exported.
*/
public static function export_user_preferences(int $userid) {
$showadvanced = get_user_preferences('definerole_showadvanced', null, $userid);
if ($showadvanced !== null) {
writer::export_user_preference('core_role',
'definerole_showadvanced',
transform::yesno($showadvanced),
get_string('privacy:metadata:preference:showadvanced', 'core_role')
);
}
}
/**
* Return all contexts for this userid.
*
* @param int $userid The user ID.
* @return contextlist The list of context IDs.
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
global $DB;
$contextlist = new contextlist();
// The role_capabilities table contains user data.
$contexts = [
CONTEXT_SYSTEM,
CONTEXT_USER,
CONTEXT_COURSECAT,
CONTEXT_COURSE,
CONTEXT_MODULE,
CONTEXT_BLOCK
];
list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
$sql = "SELECT ctx.id
FROM {context} ctx
JOIN {role_capabilities} rc
ON rc.contextid = ctx.id
AND ((ctx.contextlevel {$insql} AND rc.modifierid = :modifierid)
OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))";
$params = [
'modifierid' => $userid,
'contextlevel' => CONTEXT_USER,
'userid' => $userid
];
$params += $inparams;
$contextlist->add_from_sql($sql, $params);
// The role_assignments table contains user data.
$contexts = [
CONTEXT_SYSTEM,
CONTEXT_USER,
CONTEXT_COURSECAT,
CONTEXT_COURSE,
CONTEXT_MODULE,
CONTEXT_BLOCK
];
list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
$params = [
'userid' => $userid,
'modifierid' => $userid
];
$params += $inparams;
$sql = "SELECT ctx.id
FROM {role_assignments} ra
JOIN {context} ctx
ON ctx.id = ra.contextid
AND ctx.contextlevel {$insql}
WHERE (ra.userid = :userid
OR ra.modifierid = :modifierid)
AND ra.component != 'tool_cohortroles'";
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Get the list of users within a specific context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
if (empty($userlist)) {
return;
}
$context = $userlist->get_context();
// Include users who created or modified role capabilities.
$sql = "SELECT modifierid as userid
FROM {role_capabilities}
WHERE contextid = :contextid";
$params = [
'contextid' => $context->id
];
$userlist->add_from_sql('userid', $sql, $params);
// Include users that have a role assigned to them.
$sql = "SELECT userid
FROM {role_assignments}
WHERE contextid = :contextid";
$userlist->add_from_sql('userid', $sql, $params);
// Include users who created or modified the role assignment.
// Differentiate and exclude special cases where tool_cohortroles adds records through the
// "Assign user roles to cohort" feature into the role_assignments table.
// These records should be separately processed in tool_cohortroles.
$sql = "SELECT modifierid as userid
FROM {role_assignments}
WHERE contextid = :contextid
AND component != 'tool_cohortroles'";
$userlist->add_from_sql('userid', $sql, $params);
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The list of approved contexts for a user.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
if (empty($contextlist)) {
return;
}
$rolesnames = self::get_roles_name();
$userid = $contextlist->get_user()->id;
$ctxfields = \context_helper::get_preload_record_columns_sql('ctx');
list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
// Role Assignments export data.
$contexts = [
CONTEXT_SYSTEM,
CONTEXT_USER,
CONTEXT_COURSECAT,
CONTEXT_COURSE,
CONTEXT_MODULE,
CONTEXT_BLOCK
];
list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
$sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, $ctxfields
FROM {role_assignments} ra
JOIN {context} ctx
ON ctx.id = ra.contextid
AND ctx.contextlevel {$inctxsql}
AND (ra.userid = :userid OR ra.modifierid = :modifierid)
AND ra.component != 'tool_cohortroles'
JOIN {role} r
ON r.id = ra.roleid
WHERE ctx.id {$insql}";
$params = ['userid' => $userid, 'modifierid' => $userid];
$params += $inparams;
$params += $ctxparams;
$assignments = $DB->get_recordset_sql($sql, $params);
foreach ($assignments as $assignment) {
\context_helper::preload_from_record($assignment);
$alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
'timemodified' => transform::datetime($assignment->timemodified),
'userid' => transform::user($assignment->userid),
'modifierid' => transform::user($assignment->modifierid)
];
}
$assignments->close();
if (!empty($alldata)) {
array_walk($alldata, function($roledata, $contextid) {
$context = \context::instance_by_id($contextid);
array_walk($roledata, function($data, $rolename) use ($context) {
writer::with_context($context)->export_data(
[get_string('privacy:metadata:role_assignments', 'core_role'), $rolename],
(object)$data);
});
});
unset($alldata);
}
// Role Capabilities export data.
$strpermissions = self::get_permissions_name();
$contexts = [
CONTEXT_SYSTEM,
CONTEXT_USER,
CONTEXT_COURSECAT,
CONTEXT_COURSE,
CONTEXT_MODULE,
CONTEXT_BLOCK
];
list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
$sql = "SELECT rc.id, rc.contextid, rc.capability, rc.permission, rc.timemodified, rc.roleid, $ctxfields
FROM {context} ctx
JOIN {role_capabilities} rc
ON rc.contextid = ctx.id
AND ((ctx.contextlevel {$inctxsql} AND rc.modifierid = :modifierid)
OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))
WHERE ctx.id {$insql}";
$params = [
'modifierid' => $userid,
'contextlevel' => CONTEXT_USER,
'userid' => $userid
];
$params += $inparams;
$params += $ctxparams;
$capabilities = $DB->get_recordset_sql($sql, $params);
foreach ($capabilities as $capability) {
\context_helper::preload_from_record($capability);
$alldata[$capability->contextid][$rolesnames[$capability->roleid]][] = (object)[
'timemodified' => transform::datetime($capability->timemodified),
'capability' => $capability->capability,
'permission' => $strpermissions[$capability->permission]
];
}
$capabilities->close();
if (!empty($alldata)) {
array_walk($alldata, function($capdata, $contextid) {
$context = \context::instance_by_id($contextid);
array_walk($capdata, function($data, $rolename) use ($context) {
writer::with_context($context)->export_data(
[get_string('privacy:metadata:role_capabilities', 'core_role'), $rolename],
(object)$data);
});
});
}
}
/**
* Exports the data relating to tool_cohortroles component on role assignments by
* Assign user roles to cohort feature.
*
* @param int $userid The user ID.
*/
public static function export_user_role_to_cohort(int $userid) {
global $DB;
$rolesnames = self::get_roles_name();
$sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, r.id as roleid
FROM {role_assignments} ra
JOIN {context} ctx
ON ctx.id = ra.contextid
AND ctx.contextlevel = :contextlevel
AND ra.component = 'tool_cohortroles'
JOIN {role} r
ON r.id = ra.roleid
WHERE ctx.instanceid = :instanceid
OR ra.userid = :userid";
$params = ['userid' => $userid, 'instanceid' => $userid, 'contextlevel' => CONTEXT_USER];
$assignments = $DB->get_recordset_sql($sql, $params);
foreach ($assignments as $assignment) {
$alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[
'timemodified' => transform::datetime($assignment->timemodified),
'userid' => transform::user($assignment->userid),
'modifierid' => transform::user($assignment->modifierid)
];
}
$assignments->close();
if (!empty($alldata)) {
array_walk($alldata, function($roledata, $contextid) {
$context = \context::instance_by_id($contextid);
array_walk($roledata, function($data, $rolename) use ($context) {
writer::with_context($context)->export_related_data(
[get_string('privacy:metadata:role_cohortroles', 'core_role'), $rolename], 'cohortroles',
(object)$data);
});
});
}
}
/**
* Delete all user data for this context.
*
* @param \context $context The context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
global $DB;
// Don't remove data from role_capabilities.
// Because this data affects the whole Moodle, there are override capabilities.
// Don't belong to the modifier user.
// Remove data from role_assignments.
$DB->delete_records('role_assignments', ['contextid' => $context->id]);
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
global $DB;
// Don't remove data from role_capabilities.
// Because this data affects the whole Moodle, there are override capabilities.
// Don't belong to the modifier user.
$context = $userlist->get_context();
$userids = $userlist->get_userids();
if (empty($userids)) {
return;
}
list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$params = ['contextid' => $context->id] + $userparams;
// Remove data from role_assignments.
$DB->delete_records_select('role_assignments',
"contextid = :contextid AND userid {$usersql}", $params);
}
/**
* Delete all user data for this user only.
*
* @param approved_contextlist $contextlist The list of approved contexts for a user.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
global $DB;
// Don't remove data from role_capabilities.
// Because this data affects the whole Moodle, there are override capabilities.
// Don't belong to the modifier user.
// Remove data from role_assignments.
if (empty($contextlist->count())) {
return;
}
$userid = $contextlist->get_user()->id;
$contextids = $contextlist->get_contextids();
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
$params = ['userid' => $userid] + $contextparams;
// Only delete the roles assignments where the user is assigned in all contexts.
$DB->delete_records_select('role_assignments',
"userid = :userid AND contextid {$contextsql}", $params);
}
/**
* Delete user entries in role_assignments related to the feature
* Assign user roles to cohort feature.
*
* @param int $userid The user ID.
*/
public static function delete_user_role_to_cohort(int $userid) {
global $DB;
// Delete entries where userid is a mentor by tool_cohortroles.
$DB->delete_records('role_assignments', ['userid' => $userid, 'component' => 'tool_cohortroles']);
}
/**
* Get all the localised roles name in a simple array.
*
* @return array Array of name of the roles by roleid.
*/
protected static function get_roles_name() {
$roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL);
$rolesnames = array();
foreach ($roles as $role) {
$rolesnames[$role->id] = $role->localname;
}
return $rolesnames;
}
/**
* Get all the permissions name in a simple array.
*
* @return array Array of permissions name.
*/
protected static function get_permissions_name() {
$strpermissions = array(
CAP_INHERIT => get_string('inherit', 'role'),
CAP_ALLOW => get_string('allow', 'role'),
CAP_PREVENT => get_string('prevent', 'role'),
CAP_PROHIBIT => get_string('prohibit', 'role')
);
return $strpermissions;
}
}
+17 -7
View File
@@ -52,12 +52,11 @@ if ($return === 'manage') {
$returnurl = new moodle_url('/admin/roles/define.php', array('action'=>'view', 'roleid'=>$roleid));;
}
admin_externalpage_setup('defineroles', '', array('action' => $action, 'roleid' => $roleid),
new moodle_url('/admin/roles/define.php'));
// Check access permissions.
$systemcontext = context_system::instance();
require_login();
require_capability('moodle/role:manage', $systemcontext);
admin_externalpage_setup('defineroles', '', array('action' => $action, 'roleid' => $roleid), new moodle_url('/admin/roles/define.php'));
// Export role.
if ($action === 'export') {
@@ -104,8 +103,7 @@ if ($action === 'add' and $resettype !== 'none') {
'contextlevels' => 1,
'allowassign' => 1,
'allowoverride' => 1,
'allowswitch' => 1,
'allowview' => 1);
'allowswitch' => 1);
if ($showadvanced) {
$definitiontable = new core_role_define_role_table_advanced($systemcontext, 0);
} else {
@@ -152,8 +150,7 @@ if ($action === 'add' and $resettype !== 'none') {
'contextlevels' => $data->contextlevels,
'allowassign' => $data->allowassign,
'allowoverride' => $data->allowoverride,
'allowswitch' => $data->allowswitch,
'allowview' => $data->allowview);
'allowswitch' => $data->allowswitch);
if ($showadvanced) {
$definitiontable = new core_role_define_role_table_advanced($systemcontext, $roleid);
} else {
@@ -200,6 +197,19 @@ if (optional_param('cancel', false, PARAM_BOOL)) {
if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey() && $definitiontable->is_submission_valid()) {
$definitiontable->save_changes();
$tableroleid = $definitiontable->get_role_id();
// Trigger event.
$event = \core\event\role_capabilities_updated::create(
array(
'context' => $systemcontext,
'objectid' => $tableroleid
)
);
$event->set_legacy_logdata(array(SITEID, 'role', $action, 'admin/roles/define.php?action=view&roleid=' . $tableroleid,
$definitiontable->get_role_name(), '', $USER->id));
if (!empty($role)) {
$event->add_record_snapshot('role', $role);
}
$event->trigger();
if ($action === 'add') {
redirect(new moodle_url('/admin/roles/define.php', array('action'=>'view', 'roleid'=>$definitiontable->get_role_id())));
+7 -5
View File
@@ -46,11 +46,11 @@ if ($action) {
$baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/roles/manage.php';
$defineurl = $CFG->wwwroot . '/' . $CFG->admin . '/roles/define.php';
admin_externalpage_setup('defineroles');
// Check access permissions.
$systemcontext = context_system::instance();
require_login();
require_capability('moodle/role:manage', $systemcontext);
admin_externalpage_setup('defineroles');
// Get some basic data we are going to need.
$roles = role_fix_names(get_all_roles(), $systemcontext, ROLENAME_ORIGINAL);
@@ -85,10 +85,12 @@ switch ($action) {
die;
}
if (!delete_role($roleid)) {
// The delete failed.
// The delete failed, but mark the context dirty in case.
$systemcontext->mark_dirty();
print_error('cannotdeleterolewithid', 'error', $baseurl, $roleid);
}
// Deleted a role sitewide...
$systemcontext->mark_dirty();
redirect($baseurl);
break;
@@ -214,9 +216,9 @@ die;
function get_action_icon($url, $icon, $alt, $tooltip) {
global $OUTPUT;
return '<a title="' . $tooltip . '" href="'. $url . '">' .
$OUTPUT->pix_icon('t/' . $icon, $alt) . '</a> ';
'<img src="' . $OUTPUT->pix_url('t/' . $icon) . '" class="iconsmall" alt="' . $alt . '" /></a> ';
}
function get_spacer() {
global $OUTPUT;
return $OUTPUT->spacer();
return '<img src="' . $OUTPUT->pix_url('spacer') . '" class="iconsmall" alt="" /> ';
}
-1
View File
@@ -29,7 +29,6 @@ $toprow[] = new tabobject('manage', new moodle_url('/admin/roles/manage.php'), g
$toprow[] = new tabobject('assign', new moodle_url('/admin/roles/allow.php', array('mode'=>'assign')), get_string('allowassign', 'core_role'));
$toprow[] = new tabobject('override', new moodle_url('/admin/roles/allow.php', array('mode'=>'override')), get_string('allowoverride', 'core_role'));
$toprow[] = new tabobject('switch', new moodle_url('/admin/roles/allow.php', array('mode'=>'switch')), get_string('allowswitch', 'core_role'));
$toprow[] = new tabobject('view', new moodle_url('/admin/roles/allow.php', ['mode' => 'view']), get_string('allowview', 'core_role'));
echo $OUTPUT->tabtree($toprow, $currenttab);

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