Compare commits

..

570 Commits

Author SHA1 Message Date
Eloy Lafuente (stronk7) 73d401b462 Moodle release 3.5.6 2019-05-11 23:17:42 +02:00
Eloy Lafuente (stronk7) 7ea8581868 weekly release 3.5.5+ 2019-05-10 20:31:14 +02:00
Eloy Lafuente (stronk7) 3f923b4570 Merge branch 'MDL-65537-35-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_35_STABLE 2019-05-10 20:09:24 +02:00
David Mudrák 8ef6c25a98 MDL-65537 lang: Use fixed strings in tests, too 2019-05-10 16:14:30 +02:00
Helen Foster 007b946948 MDL-65537 lang: Import fixed English strings (en_fix) 2019-05-10 16:14:16 +02:00
Eloy Lafuente (stronk7) d1e419d86f Merge branch 'MDL-65558-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-05-10 11:30:31 +02:00
Jun Pataleta 2e190e4739 Merge branch 'MDL-65540-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-05-10 15:58:28 +08:00
Andrew Nicols e81ac514ca MDL-65558 enrol_database: use , as port separator 2019-05-10 12:24:58 +08:00
Andrew Nicols 563f08ff54 MDL-65558 auth_db: use , as port separator 2019-05-10 12:24:58 +08:00
Andrew Nicols 8e70179f4d MDL-63959 feedback: Adjust unit test for perf 2019-05-10 11:43:19 +08:00
Andrew Nicols 30ac3bcfeb Merge branch 'MDL-63959-35' of git://github.com/tobiasreischmann/moodle into MOODLE_35_STABLE 2019-05-10 11:43:13 +08:00
Shamim Rezaie b287771272 MDL-65540 core_search: Explicit component name in the str helper 2019-05-10 08:12:40 +08:00
Shamim Rezaie 4b00d8392c MDL-65540 tool_dataprivacy: Explicit component name in the str helper 2019-05-10 08:12:40 +08:00
Eloy Lafuente (stronk7) abe4ff5534 Merge branch 'MDL-65197-35' of https://github.com/paulholden/moodle into MOODLE_35_STABLE 2019-05-09 20:02:49 +02:00
Eloy Lafuente (stronk7) 5b641c4187 Merge branch 'MDL-29320-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-05-09 19:49:57 +02:00
Andrew Nicols 02dc7147c7 Merge branch 'MDL-65435_35' of git://github.com/stronk7/moodle into MOODLE_35_STABLE 2019-05-09 14:52:13 +08:00
Jun Pataleta 8ab8dee8c9 Merge branch 'MDL-65141-35' of git://github.com/jleyva/moodle into MOODLE_35_STABLE 2019-05-09 12:27:30 +08:00
Adrian Greeve b9569a887e Merge branch 'MDL-58315_35_boost_block_classes' of https://github.com/zpottie/moodle into MOODLE_35_STABLE 2019-05-09 11:35:07 +08:00
Adrian Greeve efee2e4c8b Merge branch 'MDL-65387-35' of https://github.com/lucaboesch/moodle into MOODLE_35_STABLE 2019-05-09 11:25:06 +08:00
Eloy Lafuente (stronk7) 33f22e1e83 MDL-65435 behat: Support any arg type with behat reruns
Right now, when executing a single rerun of a parallel run
using vendor/bin/behat, not all the argument alternatives
are supported (equal or space). This commit allows both to work.
2019-05-08 23:23:36 +02:00
Luca Bösch 500fc1b8f0 MDL-65387 dataformats: Table download formats choose pulldown style. 2019-05-08 20:20:11 +02:00
Michael Hawkins e36f1c9896 MDL-61738 messageinbound: Fix quota checks & filesize for email uploads
Private files uploaded by email will now honour the file quota limit,
because the filesize is set correctly and checked against users'
remaining personal quota limit. Previously, attachment size was always
set to zero, and quota was checked against the draft area (this is
not valid for email uploads, because each file is moved out of the
draft area as it is processed, so multiple files totalling greater
than the remaining quota would still pass the check).
2019-05-08 17:51:45 +02:00
Dan Marsden cd6fb4322b MDL-64708 cohort: Return url is not used anywhere in core. 2019-05-08 17:51:45 +02:00
Eloy Lafuente (stronk7) 1398145998 weekly release 3.5.5+ 2019-05-08 17:48:41 +02:00
Adrian Greeve ec6f1419dc Merge branch 'MDL-65484-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-05-08 11:24:55 +08:00
Andrew Nicols 473145c2c7 Merge branch 'MDL-35396-35' of git://github.com/mihailges/moodle into MOODLE_35_STABLE 2019-05-08 09:48:33 +08:00
Damyon Wiese 469ac6dd08 MDL-65484 assign: Scrolling overflow CSS
Use relatively positioned elements, not absolutely positioned to prevent
elements being visible when they are scrolled outside the containing drawing region.
2019-05-07 16:23:04 +08:00
Mihail Geshoski 5ddac4b5b9 MDL-35396 lesson: Fix detailed statistics display for essay questions 2019-05-07 14:00:58 +08:00
Jun Pataleta 0c8113bf8c Merge branch 'MDL-65153-35-fix1' of http://github.com/damyon/moodle into MOODLE_35_STABLE 2019-05-07 10:09:07 +08:00
Damyon Wiese f4110673d4 MDL-65153 competencies: course competencies page
The webservice to fetch the data for the course competencies page requires the
pluginbaseurl to be set.
2019-05-07 10:01:51 +08:00
Sara Arjona fdecf60bab Merge branch 'MDL-65374-35' of https://github.com/lucaboesch/moodle into
MOODLE_35_STABLE
2019-05-06 12:09:48 +02:00
Jun Pataleta bef3d096fc Merge branch 'MDL-65399-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-05-06 16:26:27 +08:00
Sara Arjona bb1cfe25cf Merge branch 'MDL-65396-35' of https://github.com/lucaboesch/moodle into MOODLE_35_STABLE 2019-05-06 10:20:15 +02:00
Shamim Rezaie 1150862f9d MDL-65399 mod_quiz: Handling the edge case when section name is '' 2019-05-06 18:14:00 +10:00
Shamim Rezaie b94ea41bbf MDL-65399 mod_quiz: UI should prevent deleting the last slot of section 2019-05-06 18:14:00 +10:00
Shamim Rezaie 6946a25e9f MDL-65399 mod_quiz: remove_slot should update the existing info
The remove_slot method should update the remaining slot's slot
attribute. It also should update the remaining slot's question number
and section info.
2019-05-06 18:14:00 +10:00
Shamim Rezaie 2a75ea0ec9 MDL-65399 mod_quiz: Remove $slots from the \mod_quiz\structure class
It's enough to have $slotsinorder, and the $slots property
was redundant. There should only be a single source of truth.
2019-05-06 18:14:00 +10:00
Jun Pataleta dafd6f136c Merge branch 'MDL-65153-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-05-06 16:13:40 +08:00
Adrian Greeve b6147f7e80 Merge branch 'MDL-64968-35' of https://github.com/lucaboesch/moodle into MOODLE_35_STABLE 2019-05-06 16:00:36 +08:00
Adrian Greeve 531036848c Merge branch 'MDL-65104-35' of git://git.cameron1729.xyz/moodle into MOODLE_35_STABLE 2019-05-06 12:01:55 +08:00
Jake Dallimore c0e1742985 Merge branch 'MDL-64988-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-05-06 10:34:51 +08:00
Luca Bösch bedb1ffc49 MDL-65396 theme_boost: Style duration chooser pulldown select. 2019-05-04 11:00:29 +02:00
Luca Bösch 4a6b23937a MDL-65374 core_grades: style "Move selected items to" pulldown. 2019-05-04 11:00:15 +02:00
Luca Bösch 83d8624eec MDL-64968 mod_lesson: Style "Yes, I'd like to try again" button. 2019-05-04 11:00:05 +02:00
Eloy Lafuente (stronk7) 6e311854b7 weekly release 3.5.5+ 2019-05-03 17:52:03 +02:00
Eloy Lafuente (stronk7) 12531500d3 Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-05-03 17:51:59 +02:00
Shamim Rezaie 73c4aa313b MDL-64988 mod_quiz: Fix questions always being added to the last section 2019-05-03 20:49:10 +10:00
zpottie b22947d3b7 MDL-58315 core: Add support for custom block classes in Boost 2019-05-03 16:17:50 +12:00
Adrian Greeve e208a8d307 Merge branch 'MDL-64851-35' of https://github.com/s-cenni/MDL-64851 into MOODLE_35_STABLE 2019-05-03 10:45:58 +08:00
Andrew Nicols a4c878c734 Merge branch 'MDL-64394-accesslog-MOODLE_35_STABLE' of https://github.com/brendanheywood/moodle into MOODLE_35_STABLE 2019-05-03 08:54:29 +08:00
AMOS bot 54d672958d Automatically generated installer lang files 2019-05-03 00:14:40 +00:00
Jun Pataleta 13e1ef0300 Merge branch 'MDL-65411-35' of git://github.com/lameze/moodle into MOODLE_35_STABLE 2019-05-02 17:02:55 +08:00
Jun Pataleta b1899fcc4a Merge branch 'MDL-65446-35' of https://github.com/ryanwyllie/moodle into MOODLE_35_STABLE 2019-05-02 15:01:31 +08:00
Jake Dallimore 31c96d5e7f Merge branch 'MDL-64439-MOODLE_35_STABLE' of https://github.com/ilya-catalyst/moodle into MOODLE_35_STABLE 2019-05-02 14:53:21 +08:00
Jun Pataleta 3bb9a613c6 Merge branch 'MDL-65273-35' of https://github.com/lucaboesch/moodle into MOODLE_35_STABLE 2019-05-01 17:24:13 +08:00
Paul Holden 29fcc59f88 MDL-65197 editor: handle empty user preference in privacy export. 2019-05-01 09:52:59 +01:00
Luca Bösch 3cf521a427 MDL-65273 roles: Roles permissions buttons styles. 2019-05-01 09:26:51 +02:00
Adrian Greeve a27c089b40 Merge branch 'MDL-65149-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-05-01 15:00:34 +08:00
Adrian Greeve 4d1fbba086 Merge branch 'MDL-64959_35_STABLE' of https://github.com/abhimanyuZ/moodle into MOODLE_35_STABLE 2019-05-01 14:32:15 +08:00
Adrian Greeve c8c229e08b Merge branch 'MDL-65178-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-05-01 11:59:16 +08:00
Simey Lameze 7d78aeece1 MDL-65411 core_calendar: wrap long description text 2019-05-01 09:56:05 +08:00
Jake Dallimore 4d0fa8abdc Merge branch 'MDL-60851-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-05-01 09:33:31 +08:00
Damyon Wiese 4c775e4618 MDL-60851 backup: coding style fixes 2019-05-01 08:51:57 +08:00
Damyon Wiese 9462d6f1c8 MDL-60851 backup: Sanitise setting dependencies
The only different between each setting dependency type is the evaluation of the condition,
and the mform js validation arguments - so that should be the only thing that is extended
by each subclass.
2019-05-01 08:51:57 +08:00
Damyon Wiese 2aeff9cfd7 MDL-60851 backup: Fix undefined $value 2019-05-01 08:51:57 +08:00
Damyon Wiese 5b01f0099f MDL-60851 backup: More unit tests for dependencies 2019-05-01 08:51:57 +08:00
Eloy Lafuente (stronk7) 6e3f19324a Merge branch 'MDL-65397-35-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_35_STABLE 2019-05-01 01:43:11 +02:00
Eloy Lafuente (stronk7) 34a46486ef weekly release 3.5.5+ 2019-05-01 00:28:41 +02:00
Eloy Lafuente (stronk7) 2a373db105 Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-05-01 00:28:39 +02:00
Juan Leyva 08135b0689 MDL-65141 tool_mobile: Return all the language translations 2019-04-30 15:25:29 +02:00
Jun Pataleta 1bd6794d80 MDL-29320 user: Make email query case-insensitive 2019-04-30 16:29:39 +08:00
Jun Pataleta 3e854512c5 MDL-29320 admin: Improve test for multiple accounts with same email
* Use Scenario Outlines
* More coverage:
  - Test for email case-sensitivity
  - Updating user profile as admin
  - Updating own user profile
2019-04-30 16:29:36 +08:00
Jun Pataleta 8326233128 MDL-29320 user: Remove @javascript tag for add new user behat test
* It's not necessary and will improve Behat execution time
2019-04-30 16:23:03 +08:00
Tobias Reischmann eb29ebefb4 MDL-63959 mod_feedback: Add phpunit tests for get_pages in completion 2019-04-30 07:57:21 +02:00
Zoltán Szarvas 638ba35597 MDL-63959 mod_feedback: Fixed nested dependency handling
For example the dependecy chain is the following: A->B->C. When a
question (A) depends on another dependent item (B) and B hasn't
displayed (because of C's response), the $value for the B's response
will be null. In this case the can_see_item() method returned
null. Because the can_see_item() returned null (not false), the
get_pages() method displayed the question A, because it checks for
explicit false: $this->can_see_item($item) !== false.
Now, false is also returned, if the dependent question is not visible.
2019-04-30 07:57:21 +02:00
Ryan Wyllie 94cbb103ef MDL-65446 admin: fix admin email option for cli install 2019-04-30 13:38:25 +08:00
Eloy Lafuente (stronk7) efaad61031 MDL-63137 mod_feedback: discern between user or id better
is_int('1') => false, so better we invert the check that is safer.
2019-04-30 08:50:20 +08:00
AMOS bot 05e4efbcee Automatically generated installer lang files 2019-04-30 00:12:35 +00:00
Eloy Lafuente (stronk7) 3451667bc9 Merge branch 'MDL-65293-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-04-29 22:46:47 +02:00
Eloy Lafuente (stronk7) 9efdbf36d7 Merge branch 'MDL-63137-35' of git://github.com/aanabit/moodle into MOODLE_35_STABLE 2019-04-29 20:11:13 +02:00
Helen Foster 23bb771193 MDL-65397 lang: Import fixed English strings (en_fix)
Significant string changes:

* direct:view,gradeimport_direct - wording corrected from 'CSV' to
  'spreadsheet'
* limitanswers_help,mod_choice - additional wording added explaining how
  the setting works with groups
2019-04-29 11:50:36 +02:00
Jun Pataleta f47cc5ce3f Merge branch 'MDL-65279-35' of https://github.com/tkorner/moodle into MOODLE_35_STABLE 2019-04-29 17:08:29 +08:00
AMOS bot 9f504db2f3 Automatically generated installer lang files 2019-04-27 00:12:52 +00:00
Eloy Lafuente (stronk7) 9e5cda1f6c weekly release 3.5.5+ 2019-04-26 18:41:11 +02:00
Amaia Anabitarte 3751ec0e68 MDL-63137 mod_feedback: PHPUnit tests for new userid parameter 2019-04-26 17:32:57 +02:00
Amaia Anabitarte 5a93c6c9ab MDL-63137 mod_feedback: mod_feedback_core_calendar_provide_event_action
Update mod_feedback_core_calendar_provide_event_action function to add a new userid parameter
Add userid to check capabilities, etc. to feedback completion and structure.
2019-04-26 17:32:57 +02:00
Amaia Anabitarte 596aa22c4e MDL-63137 mod_feedback: Pointing TODO tasks to right deprecation issue 2019-04-26 17:32:57 +02:00
Eloy Lafuente (stronk7) cc72ae7f29 MDL-60418 Behat: Fix missing $installurl 2019-04-25 23:39:11 +02:00
Eloy Lafuente (stronk7) 7aa7b392c0 Merge branch 'MDL-60418_35' of git://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-04-25 23:26:19 +02:00
Tim Hunt 11a4683cfd MDL-60418 Behat: Fix broken docs links in Behat code. 2019-04-25 21:39:28 +01:00
Eloy Lafuente (stronk7) b6af039890 Merge branch 'MDL-64151-35-fix' of https://github.com/marinaglancy/moodle into MOODLE_35_STABLE 2019-04-24 12:49:58 +02:00
Marina Glancy 69e9f234e1 MDL-64151 forms: select element without selection
Select element that is not multiple should export null when nothing is
selected. If the element is displayed there will always be something
selected.
2019-04-24 11:42:03 +02:00
Sara Arjona b7f0a3fd9c Merge branch 'MDL-65170-35' of https://github.com/snake/moodle into MOODLE_35_STABLE 2019-04-24 09:02:54 +02:00
Adrian Greeve 4f701a0e67 Merge branch 'MDL-65375-m35' of https://github.com/sammarshallou/moodle into MOODLE_35_STABLE 2019-04-24 10:31:46 +08:00
Eloy Lafuente (stronk7) 45b9bae80f Merge branch 'MDL-64151-35' of git://github.com/marinaglancy/moodle into MOODLE_35_STABLE 2019-04-23 19:39:16 +02:00
Eloy Lafuente (stronk7) 5d3bf61c27 weekly release 3.5.5+ 2019-04-23 17:36:22 +02:00
David Monllaó c344124599 Merge branch 'MDL-65102-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-04-23 13:31:05 +02:00
sam marshall 22baf5c0aa MDL-65375 Restore: Null data in other field should be serialised
If the 'other' field is empty, then following a restore of course
logs, it should still be serialised so that it is consistent with
the normal behaviour when logging.

Without this change, an event with null value for other has the
field set to NULL if you restore it, but 'N;' when the event is
initially created.
2019-04-18 15:07:40 +01:00
Adrian Greeve f1125775fe Merge branch 'MDL-29318-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-04-18 13:51:36 +08:00
Eloy Lafuente (stronk7) ca0f244e09 weekly release 3.5.5+ 2019-04-17 20:04:20 +02:00
Eloy Lafuente (stronk7) 216ea27814 Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-04-17 20:04:16 +02:00
AMOS bot e0ea44ae29 Automatically generated installer lang files 2019-04-13 00:13:30 +00:00
Eloy Lafuente (stronk7) 8ffac7d8e3 weekly release 3.5.5+ 2019-04-12 21:35:08 +02:00
Eloy Lafuente (stronk7) 8d0c6ac9dd Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-04-12 21:35:06 +02:00
Jake Dallimore 5b7563dbb2 Merge branch 'MDL-62974-35' of github.com:abgreeve/moodle into MOODLE_35_STABLE 2019-04-12 11:18:24 +08:00
Adrian Greeve 8bf1ffc9ed MDL-62974 mod_lesson: Minor update to html class. 2019-04-12 11:10:41 +08:00
Eloy Lafuente (stronk7) b3d49c46eb Merge branch 'MDL-62974-35' of https://github.com/jmvedrine/moodle into MOODLE_35_STABLE 2019-04-11 23:50:18 +02:00
Marina Glancy 98af4c736d MDL-64151 form: autocomplete element remove last choice
This is the same situation as was in MDL-56864 but now in 'course', 'autocomplete' and 'select' elements
- if the element allows multiple selection it is impossible to remove the last element
2019-04-11 16:46:33 +02:00
Sara Cenni 2653ea76be MDL-64851 badge: reviewing badges of invisible courses 2019-04-11 12:03:42 +02:00
Adrian Greeve 367a45a60b Merge branch 'MDL-64719-purge_user_cache-35' of git://github.com/leonstr/moodle into MOODLE_35_STABLE 2019-04-11 13:40:15 +08:00
Adrian Greeve 1da8aa30e0 Merge branch 'MDL-46975-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-04-10 14:26:50 +08:00
AMOS bot 2e9bc58475 Merge branch 'MOODLE_35_STABLE' into install_35_STABLE 2019-04-10 00:12:29 +00:00
Jean-Michel Vedrine dd74898f63 MDL-62974 lesson: Suppress HTML font tags 2019-04-09 23:04:26 +02:00
Eloy Lafuente (stronk7) 12476a35a6 weekly release 3.5.5+ 2019-04-09 20:37:04 +02:00
Eloy Lafuente (stronk7) bf35831359 Merge branch 'MDL-64819-35' of https://github.com/sarjona/moodle into MOODLE_35_STABLE 2019-04-09 16:04:02 +02:00
Sara Arjona cc145e54fd MDL-64819 course: fix behat errors with the move icon
Some errors have been detected when using Clean + Goutte.
2019-04-09 14:16:42 +02:00
AMOS bot 48f96614ff Automatically generated installer lang files 2019-04-09 00:11:32 +00:00
AMOS bot 4066dda725 Automatically generated installer lang files 2019-04-09 00:11:32 +00:00
Sara Arjona 0a91d215c6 Merge branch 'MDL-64819-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-04-08 14:20:03 +02:00
Adrian Greeve 6d0e1fe82d Merge branch 'MDL-65218-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-04-08 16:56:31 +08:00
Damyon Wiese b7218d8a10 MDL-64819 output: Hide icons with no title
When output from javascript they should match what gets output from php.
2019-04-08 15:42:07 +08:00
Shamim Rezaie de2f0d85e7 MDL-65293 core_calendar: Privacy deletion fix
Deleting in course context should not delete from course modules
2019-04-08 15:41:09 +10:00
Jake Dallimore 077825f8c9 MDL-65170 core_user: perf improvement for user_get_user_details_courses
We don't always need to iterate over the user's courses, so only fetch
them when we do.
2019-04-08 09:05:40 +08:00
Jake Dallimore 06d2ee0fde MDL-65170 core_user: user_get_user_details_courses respects groupmode
This had a relatively simply check for course profile visibility, which
meant that users in separate groups could see one another's profile.
This has been replaced with the more correct check in
user_can_view_profile().
2019-04-08 09:05:40 +08:00
Eloy Lafuente (stronk7) 96607cf5b3 weekly release 3.5.5+ 2019-04-05 18:32:34 +02:00
Eloy Lafuente (stronk7) b290b3eded NOBUG: Fixed file access permissions 2019-04-05 18:32:34 +02:00
Thomas Korner f059d1176c MDL-65279 core: typo in categoriesandcourses fixed
AMOS BEGIN
 MOV [categoriesandcoures,core],[categoriesandcourses,core]
AMOS END
2019-04-05 14:35:09 +02:00
Damyon Wiese 0f389d44b6 MDL-64819 output: Activity menu icons
Remove duplciate alt text from activity menu icons and the links to add new sections.
2019-04-05 12:03:10 +08:00
Eloy Lafuente (stronk7) 29dba99cdf Merge branch 'MDL-65029_35' of git://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-04-05 00:48:08 +02:00
Eloy Lafuente (stronk7) 7e7b71fbeb Merge branch 'MDL-65094-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-04-04 22:40:10 +02:00
Eloy Lafuente (stronk7) 4f2ee1dec1 Merge branch 'MDL-65038_MOODLE_35_STABLE' of https://github.com/maksudr/moodle into MOODLE_35_STABLE 2019-04-04 20:31:31 +02:00
Jun Pataleta f7a4ef3866 Merge branch 'MDL-62307_MOODLE_35_STABLE' of https://github.com/maksudr/moodle into MOODLE_35_STABLE 2019-04-03 16:47:56 +08:00
Jun Pataleta 6181040347 Merge branch 'MDL-65112-MOODLE_35_STABLE' of https://github.com/dmitriim/moodle into MOODLE_35_STABLE 2019-04-03 16:19:16 +08:00
Eloy Lafuente (stronk7) 8082ff4805 Merge branch 'MDL-64994-35-pythonmlversion' of git://github.com/mudrd8mz/moodle into MOODLE_35_STABLE 2019-04-03 00:09:45 +02:00
Eloy Lafuente (stronk7) 5e2338c868 weekly release 3.5.5+ 2019-04-02 15:52:50 +02:00
Eloy Lafuente (stronk7) 6909b8aada Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-04-02 15:52:44 +02:00
Adrian Greeve 80c1b6bcd0 Merge branch 'MDL-65144-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-04-02 10:17:37 +08:00
Brendan Heywood d6455734d8 MDL-64394 core: Fixed bug when using access log with pre_loginpage_hook 2019-04-02 11:41:00 +11:00
Ilya Tregubov c91c235fb6 MDL-64439 auth: Refresh $cm in require_login after pre_loginpage_hook. 2019-04-02 10:22:41 +11:00
Leon Stringer f9ea236c4f MDL-64719 cache: Implement purge_current_user() in \cache
\cache::make() may return a cache_disabled subclass but callers, specifically
user/lib.php:user_create_user(), invoke \cache::purge_current_user() which was
only implemented by the cache_session subclass.  Added empty
\cache::purge_current_user() which subclasses can implement, i.e.
cache_session, or not, i.e. cache_disabled.
2019-04-01 15:32:42 +01:00
Damyon Wiese 61adf3b25b MDL-65144 output: Add img-fluid to logo
Extra wide logos do not scale to the screen size - this change adds the bootstrap class
img-fluid to logos on the loginpage, signupform and in the context header.

Thanks to Maksud R for working on this.
2019-04-01 15:52:16 +08:00
Jake Dallimore e9c0b71aee Merge branch 'MDL-65089_35' of https://github.com/dvdcastro/moodle into MOODLE_35_STABLE 2019-04-01 15:34:40 +08:00
Jun Pataleta 3304b0728c Merge branch 'MDL-64524-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-04-01 13:46:34 +08:00
Damyon Wiese d831bfbf04 MDL-64524 gradingform_guide: Marking guide comments
When there are too many comments, scroll the list so they still fit in the dialogue.
2019-04-01 13:03:59 +08:00
Damyon Wiese 6bfcfd9a1f MDL-64524 assign: Styles editpdf comments
Properly display the list of comments, but limiting their size (use title to indicate the full comments).
When there are too many comments, show a scrollbar in the menu.
2019-04-01 13:03:58 +08:00
Jun Pataleta 9cbdd41129 Merge branch 'MDL-63906_35' of git://github.com/dmonllao/moodle into MOODLE_35_STABLE 2019-04-01 10:31:51 +08:00
Adrian Greeve c56206cebf Merge branch 'MDL-65173_35' of git://github.com/markn86/moodle into MOODLE_35_STABLE 2019-04-01 10:23:54 +08:00
Eloy Lafuente (stronk7) 71c0f9c055 MDL-65218 recycle bin: cover immunization via settings provider
Both for course and category recycle bins
2019-04-01 09:26:55 +08:00
Eloy Lafuente (stronk7) 5e3ce4ef7d MDL-65218 recycle bin: immunize recycle bin from backup_auto_storage
As far as recycle bin is using MODE_AUTOMATED, it observes the backup_auto_storage
setting (storing backups @ real location. For recycle bin we want to ensure that
backup files are always stored in Moodle file area. In order to achieve that, we
hack the setting here via $CFG->forced_plugin_settings, so it won't interfere other
operations.  See MDL-65218 for more information.

This hack will be removed once recycle bin switches to use its own backup mode, with
own preferences and 100% appart from MODLE_AUTOMATED.
2019-04-01 09:26:55 +08:00
Eloy Lafuente (stronk7) 1e21aeb97c MDL-65218 recycle bin: Course backups (cat bin) to use MODE_AUTOMATED
Surely this should have been done as part of MDL-63263, but it wasn't.
Better let's do it here so every recycle bin backup is using the
very same mode.
2019-04-01 09:26:54 +08:00
Tim Hunt 403f2d450c MDL-65029 questions: refactor generation of question div id
We are planning to change the id in Moodle 3.7. However, the new
method name has been back-ported to stable branches, because we
know a lot of third-party question types like to have a single
branch which supports multiple Moodle versions.
2019-03-29 13:44:46 +00:00
Jun Pataleta c8ce874199 MDL-46975 core_auth: Make email validation case-insensitive
* Make email query case-insensitive
* Check only for duplicate emails if $CFG->allowaccountssameemail
is empty.
* Compare the values in "Email address" and "Email (again)" in the
signup form in a case-insensitive fashion.
2019-03-29 13:38:19 +08:00
Jun Pataleta 13cdeaf6a4 MDL-46975 auth_email: Behat test for email validation on signup 2019-03-29 13:38:19 +08:00
Jun Pataleta 0503fc7a35 MDL-29318 login: Handle email in case-insensitive manner
* Let get_complete_user_data() handle the fetching of user data and
  handle the logic of the errors to be shown based on the exception
  it throws. This also saves us 1 DB query by eliminating the need to
  count for the users that match a given email first before fetching
  user information.
2019-03-29 13:33:55 +08:00
Jun Pataleta 6abbe519d6 MDL-29318 login: Additional test for forgot_password_data_provider() 2019-03-29 13:33:55 +08:00
Jun Pataleta bdca601d03 MDL-29318 core: Fixes for get_complete_user_data()
* Added email in the list of case-insensitive fields.
* New optional parameter $throwexception for \get_complete_user_data().
  If true, an exception will be thrown when there's no matching record
  found or when there are multiple records found for the given field
  value. If false, it will simply return false.
  Defaults to false when not set. This ensures that
  get_complete_user_data() fetches the correct user data.
2019-03-29 13:33:55 +08:00
Jun Pataleta 4477b21322 MDL-29318 core: More unit tests for get_complete_user_data() 2019-03-29 13:30:19 +08:00
AMOS bot 1625acf3eb Automatically generated installer lang files 2019-03-29 00:15:35 +00:00
David Castro 8326e3d1a9 MDL-65089 glossary: Enforcing case comparison in SQL. 2019-03-28 18:33:02 -05:00
Dmitrii Metelkin c4658fd9e2 MDL-65112 mod_lesson: fix html for shortanswer responses 2019-03-29 08:31:24 +11:00
Eloy Lafuente (stronk7) d28abb632d weekly release 3.5.5+ 2019-03-28 16:49:09 +01:00
Eloy Lafuente (stronk7) 819ff2f3d7 Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-03-28 16:49:03 +01:00
Shamim Rezaie 2787bb5593 MDL-65102 core_form: autocomplete element to handle submit event 2019-03-28 15:18:49 +11:00
Eloy Lafuente (stronk7) 2ca6891e1f Merge branch 'MDL-63196-35' of git://github.com/lameze/moodle into MOODLE_35_STABLE 2019-03-28 00:12:54 +01:00
Eloy Lafuente (stronk7) 5381aad94a Merge branch 'MDL-64996-35-untrainedstaticmodels' of git://github.com/mudrd8mz/moodle into MOODLE_35_STABLE 2019-03-27 23:46:29 +01:00
Eloy Lafuente (stronk7) 618b27a8ae Merge branch 'MDL-62992-35' of git://github.com/lameze/moodle into MOODLE_35_STABLE 2019-03-27 23:06:29 +01:00
Jun Pataleta 1ed39a4991 Merge branch 'MDL-65008_moodle_35_stable' of https://github.com/dvdcastro/moodle into MOODLE_35_STABLE 2019-03-27 10:39:49 +08:00
Simey Lameze 2427689f4c MDL-62992 quiz: fix tags filtering on random question modal 2019-03-27 10:26:33 +08:00
Simey Lameze 89b9e4f805 MDL-62992 question: conditionaly enable question tags feature 2019-03-27 10:26:33 +08:00
Paul Holden 4418ec9411 MDL-43130 access: fix user counting when retrieving assignable roles.
Previously users assigned the same role in a context via multiple
components would be counted multiple times.
2019-03-27 00:18:13 +01:00
Eloy Lafuente (stronk7) 5fbbcddd0c Merge branch 'MDL-65081-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-03-26 22:44:10 +01:00
Eloy Lafuente (stronk7) 25570f80dc Merge branch 'MDL-63152-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-03-26 13:28:31 +01:00
Eloy Lafuente (stronk7) 0f038af8de Merge branch 'MDL-63149-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-03-26 13:25:20 +01:00
Eloy Lafuente (stronk7) 5e97ea1423 Merge branch 'MDL-63151-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-03-26 13:16:06 +01:00
Shamim Rezaie 2e790a9741 MDL-65094 registration: don't encourage registration if on localhost 2019-03-26 17:26:35 +11:00
Damyon Wiese 68b61978e8 MDL-65178 competencies: count_competencies fix
Fix sql error in course_module_competency::count_competencies() function.
2019-03-26 09:49:08 +08:00
Sara Arjona 0eff5b7765 Merge branch 'MDL-64615-35' of git://github.com/jleyva/moodle into MOODLE_35_STABLE 2019-03-25 18:20:22 +01:00
Sara Arjona fd0b312303 Merge branch 'MDL-64790-35_apidoc_fix' of https://github.com/nicoroeser/moodle into MOODLE_35_STABLE 2019-03-25 12:38:30 +01:00
Mark Nelson cfa3409712 MDL-65173 message_email: removed bogus logic
This reverts commit ecb4b0260e.
2019-03-25 17:19:27 +08:00
David Mudrák 15d1157600 MDL-64994 analytics: Improve the Python package version check
Use the new method to check that the installed Python package has high
enough yet still API-compatible version.
2019-03-25 09:19:51 +01:00
David Mudrák a1026db0fe MDL-64994 analytics: Add a simple semantic version check method
This method is to be used for checking that a compatible version of the
moodlemlbackend package is installed on the server. The package is
expected to use the semantic versioning scheme (semver.org).
2019-03-25 09:19:51 +01:00
David Mudrák 959c70e87b MDL-64996 analytics: Make sure the no_teaching model is trained
Due to the bug, the no_teaching model might have been marked as
not-trained in the database. Static predictions models (i.e. those using
a target based on assumptions, not facts) are always considered as
trained. If they were marked as not-trained, the prediction scheduled
task would skip them and they would produce no predictions.

Ideally, such a fix should be done for all static models. But there is
no easy way to do it during the upgrade where accessing the analytics
API is not possible. I don't think there are many models out there that
would be affected by this so this seems to be good enough solution for
now (and the future ability to reset models will cover the rest).
2019-03-25 09:16:13 +01:00
David Mudrák 8e2360f9c8 MDL-64996 analytics: Don't mark static model as untrained after clearing
Static predictions models (i.e. those using a target based on
assumptions, not facts) are always considered as trained. Clearing them
must not mark them as untrained. Doing so would make them being skipped
by the prediction scheduled task.
2019-03-25 09:14:32 +01:00
Adrian Greeve 55d5362ab6 Merge branch 'MDL-60339-35' of git://github.com/Chocolate-lightning/moodle into MOODLE_35_STABLE 2019-03-25 11:12:12 +08:00
Adrian Greeve e1c280f951 Merge branch 'MDL-64492-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-03-25 11:00:40 +08:00
AMOS bot 238585c911 Automatically generated installer lang files 2019-03-25 00:09:32 +00:00
Abhimanyu Kumar d7903d34f0 MDL-64959 uploaduser: remove leading/trailing spaces from CSV headings
Earlier while uploading users via CSV, if any leading or trailing space was there in
headings of CSV file then error was displayed which will be difficult for a non-technical
person to understand. After this patch, leading and trailing spaces from headings will
be trimmed automatically.
2019-03-23 22:34:28 +05:30
maksudr 710b4e0a4b MDL-62307 mod_feedback: Decode HTML special char in add_form_element() 2019-03-22 15:45:16 +00:00
Mathew May 0c74fb3f82 MDL-60339 course: Course editing only checked against site:manageblocks.
Add in additional capabilities to the page. When all_editing_caps is called it'll check against
moodle/site:manageblocks & added capabilities. If moodle/site:manageblocks
was not set the user would have trouble editing the page.
2019-03-22 13:51:58 +08:00
Damyon Wiese ab3236199d MDL-65153 competencies: Urls course competencies
The template for the course competencies page expects a pluginbaseurl parameter
but the webservice that fetches when rendered by AJAX is missing this property.
2019-03-22 13:18:03 +08:00
Jun Pataleta 67d62946ff MDL-65081 core_output: Unit tests for single_select and url_select 2019-03-22 11:15:24 +08:00
Jun Pataleta 9415d26ea4 MDL-65081 core_output: Set single_select and url_select attributes 2019-03-22 11:15:24 +08:00
Damyon Wiese c2a956a63d MDL-64492 course: Hide activity icons for Ally
Empty alt text results in an image with no label.
role="presentation" does not hide - it only removes the semantic information.
If the image provides no information, make it hidden with aria-hidden.
2019-03-22 11:01:42 +08:00
Simey Lameze d9af5335c2 MDL-63196 core_calendar: add behat scenario 2019-03-22 10:46:02 +08:00
Simey Lameze 4c0ea3f45e MDL-63196 calendar: add missing option to export category events 2019-03-22 10:46:02 +08:00
Damyon Wiese d707892d0c MDL-65149 emoticons: Do not show all emoticons
Allow some emoticons to still work, but not be selectable from the text editor plugins.
2019-03-22 10:07:15 +08:00
Eloy Lafuente (stronk7) d70651f787 weekly release 3.5.5+ 2019-03-21 20:19:36 +01:00
Cameron Ball c55d75120a MDL-65104 registration: Ensure $registration is always null when no record exists 2019-03-21 16:12:31 +08:00
Adrian Greeve 59f0c4b48a Merge branch 'MDL-46803-greedy-roles-reset-MOODLE_35' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_35_STABLE 2019-03-21 11:23:42 +08:00
Eloy Lafuente (stronk7) f4ae633fa5 Merge branch 'wip-35-MDL-64563' of https://github.com/adpe/moodle into MOODLE_35_STABLE 2019-03-21 00:44:05 +01:00
Eloy Lafuente (stronk7) 89eded8477 MDL-63263 tool_recyclebin: show the note as part of the heading element
It looks better (IMO) than using admin_setting_description and works in all
branches.
2019-03-21 00:15:08 +01:00
Eloy Lafuente (stronk7) 57b5bf77b7 Merge branch 'MDL-63263-MOODLE_35_STABLE' of https://github.com/tuanngocnguyen/moodle into MOODLE_35_STABLE 2019-03-20 23:16:26 +01:00
Eloy Lafuente (stronk7) dc5d047953 Merge branch 'MDL-65022-35' of https://github.com/Dagefoerde/moodle into MOODLE_35_STABLE 2019-03-20 22:32:10 +01:00
M 8f9f22aeb3 MDL-65038 core_files: Fix typo in function mock_response 2019-03-20 20:52:48 +00:00
Jun Pataleta 500ea66aba Merge branch 'MDL-62872-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-03-20 16:30:20 +08:00
Adrian Greeve 5c12024435 Merge branch 'MDL-65005-35-fix' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-03-20 13:58:38 +08:00
Jun Pataleta 51feaeafa2 MDL-65005 tool_policy: Ensure the user's on the Dashboard after agreeing 2019-03-20 13:13:35 +08:00
Eloy Lafuente (stronk7) bccd34fa0a Merge branch 'MDL-65085_35' of git://github.com/dmonllao/moodle into MOODLE_35_STABLE 2019-03-20 00:40:38 +01:00
Eloy Lafuente (stronk7) 77e067dc2e Merge branch 'MDL-64979-m35' of https://github.com/sammarshallou/moodle into MOODLE_35_STABLE 2019-03-19 22:09:43 +01:00
sam marshall 0ec20a18a4 MDL-64979 Behat: Add option to increase timeouts 2019-03-19 17:13:47 +00:00
Adrian Greeve d402e44ab9 Merge branch 'MDL-64958-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-03-19 13:43:54 +08:00
Adrian Greeve a8ad45b9e8 Merge branch 'MDL-63144-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-03-19 11:27:32 +08:00
Eloy Lafuente (stronk7) b60590a2fa Merge branch 'MDL-64974-35' of git://github.com/sarjona/moodle into MOODLE_35_STABLE 2019-03-19 00:23:58 +01:00
Eloy Lafuente (stronk7) 25160a2a05 Merge branch 'MDL-65006-35' of git://github.com/sarjona/moodle into MOODLE_35_STABLE 2019-03-18 23:36:08 +01:00
Julien Boulen 849f7f40c8 MDL-46803 course: Prevent unenrol users with multiple roles during reset 2019-03-18 11:17:58 +01:00
David Monllaó 36ec2d7503 MDL-63906 analytics: Release the lock on \Throwable received 2019-03-18 09:31:46 +01:00
Shamim Rezaie e3a7647ec3 MDL-63152 mod_workshop: Add userid param to calendar callbacks 2019-03-18 15:53:42 +11:00
Shamim Rezaie 70c84f07d7 MDL-63152 mod_workshop: check if the module is visible to the user 2019-03-18 15:53:42 +11:00
Shamim Rezaie 485ac4aeba MDL-62872 atto_recordrtc: max_filesize detection fix 2019-03-18 15:42:15 +11:00
Jake Dallimore ca39432c7a Merge branch 'MDL-65291_35' of git://github.com/stronk7/moodle into MOODLE_35_STABLE 2019-03-16 07:19:30 +08:00
Eloy Lafuente (stronk7) e1de53be9f Merge branch 'MDL-65179-m35' of https://github.com/sammarshallou/moodle into MOODLE_35_STABLE 2019-04-16 20:44:42 +02:00
David Monllaó 7c05382b75 Merge branch 'MDL-62572-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-04-15 11:07:14 +02:00
David Monllaó 8d371c2174 Merge branch 'wip-MDL-65220-MOODLE_35_STABLE' of https://github.com/jason-platts/moodle into MOODLE_35_STABLE 2019-04-15 07:58:10 +02:00
David Monllaó 457f84654e Merge branch 'MDL-64894-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-04-15 07:45:48 +02:00
David Monllaó 87648029c4 Merge branch 'MDL-29317-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-04-15 07:43:38 +02:00
Eloy Lafuente (stronk7) 5fd2f276f1 MDL-65291 phpunit: Make a test immune to DST changes 2019-04-15 01:23:03 +02:00
Trisha Milan ba8f84021f MDL-64894 Theme: Fix unable to expand collapsible topics 2019-04-12 14:20:59 +08:00
Damyon Wiese 7f84843045 MDL-62572 backup: Duplicating an activity
Don't apply admin defaults for import when using the duplicate function.
2019-04-12 14:05:09 +08:00
Jason Platts 41bb7608e8 MDL-65220 behat: test scenarios sometimes do not clear database data 2019-03-29 15:30:30 +00:00
Jun Pataleta b9ceefadf0 MDL-29317 gradeimport_csv: Case-insensitive query for email and username
Query using the following fields for
\gradeimport_csv_load_data::check_user_exists() should be done in a
case-insensitive manner:
* email - As agreed in MDL-29315
* username - Although usernames can only be in lowercase during
  registration, usernames are being handled in a case-insensitive
  fashion when logging in. It makes sense to make check_user_exists()
  consistent with this behaviour.
2019-03-29 13:30:06 +08:00
Jun Pataleta 2ff2274ffc MDL-29317 gradeimport_csv: Tests for case-insensitivity 2019-03-29 13:30:06 +08:00
sam marshall 82a46e6f07 MDL-65179 Web service: Token last access is updated too frequently 2019-03-28 17:15:29 +00:00
David Monllaó e34384ed18 MDL-65085 analytics: noreply user sends insights 2019-03-15 13:50:09 +01:00
Nicolas Roeser 43121fbe8b MDL-64790 upgrade: parameter API doc regression fix
Partially update the API documentation of function
upgrade_plugin_savepoint.

This restores consistency between function parameters and API
documentation; as commit 17da2e6f28 (fix
for MDL-16438) had renamed parameter $dir to $plugin, but not also
applied this change to the API documentation.

Also reword the parameter comment text so that it is more meaningful to
developers: document that the parameter contains the name of the plugin.

Change the API documentation of parameter $type as well so that it is
a) correct, and
b) not in conflict with the API documentation for $plugin.
2019-03-15 11:11:44 +01:00
Nathan Nguyen fe033417a6 MDL-63263 tool_recyclebin: Apply automated backup setting
Use Automated backup settings as settings for Recycle bin backup and restore.
2019-03-15 14:53:15 +11:00
Rex Lorenzo 73c24fa02c MDL-63263 tool_recyclebin: Recycle bin should always save user data. 2019-03-15 14:53:15 +11:00
Jake Dallimore b1376641d4 weekly release 3.5.5+ 2019-03-15 11:01:27 +08:00
Paul Holden 546ea12179 MDL-46931 roles: retrieve distinct users in sub-query.
Prevents duplicate key column warning when a user is enrolled in
a course via multiple enrolment methods.
2019-03-14 01:27:42 +01:00
Eloy Lafuente (stronk7) 55c0301d33 Merge branch 'MDL-63146-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-03-14 01:22:19 +01:00
Eloy Lafuente (stronk7) cca1025271 Merge branch 'MDL-61585_35' of git://github.com/dmonllao/moodle into MOODLE_35_STABLE 2019-03-14 01:16:14 +01:00
Eloy Lafuente (stronk7) dda86847b1 Merge branch 'MDL-63524-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-03-13 23:56:58 +01:00
Andrew Nicols 12abff6943 MDL-63524 behat: Do not skip tests on Step 0 error 2019-03-14 06:55:23 +08:00
Juan Leyva e247dabc3a MDL-64615 tool_mobile: Do not modify custom download URLs 2019-03-13 17:10:36 +01:00
Jan Dageförde 22f5807e22 MDL-65022 wiki: declare the cancel button secondary 2019-03-12 09:06:22 +01:00
Shamim Rezaie 3be7a5ce18 MDL-63151 mod_wiki: Add userid param to mod_wiki calendar callbacks 2019-03-12 17:17:05 +11:00
Shamim Rezaie 34667451cf MDL-63151 mod_wiki: check if the module is visible to the user 2019-03-12 17:17:04 +11:00
Sara Arjona b02583be81 MDL-65006 policy: avoid loop when no policies need to be agreeded
Avoid an infinite loop when the user has no policies to agreed but
the policyagreed = 0.
2019-03-11 10:36:37 +01:00
Sara Arjona 4d53d44f2e MDL-64974 badges: add missing configurecriteria capability check 2019-03-11 10:25:49 +01:00
David Monllaó deb6d89f94 MDL-61585 analytics: Include missing indicators 2019-03-11 09:39:51 +01:00
Jun Pataleta 9820d27a23 MDL-64958 gradeimport_csv: Better unit tests for check_user_exists() 2019-03-11 09:36:00 +08:00
Jun Pataleta 78615db17f MDL-64958 grade_import: Ensure correct user is being fetched
* We need to ensure that we are checking the correct user account.
  Since email and idnumber are not unique fields, there's a chance that
  multiple user records will match when querying for user data using
  these fields. This might lead to a different user's grades being
  inadvertently modified during grade import. In such a case, this
  function needs to return a null userid.
2019-03-11 09:36:00 +08:00
David Castro 8d34e84bb9 MDL-65008 question: Query enhancement.
Adding core_question as an additional filter to the tag backup.
2019-03-08 16:34:25 -05:00
Sara Arjona 5e878219fb Moodle release 3.5.5 2019-03-08 11:03:11 +01:00
AMOS bot e8c0748998 Automatically generated installer lang files 2019-03-08 00:15:31 +00:00
Eloy Lafuente (stronk7) 8360ef9293 weekly release 3.5.4+ 2019-03-07 16:41:53 +01:00
Eloy Lafuente (stronk7) d750647969 Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-03-07 16:41:51 +01:00
Shamim Rezaie f20c9009fa MDL-63149 mod_survey: Add userid param to mod_survey calendar callbacks 2019-03-07 17:54:54 +11:00
Shamim Rezaie 3be433b5d2 MDL-63144 mod_lti: Add userid param to mod_lti calendar callbacks 2019-03-07 17:49:30 +11:00
Shamim Rezaie 3086259abb MDL-63144 mod_lti: Check if the module is visible to the user 2019-03-07 17:49:30 +11:00
Adrian Greeve 2a3758ace1 Merge branch 'MDL-63905_35' of git://github.com/jmvedrine/moodle into MOODLE_35_STABLE 2019-03-07 09:14:46 +08:00
Andrew Nicols a868b63085 Merge branch 'MDL-64774-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-03-06 15:47:36 +08:00
Jean-Michel Vedrine ffe4e082b0 MDL-63905 qtype_multianswer: validate imported questions 2019-03-06 08:36:43 +01:00
Andrew Nicols e4a8e40912 Merge branch 'MDL-64950-35-2' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-03-06 13:48:18 +08:00
Jun Pataleta b51a2ccba5 MDL-64950 core: Handle username in a case-insensitive fashion 2019-03-06 12:46:14 +08:00
Jun Pataleta 0cdffdca4c MDL-64950 core: Unit tests for get_complete_user_data() 2019-03-06 12:46:14 +08:00
Jun Pataleta bdf22ec3b7 MDL-64950 login: core_login_validate_forgot_password_data() unit tests 2019-03-06 12:46:14 +08:00
Andrew Nicols 5d4597cda7 MDL-64971 access: Ensure that the capability exists when fetching 2019-03-06 10:16:54 +08:00
Jun Pataleta 90a5693234 MDL-64774 user: Make email query case-insensitive 2019-03-06 09:00:32 +08:00
Jun Pataleta aec6391bc2 MDL-64774 user: Better unit tests for updating users with similar emails 2019-03-06 09:00:32 +08:00
AMOS bot 21f27a2bd3 Automatically generated installer lang files 2019-03-06 00:09:40 +00:00
Eloy Lafuente (stronk7) 9f071b48c5 Merge branch 'MDL-64943_35' of git://github.com/stronk7/moodle into MOODLE_35_STABLE 2019-03-05 22:49:54 +01:00
Eloy Lafuente (stronk7) 3717e40450 MDL-64943 behat: fix some remaining uses of old strings 2019-03-05 17:02:28 +01:00
Eloy Lafuente (stronk7) f7e4dacd1e Merge branch 'MDL-64943-35-enfix' of git://github.com/mudrd8mz/moodle into MOODLE_35_STABLE 2019-03-05 11:09:42 +01:00
Jun Pataleta c80db2680f Merge branch 'MDL-62465-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-03-05 15:29:55 +08:00
Damyon Wiese 438cf695bf MDL-62465 assign: Remove behat step
We don't need to open the menu to choose the "Grade" item, we can just click the button.
2019-03-05 14:49:51 +08:00
Adrian Greeve cc52293498 Merge branch 'MDL-64864-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-03-05 14:27:21 +08:00
Adrian Greeve 3eab97cc34 Merge branch 'MDL-64678-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-03-05 13:54:09 +08:00
Andrew Nicols e225d71259 Merge branch 'MDL-64961-m35' of https://github.com/sammarshallou/moodle into MOODLE_35_STABLE 2019-03-05 13:25:17 +08:00
Andrew Nicols 2504aa33e0 Merge branch 'MDL-64981_35' of https://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-03-05 13:23:07 +08:00
Shamim Rezaie 4480118b5d MDL-63146 mod_quiz: Add userid param to mod_quiz calendar callbacks 2019-03-05 14:23:47 +11:00
Shamim Rezaie 816e6abb1b MDL-64830 core_calendar: Do cap check on event edit form 2019-03-05 04:21:41 +01:00
Damyon Wiese d3f2f990dd MDL-64651 comments: Do not send referrer
Use blanktarget option on all comments to prevent malicious links.
2019-03-05 04:21:41 +01:00
Viktor 427463a525 MDL-62702 core_lib: fix broken verification signature 2019-03-05 04:21:41 +01:00
Mark Nelson f46413cb03 MDL-62702 core_lib: updated the 'ltiprovider' readme_moodle.txt 2019-03-05 04:21:41 +01:00
Brendan Cox 723d1a7475 MDL-62702 core_lib: parameters in POST override other LTI values
This fixes an exploit where you could alter the 'Content-Type' of the
request and bypass the case-sensitive check 'strstr'. For example,
setting it to 'application/x-www-FORM-urlencoded'. However, changing
this to use 'stristr' was also not an acceptable approach as you
could also bypass it by setting the value to 'multipart/form-data'.
2019-03-05 04:21:41 +01:00
Ryan Wyllie 070f24d006 MDL-63786 core: set $CFG->forceclean for logged in as sessions
Turn on the forceclean config setting when a user is logged in as a
different user. This is a precautionary measure, which forces all
user submitted content to be cleaned of JavaScript before rendering
it to the logged in as user.
2019-03-05 04:21:41 +01:00
Luca Bösch 911f748806 MDL-64706 theme_boost: Remove logo link in secure template 2019-03-05 04:21:41 +01:00
Jun Pataleta 9ed8cafff3 Merge branch 'MDL-64652-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-03-05 11:13:13 +08:00
Adrian Greeve d85fed227b Merge branch 'MDL-64941-35' of https://github.com/MartinGauk/moodle into MOODLE_35_STABLE 2019-03-05 11:11:58 +08:00
Andrew Nicols 0b9e9bf89d MDL-64652 mod_data: Break LEFT JOINs to multiple INNER 2019-03-05 10:17:36 +08:00
Andrew Nicols ed5a080034 MDL-64652 glossary: Break LEFT JOINs to multiple INNER 2019-03-05 10:17:36 +08:00
Andrew Nicols 419275478b MDL-64652 forum: Use an inner join when fetching ratings 2019-03-05 10:17:36 +08:00
Andrew Nicols 6a06c7ca03 MDL-64652 rating: Add optional inner join option to sql 2019-03-05 10:17:35 +08:00
Andrew Nicols 6b9cce6b98 MDL-64652 mod_forum: Performance improvement for provider
There are possibly some further improvements that can be made to:
- export_discussion_data
- export_all_posts
2019-03-05 10:17:10 +08:00
Adrian Greeve f8e7257327 Merge branch 'MDL-64863-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-03-05 09:51:11 +08:00
Jun Pataleta 37a1983740 Merge branch 'MDL-62143-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-03-05 09:41:20 +08:00
Damyon Wiese ebbb7f9a5f MDL-64864 core_competency: Include course category
These courses are passed through to the course_summary_exporter which
requires a category id in each course record.
2019-03-05 08:54:17 +08:00
Damyon Wiese 95209cb64a MDL-64678 assign: More ios touch
Only disable touch scrolling when the touch event is within the drawing region of the canvas.
2019-03-05 08:49:49 +08:00
AMOS bot 973c2551aa Automatically generated installer lang files 2019-03-04 00:09:51 +00:00
sam marshall cdfdef65b5 MDL-64961 REST web service: Fatal error in error handler 2019-03-01 11:57:52 +00:00
Tim Hunt 7f5479a142 MDL-64981 dml tests: pgsql_native_recordset_testcase port number 2019-03-01 11:14:20 +00:00
Martin Gauk 5320dc6722 MDL-64941 qtype_multianswer: keep order of existing wrapped questions 2019-03-01 09:50:05 +00:00
AMOS bot c67c536dfe Automatically generated installer lang files 2019-03-01 00:15:55 +00:00
David Mudrák 4c73fd62b0 MDL-64943 lang: Fix regression in the test caused by the reworded string 2019-02-28 20:00:52 +01:00
Eloy Lafuente (stronk7) b38eb7882b weekly release 3.5.4+ 2019-02-28 18:51:41 +01:00
Eloy Lafuente (stronk7) c4af3e8ec1 Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-02-28 18:51:38 +01:00
David Mudrák d5cdc97b2f MDL-64943 lang: Fix regressions in Behat caused by reworded strings 2019-02-28 18:07:03 +01:00
Helen Foster bc2a000664 MDL-64943 lang: Import fixed English strings (en_fix)
Significant string changes:

* importgroups_help,core_group - Correcting optional fieldnames
  (removing picture, hidepicture and adding groupidnumber, groupingname
  and enablemessaging)

* penaltyforeachincorrecttry_help,core_question - additional paragraph
  about scoring logic

* resultdownloadready,tool_dataprivacy - wording corrected (no need to
  go to a download page)

* auth_dbfielduser,auth_db - varchar data type requirement
2019-02-28 18:02:44 +01:00
Juan Leyva 651f5c494b MDL-64444 mod_assign: Use correct permissions for viewing grades
Some WebServices does not use the correct permissions.
Now we are using assign own API (require_view_grades()) instead.

Note this patch is different from the 36_STABLE and master ones
because there isn't context freezing here. Just we decided to
apply the changes for consistent perm evaluation in all branches.
2019-02-28 01:25:13 +01:00
Sara Arjona 536faec42a Merge branch 'MDL-55135-35-competencies-manage-in-coursecontext' of https://github.com/wjroes/moodle into MOODLE_35_STABLE 2019-02-27 11:51:51 +01:00
Sara Arjona c7ff973845 Merge branch 'MDL-62454-35' of git://github.com/bmbrands/moodle into MOODLE_35_STABLE 2019-02-27 08:58:31 +01:00
Andrew Nicols 3235bb616d Merge branch 'MDL-64889_35_STABLE' of https://github.com/marxjohnson/moodle into MOODLE_35_STABLE 2019-02-27 14:44:18 +08:00
Andrew Nicols 86c240ddfa Merge branch 'wip-35-MDL-62345' of https://github.com/adpe/moodle into MOODLE_35_STABLE 2019-02-27 14:14:35 +08:00
Andrew Nicols a94b5db132 Merge branch 'MDL-63674-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-02-27 13:04:33 +08:00
Andrew Nicols 47ff684a89 Merge branch 'MDL-64591_35' of https://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-02-27 09:55:05 +08:00
AMOS bot 50733f26f7 Automatically generated installer lang files 2019-02-27 00:09:51 +00:00
Eloy Lafuente (stronk7) d14925e818 Merge branch 'MDL-63417-35' of git://github.com/mihailges/moodle into MOODLE_35_STABLE 2019-02-26 23:19:25 +01:00
Sara Arjona a5dfb4cb3b Merge branch 'MDL-43428-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-02-26 14:09:15 +01:00
Tim Hunt 591a7952c2 MDL-64591 User tours: don't show during redirects & other bad times 2019-02-26 13:06:36 +00:00
Shamim Rezaie f4713ca7ec MDL-43428 accessrule_timelimit: timeclose can be ealier than timelimit 2019-02-26 14:45:37 +11:00
Adrian Greeve ce0a325481 Merge branch 'MDL-64640-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-02-25 10:29:35 +01:00
Andrew Nicols e12a258678 Merge branch 'MDL-64561-35-test' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-02-25 15:53:34 +08:00
Charles Fulton 2f9592c57a MDL-64561 install: show help text before database check 2019-02-25 16:44:35 +11:00
Shamim Rezaie 79cbc5ca4c MDL-63674 core_messaging: Bidi text support 2019-02-25 14:44:05 +11:00
Adrian Perez e6e776dc77 MDL-62345 navigation: Change data-key for dashboard rootnode 2019-02-22 16:59:04 +01:00
Andrew Nicols f5dde8d05e weekly release 3.5.4+ 2019-02-22 10:51:25 +08:00
Andrew Nicols e8833c4a18 Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-02-22 10:51:20 +08:00
Bas Brands a71f1f4336 MDL-62454 theme_boost: numerical qtype answer inline 2019-02-21 14:38:32 +01:00
Adrian Greeve 6e3e7d3a01 Merge branch 'MDL-64729-35' into MOODLE_35_STABLE 2019-02-21 12:36:34 +01:00
John Beedell a37d6ab8ff MDL-64729 mod_glossary: glossary_get_entries_search case sensitivity 2019-02-21 12:35:45 +01:00
Adrian Greeve 96803a9db7 Merge branch 'MDL-64856_m35v1' of git://github.com/sbourget/moodle into MOODLE_35_STABLE 2019-02-20 18:06:16 +01:00
Adrian Greeve dfff9d51bb Merge branch 'MDL-64200-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-20 16:00:43 +01:00
Adrian Greeve c9bb208ba8 Merge branch 'MDL-64450-35' of git://github.com/peterRd/moodle into MOODLE_35_STABLE 2019-02-20 11:39:10 +01:00
Matteo Scaramuccia 7b5b613820 MDL-64443 git: Excluded vim swap files
Vim swap filenames are deterministic someway.
Refs:
- http://vimdoc.sourceforge.net/htmldoc/recover.html#swap-file
- https://github.com/vim/vim/blob/4efe73b478d3ba689078da502fd96f45204ff1f5/src/memline.c#L4683
- https://unix.stackexchange.com/a/326737
- https://github.com/github/gitignore/blob/master/Global/Vim.gitignore
2019-02-20 10:24:31 +01:00
David Monllaó 93551b5f58 MDL-64500 tool_analytics: noanalysables negation better than analysables 2019-02-20 10:10:18 +01:00
Andrew Nicols 6fb045026e Merge branch 'MDL-64570-35-fix1' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-20 10:55:32 +08:00
Damyon Wiese a6ad453ad7 MDL-64570 user: input field purpose
Do not autocomplete the user fields when editing another user.
2019-02-20 09:51:32 +08:00
Eloy Lafuente (stronk7) 6456fa0617 Merge branch 'MDL-64679_35' of git://github.com/dmonllao/moodle into MOODLE_35_STABLE 2019-02-20 00:07:09 +01:00
Eloy Lafuente (stronk7) 903be41022 Merge branch 'MDL-63134-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-02-20 00:01:11 +01:00
Eloy Lafuente (stronk7) 72163b6f59 Merge branch 'MDL-64806-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-19 23:35:13 +01:00
Eloy Lafuente (stronk7) 461981dca0 Merge branch 'MDL-64242_35' of git://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-02-19 23:23:14 +01:00
Eloy Lafuente (stronk7) d9b034dadb Merge branch 'MDL-62008-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-19 17:24:03 +01:00
Eloy Lafuente (stronk7) 0937c18c6d Merge branch 'MDL-64500_35' of git://github.com/dmonllao/moodle into MOODLE_35_STABLE 2019-02-19 17:10:56 +01:00
Eloy Lafuente (stronk7) 2e80ca02f3 Merge branch 'MDL-64540-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-19 15:42:11 +01:00
Adrian Greeve 331aec2f27 Merge branch 'MDL-60459_35' of git://github.com/markn86/moodle into MOODLE_35_STABLE 2019-02-19 11:51:11 +01:00
David Monllaó 6d31a91aff MDL-64570 user: Remove empty line 2019-02-19 09:26:57 +01:00
David Monllaó df51b94410 Merge branch 'MDL-64570-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-19 09:26:27 +01:00
David Monllaó c96968b7e9 Merge branch 'MDL-45151-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-19 06:40:33 +01:00
Damyon Wiese e995a79f7b MDL-64540 assign: Backport of MDL-60008
This patch combines the following changes:

* Basically we should produce a combined PDF from all the files that it was possible to convert.
* If any one submission input file fails conversion, it should just be omitted in the result.
* When not all files are available in the online pdf, display a warning to graders
that some files must be downloaded.
* Better support for information messages from the conversion process.
* Remove the z-index values from the expand / collapse panels. They cause errors when mixed with dialogues.
* The edit pdf menus are all broken on small screen sizes. They consume 100% of the page with for no reason.
* The heights of the buttons to hide/show panels are arbitrarily big. There is not need to set them specifically.
2019-02-19 10:23:50 +08:00
Damyon Wiese f148fa37cb MDL-64570 user: coding style
Fix cibot warnings on line length.
2019-02-19 09:45:24 +08:00
Damyon Wiese 1e1ab33625 MDL-64570 accessibility: autocomplete user profile fields
Only if editing your own user details and not logged in as someone else.
2019-02-19 09:45:24 +08:00
Damyon Wiese b049fa2c8d MDL-64570 accessibility: purpose login fields
Provide the autocomplete attribute and username / current-password values to username
and password fields in login forms.

https://www.w3.org/WAI/WCAG21/Understanding/identify-input-purpose.html
2019-02-19 09:45:23 +08:00
Adrian Greeve d6f6c78c73 Merge branch 'MDL-64452-35-cachesession' of git://github.com/mudrd8mz/moodle into MOODLE_35_STABLE 2019-02-18 15:55:59 +01:00
Mark Johnson 4c0a87629f MDL-64889 completion: Fix performance of get_course_progress_percentage 2019-02-18 14:06:37 +00:00
willem fb5836b42e MDL-55135 competencies: fix capabilities managing course competencies
Capability check in a course was using global competency capabilities 
moodle/competency:competencyview and  moodle/competency:competencymanage 
instead of the course equivalents. Users outside the course context 
could not manage course competencies.
2019-02-18 10:51:02 +01:00
AMOS bot 8fd354bc92 Automatically generated installer lang files 2019-02-16 00:14:07 +00:00
David Mudrák 8374e2db3f MDL-64452 cache: Add tests for key prefix based on session id
Unfortunately, we can't simply use session_id() to regenerate the
session id in unit tests. Starting from PHP 7.2, it would trigger
"session_id(): Cannot change session id when headers already sent",
refer to MDL-60978 and PHP bug #75628 for more details.

As a workaround, we use a static property allowing us to inject the
value that we then use as a session identifier. This is reasonably
enough to make sure that the identifier is used as a part of the key
prefix.
2019-02-15 09:38:09 +01:00
David Mudrák c4f137749d MDL-64452 cache: Always use the current session id in the key prefix
The current logic in the cache_session::check_tracked_user() is not
right. We must always set the current session id. A typical use case is
when the cache instance is instantiated for a not logged in user. We
can't let the sessionid property null in that case as it forms an
important part of the parsed key.

Similarly, even if we have the same user currently loaded, we must still
set the sessionid to make sure the data will be associated with the
current PHP session. Same user (including visitors or guest users) can
access the site from different browsers and each must end up with its
own key prefix.
2019-02-15 09:38:09 +01:00
David Monllaó 18735c9f51 MDL-64679 tool_analytics: Allow trained models to be cleared 2019-02-15 08:43:34 +01:00
Damyon Wiese 77474f4733 MDL-64863 tool_lp: Progress if needed
Do not immediately show progress bars since most operations work
in under a second. This will use the default timeout (5 seconds)
before showing progress bars.
2019-02-15 09:10:29 +08:00
Andrew Nicols 41a15e6d73 weekly release 3.5.4+ 2019-02-15 08:29:24 +08:00
Andrew Nicols bcd2debd4e Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-02-15 08:29:22 +08:00
Stephen Bourget 4440ca8121 MDL-64856 mod_glossary: Always show the settings cog on the view page. 2019-02-14 12:47:01 -05:00
Jun Pataleta 4d67bcdb5e Merge branch 'MDL-64736-35-2' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-02-14 15:00:42 +08:00
Jun Pataleta af3214adae Merge branch 'MDL-63892-35-rework' of git://github.com/mickhawkins/moodle into MOODLE_35_STABLE 2019-02-13 21:00:46 +08:00
Michael Hawkins a3f16eb4ea MDL-63892 mod_forum: Behat update for post order 2019-02-13 16:47:46 +08:00
Jun Pataleta 579700dcf4 Merge branch 'MDL-64835-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-02-13 16:27:00 +08:00
Andrew Nicols ea2ed45ec7 Merge branch 'MDL-64714-35' of git://github.com/cescobedo/moodle into MOODLE_35_STABLE 2019-02-13 11:25:24 +08:00
Andrew Nicols c35399cc17 Merge branch 'MDL-63892-35-rework' of git://github.com/mickhawkins/moodle into MOODLE_35_STABLE 2019-02-13 10:19:56 +08:00
Andrew Nicols f0f468ba1f MDL-64835 JS: Reduce cache invalidation checks
The cache invalidation check was previously occuring every time either
the `set` or `get` function was called on the cache. However, the cache
invalidation check is based on the jsrev which is static for the
lifetime of the page.

This change moved the invalidation to happen during the setup of the AMD
module such that it only happens one time per storage type (Local +
Session).
2019-02-13 10:13:56 +08:00
Andrew Nicols 8bb8d213db MDL-64835 JS: Stop using the jsrev in the jsrevPrefix
We only use the jsrevPrefix to determine if the cache should be
invalidated, but the prefix that we were using is based on the new
jsrev.

For example, the jsrevPrefix will be:

    hash(wwwroot + '/ + config.jsrev) + '/jsrev'

Where config.jsrev is the _current_ (new) jsrev.

As a result when searching for the jsrev used to store the data which is
currently in the storage cache, no key is returned, and we instead set
an 'initial' value and the cache is not cleared

This patch changes the jsrevPrefix to be:

    hash(wwwroot) + '/jsrev'

Since the wwwroot does not change, the key remains static for the
current site. As a result, when the jsrev is bumped via a Moodle cache
purge, we are able to correctly fetch the old jsrev from the cache,
determine that the jsrev has changed, and purge the cache.
2019-02-13 10:13:56 +08:00
AMOS bot a75f2c2f1b Automatically generated installer lang files 2019-02-13 00:11:52 +00:00
Eloy Lafuente (stronk7) 85da5ed5e2 Merge branch 'MDL-64420-2_35' of https://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-02-12 12:56:46 +01:00
David Monllaó 82b6519647 Merge branch 'MDL-64590_35' of https://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-02-12 12:47:06 +01:00
David Monllaó 799e4e2fbf Merge branch 'MDL-64730-lti-adv-0score-35' of https://github.com/CengageEng/moodle into MOODLE_35_STABLE 2019-02-12 12:33:38 +01:00
John Beedell ecbcbb2a7f MDL-64420 qtype: gapselect unit tests unsafe 2019-02-12 11:27:01 +00:00
David Monllaó 6699b20eb9 MDL-63706 tasks: Fix typo in pathtophp 2019-02-12 09:49:51 +01:00
David Monllaó 5af18c34e3 Merge branch 'MDL-63706_35' of git://github.com/markn86/moodle into MOODLE_35_STABLE 2019-02-12 09:46:39 +01:00
David Monllaó fb911d3422 Merge branch 'MDL-32096-35' of git://github.com/peterRd/moodle into MOODLE_35_STABLE 2019-02-12 09:41:45 +01:00
Andrew Nicols 895ec79efd Merge branch 'MDL-64291_35' of https://github.com/KietChan/moodle into MOODLE_35_STABLE 2019-02-12 10:55:53 +08:00
Jun Pataleta 7ccf3ebdf2 Merge branch 'MDL-64493-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-12 10:10:28 +08:00
Andrew Nicols e3c4a1fc9f MDL-64736 course: Rewrite behat step to avoid changing a checkbox 2019-02-12 07:43:54 +08:00
Eloy Lafuente (stronk7) 1bcf9c913f Merge branch 'MDL-61326-35' of git://github.com/peterRd/moodle into MOODLE_35_STABLE 2019-02-12 00:20:43 +01:00
Peter ecf8e7eda9 MDL-61326 repository_equella: Pass proper labels for roles with no name 2019-02-12 07:11:16 +08:00
Eloy Lafuente (stronk7) 9b6f09eeeb Merge branch 'MDL-64694_35' of git://github.com/dmonllao/moodle into MOODLE_35_STABLE 2019-02-12 00:10:35 +01:00
Eloy Lafuente (stronk7) 83e40aa825 Merge branch 'MDL-64606-35' of https://github.com/lucaboesch/moodle into MOODLE_35_STABLE 2019-02-12 00:02:44 +01:00
Eloy Lafuente (stronk7) 008121e57f Merge branch 'MDL-64238-35' of git://github.com/peterRd/moodle into MOODLE_35_STABLE 2019-02-11 23:57:18 +01:00
Peter 67bc6c6ebb MDL-64238 mod_quiz: Check enrollment on calendar_action generator
* Updated unit tests to account for participants
2019-02-12 06:26:23 +08:00
Peter 649ffed15d MDL-64238 mod_lesson: Check enrollment calendar_action generator
* Updated unit tests to account for participants
2019-02-12 06:26:23 +08:00
Eloy Lafuente (stronk7) 57ac26edae Merge branch 'MDL-64725-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-02-11 17:05:02 +01:00
Eloy Lafuente (stronk7) f05e71a443 Merge branch 'M3.5-MDL-64599' of https://github.com/marcusboon/moodle into MOODLE_35_STABLE 2019-02-11 12:51:20 +01:00
Eloy Lafuente (stronk7) 0cccbe18f2 Merge branch 'MDL-64385-35' of git://github.com/aanabit/moodle into MOODLE_35_STABLE 2019-02-11 12:35:43 +01:00
Sara Arjona 861b48d332 Merge branch 'MDL-64031-35' of https://github.com/lethevinh/moodle into MOODLE_35_STABLE 2019-02-11 12:33:21 +01:00
David Monllaó 5719590cb1 Merge branch 'MDL-64391_35' of git://github.com/vmdef/moodle into MOODLE_35_STABLE 2019-02-11 11:09:35 +01:00
Sara Arjona 571b22a693 Merge branch 'MDL-48338-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-02-11 10:41:31 +01:00
David Monllaó 603aaf66c4 Merge branch 'MDL-62666-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-02-11 09:49:00 +01:00
Tim Hunt 99f29e2580 MDL-64242 qtype_essay: more efficient query in restore code
Thanks to Juan Ibarra for the suggestion that lead to this fix.
2019-02-11 08:40:57 +00:00
Andrew Nicols 3ae9b14420 Merge branch 'MDL-64597-35' of git://github.com/junpataleta/moodle into MOODLE_35_STABLE 2019-02-11 16:34:56 +08:00
Jun Pataleta 302a14d287 Merge branch 'MDL-64488-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-11 16:05:20 +08:00
Jun Pataleta 1e41439336 Merge branch 'MDL-64644_35' of git://github.com/markn86/moodle into MOODLE_35_STABLE 2019-02-11 15:28:29 +08:00
Shamim Rezaie b8ddf80ca6 MDL-63134 mod_chat: Check if the module is visible to the user 2019-02-11 16:10:41 +11:00
Shamim Rezaie d2abeb3b3c MDL-63134 mod_chat: Add userid param to mod_chat calendar callbacks 2019-02-11 16:10:41 +11:00
AMOS bot fd0bbd3201 Automatically generated installer lang files 2019-02-10 00:10:24 +00:00
Adrian Perez ed73a073a3 MDL-64563 theme_boost: Add page site admin category name word-break 2019-02-09 20:17:03 +01:00
Luca Bösch 1084a0afe4 MDL-64606 templates: Show & instead of & in url-select. 2019-02-08 13:21:45 +01:00
Jun Pataleta 43f894f2ba weekly release 3.5.4+ 2019-02-08 14:54:34 +08:00
Damyon Wiese 29086bc3b3 MDL-64806 theme_boost: Do not label "More" icon
The icon is next to the text that says the same thing. Hide it from screenreaders.
2019-02-08 09:37:42 +08:00
Jun Pataleta 395b1f8fe7 Merge branch 'MDL-63614_35' of https://github.com/stronk7/moodle into MOODLE_35_STABLE 2019-02-08 08:38:00 +08:00
Eloy Lafuente (stronk7) 1a20233e7f MDL-63614 tests: Perform attempt the old way
The functions being used here only are available for 36_STABLE and up,
so we switch to the old way of performing an attempt.
2019-02-08 00:13:34 +01:00
Eloy Lafuente (stronk7) 2a26069c13 Merge branch 'MDL-62680-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-07 10:22:39 +01:00
Anthony Ales 4e9c2677e5 MDL-48338 forum: Missing #unread in discussion post url
When a user user selects the unread messages link from the forum
discussion page, the link does not include '#unread' in the url.
This patch appends '#unread' to the url by changing the appropriate
value in the reference link assigned to $out within the function
forum_cm_info_view() of the 'lib.php'file.

A similar change is on the forum index.
2019-02-07 15:17:21 +08:00
Andrew Nicols 763c1bc6fb Merge branch 'MDL-64633-35' of https://github.com/ewallah/moodle into MOODLE_35_STABLE 2019-02-07 14:54:05 +08:00
Peter Eliyahu Kornfeld e5f929a854 MDL-60459 core_course: set default for 'visibleoncoursepage' 2019-02-07 10:54:25 +08:00
Damyon Wiese 78bb834249 MDL-62680 output: Only hide icons with no label
For accessibility we don't want to read an icon with a label immediately next to the label,
but in this case it's clearer for the icon to have no alt text / title for both
screen readers and non-screen readers. Worse is not reading important information just
because it's displayed as an icon.
2019-02-07 10:12:47 +08:00
Eloy Lafuente (stronk7) a4c9320fae Merge branch 'MDL-64577-35' of https://github.com/lucaboesch/moodle into MOODLE_35_STABLE 2019-02-07 00:47:14 +01:00
Eloy Lafuente (stronk7) c59ad632a2 Merge branch 'MDL-64551-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-02-06 23:44:57 +01:00
Eloy Lafuente (stronk7) ab2a6da0da Merge branch 'MDL-64469-35' of https://github.com/lethevinh/moodle into MOODLE_35_STABLE 2019-02-06 22:55:29 +01:00
Eloy Lafuente (stronk7) fb14b2aab7 Merge branch 'MDL-63372-35' of https://github.com/lucaboesch/moodle into MOODLE_35_STABLE 2019-02-06 18:58:26 +01:00
Eloy Lafuente (stronk7) cf775cb602 Merge branch 'MDL-63148-35' of git://github.com/peterRd/moodle into MOODLE_35_STABLE 2019-02-06 13:28:40 +01:00
Eloy Lafuente (stronk7) 0603a6db6d Merge branch 'MDL-63614_M35v1' of https://github.com/sbourget/moodle into MOODLE_35_STABLE 2019-02-06 13:20:01 +01:00
Mihail Geshoski 9fb8d55550 MDL-63417 lesson: Re-apply class variable to the question response 2019-02-06 15:02:34 +08:00
Jun Pataleta 9f19bb9dfb Merge branch 'MDL-61405-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-06 13:12:16 +08:00
Damyon Wiese 06e372a3c8 MDL-61405 assign: Multiple pdfs are expected
In the same page it is normal (expected) to have multiple links to different annotated pdfs.

In the grading page, we also abort pending ajax progress when the current user is changed.
2019-02-06 09:38:08 +08:00
Eloy Lafuente (stronk7) 2980c823f8 Merge branch 'MDL-63516-MOODLE_35_STABLE' of https://github.com/dmitriim/moodle into MOODLE_35_STABLE 2019-02-06 00:16:48 +01:00
Dmitrii Metelkin c025ce8af1 MDL-63516 groups: fix unexpected debugging message 2019-02-06 09:39:55 +11:00
Sara Arjona 3144a87a57 Merge branch 'MDL-62893_35' of https://github.com/mfabriczy/moodle into MOODLE_35_STABLE 2019-02-05 20:06:58 +01:00
Eloy Lafuente (stronk7) 07579a6bba Merge branch 'MDL-61441_35' of https://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-02-05 13:09:12 +01:00
cescobedo 1210555318 MDL-64714 core_auth: Fix early break foreach in delete_data_for_user 2019-02-05 12:51:59 +01:00
Marcus Fabriczy 68bc7c4658 MDL-62893 mod: Grade visibility bug in the Outline/Complete reports
Grades that have been hidden will appear in the outline/complete
report - even if the user is a student.

The modules that have been fixed are:
* mod_assign
* mod_data
* mod_forum
* mod_glossary
* mod_lesson
* mod_scorm
* mod_workshop
2019-02-05 20:12:14 +10:30
Peter f0f73daeb9 MDL-64450 mod_lesson: Update the css for lesson forms
* Reduce the width for the mediaplugin when displayed in forms
* Correct the css to exclude mediaplugin when applying styles
2019-02-05 12:55:22 +08:00
Olivier Piton 46f6c0da7b MDL-61535 report_security: SQL Perf improvement 2019-02-05 01:44:29 +01:00
Eloy Lafuente (stronk7) b69c36612d Merge branch 'wip-MDL-64404-35' of https://github.com/Beedell/moodle into MOODLE_35_STABLE 2019-02-05 01:31:24 +01:00
Eloy Lafuente (stronk7) c2587d48ba Merge branch 'MDL-64649-35' of https://github.com/felicemcc/moodle into MOODLE_35_STABLE 2019-02-04 16:51:46 +01:00
Eloy Lafuente (stronk7) 9400329867 Merge branch 'MDL-63975-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-02-04 13:22:03 +01:00
Damyon Wiese 2486b50a7b MDL-62008 output: Help icon text is escaped
The argument to render the pix_icon template from the help_icon template should not
be escaped, they will be escaped by the pix_icon template when it generates the HTML.
2019-02-04 13:46:30 +08:00
Damyon Wiese ac3a49cd4a MDL-62465 assign: Allow grade scrolling
Remove the custom override that disables no-overflow in the grading table. This page is better to use
when the grading table is scrollable and the controls around it are not scrollable.
2019-02-04 11:40:37 +08:00
Damyon Wiese 9cf38a5d24 MDL-62465 grade: scrolling CSS
Grading pages have their own special javascript to force "fixed" headers
when scrolling a large table. They rely on the entire page being scrolled,
not just the main region.
2019-02-04 11:40:37 +08:00
Damyon Wiese 1b7a0a4d1a MDL-62465 CSS: scrolling tables
Tables displayed inside a flex box container need position:relative to
calculate their size or they cause incorrect scrollable regions to appear in the page.
2019-02-04 11:40:37 +08:00
Jun Pataleta d403ff368e MDL-64725 composer: Use lowercase for package name of dev dependencies 2019-02-04 09:36:53 +08:00
David Monllaó 541122f622 MDL-64694 report_insights: Remove unnecessary cell classes 2019-02-01 09:10:07 +01:00
Luca Bösch 960fef4854 MDL-64577 grade: style "Add ID numbers" button. 2019-02-01 07:08:18 +01:00
Luca Bösch 88e90e3a6b MDL-63372 theme_boost: leave bootstrap card-decks untouched. 2019-02-01 07:01:33 +01:00
David Monllao 16e46ae78b MDL-64500 tool_analytics: No invalid analysables message 2019-02-01 06:59:23 +01:00
Damyon Wiese db3008e2fa MDL-45151 assign: Add anonymous flag to events if blindmarking 2019-02-01 09:14:12 +08:00
Jun Pataleta 06c98804f8 weekly release 3.5.4+ 2019-02-01 08:57:10 +08:00
Jun Pataleta 8e85d900db Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-02-01 08:57:09 +08:00
Eloy Lafuente (stronk7) e25999cfeb Merge branch 'MDL-64737-35-attoprivacysql' of git://github.com/mudrd8mz/moodle into MOODLE_35_STABLE 2019-01-31 22:46:46 +01:00
Sara Arjona a2740b43c5 MDL-62514 form: Add missing data-tags attribute
The data-tags=1 attribute was missing for the autocomplete forms
without suggestions.
2019-01-31 13:53:47 +01:00
David Mudrák b14eb813a0 MDL-64737 editor_atto: Fix the privacy export_user_data() implementation
Multiple issues fixed:

* Fixed order of the statements to avoid access to undefined variables.
* Fixed population of the SQL query parameter to make sure they match
  the placeholder in the query.
* Fixed missing table aliases in the second query to make sure the query
  actually works as expected.
2019-01-31 12:51:18 +01:00
David Mudrák 7ed8b29579 MDL-64737 privacy: Fix privacy provider testsuite file names
Only files ending with "_test.php" suffix are implicit part of a
testsuite. So these two were not actually executed.
2019-01-31 12:51:18 +01:00
Felice Candilio 64d7b87888 MDL-64649 amd: Removing underscores from icons in [Roles/Groups] forms 2019-01-31 11:03:02 +01:00
Damyon Wiese 5944f26805 MDL-63975 assign: Fix error when there is no grader 2019-01-31 13:09:30 +08:00
Damyon Wiese 420daee391 MDL-64200 atto_media: Improve behat test
By setting the window size before the modal dialogs are opened, we will get
consistent behaviour when interacting with the modal.
2019-01-31 11:56:18 +08:00
Eloy Lafuente (stronk7) 2afeb308b6 Merge branch 'MDL-64320_35' of git://github.com/dmonllao/moodle into MOODLE_35_STABLE 2019-01-31 00:30:17 +01:00
Eloy Lafuente (stronk7) eacb5e71d5 Merge branch 'MDL-64521_35' of https://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-01-30 23:49:08 +01:00
Eloy Lafuente (stronk7) ad2ee11aae Merge branch 'MDL-62514-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-01-30 23:01:27 +01:00
Claude Vervoort be5dd33e4d MDL-64730 LTI Adv: do not ignore 0 score 2019-01-30 16:15:23 -05:00
Sara Arjona a16553fc55 Merge branch 'MDL-47247-35' of git://github.com/mihailges/moodle into MOODLE_35_STABLE 2019-01-30 14:03:27 +01:00
David Monllao a8159737cf MDL-64320 analytics: Validate discrete indicators separately 2019-01-30 12:11:40 +01:00
Andrew Nicols 88c0ab547b MDL-62514 behat: Inplace editable pendingjs wrapper 2019-01-30 08:26:31 +08:00
Andrew Nicols 9b71e8a8b0 MDL-62514 behat: Remove potentially conflicting names from description 2019-01-30 08:26:31 +08:00
Andrew Nicols 6c461125c5 MDL-62514 behat: Add additional autocomplete validation 2019-01-30 08:26:31 +08:00
Andrew Nicols e3138b870e MDL-62514 behat: Rewrite handling of autocomplete
This includes a minor restructure of the autocomplete JS to make use of
promises and improve tracking of pending JS.

In particular it improves the way in which throttled text input is
handled to ensure that the behat does not continue until:
- typing is fully complete; and
- all possible ajax requests have been sent; and
- all possible ajax requests complete; and
- the suggestions are updated.

A number of conditions existed where behat would move on to the next
step too early in a race condition effect between Behat and Autocomplete.
2019-01-30 08:26:31 +08:00
Andrew Nicols eb18ff3cf3 MDL-62514 behat: Add a wait_for_pending_js to form field 2019-01-30 08:26:31 +08:00
AMOS bot 8c435f5f42 Automatically generated installer lang files 2019-01-30 00:10:24 +00:00
Eloy Lafuente (stronk7) 75153c10e6 Merge branch 'MDL-64424-35-expiredfrontpage' of git://github.com/mudrd8mz/moodle into MOODLE_35_STABLE 2019-01-29 23:48:45 +01:00
Eloy Lafuente (stronk7) 328aa06432 Merge branch 'MDL-64464_35' of https://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-01-29 19:41:03 +01:00
Sara Arjona 64a588ccca Merge branch 'MDL-63168_35' of git://github.com/markn86/moodle into MOODLE_35_STABLE 2019-01-29 13:01:10 +01:00
Sara Arjona 2844f968b0 Merge branch 'MDL-64313-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-01-29 12:35:49 +01:00
Sara Arjona 82e028d7bd Merge branch 'MDL-61623-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-01-29 11:20:34 +01:00
Damyon Wiese c14b0c9bcd MDL-61623 accessibility: Use role, not aria-role 2019-01-29 14:00:06 +08:00
Mihail Geshoski 7c815adea4 MDL-47247 mod_folder: Apply site config when showexpanded is not set 2019-01-29 08:59:05 +08:00
Sara Arjona a5fb32a623 Merge branch 'MDL-62668-35' of git://github.com/jleyva/moodle into MOODLE_35_STABLE 2019-01-28 19:43:34 +01:00
Binh Thai c0d4b3ba08 MDL-64291 GDPR export: Context paths can be very long, not unique 2019-01-28 20:04:35 +07:00
Sara Arjona 4a6403f068 Merge branch 'MDL-56604-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-01-28 13:33:07 +01:00
Sara Arjona 1e0cf52994 Merge branch 'MDL-63378-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-01-28 11:38:24 +01:00
Sara Arjona 6ad3397d69 Merge branch 'MDL-54804_35' of https://github.com/mfabriczy/moodle into MOODLE_35_STABLE 2019-01-28 10:21:52 +01:00
Garrett Boone 4fc6d79fa3 MDL-64640 feedback: Fix target link on deletion 2019-01-27 18:15:51 +08:00
Andrew Nicols cbf5a395a3 MDL-64640 usertours: Fix target link on deletion 2019-01-27 18:15:51 +08:00
Eloy Lafuente (stronk7) be521ca625 weekly release 3.5.4+ 2019-01-24 15:12:31 +01:00
Eloy Lafuente (stronk7) 16e61e37ac Merge branch 'install_35_STABLE' of https://git.in.moodle.com/amosbot/moodle-install into MOODLE_35_STABLE 2019-01-24 15:12:28 +01:00
Shamim Rezaie e39f009680 MDL-52132 qbehaviour_manualgraded: no change when comment is left blank 2019-01-24 16:20:20 +08:00
Damyon Wiese be1f9cfba2 MDL-56604 assign: Group submission status
On the page listing all assignments for the course,
show the status of the group submission if teamsubmissions is enabled
for the assignment.
2019-01-24 14:34:47 +08:00
Jun Pataleta b895b8b74f MDL-64597 behat: Properly import behat_util when dropping parallel sites 2019-01-24 12:51:49 +08:00
Damyon Wiese 4777f33bbe MDL-64493 completion: Manual completion Ally
Do not use duplicate title attributes on buttons, use aria-live to force the correct state to be
read after clicking on a button.
2019-01-24 08:37:18 +08:00
Damyon Wiese 2f4185c8ba MDL-64488 output: User picture Ally
Do not include alt and title for a user picture if it is hidden from screen readers.

Use aria-hidden to properly hide the image from screen readers.
2019-01-24 08:32:16 +08:00
Eloy Lafuente (stronk7) 8eaffb287a Merge branch 'MDL-64240-35' of git://github.com/mickhawkins/moodle into MOODLE_35_STABLE 2019-01-24 00:57:03 +01:00
Eloy Lafuente (stronk7) 1f666f276e Merge branch 'MDL-62963-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-01-24 00:38:37 +01:00
Eloy Lafuente (stronk7) d7072f15e9 Merge branch 'MDL-64609-35' of git://github.com/merrill-oakland/moodle into MOODLE_35_STABLE 2019-01-23 18:05:46 +01:00
Mark Sharp cf1f48b322 MDL-64391 core_analytics: courseextendednamedisplay 2019-01-23 12:04:01 +00:00
David Mudrák 787991f1d4 MDL-64424 privacy: Use system context purpose on the front page, too
For activities on the site's front page, use the purpose and retention
periods as defined for the system context, not for the courses.
2019-01-23 11:11:36 +01:00
Mark Nelson b5a94c3e85 MDL-64644 completion: fixed assertions in privacy test 2019-01-23 17:31:17 +08:00
Mark Nelson 2e77251c8b MDL-64644 completion: set status correctly in provider 2019-01-23 17:31:17 +08:00
Mark Nelson 124c24eb0e MDL-64644 completion: ensure we return array for provider 2019-01-23 17:31:17 +08:00
Sara Arjona f958fafc60 Merge branch 'MDL-64107-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-01-23 10:22:32 +01:00
Sara Arjona 70a11e3daa Merge branch 'MDL-63628-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-01-23 08:25:19 +01:00
Mark Nelson 58a6e4bfe4 MDL-63168 core_message: added unit test 2019-01-23 13:24:17 +08:00
eWallah 6e81e436bf MDL-63168 core_message: fix failures in migrate_message_data task. 2019-01-23 13:24:17 +08:00
Eric Merrill 85fec2b605 MDL-64609 gradebook: Prevent infinite loop in regrading 2019-01-22 21:42:28 -05:00
Jake Dallimore b8360b3cfb Merge branch 'MDL-52132-35' of git://github.com/rezaies/moodle into MOODLE_35_STABLE 2019-01-23 09:21:36 +08:00
Eloy Lafuente (stronk7) 2baaed1860 Merge branch 'MDL-63870_35' of https://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-01-23 00:09:47 +01:00
Eloy Lafuente (stronk7) b56666b99c Merge branch 'MDL-64465_35' of https://github.com/timhunt/moodle into MOODLE_35_STABLE 2019-01-23 00:02:07 +01:00
Eloy Lafuente (stronk7) 983ae52810 Merge branch 'MDL-64629-35' of git://github.com/sarjona/moodle into MOODLE_35_STABLE 2019-01-22 19:01:06 +01:00
Shamim Rezaie 2c6d5bf004 MDL-64521 groups: add more unit tests
These tests were created for MDL-64526, just before MDL-64521 came along
and removed the buggy code. These are good tests, so they are being
kept.
2019-01-22 16:43:38 +00:00
Tim Hunt 11cf3ecc56 MDL-64521 grouplib: reduce memory use in groups_get_all_groups
This avoids loading multiple copies of g.* when $withmembers is true
2019-01-22 16:43:36 +00:00
Sara Arjona 3ebff5cc76 Merge branch 'MDL-63480-35' of git://github.com/mihailges/moodle into MOODLE_35_STABLE 2019-01-22 15:19:14 +01:00
Justus Dieckmann 609203ada6 MDL-58256 group: prevents users to be added to a group twice 2019-01-22 13:05:34 +01:00
eWallah b50e1b2450 MDL-64633 behat: fix FormatterNotFoundException when updating steps. 2019-01-22 11:35:36 +01:00
Jun Pataleta 6649b4f560 MDL-63706 tool_task: Remove run_task_now.feature
This test cannot be run on Behat anymore as the "Run now" feature
depends on $CFG->pathtophp. Even if it's set, the task executed via
"Run now" will be executed for the installed site itself and not on the
Behat test site.

Backport of MDL-60514.
2019-01-22 17:14:21 +08:00
Toni Barberà Melià 365435182e MDL-63706 tasks: added new config parameter. changes in cron execution
Backport of MDL-60514.
2019-01-22 17:14:21 +08:00
Sara Arjona 279ec1f986 Merge branch 'MDL-64486-35' of git://github.com/peterRd/moodle into MOODLE_35_STABLE 2019-01-22 08:23:31 +01:00
Michael Hawkins b52735e2b4 MDL-63892 mod_forum: Updating lib unit test 2019-01-22 13:55:10 +08:00
Michael Hawkins ee95b9c319 MDL-63892 mod_forum: Fix last post details in forum view 2019-01-22 13:55:10 +08:00
Michael Hawkins 81e8a74a7b MDL-63892 mod_forum: Correction to timestamp added to edit strings 2019-01-22 13:55:10 +08:00
Peter 5a76a51e3a MDL-32096 core_report: Remove duplicate filters in reports
* Remove duplicate filters from activity completion and course completion report pages
2019-01-22 13:41:31 +08:00
Damyon Wiese 152e59f56d MDL-63628 accessibility: Trigger file links with keyboard 2019-01-22 08:41:01 +08:00
AMOS bot d41a75ffad Automatically generated installer lang files 2019-01-22 00:10:06 +00:00
David Mudrák f9d389f45b MDL-64553 message: Add index for the notifications.useridfrom field
The useridfrom would normally be a foreign key to the users table. But
it can also contain some extra negative values with special semantics
(-10 or -20 for no-reply or support user). Therefore we can't make it a
foreign key and the index must be created explicitly.
2019-01-21 13:31:17 +01:00
Jake Dallimore 284b7c820e Merge branch 'MDL-28445-35' of git://github.com/peterRd/moodle into MOODLE_35_STABLE 2019-01-21 15:59:10 +08:00
Jun Pataleta 6a09040e4d MDL-62666 course: Only set the groups setting to true when necessary
* Plus update the comment to be more descriptive.
2019-01-21 14:43:19 +08:00
Andrew Hancox 46bd72dc4f MDL-62666 course: Ignore restore_general_groups on activity duplication 2019-01-21 14:43:19 +08:00
Mihail Geshoski 1f3fd18541 MDL-63480 reports: Fix name filters in completion reports 2019-01-21 09:24:52 +08:00
Jake Dallimore 247b70b0de Merge branch 'MDL-60972-35_delete_section_files' of https://github.com/awagner/moodle into MOODLE_35_STABLE 2019-01-21 09:03:46 +08:00
Tim Hunt 61319327b1 MDL-64590 questions: wrong comments shown in the state history table 2019-01-18 18:06:58 +00:00
Sara Arjona 1237fe9140 MDL-64629 theme_clean: Remove underscore near the help icon 2019-01-18 14:33:06 +01:00
Sara Arjona e489ebbb0b Merge branch 'MDL-62968-35' of git://github.com/mickhawkins/moodle into MOODLE_35_STABLE 2019-01-18 12:40:07 +01:00
Amaia Anabitarte 15c3d7e208 MDL-64385 user: Case insensitive comparison for email domains 2019-01-18 10:12:18 +01:00
Marcus Boon c1aa2c28c2 MDL-64599 phpunit: Fix typo in arraydataset 2019-01-18 07:10:20 +10:00
Tim Hunt 901c95587f MDL-63870 quiz: new preview should abandon, not finish, current attempt 2019-01-17 17:55:41 +00:00
Eloy Lafuente (stronk7) b39f7194a8 weekly release 3.5.4+ 2019-01-17 17:47:58 +01:00
Andreas Wagner 9ebaea25f6 MDL-60972 core_course: delete section files, when section is deleted. 2019-01-17 08:18:34 +01:00
Peter a67284cb47 MDL-28445 mod_glossary: Use compound strings as opposed to anglicised
* Use compound strings on buttons to help with proper translations
* Updated behat tests
2019-01-17 10:59:13 +08:00
Eloy Lafuente (stronk7) f14ed54861 Merge branch 'MDL-63103-m35' of https://github.com/NeillM/moodle into MOODLE_35_STABLE 2019-01-16 19:02:36 +01:00
Sara Arjona e618ee9fb5 Merge branch 'MDL-63916-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-01-16 15:33:57 +01:00
Eloy Lafuente (stronk7) b4ce080632 Merge branch 'MDL-63607-35' of git://github.com/andrewnicols/moodle into MOODLE_35_STABLE 2019-01-16 00:37:21 +01:00
Sara Arjona a660a74f7a Merge branch 'MDL-64346-35' of git://github.com/abgreeve/moodle into MOODLE_35_STABLE 2019-01-15 15:38:40 +01:00
Adrian Greeve 017578d64f MDL-64346 mod_resource: Fix problems with # in file name. 2019-01-15 14:30:35 +01:00
Sara Arjona e37c1f7ed0 Merge branch 'MDL-62439-35' of https://github.com/lucaboesch/moodle into MOODLE_35_STABLE 2019-01-15 12:02:37 +01:00
Sara Arjona 57768467dc Merge branch 'MDL-63881-35' of https://github.com/lucaboesch/moodle into MOODLE_35_STABLE 2019-01-15 11:39:26 +01:00
Andrew Nicols b562767744 MDL-52132 core_question: Comment is different if format has changed 2019-01-15 18:57:42 +11:00
Shamim Rezaie 95f2f79218 MDL-52132 qbehaviour_manualgraded: unit test for changing comment format 2019-01-15 18:57:41 +11:00
Eloy Lafuente (stronk7) 021143d5cc Merge branch 'MDL-63677-35' of git://github.com/sarjona/moodle into MOODLE_35_STABLE 2019-01-14 23:04:07 +01:00
Sara Arjona fcd19e1faf Merge branch 'MDL-60082-35' of git://github.com/damyon/moodle into MOODLE_35_STABLE 2019-01-14 12:28:30 +01:00
Shamim Rezaie c9d4bb2d53 MDL-64551 core_question: Fix double ampersand escaping in tag button 2019-01-14 18:24:12 +11:00
Tim Hunt 8b1bf65b22 MDL-64465 qtypes: fix incorrect context passed to format_string 2019-01-11 10:52:49 +00:00
Tim Hunt 6f60c7a6f2 MDL-64464 drag-drop qtypes: allow <span lang=".."> id draggables
This is for accessibility, so that screen readers can read the drag
items with correct pronunciation.
2019-01-11 10:52:34 +00:00
Tim Hunt 8c6a45020e MDL-61441 accesslib: get_users_by_capability groups perf improvement 2019-01-11 10:52:17 +00:00
Sara Arjona 38f65afecf MDL-63677 core_user: Avoid redirection during signup
Purge cache just for the current user to avoid redirection when 2
simultaneous users try to sign up at the same time and some policy
has to be agreed.
The 'createduser' invalidation event has been removed also because
is not used any more.
Thanks John Azinheira for spotting it!
2019-01-11 10:26:14 +01:00
Neill Magill cd05eba738 MDL-63103 filebrowser: Speed up finding activities with files
Before this change the query examined at every course_module record in
the context table.

With this change we use the course_modules table to more efficiently
find all the activities in the course, which means that many less
records in the context table need to be examined.
2019-01-11 09:06:06 +00:00
VinhLe 4b1a578e2e MDL-64469 Question bank: Change link questions in category question.
Make it easier to navigate from the category list to the questions in a category.
2019-01-11 11:31:11 +07:00
VinhLe 22497d9d74 MDL-64031 enrol_manual: Fix hard-coded list of user fields
Respect get_extra_user_fields() in PHP code
2019-01-11 11:25:43 +07:00
Luca Bösch 1e90a547e9 MDL-63881 tool_dataprivacy: 'Contact the privacy officer' profile link. 2019-01-10 22:15:35 +01:00
Luca Bösch e2e9df59d7 MDL-62439 output: Debugstringids in overlay windows. 2019-01-10 22:15:06 +01:00
Marcus Fabriczy 88d5dbb63f MDL-54804 templates: Prevent posting when no option is selected
When no value is set for an option element and a user selects it, a
POST request is made, which is incorrect. Usually that option is a
placeholder value, e.g., "Choose..." - the form expecting the end user
to choose an actual value.
2019-01-10 09:05:29 +10:30
Damyon Wiese e293c3deb3 MDL-62143 accessibility: Label breadcrumbs 2019-01-09 15:18:42 +08:00
Peter f8be708257 MDL-64486 mod_glossary: Add missing separator for special links 2019-01-03 08:39:46 +08:00
Peter 40bf3feacd MDL-63148 mod_scorm: Accept userid param in event action
* Update lib scorm functions to accept and use a passed in userid
* Additional phpunit tests
2019-01-02 14:36:20 +08:00
Michael Hawkins 3691ff2f40 MDL-62968 Boost: Adding editor SCSS support 2019-01-02 14:21:24 +08:00
Stephen Bourget 29d25b33a5 MDL-63614 badges: Add COMPLETION_FAIL support to badge criteria 2018-12-19 10:31:28 -05:00
Michael Hawkins 9d046294fb MDL-64240 mod_forum: Clean forum post text before storing
Previously only edited messages were cleaned, so longer strings could
be stored in the database, which would never be displayed.
This update takes into account trusted text before cleaning (as editing does).
2018-12-18 15:10:21 +08:00
Michael Hawkins 968c6115dc MDL-64240 mod_forum: Update word count to use current message length
Previously this used the length of the message stored in the database,
before scripts etc are cleaned to display the content. That resulted
in cases where the count would seem much larger than the message size.
2018-12-18 15:10:16 +08:00
Damyon Wiese 16668320a6 MDL-60082 assign: Grading worksheet with no grade
If the grade type is NONE - do not include the maxgrade column.
2018-12-18 11:14:19 +08:00
John Beedell dfce9c02d2 MDL-64404 qtype: gapselect currency like options dont show 2018-12-17 12:15:39 +00:00
Damyon Wiese 512044f0c9 MDL-62963 boost: Increase contrast btn-secondary
The background colour of these buttons is too light, so they don't look like buttons.
2018-12-17 15:49:45 +08:00
Damyon Wiese 1aaa130376 MDL-63378 theme_boost: Contrast of menu items
Enforce the :active menu text colour during a mouse click on an action menu.
2018-12-17 14:07:18 +08:00
Damyon Wiese ee38a8d1e4 MDL-64107 questions: Increase highlight contrast
When a question has just been edited, it is highlighted. We need to ensure
the colour contrast of text on background is accessible.
2018-12-17 12:36:03 +08:00
Damyon Wiese 55a1e8b719 MDL-63916 backup: Do not display timestamp
Convert the date+time field to a userdate for display.
2018-12-12 12:20:18 +08:00
Damyon Wiese 7afbae7e1a MDL-64313 assign: feedback viewed event
When a student views their submission, if it has feedback create an event.
2018-12-11 14:07:23 +08:00
Juan Leyva d6b498f6ae MDL-62668 mod_workshop: Return feedback for reviewer in assessment phase
Teachers were not able to view the existing feedback.
2018-11-16 15:49:18 +01:00
Andrew Nicols 866cabf59d MDL-63607 behat: Remove theme from config whitelist 2018-10-10 12:06:42 +08:00
557 changed files with 10371 additions and 2572 deletions
+10 -2
View File
@@ -9,10 +9,18 @@
#
# 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.*
+1 -1
View File
@@ -710,7 +710,7 @@ if ($interactive) {
cli_separator();
cli_heading(get_string('cliadminemail', 'install'));
$prompt = get_string('clitypevaluedefault', 'admin', $options['adminemail']);
$options['adminemail'] = cli_input($prompt);
$options['adminemail'] = cli_input($prompt, $options['adminemail']);
}
// Validate that the address provided was an e-mail address.
+6 -6
View File
@@ -82,11 +82,6 @@ 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);
@@ -109,12 +104,17 @@ 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
}
+1 -2
View File
@@ -823,8 +823,7 @@ class core_admin_renderer extends plugin_renderer_base {
*/
protected function registration_warning($registered) {
if (!$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'));
+5 -2
View File
@@ -69,8 +69,11 @@ class core_role_check_users_selector extends user_selector_base {
if ($coursecontext and $coursecontext != SITEID) {
$sql1 = " FROM {user} u
JOIN {user_enrolments} ue ON (ue.userid = u.id)
JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid1)
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
WHERE $wherecondition";
$params['courseid1'] = $coursecontext->instanceid;
+1 -1
View File
@@ -325,7 +325,7 @@ if ($hassiteconfig or has_any_capability($capabilities, $systemcontext)) {
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_skip_modif_prev', new lang_string('skipmodifprev', 'backup'), new lang_string('skipmodifprevhelp', 'backup'), 0));
// Automated defaults section.
$temp->add(new admin_setting_heading('automatedsettings', new lang_string('automatedsettings','backup'), ''));
$temp->add(new admin_setting_heading('automatedsettings', new lang_string('automatedsettings','backup'), new lang_string('recyclebin_desc', 'backup')));
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_users', new lang_string('generalusers', 'backup'), new lang_string('configgeneralusers', 'backup'), 1));
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_role_assignments', new lang_string('generalroleassignments','backup'), new lang_string('configgeneralroleassignments','backup'), 1));
$temp->add(new admin_setting_configcheckbox('backup/backup_auto_activities', new lang_string('generalactivities','backup'), new lang_string('configgeneralactivities','backup'), 1));
+2 -1
View File
@@ -7,7 +7,8 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
// "systempaths" settingpage
$temp = new admin_settingpage('systempaths', new lang_string('systempaths','admin'));
$temp->add(new admin_setting_configexecutable('pathtophp', new lang_string('pathtophp', 'admin'),
new lang_string('configpathtophp', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('pathtodu', new lang_string('pathtodu', 'admin'), new lang_string('configpathtodu', 'admin'), ''));
$temp->add(new admin_setting_configexecutable('aspellpath', new lang_string('aspellpath', 'admin'), new lang_string('edhelpaspellpath'), ''));
$temp->add(new admin_setting_configexecutable('pathtodot', new lang_string('pathtodot', 'admin'), new lang_string('pathtodot_help', 'admin'), ''));
+2 -2
View File
@@ -58,7 +58,7 @@ class behat_admin extends behat_base {
// We expect admin block to be visible, otherwise go to homepage.
if (!$this->getSession()->getPage()->find('css', '.block_settings')) {
$this->getSession()->visit($this->locate_path('/'));
$this->wait(self::TIMEOUT * 1000, self::PAGE_READY_JS);
$this->wait(self::get_timeout() * 1000, self::PAGE_READY_JS);
}
// Search by label.
@@ -67,7 +67,7 @@ class behat_admin extends behat_base {
$submitsearch = $this->find('css', 'form.adminsearchform input[type=submit]');
$submitsearch->press();
$this->wait(self::TIMEOUT * 1000, self::PAGE_READY_JS);
$this->wait(self::get_timeout() * 1000, self::PAGE_READY_JS);
// Admin settings does not use the same DOM structure than other moodle forms
// but we also need to use lib/behat/form_field/* to deal with the different moodle form elements.
@@ -1,57 +1,74 @@
@core @core_admin
Feature: Enable multiple accounts to have the same email address
In order to have multiple accounts registerd on the system with the same email address
@core @core_admin @core_user
Feature: Allowing multiple accounts to have the same email address
In order to manage user accounts
As an admin
I need to enable multiple accounts to be registered with the same email address and verify it is applied
I need to be able to set whether to allow multiple accounts with the same email or not
Background:
Given I log in as "admin"
Scenario: Enable registration of multiple accounts with the same email address
Scenario Outline: Create a user with the same email as an existing user
Given the following config values are set as admin:
| allowaccountssameemail | 1 |
When I navigate to "Add a new user" node in "Site administration>Users>Accounts"
| allowaccountssameemail | <allowsameemail> |
And the following "users" exist:
| username | firstname | lastname | email |
| s1 | John | Doe | s1@example.com |
When I log in as "admin"
And I navigate to "Users > Accounts > Add a new user" in site administration
And I set the following fields to these values:
| Username | testmultiemailuser1 |
| Choose an authentication method | Manual accounts |
| New password | test@User1 |
| First name | Test |
| Surname | Multi1 |
| Email address | testmultiemailuser@example.com |
| Username | s2 |
| First name | Jane |
| Surname | Doe |
| Email address | <email> |
| New password | test |
And I press "Create user"
And I should see "Test Multi1"
And I press "Add a new user"
And I set the following fields to these values:
| Username | testmultiemailuser2 |
| Choose an authentication method | Manual accounts |
| New password | test@User2 |
| First name | Test |
| Surname | Multi2 |
| Email address | testmultiemailuser@example.com |
And I press "Create user"
Then I should see "Test Multi2"
And I should not see "This email address is already registered"
Then I should <expect> "This email address is already registered."
Scenario: Disable registration of multiple accounts with the same email address
Examples:
| allowsameemail | email | expect |
| 0 | s1@example.com | see |
| 0 | S1@EXAMPLE.COM | see |
| 1 | s1@example.com | not see |
| 1 | S1@EXAMPLE.COM | not see |
Scenario Outline: Update a user with the same email as an existing user
Given the following config values are set as admin:
| allowaccountssameemail | 0 |
When I navigate to "Add a new user" node in "Site administration>Users>Accounts"
And I set the following fields to these values:
| Username | testmultiemailuser1 |
| Choose an authentication method | Manual accounts |
| New password | test@User1 |
| First name | Test |
| Surname | Multi1 |
| Email address | testmultiemailuser@example.com |
And I press "Create user"
And I should see "Test Multi1"
And I press "Add a new user"
And I set the following fields to these values:
| Username | testmultiemailuser2 |
| Choose an authentication method | Manual accounts |
| New password | test@User2 |
| First name | Test |
| Surname | Multi2 |
| Email address | testmultiemailuser@example.com |
And I press "Create user"
Then I should see "This email address is already registered"
| allowaccountssameemail | <allowsameemail> |
And the following "users" exist:
| username | firstname | lastname | email |
| s1 | John | Doe | s1@example.com |
| s2 | Jane | Doe | s2@example.com |
When I log in as "admin"
And I navigate to "Users > Accounts > Browse list of users" in site administration
And I click on "Edit" "link" in the "Jane Doe" "table_row"
And I set the field "Email address" to "<email>"
And I press "Update profile"
Then I should <expect> "This email address is already registered."
Examples:
| allowsameemail | email | expect |
| 0 | s1@example.com | see |
| 0 | S1@EXAMPLE.COM | see |
| 1 | s1@example.com | not see |
| 1 | S1@EXAMPLE.COM | not see |
| 0 | S2@EXAMPLE.COM | not see |
| 1 | S2@EXAMPLE.COM | not see |
Scenario Outline: Update own user profile with the same email as an existing user
Given the following config values are set as admin:
| allowaccountssameemail | <allowsameemail> |
And the following "users" exist:
| username | firstname | lastname | email |
| s1 | John | Doe | s1@example.com |
| s2 | Jane | Doe | s2@example.com |
When I log in as "s2"
And I open my profile in edit mode
And I set the field "Email address" to "<email>"
And I press "Update profile"
Then I should <expect> "This email address is already registered."
Examples:
| allowsameemail | email | expect |
| 0 | s1@example.com | see |
| 0 | S1@EXAMPLE.COM | see |
| 1 | s1@example.com | not see |
| 1 | S1@EXAMPLE.COM | not see |
| 0 | S2@EXAMPLE.COM | not see |
| 1 | S2@EXAMPLE.COM | not see |
@@ -153,6 +153,12 @@ class invalid_analysables implements \renderable, \templatable {
$data->analysables[] = $obj;
}
if (empty($data->analysables)) {
$data->noanalysables = [
'message' => get_string('noinvalidanalysables', 'tool_analytics'),
'announce' => true,
];
}
return $data;
}
}
@@ -247,7 +247,7 @@ class models_list implements \renderable, \templatable {
}
// Clear model.
if (!empty($predictioncontexts)) {
if (!empty($predictioncontexts) || $model->is_trained()) {
$actionid = 'clear-' . $model->get_id();
$PAGE->requires->js_call_amd('tool_analytics/model', 'confirmAction', [$actionid, 'clear']);
$urlparams['action'] = 'clear';
@@ -62,7 +62,7 @@ $string['indicators'] = 'Indicators';
$string['info'] = 'Info';
$string['insights'] = 'Insights';
$string['invalidanalysables'] = 'Invalid site elements';
$string['invalidanalysablesinfo'] = 'This pages lists this site analysable elements that can not be used by this prediction model. The listed elements can not be used neither to train the prediction model nor the prediction model can get predictions for them.';
$string['invalidanalysablesinfo'] = 'This page lists analysable elements that can\'t be used by this prediction model. The listed elements can\'t be used either to train the prediction model nor can the prediction model obtain predictions for them.';
$string['invalidanalysablestable'] = 'Invalid site analysable elements table';
$string['invalidprediction'] = 'Invalid to get predictions';
$string['invalidtraining'] = 'Invalid to train the model';
@@ -75,6 +75,7 @@ $string['nextpage'] = 'Next page';
$string['nodatatoevaluate'] = 'There is no data to evaluate the model';
$string['nodatatopredict'] = 'No new elements to get predictions for';
$string['nodatatotrain'] = 'There is no new data that can be used for training';
$string['noinvalidanalysables'] = 'This site does not contain any invalid analysable element.';
$string['notdefined'] = 'Not yet defined';
$string['pluginname'] = 'Analytic models';
$string['predictionresults'] = 'Prediction results';
@@ -48,31 +48,38 @@
<div class="box">
<h3>{{#str}}modelinvalidanalysables, tool_analytics, {{modelname}}{{/str}}</h3>
<div>{{#str}}invalidanalysablesinfo, tool_analytics{{/str}}</div>
<div class="m-t-2 m-b-1">
<span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
<span>{{#next}}{{> core/single_button}}{{/next}}</span>
</div>
<table class="generaltable fullwidth">
<caption class="accesshide">{{#str}}invalidanalysablestable, tool_analytics{{/str}}</caption>
<thead>
<tr>
<th scope="col">{{#str}}name{{/str}}</th>
<th scope="col">{{#str}}invalidtraining, tool_analytics{{/str}}</th>
<th scope="col">{{#str}}invalidprediction, tool_analytics{{/str}}</th>
</tr>
</thead>
<tbody>
{{#analysables}}
<tr>
<td>{{{url}}}</td>
<td>{{validtraining}}</td>
<td>{{validprediction}}</td>
</tr>
{{/analysables}}
</tbody>
</table>
<div class="m-t-1 m-b-2">
<span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
<span>{{#next}}{{> core/single_button}}{{/next}}</span>
</div>
{{#noanalysables}}
<div class="m-t-2 m-b-1">
{{> core/notification_info}}
</div>
{{/noanalysables}}
{{^noanalysables}}
<div class="m-t-2 m-b-1">
<span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
<span>{{#next}}{{> core/single_button}}{{/next}}</span>
</div>
<table class="generaltable fullwidth">
<caption class="accesshide">{{#str}}invalidanalysablestable, tool_analytics{{/str}}</caption>
<thead>
<tr>
<th scope="col">{{#str}}name{{/str}}</th>
<th scope="col">{{#str}}invalidtraining, tool_analytics{{/str}}</th>
<th scope="col">{{#str}}invalidprediction, tool_analytics{{/str}}</th>
</tr>
</thead>
<tbody>
{{#analysables}}
<tr>
<td>{{{url}}}</td>
<td>{{validtraining}}</td>
<td>{{validprediction}}</td>
</tr>
{{/analysables}}
</tbody>
</table>
<div class="m-t-1 m-b-2">
<span>{{#prev}}{{> core/single_button}}{{/prev}}</span>
<span>{{#next}}{{> core/single_button}}{{/next}}</span>
</div>
{{/noanalysables}}
</div>
+11
View File
@@ -109,6 +109,17 @@ require_once(__DIR__ . '/../../../../lib/behat/lib.php');
require_once(__DIR__ . '/../../../../lib/behat/classes/behat_command.php');
require_once(__DIR__ . '/../../../../lib/behat/classes/behat_config_manager.php');
// Remove error handling overrides done in config.php. This is consistent with admin/tool/behat/cli/util_single_run.php.
$CFG->debug = (E_ALL | E_STRICT);
$CFG->debugdisplay = 1;
error_reporting($CFG->debug);
ini_set('display_errors', '1');
ini_set('log_errors', '1');
// Import the necessary libraries.
require_once($CFG->libdir . '/setuplib.php');
require_once($CFG->libdir . '/behat/classes/util.php');
// For drop option check if parallel site.
if ((empty($options['parallel'])) && ($options['drop']) || $options['updatesteps']) {
$options['parallel'] = behat_config_manager::get_behat_run_config_value('parallel');
+1 -1
View File
@@ -218,7 +218,7 @@ if ($options['install']) {
// Run behat command to get steps in feature files.
$featurestepscmd = behat_command::get_behat_command(true);
$featurestepscmd .= ' --config ' . behat_config_manager::get_behat_cli_config_filepath();
$featurestepscmd .= ' --dry-run --format=moodle_step_count';
$featurestepscmd .= ' --dry-run --format=moodle_stepcount';
$processes = cli_execute_parallel(array($featurestepscmd), __DIR__ . "/../../../../");
$status = print_update_step_output(array_pop($processes), $behatstepfile);
+3 -3
View File
@@ -162,11 +162,11 @@ class tool_behat_renderer extends plugin_renderer_base {
$html .= $this->output->heading($title);
// Info.
$installurl = behat_command::DOCS_URL . '#Installation';
$installurl = behat_command::DOCS_URL;
$installlink = html_writer::tag('a', $installurl, array('href' => $installurl, 'target' => '_blank'));
$writetestsurl = behat_command::DOCS_URL . '#Writing_features';
$writetestsurl = 'https://docs.moodle.org/dev/Writing acceptance tests';
$writetestslink = html_writer::tag('a', $writetestsurl, array('href' => $writetestsurl, 'target' => '_blank'));
$writestepsurl = behat_command::DOCS_URL . '#Adding_steps_definitions';
$writestepsurl = 'https://docs.moodle.org/dev/Writing_new_acceptance_test_step_definitions';
$writestepslink = html_writer::tag('a', $writestepsurl, array('href' => $writestepsurl, 'target' => '_blank'));
$infos = array(
get_string('installinfo', 'tool_behat', $installlink),
@@ -920,9 +920,17 @@ class expired_contexts_manager {
* @return bool
*/
protected static function is_course_context_expired_or_unprotected_for_user(\context $context, \stdClass $user) {
$expiryrecords = self::get_nested_expiry_info_for_courses($context->path);
$info = $expiryrecords[$context->path]->info;
if ($context->get_course_context()->instanceid == SITEID) {
// The is an activity in the site course (front page).
$purpose = data_registry::get_effective_contextlevel_value(CONTEXT_SYSTEM, 'purpose');
$info = static::get_expiry_info($purpose);
} else {
$expiryrecords = self::get_nested_expiry_info_for_courses($context->path);
$info = $expiryrecords[$context->path]->info;
}
if ($info->is_fully_expired()) {
// This context is fully expired.
return true;
@@ -277,7 +277,7 @@ $string['resubmitrequestasnew'] = 'Resubmit as new request';
$string['resubmitrequest'] = 'Resubmit {$a->type} request for {$a->username}';
$string['resubmittedrequest'] = 'The existing {$a->type} request for {$a->username} was cancelled and resubmitted';
$string['resultdeleted'] = 'You recently requested to have your account and personal data in {$a} to be deleted. This process has been completed and you will no longer be able to log in.';
$string['resultdownloadready'] = 'Your copy of your personal data in {$a} that you recently requested is now available for download. Please click on the link below to go to the download page.';
$string['resultdownloadready'] = 'Your copy of your personal data from {$a} that you recently requested is now available for download from the following link.';
$string['reviewdata'] = 'Review data';
$string['retentionperiod'] = 'Retention period';
$string['retentionperiod_help'] = 'The retention period specifies the length of time that data should be kept for. When the retention period has expired, the data is flagged and listed for deletion, awaiting admin confirmation.';
-10
View File
@@ -15,16 +15,6 @@
overflow-y: scroll;
}
dd a.contactdpo {
/* Reverting dd's left margin */
margin-left: -10px;
}
.card dd a.contactdpo {
/* Reverting dd's left margin */
margin-left: inherit;
}
[data-region="data-requests-table"] .moodle-actionmenu {
min-width: 150px;
}
@@ -137,7 +137,7 @@
}} data-status="{{status}}"{{!
}}>
<td>{{typename}}</td>
<td>{{#userdate}} {{timecreated}}, {{#str}} strftimedatetime {{/str}} {{/userdate}}</td>
<td>{{#userdate}} {{timecreated}}, {{#str}} strftimedatetime, core_langconfig {{/str}} {{/userdate}}</td>
<td><a href="{{requestedbyuser.profileurl}}" title="{{#str}}viewprofile{{/str}}">{{requestedbyuser.fullname}}</a></td>
<td>
<span class="label {{statuslabelclass}}" title="{{statuslabeltitle}}">{{statuslabel}}</span>
@@ -67,7 +67,8 @@
<a href="mailto:{{foruser.email}}">{{foruser.email}}</a>
<div class="clearfix m-t-1 m-b-1">
<span class="pull-left m-r-1">
<strong>{{#str}}daterequesteddetail, tool_dataprivacy{{/str}}</strong> {{#userdate}} {{timecreated}}, {{#str}} strftimedatetime {{/str}} {{/userdate}}
<strong>{{#str}}daterequesteddetail, tool_dataprivacy{{/str}}</strong>
{{#userdate}} {{timecreated}}, {{#str}} strftimedatetime, core_langconfig {{/str}} {{/userdate}}
</span>
<span class="pull-left m-r-1">
<strong>{{#str}}statusdetail, tool_dataprivacy{{/str}}</strong>
@@ -2222,6 +2222,40 @@ class tool_dataprivacy_expired_contexts_testcase extends advanced_testcase {
$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($blockcontext, $user));
}
/**
* Test the is_context_expired functions when supplied with the front page course.
*/
public function test_is_context_expired_frontpage() {
$this->resetAfterTest();
$purposes = $this->setup_basics('PT1H', 'PT1H', 'P1D');
$frontcourse = get_site();
$frontcoursecontext = \context_course::instance($frontcourse->id);
$sitenews = $this->getDataGenerator()->create_module('forum', ['course' => $frontcourse->id]);
$cm = get_coursemodule_from_instance('forum', $sitenews->id);
$sitenewscontext = \context_module::instance($cm->id);
$user = $this->getDataGenerator()->create_user(['lastaccess' => time() - YEARSECS]);
$this->assertFalse(expired_contexts_manager::is_context_expired($frontcoursecontext));
$this->assertFalse(expired_contexts_manager::is_context_expired($sitenewscontext));
$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($frontcoursecontext, $user));
$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($sitenewscontext, $user));
// Protecting the course contextlevel does not impact the front page.
$purposes->course->set('protected', 1)->save();
$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($frontcoursecontext, $user));
$this->assertTrue(expired_contexts_manager::is_context_expired_or_unprotected_for_user($sitenewscontext, $user));
// Protecting the system contextlevel affects the front page, too.
$purposes->system->set('protected', 1)->save();
$this->assertFalse(expired_contexts_manager::is_context_expired_or_unprotected_for_user($frontcoursecontext, $user));
$this->assertFalse(expired_contexts_manager::is_context_expired_or_unprotected_for_user($sitenewscontext, $user));
}
/**
* Test the is_context_expired functions when supplied with an expired course.
*/
@@ -137,14 +137,14 @@ abstract class restore_tool_log_logstore_subplugin extends restore_subplugin {
}
}
}
// Now we want to serialize it so we can store it in the DB.
$data->other = serialize($data->other);
} else {
$message = "Event class not found: \"$eventclass\". Skipping log record.";
$this->log($message, backup::LOG_DEBUG);
return; // No such class, can not restore.
}
}
// Now we want to serialize it so we can store it in the DB.
$data->other = serialize($data->other);
return $data;
}
+1
View File
@@ -422,6 +422,7 @@ class external extends external_api {
'comppath' => competency_path_exporter::get_read_structure(),
))),
'manageurl' => new external_value(PARAM_LOCALURL, 'Url to the manage competencies page.'),
'pluginbaseurl' => new external_value(PARAM_LOCALURL, 'Url to the course competencies page.'),
));
}
@@ -113,6 +113,7 @@ class course_competencies_page implements renderable, templatable {
$data->courseid = $this->courseid;
$data->pagecontextid = $this->context->id;
$data->competencies = array();
$data->pluginbaseurl = (new moodle_url('/admin/tool/lp'))->out(true);
$gradable = is_enrolled($this->context, $USER, 'moodle/competency:coursecompetencygradable');
if ($gradable) {
@@ -66,7 +66,7 @@
<div class="clearfix"></div>
{{/canmanagecoursecompetencies}}
{{#competency}}
<a href="{{pluginbaseurl}}user_competency_in_course.php?courseid={{courseid}}&competencyid={{competency.id}}&userid={{gradableuserid}}"
<a href="{{pluginbaseurl}}/user_competency_in_course.php?courseid={{courseid}}&competencyid={{competency.id}}&userid={{gradableuserid}}"
id="competency-info-link-{{competency.id}}"
title="{{#str}}viewdetails, tool_lp{{/str}}">
<p><strong>{{{competency.shortname}}} <em>{{competency.idnumber}}</em></strong></p>
+1 -1
View File
@@ -116,7 +116,7 @@ class tool_lp_external_testcase extends externallib_advanced_testcase {
$this->userrole = create_role('User role', 'lpuserrole', 'learning plan user role description');
assign_capability('moodle/competency:competencymanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:competencycompetencyconfigure', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:coursecompetencyconfigure', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:planmanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:planmanagedraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->creatorrole, $syscontext->id);
@@ -274,7 +274,6 @@ class framework_importer {
// We are calling from browser, display progress bar.
if ($this->useprogressbar === true) {
$this->progress = new \core\progress\display_if_slow(get_string('processingfile', 'tool_lpimportcsv'));
$this->progress->start_html();
} else {
// Avoid html output on CLI scripts.
$this->progress = new \core\progress\none();
@@ -464,7 +463,6 @@ class framework_importer {
$framework = api::create_framework($record);
if ($this->useprogressbar === true) {
$this->progress = new \core\progress\display_if_slow(get_string('importingfile', 'tool_lpimportcsv'));
$this->progress->start_html();
} else {
$this->progress = new \core\progress\none();
}
@@ -672,7 +672,7 @@ class manager {
$attachment->charset = $partdata->getCharset();
$attachment->description = $partdata->getDescription();
$attachment->contentid = $partdata->getContentId();
$attachment->filesize = $messagedata->getBodyPartSize($part);
$attachment->filesize = $partdata->getBytes();
if (!empty($CFG->antiviruses)) {
mtrace("--> Attempting virus scan of '{$attachment->filename}'");
@@ -109,7 +109,7 @@ $string['sslv3'] = 'SSLv2 (Force SSL Version 3)';
$string['taskcleanup'] = 'Cleanup of unverified incoming email';
$string['taskpickup'] = 'Incoming email pickup';
$string['tls'] = 'TLS (TLS; started via protocol-level negotiation over unencrypted channel; RECOMMENDED way of initiating secure connection)';
$string['tlsv1'] = 'TLSv1 (TLS direct version 1.x connection to server)';
$string['tlsv1'] = 'TLSv1 (direct connection to TLS server version 1.x)';
$string['validateaddress'] = 'Validate sender email address';
$string['validateaddress_help'] = 'When a message is received from a user, Moodle attempts to validate the message by comparing the email address of the sender with the email address in their user profile.
+1 -1
View File
@@ -99,7 +99,7 @@ class api {
$lang = array();
if (!empty($addoninfo['lang'])) {
$stringmanager = get_string_manager();
$langs = $stringmanager->get_list_of_translations();
$langs = $stringmanager->get_list_of_translations(true);
foreach ($langs as $langid => $langname) {
foreach ($addoninfo['lang'] as $stringinfo) {
$lang[$langid][$stringinfo[0]] =
+6
View File
@@ -66,6 +66,12 @@ function tool_mobile_create_app_download_url() {
}
$downloadurl = new moodle_url($mobilesettings->setuplink);
// Do not update the URL if it is a custom one (we may break it completely).
if ($mobilesettings->setuplink != 'https://download.moodle.org/mobile') {
return $downloadurl;
}
$downloadurl->param('version', $CFG->version);
$downloadurl->param('lang', current_language());
+5 -5
View File
@@ -64,11 +64,11 @@ $string['managerules'] = 'Event monitoring rules';
$string['messageprovider:notification'] = 'Notifications of rule subscriptions';
$string['messagetemplate'] = 'Notification message';
$string['messagetemplate_help'] = 'A notification message is sent to subscribers once the notification threshold has been reached. It can include any or all of the following placeholders:
<br /><br />
* Link to the location of the event {link}<br />
* Link to the area monitored {modulelink}<br />
* Rule name {rulename}<br />
* Description {description}<br />
* Link to the location of the event {link}
* Link to the area monitored {modulelink}
* Rule name {rulename}
* Description {description}
* Event {eventname}';
$string['messagetemplate_link'] = 'admin/tool/monitor/managerules';
$string['moduleinstance'] = 'Instance';
@@ -232,6 +232,10 @@ class page_agreedocs implements renderable, templatable {
];
redirect(new moodle_url('/admin/tool/policy/view.php', $urlparams));
}
} else {
// Update the policyagreed for the user to avoid infinite loop because there are no policies to-be-accepted.
api::update_policyagreed($userid);
$this->redirect_to_previous_url();
}
}
@@ -80,7 +80,7 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I should not see "Next"
And I should see "Course overview"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "1 of 4 (25%)" "link" in the "This site policy" "table_row"
And I click on "Consent not given" "link" in the "User One" "table_row"
@@ -292,3 +292,23 @@ Feature: Viewing acceptances reports and accepting on behalf of other users
And I should see "2 of 2" in the "User One" "table_row"
And "Consent given on behalf of user" "icon" should exist in the "User Two" "table_row"
And I should see "2 of 2" in the "User Two" "table_row"
Scenario: View acceptances made by users on their own after inactivating a policy
Given I log in as "user1"
And I should see "This site policy"
And I should not see "Course overview"
And I press "Next"
And I set the field "I agree to the This site policy" to "1"
And I press "Next"
And I should see "Course overview"
And I log out
And I log in as "admin"
And I navigate to "Users > Privacy and policies > Manage policies" in site administration
And I click on "Actions" "link_or_button" in the "This privacy policy" "table_row"
And I click on "Set status to \"Active\"" "link" in the "This privacy policy" "table_row"
And I press "Continue"
And I click on "Set status to \"Inactive\"" "link" in the "This privacy policy" "table_row"
And I press "Continue"
And I log out
When I log in as "user1"
Then I should see "Course overview"
+16 -2
View File
@@ -108,6 +108,16 @@ class category_bin extends base_bin {
require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
// As far as recycle bin is using MODE_AUTOMATED, it observes the backup_auto_storage
// setting (storing backups @ real location. For recycle bin we want to ensure that
// backup files are always stored in Moodle file area. In order to achieve that, we
// hack the setting here via $CFG->forced_plugin_settings, so it won't interfere other
// operations. See MDL-65218 for more information.
// This hack will be removed once recycle bin switches to use its own backup mode, with
// own preferences and 100% appart from MODLE_AUTOMATED.
// TODO: Remove this as part of MDL-65228.
$CFG->forced_plugin_settings['backup'] = ['backup_auto_storage' => 0];
// Backup the course.
$user = get_admin();
$controller = new \backup_controller(
@@ -115,11 +125,15 @@ class category_bin extends base_bin {
$course->id,
\backup::FORMAT_MOODLE,
\backup::INTERACTIVE_NO,
\backup::MODE_GENERAL,
\backup::MODE_AUTOMATED,
$user->id
);
$controller->execute_plan();
// We don't need the forced setting anymore, hence unsetting it.
// TODO: Remove this as part of MDL-65228.
unset($CFG->forced_plugin_settings['backup']);
// Grab the result.
$result = $controller->get_results();
if (!isset($result['backup_destination'])) {
@@ -233,7 +247,7 @@ class category_bin extends base_bin {
$tempdir,
$course->id,
\backup::INTERACTIVE_NO,
\backup::MODE_GENERAL,
\backup::MODE_AUTOMATED,
$user->id,
\backup::TARGET_NEW_COURSE
);
+16 -2
View File
@@ -112,6 +112,16 @@ class course_bin extends base_bin {
return;
}
// As far as recycle bin is using MODE_AUTOMATED, it observes the backup_auto_storage
// setting (storing backups @ real location. For recycle bin we want to ensure that
// backup files are always stored in Moodle file area. In order to achieve that, we
// hack the setting here via $CFG->forced_plugin_settings, so it won't interfere other
// operations. See MDL-65218 for more information.
// This hack will be removed once recycle bin switches to use its own backup mode, with
// own preferences and 100% appart from MODLE_AUTOMATED.
// TODO: Remove this as part of MDL-65228.
$CFG->forced_plugin_settings['backup'] = ['backup_auto_storage' => 0];
// Backup the activity.
$user = get_admin();
$controller = new \backup_controller(
@@ -119,11 +129,15 @@ class course_bin extends base_bin {
$cm->id,
\backup::FORMAT_MOODLE,
\backup::INTERACTIVE_NO,
\backup::MODE_GENERAL,
\backup::MODE_AUTOMATED,
$user->id
);
$controller->execute_plan();
// We don't need the forced setting anymore, hence unsetting it.
// TODO: Remove this as part of MDL-65228.
unset($CFG->forced_plugin_settings['backup']);
// Grab the result.
$result = $controller->get_results();
if (!isset($result['backup_destination'])) {
@@ -224,7 +238,7 @@ class course_bin extends base_bin {
$tempdir,
$this->_courseid,
\backup::INTERACTIVE_NO,
\backup::MODE_GENERAL,
\backup::MODE_AUTOMATED,
$user->id,
\backup::TARGET_EXISTING_ADDING
);
@@ -176,4 +176,116 @@ class tool_recyclebin_category_bin_tests extends advanced_testcase {
$course = reset($courses);
$this->assertEquals('Test course 2', $course->fullname);
}
/**
* Provider for test_course_restore_with_userdata() and test_course_restore_without_userdata()
*
* Used to verify that recycle bin is immune to various settings. Provides plugin, name, value for
* direct usage with set_config()
*/
public function recycle_bin_settings_provider() {
return [
'backup/backup_auto_storage moodle' => [[
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 0],
]],
'backup/backup_auto_storage external' => [[
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 1],
(object)['plugin' => 'backup', 'name' => 'backup_auto_destination', 'value' => true],
]],
'backup/backup_auto_storage mixed' => [[
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 2],
(object)['plugin' => 'backup', 'name' => 'backup_auto_destination', 'value' => true],
]],
];
}
/**
* Tests that user data is restored when course is restored.
*
* @dataProvider recycle_bin_settings_provider
* @param array $settings array of plugin, name, value stdClass().
*/
public function test_course_restore_with_userdata($settings) {
global $DB;
// Force configuration changes from provider.
foreach ($settings as $setting) {
// Need to create a directory for backup_auto_destination.
if ($setting->plugin === 'backup' && $setting->name === 'backup_auto_destination' && $setting->value === true) {
$setting->value = make_request_directory();
}
set_config($setting->name, $setting->value, $setting->plugin);
}
// We want user data to be included for this test.
set_config('backup_auto_users', true, 'backup');
$student = $this->getDataGenerator()->create_and_enrol($this->course, 'student');
// Delete course.
delete_course($this->course, false);
$this->assertFalse($DB->record_exists('course', ['id' => $this->course->id]));
// Verify there is now a backup @ cat recycle bin file area.
$recyclebin = new \tool_recyclebin\category_bin($this->course->category);
$this->assertEquals(1, count($recyclebin->get_items()));
// Restore the recycle bin item.
$recyclebin->restore_item(current($recyclebin->get_items()));
// Get the new course.
$newcourse = $DB->get_record('course', ['shortname' => $this->course->shortname], '*', MUST_EXIST);
// Check that it was removed from the recycle bin.
$this->assertEquals(0, count($recyclebin->get_items()));
// Verify that student DOES continue enrolled.
$this->assertTrue(is_enrolled(context_course::instance($newcourse->id), $student->id));
}
/**
* Tests that user data is not restored when course is restored.
*
* @dataProvider recycle_bin_settings_provider
* @param array $settings array of plugin, name, value stdClass().
*/
public function test_course_restore_without_userdata($settings) {
global $DB;
// Force configuration changes from provider.
foreach ($settings as $setting) {
// Need to create a directory for backup_auto_destination.
if ($setting->plugin === 'backup' && $setting->name === 'backup_auto_destination' && $setting->value === true) {
$setting->value = make_request_directory();
}
set_config($setting->name, $setting->value, $setting->plugin);
}
// We want user data to be included for this test.
set_config('backup_auto_users', false, 'backup');
$student = $this->getDataGenerator()->create_and_enrol($this->course, 'student');
// Delete course.
delete_course($this->course, false);
$this->assertFalse($DB->record_exists('course', ['id' => $this->course->id]));
// Verify there is now a backup @ cat recycle bin file area.
$recyclebin = new \tool_recyclebin\category_bin($this->course->category);
$this->assertEquals(1, count($recyclebin->get_items()));
// Restore the recycle bin item.
$recyclebin->restore_item(current($recyclebin->get_items()));
// Get the new course.
$newcourse = $DB->get_record('course', ['shortname' => $this->course->shortname], '*', MUST_EXIST);
// Check that it was removed from the recycle bin.
$this->assertEquals(0, count($recyclebin->get_items()));
// Verify that student DOES NOT continue enrolled.
$this->assertFalse(is_enrolled(context_course::instance($newcourse->id), $student->id));
}
}
+144 -1
View File
@@ -55,7 +55,7 @@ class tool_recyclebin_course_bin_tests extends advanced_testcase {
$this->course = $this->getDataGenerator()->create_course();
$this->quiz = $this->getDataGenerator()->get_plugin_generator('mod_quiz')->create_instance(array(
'course' => $this->course->id
'course' => $this->course->id, 'grade' => 100.0, 'sumgrades' => 1
));
}
@@ -173,4 +173,147 @@ class tool_recyclebin_course_bin_tests extends advanced_testcase {
$deletedbook = reset($items);
$this->assertEquals($book->name, $deletedbook->name);
}
/**
* Provider for test_coursemodule_restore_with_userdata() and test_coursemodule_restore_without_userdata()
*
* Used to verify that recycle bin is immune to various settings. Provides plugin, name, value for
* direct usage with set_config()
*/
public function recycle_bin_settings_provider() {
return [
'backup/backup_auto_storage moodle' => [[
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 0],
]],
'backup/backup_auto_storage external' => [[
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 1],
(object)['plugin' => 'backup', 'name' => 'backup_auto_destination', 'value' => true],
]],
'backup/backup_auto_storage mixed' => [[
(object)['plugin' => 'backup', 'name' => 'backup_auto_storage', 'value' => 2],
(object)['plugin' => 'backup', 'name' => 'backup_auto_destination', 'value' => true],
]],
];
}
/**
* Tests that user data is restored when module is restored.
*
* @dataProvider recycle_bin_settings_provider
* @param array $settings array of plugin, name, value stdClass().
*/
public function test_coursemodule_restore_with_userdata($settings) {
// Force configuration changes from provider.
foreach ($settings as $setting) {
// Need to create a directory for backup_auto_destination.
if ($setting->plugin === 'backup' && $setting->name === 'backup_auto_destination' && $setting->value === true) {
$setting->value = make_request_directory();
}
set_config($setting->name, $setting->value, $setting->plugin);
}
$student = $this->getDataGenerator()->create_and_enrol($this->course, 'student');
$this->setUser($student);
set_config('backup_auto_users', true, 'backup');
$this->create_quiz_attempt($this->quiz, $student);
// Delete quiz.
$cm = get_coursemodule_from_instance('quiz', $this->quiz->id);
course_delete_module($cm->id);
phpunit_util::run_all_adhoc_tasks();
$quizzes = get_coursemodules_in_course('quiz', $this->course->id);
$this->assertEquals(0, count($quizzes));
// Restore quiz.
$recyclebin = new \tool_recyclebin\course_bin($this->course->id);
foreach ($recyclebin->get_items() as $item) {
$recyclebin->restore_item($item);
}
$quizzes = get_coursemodules_in_course('quiz', $this->course->id);
$this->assertEquals(1, count($quizzes));
$cm = array_pop($quizzes);
// Check if user quiz attempt data is restored.
$attempts = quiz_get_user_attempts($cm->instance, $student->id);
$this->assertEquals(1, count($attempts));
$attempt = array_pop($attempts);
$attemptobj = quiz_attempt::create($attempt->id);
$this->assertEquals($student->id, $attemptobj->get_userid());
$this->assertEquals(true, $attemptobj->is_finished());
}
/**
* Tests that user data is not restored when module is restored.
*
* @dataProvider recycle_bin_settings_provider
* @param array $settings array of plugin, name, value stdClass().
*/
public function test_coursemodule_restore_without_userdata($settings) {
// Force configuration changes from provider.
foreach ($settings as $setting) {
// Need to create a directory for backup_auto_destination.
if ($setting->plugin === 'backup' && $setting->name === 'backup_auto_destination' && $setting->value === true) {
$setting->value = make_request_directory();
}
set_config($setting->name, $setting->value, $setting->plugin);
}
$student = $this->getDataGenerator()->create_and_enrol($this->course, 'student');
$this->setUser($student);
set_config('backup_auto_users', false, 'backup');
$this->create_quiz_attempt($this->quiz, $student);
// Delete quiz.
$cm = get_coursemodule_from_instance('quiz', $this->quiz->id);
course_delete_module($cm->id);
phpunit_util::run_all_adhoc_tasks();
$quizzes = get_coursemodules_in_course('quiz', $this->course->id);
$this->assertEquals(0, count($quizzes));
// Restore quiz.
$recyclebin = new \tool_recyclebin\course_bin($this->course->id);
foreach ($recyclebin->get_items() as $item) {
$recyclebin->restore_item($item);
}
$quizzes = get_coursemodules_in_course('quiz', $this->course->id);
$this->assertEquals(1, count($quizzes));
$cm = array_pop($quizzes);
// Check if user quiz attempt data is restored.
$attempts = quiz_get_user_attempts($cm->instance, $student->id);
$this->assertEquals(0, count($attempts));
}
/**
* Add a question to quiz and create a quiz attempt.
* @param \stdClass $quiz Quiz
* @param \stdClass $student User
* @throws coding_exception
* @throws moodle_exception
*/
private function create_quiz_attempt($quiz, $student) {
// Add Question.
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
$cat = $questiongenerator->create_question_category();
$numq = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
quiz_add_quiz_question($numq->id, $quiz);
// Create quiz attempt.
$quizobj = quiz::create($quiz->id, $student->id);
$quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
$quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
$timenow = time();
$attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $student->id);
quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
quiz_attempt_save_started($quizobj, $quba, $attempt);
$attemptobj = quiz_attempt::create($attempt->id);
$tosubmit = array(1 => array('answer' => '0'));
$attemptobj->process_submitted_actions($timenow, false, $tosubmit);
$attemptobj = quiz_attempt::create($attempt->id);
$attemptobj->process_finish($timenow, false);
}
}
+1 -1
View File
@@ -23,7 +23,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['cannotfit'] = 'The replacement is longer than original and shortening is not allow, cannot continue.';
$string['cannotfit'] = 'The replacement is longer than the original and shortening is not allowed; cannot continue.';
$string['disclaimer'] = 'I understand the risks of this operation';
$string['doit'] = 'Yes, do it!';
$string['excludedtables'] = 'Several tables are not updated as part of the text replacement. These include configuration, log, events, and session tables.';
+95
View File
@@ -0,0 +1,95 @@
<?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 scheduled tasks admin pages.
*
* @package tool_task
* @copyright 2018 Toni Barbera <toni@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_task;
defined('MOODLE_INTERNAL') || die();
/**
* Running tasks from CLI.
*
* @copyright 2018 Toni Barbera <toni@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class run_from_cli {
/**
* Find the path of PHP CLI binary.
*
* @return string|false The PHP CLI executable PATH
*/
protected static function find_php_cli_path() {
global $CFG;
if (!empty($CFG->pathtophp) && is_executable(trim($CFG->pathtophp))) {
return $CFG->pathtophp;
}
return false;
}
/**
* Returns if Moodle have access to PHP CLI binary or not.
*
* @return bool
*/
public static function is_runnable():bool {
return self::find_php_cli_path() !== false;
}
/**
* Executes a cron from web invocation using PHP CLI.
*
* @param \core\task\task_base $task Task that be executed via CLI.
* @return bool
* @throws \moodle_exception
*/
public static function execute(\core\task\task_base $task):bool {
global $CFG;
if (!self::is_runnable()) {
$redirecturl = new \moodle_url('/admin/settings.php', ['section' => 'systempaths']);
throw new \moodle_exception('cannotfindthepathtothecli', 'tool_task', $redirecturl->out());
} else {
// Shell-escaped path to the PHP binary.
$phpbinary = escapeshellarg(self::find_php_cli_path());
// Shell-escaped path CLI script.
$pathcomponents = [$CFG->dirroot, $CFG->admin, 'tool', 'task', 'cli', 'schedule_task.php'];
$scriptpath = escapeshellarg(implode(DIRECTORY_SEPARATOR, $pathcomponents));
// Shell-escaped task name.
$classname = get_class($task);
$taskarg = escapeshellarg("--execute={$classname}");
// Build the CLI command.
$command = "{$phpbinary} {$scriptpath} {$taskarg}";
// Execute it.
passthru($command);
}
return true;
}
}
+31 -5
View File
@@ -25,6 +25,7 @@
$string['asap'] = 'ASAP';
$string['backtoscheduledtasks'] = 'Back to scheduled tasks';
$string['blocking'] = 'Blocking';
$string['cannotfindthepathtothecli'] = 'Cannot find the path to the PHP CLI executable so task execution aborted. Set the "Path to PHP CLI" setting in "Site administration / Server / System paths"';
$string['clearfaildelay_confirm'] = 'Are you sure you want to clear the fail delay for task \'{$a}\'? After clearing the delay, the task will run according to its normal schedule.';
$string['component'] = 'Component';
$string['corecomponent'] = 'Core';
@@ -48,13 +49,38 @@ $string['scheduledtasks'] = 'Scheduled tasks';
$string['scheduledtaskchangesdisabled'] = 'Modifications to the list of scheduled tasks have been prevented in Moodle configuration';
$string['taskdisabled'] = 'Task disabled';
$string['taskscheduleday'] = 'Day';
$string['taskscheduleday_help'] = 'Day of month field for task schedule. The field uses the same format as unix cron. Some examples are:<br/><ul><li><strong>*</strong> Every day</li><li><strong>*/2</strong> Every 2nd day</li><li><strong>1</strong> The first of every month</li><li><strong>1,15</strong> The first and fifteenth of every month</li></ul>';
$string['taskscheduleday_help'] = 'Day of month field for task schedule. The field uses the same format as unix cron. Some examples are:
* <strong>*</strong> Every day
* <strong>*/2</strong> Every 2nd day
* <strong>1</strong> The first of every month
* <strong>1,15</strong> The first and fifteenth of every month';
$string['taskscheduledayofweek'] = 'Day of week';
$string['taskscheduledayofweek_help'] = 'Day of week field for task schedule. The field uses the same format as unix cron. Some examples are:<br/><ul><li><strong>*</strong> Every day</li><li><strong>0</strong> Every Sunday</li><li><strong>6</strong> Every Saturday</li><li><strong>1,5</strong> Every Monday and Friday</li></ul>';
$string['taskscheduledayofweek_help'] = 'Day of week field for task schedule. The field uses the same format as unix cron. Some examples are:
* <strong>*</strong> Every day
* <strong>0</strong> Every Sunday
* <strong>6</strong> Every Saturday
* <strong>1,5</strong> Every Monday and Friday';
$string['taskschedulehour'] = 'Hour';
$string['taskschedulehour_help'] = 'Hour field for task schedule. The field uses the same format as unix cron. Some examples are:<br/><ul><li><strong>*</strong> Every hour</li><li><strong>*/2</strong> Every 2 hours</li><li><strong>2-10</strong> Every hour from 2am until 10am (inclusive)</li><li><strong>2,6,9</strong> 2am, 6am and 9am</li></ul>';
$string['taskschedulehour_help'] = 'Hour field for task schedule. The field uses the same format as unix cron. Some examples are:
* <strong>*</strong> Every hour
* <strong>*/2</strong> Every 2 hours
* <strong>2-10</strong> Every hour from 2am until 10am (inclusive)
* <strong>2,6,9</strong> 2am, 6am and 9am';
$string['taskscheduleminute'] = 'Minute';
$string['taskscheduleminute_help'] = 'Minute field for task schedule. The field uses the same format as unix cron. Some examples are:<br/><ul><li><strong>*</strong> Every minute</li><li><strong>*/5</strong> Every 5 minutes</li><li><strong>2-10</strong> Every minute between 2 and 10 past the hour (inclusive)</li><li><strong>2,6,9</strong> 2 6 and 9 minutes past the hour</li></ul>';
$string['taskscheduleminute_help'] = 'Minute field for task schedule. The field uses the same format as unix cron. Some examples are:
* <strong>*</strong> Every minute
* <strong>*/5</strong> Every 5 minutes
* <strong>2-10</strong> Every minute between 2 and 10 past the hour (inclusive)
* <strong>2,6,9</strong> 2, 6 and 9 minutes past the hour';
$string['taskschedulemonth'] = 'Month';
$string['taskschedulemonth_help'] = 'Month field for task schedule. The field uses the same format as unix cron. Some examples are:<br/><ul><li><strong>*</strong> Every month</li><li><strong>*/2</strong> Every second month</li><li><strong>1</strong> Every January</li><li><strong>1,5</strong> Every January and May</li></ul>';
$string['taskschedulemonth_help'] = 'Month field for task schedule. The field uses the same format as unix cron. Some examples are:
* <strong>*</strong> Every month
* <strong>*/2</strong> Every second month
* <strong>1</strong> Every January
* <strong>1,5</strong> Every January and May';
$string['privacy:metadata'] = 'The Scheduled task configuration plugin does not store any personal data.';
+2 -1
View File
@@ -62,6 +62,7 @@ class tool_task_renderer extends plugin_renderer_base {
$asap = get_string('asap', 'tool_task');
$disabledstr = get_string('taskdisabled', 'tool_task');
$plugindisabledstr = get_string('plugindisabled', 'tool_task');
$runnabletasks = tool_task\run_from_cli::is_runnable();
foreach ($tasks as $task) {
$customised = $task->is_customised() ? $no : $yes;
if (empty($CFG->preventscheduledtaskchanges)) {
@@ -105,7 +106,7 @@ class tool_task_renderer extends plugin_renderer_base {
}
$runnow = '';
if (!$disabled && get_config('tool_task', 'enablerunnow')) {
if ( ! $disabled && get_config('tool_task', 'enablerunnow') && $runnabletasks ) {
$runnow = html_writer::div(html_writer::link(
new moodle_url('/admin/tool/task/schedule_task.php',
array('task' => get_class($task))),
+2 -1
View File
@@ -88,7 +88,8 @@ echo html_writer::start_tag('pre');
$CFG->mtrace_wrapper = 'tool_task_mtrace_wrapper';
// Run the specified task (this will output an error if it doesn't exist).
cron_run_single_task($task);
\tool_task\run_from_cli::execute($task);
echo html_writer::end_tag('pre');
$output = $PAGE->get_renderer('tool_task');
@@ -1,35 +0,0 @@
@tool @tool_task
Feature: Run tasks from web interface
In order to run scheduled tasks immediately
As an admin
I need to be able to run a task from the web interface
Scenario: Run a task
Given I log in as "admin"
When I navigate to "Scheduled tasks" node in "Site administration > Server"
Then I should see "Never" in the "Log table cleanup" "table_row"
And I click on "Run now" "text" in the "Log table cleanup" "table_row"
And I should see "Are you sure you want to run this task"
And I press "Run now"
And I should see "Log table cleanup" in the "h2" "css_element"
And I should see "Scheduled task complete: Log table cleanup"
And I follow "Back to scheduled tasks"
And I should not see "Never" in the "Log table cleanup" "table_row"
Scenario: Cancel running a task
Given I log in as "admin"
When I navigate to "Scheduled tasks" node in "Site administration > Server"
And I click on "Run now" "text" in the "Log table cleanup" "table_row"
And I press "Cancel"
# Confirm we're back on the scheduled tasks page by looking for the table.
Then "Log table cleanup" "table_row" should exist
Scenario: Cannot run a task when the option is disabled
Given the following config values are set as admin:
| enablerunnow | 0 | tool_task |
When I log in as "admin"
And I navigate to "Scheduled tasks" node in "Site administration > Server"
Then I should not see "Run now"
@@ -104,8 +104,7 @@ $string['reset_help'] = 'Whether to reset the course after creating/updating it.
$string['result'] = 'Result';
$string['restoreafterimport'] = 'Restore after import';
$string['rowpreviewnum'] = 'Preview rows';
$string['rowpreviewnum_help'] = 'Number of rows from the CSV file that will be previewed in the next page. This option exists in
order to limit the next page size.';
$string['rowpreviewnum_help'] = 'Number of rows from the CSV file that will be previewed on the following page. This option is for limiting the size of the following page.';
$string['shortnametemplate'] = 'Template to generate a shortname';
$string['shortnametemplate_help'] = 'The short name of the course is displayed in the navigation. You may use template syntax here (%f = fullname, %i = idnumber), or enter an initial value that is incremented.';
$string['templatefile'] = 'Restore from this file after upload';
+1
View File
@@ -183,6 +183,7 @@ function uu_validate_user_upload_columns(csv_import_reader $cir, $stdfields, $pr
$processed = array();
foreach ($columns as $key=>$unused) {
$field = $columns[$key];
$field = trim($field);
$lcfield = core_text::strtolower($field);
if (in_array($field, $stdfields) or in_array($lcfield, $stdfields)) {
// standard fields are only lowercase
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/str","core/notification"],function(a,b,c){var d={removeStep:function(d){d.preventDefault(),b.get_strings([{key:"confirmstepremovaltitle",component:"tool_usertours"},{key:"confirmstepremovalquestion",component:"tool_usertours"},{key:"yes",component:"moodle"},{key:"no",component:"moodle"}]).done(function(b){c.confirm(b[0],b[1],b[2],b[3],a.proxy(function(){window.location=a(this).attr("href")},d.currentTarget))})},setup:function(){a("body").delegate('[data-action="delete"]',"click",d.removeStep)}};return{setup:d.setup}});
define(["jquery","core/str","core/notification"],function(a,b,c){var d={removeStep:function(d){d.preventDefault();var e=a(d.currentTarget).attr("href");b.get_strings([{key:"confirmstepremovaltitle",component:"tool_usertours"},{key:"confirmstepremovalquestion",component:"tool_usertours"},{key:"yes",component:"moodle"},{key:"no",component:"moodle"}]).then(function(a){c.confirm(a[0],a[1],a[2],a[3],function(){window.location=e})})["catch"]()},setup:function(){a("body").delegate('[data-action="delete"]',"click",d.removeStep)}};return{setup:d.setup}});
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/ajax","core/str","core/notification"],function(a,b,c,d){var e={removeTour:function(b){b.preventDefault(),c.get_strings([{key:"confirmtourremovaltitle",component:"tool_usertours"},{key:"confirmtourremovalquestion",component:"tool_usertours"},{key:"yes",component:"moodle"},{key:"no",component:"moodle"}]).done(function(c){d.confirm(c[0],c[1],c[2],c[3],a.proxy(function(){window.location=a(this).attr("href")},b.currentTarget))})},setup:function(){a("body").delegate('[data-action="delete"]',"click",e.removeTour)}};return{setup:e.setup}});
define(["jquery","core/ajax","core/str","core/notification"],function(a,b,c,d){var e={removeTour:function(b){b.preventDefault();var e=a(b.currentTarget).attr("href");c.get_strings([{key:"confirmtourremovaltitle",component:"tool_usertours"},{key:"confirmtourremovalquestion",component:"tool_usertours"},{key:"yes",component:"moodle"},{key:"no",component:"moodle"}]).then(function(a){d.confirm(a[0],a[1],a[2],a[3],function(){window.location=e})})["catch"]()},setup:function(){a("body").delegate('[data-action="delete"]',"click",e.removeTour)}};return{setup:e.setup}});
+10 -5
View File
@@ -18,6 +18,7 @@ function($, str, notification) {
*/
removeStep: function(e) {
e.preventDefault();
var targetUrl = $(e.currentTarget).attr('href');
str.get_strings([
{
key: 'confirmstepremovaltitle',
@@ -35,11 +36,15 @@ function($, str, notification) {
key: 'no',
component: 'moodle'
}
]).done(function(s) {
notification.confirm(s[0], s[1], s[2], s[3], $.proxy(function() {
window.location = $(this).attr('href');
}, e.currentTarget));
});
])
.then(function(s) {
notification.confirm(s[0], s[1], s[2], s[3], function() {
window.location = targetUrl;
});
return;
})
.catch();
},
/**
+10 -6
View File
@@ -18,7 +18,7 @@ function($, ajax, str, notification) {
*/
removeTour: function(e) {
e.preventDefault();
var targetUrl = $(e.currentTarget).attr('href');
str.get_strings([
{
key: 'confirmtourremovaltitle',
@@ -36,11 +36,15 @@ function($, ajax, str, notification) {
key: 'no',
component: 'moodle'
}
]).done(function(s) {
notification.confirm(s[0], s[1], s[2], s[3], $.proxy(function() {
window.location = $(this).attr('href');
}, e.currentTarget));
});
])
.then(function(s) {
notification.confirm(s[0], s[1], s[2], s[3], function() {
window.location = targetUrl;
});
return;
})
.catch();
},
/**
+6
View File
@@ -497,6 +497,12 @@ class helper {
return;
}
if (in_array($PAGE->pagelayout, ['maintenance', 'print', 'redirect'])) {
// Do not try to show user tours inside iframe, in maintenance mode,
// when printing, or during redirects.
return;
}
if (self::$bootstrapped) {
return;
}
+2 -2
View File
@@ -155,7 +155,7 @@ $string['newtable'] = 'New table';
$string['newtablefrommysql'] = 'New table from MySQL';
$string['new_table_from_mysql'] = 'New table from MySQL';
$string['nofieldsspecified'] = 'No fields specified';
$string['nomasterprimaryuniquefound'] = 'The column(s) that you foreign key references must be included in a primary or unique KEY in the referenced table. Note, the column being in a UNIQUE INDEX is not good enough.';
$string['nomasterprimaryuniquefound'] = 'The column(s) that your foreign key references must be included in a primary or unique KEY in the referenced table. Note that the column being in a UNIQUE INDEX is not good enough.';
$string['nomissingindexesfound'] = 'No missing indexes have been found, your DB doesn\'t need further actions.';
$string['noreffieldsspecified'] = 'No reference fields specified';
$string['noreftablespecified'] = 'Specified reference table not found';
@@ -217,6 +217,6 @@ $string['yeswrongdefaultsfound'] = '<p>Some inconsistent defaults have been foun
<p>After doing that, it\'s highly recommended to execute this utility again to check that no more inconsistent defaults are found.</p>';
$string['yeswrongintsfound'] = '<p>Some wrong integers have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to fix them. Remember to backup your data first!</p>
<p>After fixing them, it is highly recommended to execute this utility again to check that no more wrong integers are found.</p>';
$string['yeswrongoraclesemanticsfound'] = '<p>Some Oracle columns using BYTE semantics have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to create all them. Remember to backup your data first!</p>
$string['yeswrongoraclesemanticsfound'] = '<p>Some Oracle columns using BYTE semantics have been found in your DB. Here are their details and the needed SQL statements to be executed with your favourite SQL interface to convert them all. Remember to backup your data first!</p>
<p>After doing that, it\'s highly recommended to execute this utility again to check that no more wrong semantics are found.</p>';
$string['privacy:metadata'] = 'The XMLDB editor plugin does not store any personal data.';
+34 -19
View File
@@ -577,9 +577,14 @@ abstract class base {
return $result;
}
// Remove samples the target consider invalid.
$this->analysabletarget->add_sample_data($samplesdata);
$this->analysabletarget->filter_out_invalid_samples($sampleids, $analysable, $includetarget);
try {
// Remove samples the target consider invalid.
$this->analysabletarget->add_sample_data($samplesdata);
$this->analysabletarget->filter_out_invalid_samples($sampleids, $analysable, $includetarget);
} catch (\Throwable $e) {
$dataset->close_process();
throw $e;
}
if (!$sampleids) {
$result->status = \core_analytics\model::NO_DATASET;
@@ -588,19 +593,24 @@ abstract class base {
return $result;
}
foreach ($this->indicators as $key => $indicator) {
// The analyser attaches the main entities the sample depends on and are provided to the
// indicator to calculate the sample.
$this->indicators[$key]->add_sample_data($samplesdata);
}
try {
foreach ($this->indicators as $key => $indicator) {
// The analyser attaches the main entities the sample depends on and are provided to the
// indicator to calculate the sample.
$this->indicators[$key]->add_sample_data($samplesdata);
}
// Here we start the memory intensive process that will last until $data var is
// unset (until the method is finished basically).
if ($includetarget) {
$data = $timesplitting->calculate($sampleids, $this->get_samples_origin(), $this->indicators, $ranges,
$this->analysabletarget);
} else {
$data = $timesplitting->calculate($sampleids, $this->get_samples_origin(), $this->indicators, $ranges);
// Here we start the memory intensive process that will last until $data var is
// unset (until the method is finished basically).
if ($includetarget) {
$data = $timesplitting->calculate($sampleids, $this->get_samples_origin(), $this->indicators, $ranges,
$this->analysabletarget);
} else {
$data = $timesplitting->calculate($sampleids, $this->get_samples_origin(), $this->indicators, $ranges);
}
} catch (\Throwable $e) {
$dataset->close_process();
throw $e;
}
if (!$data) {
@@ -610,11 +620,16 @@ abstract class base {
return $result;
}
// Add extra metadata.
$this->add_model_metadata($data);
try {
// Add extra metadata.
$this->add_model_metadata($data);
// Write all calculated data to a file.
$file = $dataset->store($data);
// Write all calculated data to a file.
$file = $dataset->store($data);
} catch (\Throwable $e) {
$dataset->close_process();
throw $e;
}
// Flag the model + analysable + timesplitting as analysed.
$dataset->close_process();
+16 -4
View File
@@ -169,10 +169,7 @@ abstract class base extends \core_analytics\calculable {
if (!is_null($calculatedvalue)) {
$notnulls[$sampleid] = $sampleid;
if ($calculatedvalue > self::MAX_VALUE || $calculatedvalue < self::MIN_VALUE) {
throw new \coding_exception('Calculated values should be higher than ' . self::MIN_VALUE .
' and lower than ' . self::MAX_VALUE . ' ' . $calculatedvalue . ' received');
}
$this->validate_calculated_value($calculatedvalue);
}
$calculations[$sampleid] = $calculatedvalue;
@@ -182,4 +179,19 @@ abstract class base extends \core_analytics\calculable {
return array($features, $newcalculations, $notnulls);
}
/**
* Validates the calculated value.
*
* @throws \coding_exception
* @param float $calculatedvalue
* @return true
*/
protected function validate_calculated_value($calculatedvalue) {
if ($calculatedvalue > self::MAX_VALUE || $calculatedvalue < self::MIN_VALUE) {
throw new \coding_exception('Calculated values should be higher than ' . self::MIN_VALUE .
' and lower than ' . self::MAX_VALUE . ' ' . $calculatedvalue . ' received');
}
return true;
}
}
+1 -3
View File
@@ -41,9 +41,7 @@ abstract class binary extends discrete {
* @return array
*/
public static final function get_classes() {
// It does not really matter, all \core_analytics\local\indicator\discrete get_classes calls have been overwriten as we
// only need 1 column here.
return array(0);
return [-1, 1];
}
/**
+26 -8
View File
@@ -52,8 +52,7 @@ abstract class discrete extends base {
public static function get_feature_headers() {
$fullclassname = '\\' . get_called_class();
$headers = array($fullclassname);
foreach (self::get_classes() as $class) {
foreach (static::get_classes() as $class) {
$headers[] = $fullclassname . '/' . $class;
}
@@ -116,26 +115,45 @@ abstract class discrete extends base {
*/
protected function to_features($calculatedvalues) {
$classes = self::get_classes();
$classes = static::get_classes();
foreach ($calculatedvalues as $sampleid => $calculatedvalue) {
$classindex = array_search($calculatedvalue, $classes, true);
// Using intval as it may come as a float from the db.
$classindex = array_search(intval($calculatedvalue), $classes, true);
if (!$classindex) {
throw new \coding_exception(get_class($this) . ' calculated "' . $calculatedvalue .
'" which is not one of its defined classes (' . json_encode($classes) . ')');
if ($classindex === false && !is_null($calculatedvalue)) {
throw new \coding_exception(get_class($this) . ' calculated value "' . $calculatedvalue .
'" is not one of its defined classes (' . json_encode($classes) . ')');
}
// We transform the calculated value into multiple features, one for each of the possible classes.
$features = array_fill(0, count($classes), 0);
// 1 to the selected value.
$features[$classindex] = 1;
if (!is_null($calculatedvalue)) {
$features[$classindex] = 1;
}
$calculatedvalues[$sampleid] = $features;
}
return $calculatedvalues;
}
/**
* Validates the calculated value.
*
* @param float $calculatedvalue
* @return true
*/
protected function validate_calculated_value($calculatedvalue) {
// Using intval as it may come as a float from the db.
if (!in_array(intval($calculatedvalue), static::get_classes())) {
throw new \coding_exception(get_class($this) . ' calculated value "' . $calculatedvalue .
'" is not one of its defined classes (' . json_encode(static::get_classes()) . ')');
}
return true;
}
}
+1 -1
View File
@@ -196,7 +196,7 @@ abstract class base extends \core_analytics\calculable {
$message->component = 'moodle';
$message->name = 'insights';
$message->userfrom = get_admin();
$message->userfrom = \core_user::get_noreply_user();
$message->userto = $user;
$insighturl = new \moodle_url('/report/insights/insights.php?modelid=' . $modelid . '&contextid=' . $context->id);
+4 -1
View File
@@ -1480,7 +1480,10 @@ class model {
// 1 db read per context.
$this->purge_insights_cache();
$this->model->trained = 0;
if (!$this->is_static()) {
$this->model->trained = 0;
}
$this->model->timemodified = time();
$this->model->usermodified = $USER->id;
$DB->update_record('analytics_models', $this->model);
+90
View File
@@ -0,0 +1,90 @@
<?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/>.
/**
* Test indicator.
*
* @package core_analytics
* @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Test indicator.
*
* @package core_analytics
* @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class test_indicator_discrete extends \core_analytics\local\indicator\discrete {
/**
* Returns the name.
*
* If there is a corresponding '_help' string this will be shown as well.
*
* @return \lang_string
*/
public static function get_name() : \lang_string {
// Using a string that exists and contains a corresponding '_help' string.
return new \lang_string('allowstealthmodules');
}
/**
* The different classes this discrete indicator provides.
* @return [type] [description]
*/
protected static function get_classes() {
return [0, 1, 2, 3, 4];
}
/**
* Just for testing.
*
* @param float $value
* @param string $subtype
* @return string
*/
public function get_calculation_outcome($value, $subtype = false) {
return self::OUTCOME_OK;
}
/**
* Custom indicator calculated value display as otherwise we would display meaningless numbers to users.
*
* @param float $value
* @param string $subtype
* @return string
*/
public function get_display_value($value, $subtype = false) {
return $value;
}
/**
* calculate_sample
*
* @param int $sampleid
* @param string $sampleorigin
* @param int $starttime
* @param int $endtime
* @return float
*/
protected function calculate_sample($sampleid, $sampleorigin, $starttime = false, $endtime = false) {
return 4;
}
}
+1 -1
View File
@@ -31,7 +31,7 @@ defined('MOODLE_INTERNAL') || die();
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class test_indicator_random extends \core_analytics\local\indicator\binary {
class test_indicator_random extends \core_analytics\local\indicator\linear {
/**
* Returns a lang_string object representing the name for the indicator.
+99
View File
@@ -0,0 +1,99 @@
<?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/>.
/**
* Unit tests for the indicator API.
*
* @package core_analytics
* @copyright 2019 David Monllaó {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once(__DIR__ . '/fixtures/test_indicator_max.php');
require_once(__DIR__ . '/fixtures/test_indicator_discrete.php');
require_once(__DIR__ . '/fixtures/test_indicator_min.php');
/**
* Unit tests for the model.
*
* @package core_analytics
* @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class analytics_indicator_testcase extends advanced_testcase {
/**
* test_validate_calculated_value
*
* @param string $indicatorclass
* @param array $returnedvalue
* @dataProvider validate_calculated_value
* @return null
*/
public function test_validate_calculated_value($indicatorclass, $returnedvalue) {
$indicator = new $indicatorclass();
list($values, $unused) = $indicator->calculate([1], 'notrelevanthere');
$this->assertEquals($returnedvalue, $values[0]);
}
/**
* Data provider for test_validate_calculated_value
*
* @return array
*/
public function validate_calculated_value() {
return [
'max' => ['test_indicator_max', [1]],
'min' => ['test_indicator_min', [-1]],
'discrete' => ['test_indicator_discrete', [0, 0, 0, 0, 1]],
];
}
/**
* test_validate_calculated_value_exceptions
*
* @param string $indicatorclass
* @param string $willreturn
* @dataProvider validate_calculated_value_exceptions
* @expectedException \coding_exception
* @return null
*/
public function test_validate_calculated_value_exceptions($indicatorclass, $willreturn) {
$indicator = new $indicatorclass();
$indicatormock = $this->getMockBuilder(get_class($indicator))
->setMethods(['calculate_sample'])
->getMock();
$indicatormock->method('calculate_sample')->willReturn($willreturn);
list($values, $unused) = $indicatormock->calculate([1], 'notrelevanthere');
}
/**
* Data provider for test_validate_calculated_value_exceptions
*
* @return array
*/
public function validate_calculated_value_exceptions() {
return [
'max' => ['test_indicator_max', 2],
'min' => ['test_indicator_min', -2],
'discrete' => ['test_indicator_discrete', 7],
];
}
}
+24
View File
@@ -168,10 +168,34 @@ class analytics_model_testcase extends advanced_testcase {
$this->assertEmpty($DB->count_records('analytics_predict_samples'));
$this->assertEmpty($DB->count_records('analytics_used_files'));
// Check that the model is marked as not trained after clearing (as it is not a static one).
$this->assertEquals(0, $DB->get_field('analytics_models', 'trained', array('id' => $this->modelobj->id)));
set_config('enabled_stores', '', 'tool_log');
get_log_manager(true);
}
/**
* Test behaviour of {\core_analytics\model::clear()} for static models.
*/
public function test_clear_static() {
global $DB;
$this->resetAfterTest();
$statictarget = new test_static_target_shortname();
$indicators['test_indicator_max'] = \core_analytics\manager::get_indicator('test_indicator_max');
$model = \core_analytics\model::create($statictarget, $indicators, '\core\analytics\time_splitting\quarters');
$modelobj = $model->get_model_obj();
// Static models are always considered trained.
$this->assertEquals(1, $DB->get_field('analytics_models', 'trained', array('id' => $modelobj->id)));
$model->clear();
// Check that the model is still marked as trained even after clearing.
$this->assertEquals(1, $DB->get_field('analytics_models', 'trained', array('id' => $modelobj->id)));
}
public function test_model_manager() {
$this->resetAfterTest(true);
+1 -1
View File
@@ -455,7 +455,7 @@ class core_analytics_prediction_testcase extends advanced_testcase {
$indicator = $this->getMockBuilder('test_indicator_max')->setMethods(['calculate_sample'])->getMock();
$indicator->expects($this->never())->method('calculate_sample');
$existingcalcs = array(111 => 1, 222 => 0.5);
$existingcalcs = array(111 => 1, 222 => -1);
$sampleids = array(111 => 111, 222 => 222);
list($values, $unused) = $indicator->calculate($sampleids, $sampleorigin, $starttime, $endtime, $existingcalcs);
}
+1 -1
View File
@@ -33,7 +33,7 @@ $string['auth_dbextencodinghelp'] = 'Encoding used in external database';
$string['auth_dbextrafields'] = 'These fields are optional. You can choose to pre-fill some Moodle user fields with information from the <b>external database fields</b> that you specify here. <p>If you leave these blank, then defaults will be used.</p><p>In either case, the user will be able to edit all of these fields after they log in.</p>';
$string['auth_dbfieldpass'] = 'Name of the field containing passwords';
$string['auth_dbfieldpass_key'] = 'Password field';
$string['auth_dbfielduser'] = 'Name of the field containing usernames';
$string['auth_dbfielduser'] = 'Name of the field containing usernames. This field must be a varchar data type.';
$string['auth_dbfielduser_key'] = 'Username field';
$string['auth_dbhost'] = 'The computer hosting the database server. Use a system DSN entry if using ODBC. Use a PDO DSN entry if using PDO.';
$string['auth_dbhost_key'] = 'Host';
+7
View File
@@ -99,6 +99,13 @@ class auth_db_testcase extends advanced_testcase {
case 'mssql':
set_config('type', 'mssqlnative', 'auth_db');
set_config('sybasequoting', '1', 'auth_db');
// The native sqlsrv driver uses a comma as separator between host and port.
$dbhost = $CFG->dbhost;
if (!empty($dboptions['dbport'])) {
$dbhost .= ',' . $dboptions['dbport'];
}
set_config('host', $dbhost, 'auth_db');
break;
default:
+33
View File
@@ -63,3 +63,36 @@ Feature: User must accept policy when logging in and signing up
And I log in as "user1"
And I open my profile in edit mode
And the field "First name" matches value "User1"
Scenario Outline: Email validation during email registration
Given the following config values are set as admin:
| allowaccountssameemail | <allowsameemail> |
| registerauth | email |
| passwordpolicy | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| s1 | John | Doe | s1@example.com |
And I am on site homepage
And I follow "Log in"
When I press "Create new account"
And I set the following fields to these values:
| Username | s2 |
| Password | test |
| Email address | <email1> |
| Email (again) | <email2> |
| First name | Jane |
| Surname | Doe |
And I press "Create my new account"
Then I should <expect> "This email address is already registered. Perhaps you created an account in the past?"
And I should <expect2> "Invalid email address"
Examples:
| allowsameemail | email1 | email2 | expect | expect2 |
| 0 | s1@example.com | s1@example.com | see | not see |
| 0 | S1@EXAMPLE.COM | S1@EXAMPLE.COM | see | not see |
| 0 | s1@example.com | S1@EXAMPLE.COM | see | not see |
| 0 | s2@example.com | s1@example.com | not see | see |
| 1 | s1@example.com | s1@example.com | not see | not see |
| 1 | S1@EXAMPLE.COM | S1@EXAMPLE.COM | not see | not see |
| 1 | s1@example.com | S1@EXAMPLE.COM | not see | not see |
| 1 | s1@example.com | s2@example.com | not see | see |
+1 -5
View File
@@ -36,11 +36,7 @@ $string['auth_ldap_contexts_key'] = 'Contexts';
$string['auth_ldap_create_context'] = 'If you enable user creation with email confirmation, specify the context where users are created. This context should be different from other users to prevent security issues. You don\'t need to add this context to ldap_context-variable, Moodle will search for users from this context automatically.<br /><b>Note!</b> You have to modify the method user_create() in file auth/ldap/auth.php to make user creation work';
$string['auth_ldap_create_context_key'] = 'Context for new users';
$string['auth_ldap_create_error'] = 'Error creating user in LDAP.';
$string['auth_ldapdescription'] = 'This method provides authentication against an external LDAP server.
If the given username and password are valid, Moodle creates a new user
entry in its database. This module can read user attributes from LDAP and prefill
wanted fields in Moodle. For following logins only the username and
password are checked.';
$string['auth_ldapdescription'] = 'This method provides authentication against an external LDAP server. If the given username and password are valid, Moodle creates a new user entry in its database. This plugin can read user attributes from LDAP and prefill wanted fields in Moodle. For following logins only the username and password are checked.';
$string['auth_ldap_expiration_desc'] = 'Select \'{$a->no}\' to disable expired password checking or \'{$a->ldapserver}\' to read the password expiry time directly from the LDAP server.';
$string['auth_ldap_expiration_key'] = 'Expiry';
$string['auth_ldap_expiration_warning_desc'] = 'Number of days before password expiry warning is issued.';
+6 -4
View File
@@ -273,13 +273,15 @@ class provider implements
return;
}
$userid = $contextlist->get_user()->id;
foreach ($contextlist->get_contexts() as $context) {
if ($context->contextlevel != CONTEXT_USER) {
return;
continue;
}
if ($context->instanceid == $userid) {
// Because we only use user contexts the instance ID is the user ID.
$DB->delete_records('mnet_log', ['userid' => $context->instanceid]);
}
// Because we only use user contexts the instance ID is the user ID.
$DB->delete_records('mnet_log', ['userid' => $context->instanceid]);
}
}
}
+6 -3
View File
@@ -178,12 +178,15 @@ class provider implements
if (empty($contextlist->count())) {
return;
}
$userid = $contextlist->get_user()->id;
foreach ($contextlist->get_contexts() as $context) {
if ($context->contextlevel != CONTEXT_USER) {
return;
continue;
}
if ($context->instanceid == $userid) {
// Because we only use user contexts the instance ID is the user ID.
static::delete_user_data($context->instanceid);
}
// Because we only use user contexts the instance ID is the user ID.
static::delete_user_data($context->instanceid);
}
}
+1 -1
View File
@@ -32,7 +32,7 @@ $string['auth_shibboleth_login'] = 'Shibboleth login';
$string['auth_shibboleth_login_long'] = 'Login to Moodle via Shibboleth';
$string['auth_shibboleth_manual_login'] = 'Manual login';
$string['auth_shibboleth_select_member'] = 'I\'m a member of ...';
$string['auth_shibboleth_select_organization'] = 'For authentication via Shibboleth, please select your organization from the drop down list:';
$string['auth_shibboleth_select_organization'] = 'For authentication via Shibboleth, please select your organisation from the drop-down menu:';
$string['auth_shib_convert_data'] = 'Data modification API';
$string['auth_shib_convert_data_description'] = 'You can use this API to further modify the data provided by Shibboleth. Read the <a href="../auth/shibboleth/README.txt">README</a> for further instructions.';
$string['auth_shib_convert_data_warning'] = 'The file does not exist or is not readable by the webserver process!';
@@ -311,11 +311,11 @@ class backup_controller extends base_controller {
// Basic/initial prevention against time/memory limits
core_php_time_limit::raise(1 * 60 * 60); // 1 hour for 1 course initially granted
raise_memory_limit(MEMORY_EXTRA);
// If this is not a course backup, inform the plan we are not
// If this is not a course backup, or single activity backup (e.g. duplicate) inform the plan we are not
// including all the activities for sure. This will affect any
// task/step executed conditionally to stop including information
// for section and activity backup. MDL-28180.
if ($this->get_type() !== backup::TYPE_1COURSE) {
if ($this->get_type() !== backup::TYPE_1COURSE && $this->get_type() !== backup::TYPE_1ACTIVITY) {
$this->log('notifying plan about excluded activities by type', backup::LOG_DEBUG);
$this->plan->set_excluding_activities();
}
@@ -326,11 +326,11 @@ class restore_controller extends base_controller {
// Basic/initial prevention against time/memory limits
core_php_time_limit::raise(1 * 60 * 60); // 1 hour for 1 course initially granted
raise_memory_limit(MEMORY_EXTRA);
// If this is not a course restore, inform the plan we are not
// If this is not a course restore or single activity restore (e.g. duplicate), inform the plan we are not
// including all the activities for sure. This will affect any
// task/step executed conditionally to stop processing information
// for section and activity restore. MDL-28180.
if ($this->get_type() !== backup::TYPE_1COURSE) {
if ($this->get_type() !== backup::TYPE_1COURSE && $this->get_type() !== backup::TYPE_1ACTIVITY) {
$this->log('notifying plan about excluded activities by type', backup::LOG_DEBUG);
$this->plan->set_excluding_activities();
}
+5 -1
View File
@@ -2270,7 +2270,11 @@ class backup_questions_structure_step extends backup_structure_step {
FROM {tag} t
JOIN {tag_instance} ti ON ti.tagid = t.id
WHERE ti.itemid = ?
AND ti.itemtype = 'question'", array(backup::VAR_PARENTID));
AND ti.itemtype = 'question'
AND ti.component = 'core_question'",
[
backup::VAR_PARENTID
]);
// don't need to annotate ids nor files
// (already done by {@link backup_annotate_all_question_files}
@@ -580,6 +580,17 @@ abstract class backup_controller_dbops extends backup_dbops {
'backup_import_competencies' => 'competencies'
);
self::apply_admin_config_defaults($controller, $settings, true);
if ((!$controller->get_interactive()) &&
$controller->get_type() == backup::TYPE_1ACTIVITY) {
// This is duplicate - there is no concept of defaults - these settings must be on.
$settings = array(
'activities',
'blocks',
'filters',
'questionbank'
);
self::force_enable_settings($controller, $settings);
}
break;
case backup::MODE_AUTOMATED:
// Load the automated defaults.
@@ -607,6 +618,30 @@ abstract class backup_controller_dbops extends backup_dbops {
}
}
/**
* Turn these settings on. No defaults from admin settings.
*
* @param backup_controller $controller
* @param array $settings a map from admin config names to setting names (Config name => Setting name)
*/
private static function force_enable_settings(backup_controller $controller, array $settings) {
$plan = $controller->get_plan();
foreach ($settings as $config => $settingname) {
$value = true;
if ($plan->setting_exists($settingname)) {
$setting = $plan->get_setting($settingname);
// We do not allow this setting to be locked for a duplicate function.
if ($setting->get_status() !== base_setting::NOT_LOCKED) {
$setting->set_status(base_setting::NOT_LOCKED);
}
$setting->set_value($value);
$setting->set_status(base_setting::LOCKED_BY_CONFIG);
} else {
$controller->log('Unknown setting: ' . $setting, BACKUP::LOG_DEBUG);
}
}
}
/**
* Sets the controller settings default values from the admin config.
*
@@ -183,6 +183,18 @@ abstract class restore_controller_dbops extends restore_dbops {
);
self::apply_admin_config_defaults($controller, $settings, true);
}
if ($controller->get_mode() == backup::MODE_IMPORT &&
(!$controller->get_interactive()) &&
$controller->get_type() == backup::TYPE_1ACTIVITY) {
// This is duplicate - there is no concept of defaults - these settings must be on.
$settings = array(
'activities',
'blocks',
'filters',
'questionbank'
);
self::force_enable_settings($controller, $settings);
};
// Add some dependencies.
$plan = $controller->get_plan();
@@ -233,6 +245,30 @@ abstract class restore_controller_dbops extends restore_dbops {
return $value;
}
/**
* Turn these settings on. No defaults from admin settings.
*
* @param restore_controller $controller
* @param array $settings a map from admin config names to setting names (Config name => Setting name)
*/
private static function force_enable_settings(restore_controller $controller, array $settings) {
$plan = $controller->get_plan();
foreach ($settings as $config => $settingname) {
$value = true;
if ($plan->setting_exists($settingname)) {
$setting = $plan->get_setting($settingname);
// We do not allow this setting to be locked for a duplicate function.
if ($setting->get_status() !== base_setting::NOT_LOCKED) {
$setting->set_status(base_setting::NOT_LOCKED);
}
$setting->set_value($value);
$setting->set_status(base_setting::LOCKED_BY_CONFIG);
} else {
$controller->log('Unknown setting: ' . $settingname, BACKUP::LOG_DEBUG);
}
}
}
/**
* Sets the controller settings default values from the admin config.
*
+141 -259
View File
@@ -1,5 +1,4 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@@ -82,7 +81,7 @@ abstract class setting_dependency {
* Destroy all circular references. It helps PHP 5.2 a lot!
*/
public function destroy() {
// No need to destroy anything recursively here, direct reset
// No need to destroy anything recursively here, direct reset.
$this->setting = null;
$this->dependentsetting = null;
}
@@ -94,16 +93,19 @@ abstract class setting_dependency {
* @return bool
*/
final public function process_change($changetype, $oldvalue) {
// Check the type of change requested
// Check the type of change requested.
switch ($changetype) {
// Process a status change
case base_setting::CHANGED_STATUS: return $this->process_status_change($oldvalue);
// Process a visibility change
case base_setting::CHANGED_VISIBILITY: return $this->process_visibility_change($oldvalue);
// Process a value change
case base_setting::CHANGED_VALUE: return $this->process_value_change($oldvalue);
// Process a status change.
case base_setting::CHANGED_STATUS:
return $this->process_status_change($oldvalue);
// Process a visibility change.
case base_setting::CHANGED_VISIBILITY:
return $this->process_visibility_change($oldvalue);
// Process a value change.
case base_setting::CHANGED_VALUE:
return $this->process_value_change($oldvalue);
}
// Throw an exception if we get this far
// Throw an exception if we get this far.
throw new backup_ui_exception('unknownchangetype');
}
/**
@@ -112,11 +114,11 @@ abstract class setting_dependency {
* @return bool
*/
protected function process_visibility_change($oldvisibility) {
// Store the current dependent settings visibility for comparison
// Store the current dependent settings visibility for comparison.
$prevalue = $this->dependentsetting->get_visibility();
// Set it regardless of whether we need to
// Set it regardless of whether we need to.
$this->dependentsetting->set_visibility($this->setting->get_visibility());
// Return true if it changed
// Return true if it changed.
return ($prevalue != $this->dependentsetting->get_visibility());
}
/**
@@ -182,15 +184,16 @@ class setting_dependency_disabledif_equals extends setting_dependency {
*/
public function __construct(base_setting $setting, base_setting $dependentsetting, $value, $defaultvalue = false) {
parent::__construct($setting, $dependentsetting, $defaultvalue);
$this->value = ($value)?(string)$value:0;
$this->value = ($value) ? (string)$value : 0;
}
/**
* Returns true if the dependent setting is locked by this setting_dependency.
* @return bool
*/
public function is_locked() {
// If the setting is locked or the dependent setting should be locked then return true
if ($this->setting->get_status() !== base_setting::NOT_LOCKED || $this->setting->get_value() == $this->value) {
// If the setting is locked or the dependent setting should be locked then return true.
if ($this->setting->get_status() !== base_setting::NOT_LOCKED ||
$this->evaluate_disabled_condition($this->setting->get_value())) {
return true;
}
// Else the dependent setting is not locked by this setting_dependency.
@@ -208,17 +211,25 @@ class setting_dependency_disabledif_equals extends setting_dependency {
return false;
}
$prevalue = $this->dependentsetting->get_value();
// If the setting is the desired value enact the dependency
if ($this->setting->get_value() == $this->value) {
// If the setting is the desired value enact the dependency.
$settingvalue = $this->setting->get_value();
if ($this->evaluate_disabled_condition($settingvalue)) {
// The dependent setting needs to be locked by hierachy and set to the
// default value.
$this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
$this->dependentsetting->set_value($this->defaultvalue);
// For checkboxes the default value is false, but when the setting is
// locked, the value should inherit from the parent setting.
if ($this->defaultvalue === false) {
$this->dependentsetting->set_value($settingvalue);
} else {
$this->dependentsetting->set_value($this->defaultvalue);
}
} else if ($this->dependentsetting->get_status() == base_setting::LOCKED_BY_HIERARCHY) {
// We can unlock the dependent setting
// We can unlock the dependent setting.
$this->dependentsetting->set_status(base_setting::NOT_LOCKED);
}
// Return true if the value has changed for the dependent setting
// Return true if the value has changed for the dependent setting.
return ($prevalue != $this->dependentsetting->get_value());
}
/**
@@ -227,17 +238,18 @@ class setting_dependency_disabledif_equals extends setting_dependency {
* @return bool
*/
protected function process_status_change($oldstatus) {
// Store the dependent status
// Store the dependent status.
$prevalue = $this->dependentsetting->get_status();
// Store the current status
// Store the current status.
$currentstatus = $this->setting->get_status();
if ($currentstatus == base_setting::NOT_LOCKED) {
if ($prevalue == base_setting::LOCKED_BY_HIERARCHY && $this->setting->get_value() != $this->value) {
// Dependency has changes, is not fine, unlock the dependent setting
if ($prevalue == base_setting::LOCKED_BY_HIERARCHY &&
!$this->evaluate_disabled_condition($this->setting->get_value())) {
// Dependency has changes, is not fine, unlock the dependent setting.
$this->dependentsetting->set_status(base_setting::NOT_LOCKED);
}
} else {
// Make sure the dependent setting is also locked, in this case by hierarchy
// Make sure the dependent setting is also locked, in this case by hierarchy.
$this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
}
// Return true if the dependent setting has changed.
@@ -248,17 +260,17 @@ class setting_dependency_disabledif_equals extends setting_dependency {
* @return bool True if there were changes
*/
public function enforce() {
// This will be set to true if ANYTHING changes
// This will be set to true if ANYTHING changes.
$changes = false;
// First process any value changes
// First process any value changes.
if ($this->process_value_change($this->setting->get_value())) {
$changes = true;
}
// Second process any status changes
// Second process any status changes.
if ($this->process_status_change($this->setting->get_status())) {
$changes = true;
}
// Finally process visibility changes
// Finally process visibility changes.
if ($this->process_visibility_change($this->setting->get_visibility())) {
$changes = true;
}
@@ -271,152 +283,72 @@ class setting_dependency_disabledif_equals extends setting_dependency {
*/
public function get_moodleform_properties() {
return array(
'setting'=>$this->dependentsetting->get_ui_name(),
'dependenton'=>$this->setting->get_ui_name(),
'condition'=>'eq',
'value'=>$this->value
'setting' => $this->dependentsetting->get_ui_name(),
'dependenton' => $this->setting->get_ui_name(),
'condition' => 'eq',
'value' => $this->value
);
}
/**
* Evaluate the current value of the setting and return true if the dependent setting should be locked or false.
* This function should be abstract, but there will probably be existing sub-classes so we must provide a default
* implementation.
* @param mixed $value The value of the parent setting.
* @return bool
*/
protected function evaluate_disabled_condition($value) {
return $value == $this->value;
}
}
/**
* A dependency that disables the secondary setting if the primary setting is
* not equal to the provided value
*
* @copyright 2011 Darko Miletic <dmiletic@moodlerooms.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class setting_dependency_disabledif_not_equals extends setting_dependency_disabledif_equals {
/**
* Evaluate the current value of the setting and return true if the dependent setting should be locked or false.
* @param mixed $value The value of the parent setting.
* @return bool
*/
protected function evaluate_disabled_condition($value) {
return $value != $this->value;
}
/**
* Returns an array of properties suitable to be used to define a moodleforms
* disabled command
* @return array
*/
public function get_moodleform_properties() {
return array(
'setting' => $this->dependentsetting->get_ui_name(),
'dependenton' => $this->setting->get_ui_name(),
'condition' => 'notequal',
'value' => $this->value
);
}
}
/**
* A dependency that disables the secondary setting if the primary setting is
* not equal to the provided value
*
* @copyright 2011 Darko Miletic <dmiletic@moodlerooms.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class setting_dependency_disabledif_not_equals extends setting_dependency_disabledif_equals {
/**
* Enforces the dependency if required.
* @return bool True if there were changes
*/
public function enforce() {
// This will be set to true if ANYTHING changes
$changes = false;
// First process any value changes
if (!$this->process_value_change($this->setting->get_value())) {
$changes = true;
}
// Second process any status changes
if ($this->process_status_change($this->setting->get_status())) {
$changes = true;
}
// Finally process visibility changes
if ($this->process_visibility_change($this->setting->get_visibility())) {
$changes = true;
}
return $changes;
}
/**
* Returns an array of properties suitable to be used to define a moodleforms
* disabled command
* @return array
*/
public function get_moodleform_properties() {
return array(
'setting'=>$this->dependentsetting->get_ui_name(),
'dependenton'=>$this->setting->get_ui_name(),
'condition'=>'notequal',
'value'=>$this->value
);
}
}
* Disable if a value is in a list.
*/
class setting_dependency_disabledif_in_array extends setting_dependency_disabledif_equals {
//with array
class setting_dependency_disabledif_equals2 extends setting_dependency {
/**
* The value to compare to
* @var mixed
*/
protected $value;
/**
* Creates the dependency
*
* @param base_setting $setting
* @param base_setting $dependentsetting
* @param mixed $value
* @param mixed $defaultvalue
*/
public function __construct(base_setting $setting, base_setting $dependentsetting, array $value, $defaultvalue = false) {
parent::__construct($setting, $dependentsetting, $defaultvalue);
$this->value = $value;
}
/**
* Returns true if the dependent setting is locked by this setting_dependency.
* Evaluate the current value of the setting and return true if the dependent setting should be locked or false.
* @param mixed $value The value of the parent setting.
* @return bool
*/
public function is_locked() {
// If the setting is locked or the dependent setting should be locked then return true
if ($this->setting->get_status() !== base_setting::NOT_LOCKED || in_array($this->setting->get_value(), $this->value)) {
return true;
}
// Else the dependent setting is not locked by this setting_dependency.
return false;
}
/**
* Processes a value change in the primary setting
* @param mixed $oldvalue
* @return bool
*/
protected function process_value_change($oldvalue) {
$prevalue = $this->dependentsetting->get_value();
// If the setting is the desired value enact the dependency
if (in_array($this->setting->get_value(), $this->value)) {
// The dependent setting needs to be locked by hierachy and set to the
// default value.
$this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
$this->dependentsetting->set_value($this->defaultvalue);
} else if ($this->dependentsetting->get_status() == base_setting::LOCKED_BY_HIERARCHY) {
// We can unlock the dependent setting
$this->dependentsetting->set_status(base_setting::NOT_LOCKED);
}
// Return true if the value has changed for the dependent setting
return ($prevalue != $this->dependentsetting->get_value());
}
/**
* Processes a status change in the primary setting
* @param mixed $oldstatus
* @return bool
*/
protected function process_status_change($oldstatus) {
// Store the dependent status
$prevalue = $this->dependentsetting->get_status();
// Store the current status
$currentstatus = $this->setting->get_status();
if ($currentstatus == base_setting::NOT_LOCKED) {
if ($prevalue == base_setting::LOCKED_BY_HIERARCHY && !in_array($this->setting->get_value(), $this->value)) {
// Dependency has changes, is not fine, unlock the dependent setting
$this->dependentsetting->set_status(base_setting::NOT_LOCKED);
}
} else {
// Make sure the dependent setting is also locked, in this case by hierarchy
$this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
}
// Return true if the dependent setting has changed.
return ($prevalue != $this->dependentsetting->get_status());
}
/**
* Enforces the dependency if required.
* @return bool True if there were changes
*/
public function enforce() {
// This will be set to true if ANYTHING changes
$changes = false;
// First process any value changes
if ($this->process_value_change($this->setting->get_value())) {
$changes = true;
}
// Second process any status changes
if ($this->process_status_change($this->setting->get_status())) {
$changes = true;
}
// Finally process visibility changes
if ($this->process_visibility_change($this->setting->get_visibility())) {
$changes = true;
}
return $changes;
protected function evaluate_disabled_condition($value) {
return in_array($value, $this->value);
}
/**
* Returns an array of properties suitable to be used to define a moodleforms
* disabled command
@@ -424,14 +356,19 @@ class setting_dependency_disabledif_equals2 extends setting_dependency {
*/
public function get_moodleform_properties() {
return array(
'setting'=>$this->dependentsetting->get_ui_name(),
'dependenton'=>$this->setting->get_ui_name(),
'condition'=>'eq',
'value'=>$this->value
'setting' => $this->dependentsetting->get_ui_name(),
'dependenton' => $this->setting->get_ui_name(),
'condition' => 'eq',
'value' => $this->value
);
}
}
/**
* This class is here for backwards compatibility (terrible name).
*/
class setting_dependency_disabledif_equals2 extends setting_dependency_disabledif_in_array {
}
/**
* A dependency that disables the secondary element if the primary element is
@@ -452,9 +389,9 @@ class setting_dependency_disabledif_checked extends setting_dependency_disabledi
*/
public function get_moodleform_properties() {
return array(
'setting'=>$this->dependentsetting->get_ui_name(),
'dependenton'=>$this->setting->get_ui_name(),
'condition'=>'checked'
'setting' => $this->dependentsetting->get_ui_name(),
'dependenton' => $this->setting->get_ui_name(),
'condition' => 'checked'
);
}
}
@@ -478,9 +415,9 @@ class setting_dependency_disabledif_not_checked extends setting_dependency_disab
*/
public function get_moodleform_properties() {
return array(
'setting'=>$this->dependentsetting->get_ui_name(),
'dependenton'=>$this->setting->get_ui_name(),
'condition'=>'notchecked'
'setting' => $this->dependentsetting->get_ui_name(),
'dependenton' => $this->setting->get_ui_name(),
'condition' => 'notchecked'
);
}
}
@@ -497,6 +434,16 @@ class setting_dependency_disabledif_not_empty extends setting_dependency_disable
parent::__construct($setting, $dependentsetting, false, $defaultvalue);
$this->value = false;
}
/**
* Evaluate the current value of the setting and return true if the dependent setting should be locked or false.
* @param mixed $value The value of the parent setting.
* @return bool
*/
protected function evaluate_disabled_condition($value) {
return !empty($value);
}
/**
* Returns an array of properties suitable to be used to define a moodleforms
* disabled command
@@ -504,50 +451,12 @@ class setting_dependency_disabledif_not_empty extends setting_dependency_disable
*/
public function get_moodleform_properties() {
return array(
'setting'=>$this->dependentsetting->get_ui_name(),
'dependenton'=>$this->setting->get_ui_name(),
'condition'=>'notequal',
'value'=>''
'setting' => $this->dependentsetting->get_ui_name(),
'dependenton' => $this->setting->get_ui_name(),
'condition' => 'notequal',
'value' => ''
);
}
/**
* Processes a value change in the primary setting
* @param mixed $oldvalue
* @return bool
*/
protected function process_value_change($oldvalue) {
$prevalue = $this->dependentsetting->get_value();
// If the setting is the desired value enact the dependency
$value = $this->setting->get_value();
if (!empty($value)) {
// The dependent setting needs to be locked by hierachy and set to the
// default value.
$this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
if ($this->defaultvalue === false) {
$this->dependentsetting->set_value($value);
} else {
$this->dependentsetting->set_value($this->defaultvalue);
}
} else if ($this->dependentsetting->get_status() == base_setting::LOCKED_BY_HIERARCHY) {
// We can unlock the dependent setting
$this->dependentsetting->set_status(base_setting::NOT_LOCKED);
}
// Return true if the value has changed for the dependent setting
return ($prevalue != $this->dependentsetting->get_value());
}
/**
* Returns true if the dependent setting is locked by this setting_dependency.
* @return bool
*/
public function is_locked() {
// If the setting is locked or the dependent setting should be locked then return true
if ($this->setting->get_status() !== base_setting::NOT_LOCKED || !empty($value)) {
return true;
}
// Else the dependent setting is not locked by this setting_dependency.
return false;
}
}
/**
@@ -562,6 +471,16 @@ class setting_dependency_disabledif_empty extends setting_dependency_disabledif_
parent::__construct($setting, $dependentsetting, false, $defaultvalue);
$this->value = false;
}
/**
* Evaluate the current value of the setting and return true if the dependent setting should be locked or false.
* @param mixed $value The value of the parent setting.
* @return bool
*/
protected function evaluate_disabled_condition($value) {
return empty($value);
}
/**
* Returns an array of properties suitable to be used to define a moodleforms
* disabled command
@@ -569,47 +488,10 @@ class setting_dependency_disabledif_empty extends setting_dependency_disabledif_
*/
public function get_moodleform_properties() {
return array(
'setting'=>$this->dependentsetting->get_ui_name(),
'dependenton'=>$this->setting->get_ui_name(),
'condition'=>'notequal',
'value'=>''
'setting' => $this->dependentsetting->get_ui_name(),
'dependenton' => $this->setting->get_ui_name(),
'condition' => 'notequal',
'value' => ''
);
}
/**
* Processes a value change in the primary setting
* @param mixed $oldvalue
* @return bool
*/
protected function process_value_change($oldvalue) {
$prevalue = $this->dependentsetting->get_value();
// If the setting is the desired value enact the dependency
$value = $this->setting->get_value();
if (empty($value)) {
// The dependent setting needs to be locked by hierachy and set to the
// default value.
$this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
if ($this->defaultvalue === false) {
$this->dependentsetting->set_value($value);
} else {
$this->dependentsetting->set_value($this->defaultvalue);
}
} else if ($this->dependentsetting->get_status() == base_setting::LOCKED_BY_HIERARCHY) {
// We can unlock the dependent setting
$this->dependentsetting->set_status(base_setting::NOT_LOCKED);
}
// Return true if the value has changed for the dependent setting
return ($prevalue != $this->dependentsetting->get_value());
}
/**
* Returns true if the dependent setting is locked by this setting_dependency.
* @return bool
*/
public function is_locked() {
// If the setting is locked or the dependent setting should be locked then return true
if ($this->setting->get_status() !== base_setting::NOT_LOCKED || empty($value)) {
return true;
}
// Else the dependent setting is not locked by this setting_dependency.
return false;
}
}
+49 -5
View File
@@ -45,7 +45,7 @@ class backp_settings_testcase extends basic_testcase {
/**
* test base_setting class
*/
function test_base_setting() {
public function test_base_setting() {
// Instantiate base_setting and check everything
$bs = new mock_base_setting('test', base_setting::IS_BOOLEAN);
$this->assertTrue($bs instanceof base_setting);
@@ -290,10 +290,54 @@ class backp_settings_testcase extends basic_testcase {
$this->assertEquals($ubs3->get_status(), $ubs1->get_status());
}
/**
* Test that locked and unlocked states on dependent backup settings at the same level
* correctly do not flow from the parent to the child setting when the setting is locked by permissions.
*/
public function test_dependency_empty_locked_by_permission_child_is_not_unlocked() {
// Check dependencies are working ok.
$bs1 = new mock_backup_setting('test1', base_setting::IS_INTEGER, 2);
$bs1->set_level(1);
$bs2 = new mock_backup_setting('test2', base_setting::IS_INTEGER, 2);
$bs2->set_level(1); // Same level *must* work.
$bs1->add_dependency($bs2, setting_dependency::DISABLED_EMPTY);
$bs1->set_status(base_setting::LOCKED_BY_PERMISSION);
$this->assertEquals(base_setting::LOCKED_BY_HIERARCHY, $bs2->get_status());
$this->assertEquals(base_setting::LOCKED_BY_PERMISSION, $bs1->get_status());
$bs2->set_status(base_setting::LOCKED_BY_PERMISSION);
$this->assertEquals(base_setting::LOCKED_BY_PERMISSION, $bs1->get_status());
// Unlocking the parent should NOT unlock the child.
$bs1->set_status(base_setting::NOT_LOCKED);
$this->assertEquals(base_setting::LOCKED_BY_PERMISSION, $bs2->get_status());
}
/**
* Test that locked and unlocked states on dependent backup settings at the same level
* correctly do flow from the parent to the child setting when the setting is locked by config.
*/
public function test_dependency_not_empty_locked_by_config_parent_is_unlocked() {
$bs1 = new mock_backup_setting('test1', base_setting::IS_INTEGER, 0);
$bs1->set_level(1);
$bs2 = new mock_backup_setting('test2', base_setting::IS_INTEGER, 0);
$bs2->set_level(1); // Same level *must* work.
$bs1->add_dependency($bs2, setting_dependency::DISABLED_NOT_EMPTY);
$bs1->set_status(base_setting::LOCKED_BY_CONFIG);
$this->assertEquals(base_setting::LOCKED_BY_HIERARCHY, $bs2->get_status());
$this->assertEquals(base_setting::LOCKED_BY_CONFIG, $bs1->get_status());
// Unlocking the parent should unlock the child.
$bs1->set_status(base_setting::NOT_LOCKED);
$this->assertEquals(base_setting::NOT_LOCKED, $bs2->get_status());
}
/**
* test backup_setting class
*/
function test_backup_setting() {
public function test_backup_setting() {
// Instantiate backup_setting class and set level
$bs = new mock_backup_setting('test', base_setting::IS_INTEGER, null);
$bs->set_level(1);
@@ -340,7 +384,7 @@ class backp_settings_testcase extends basic_testcase {
/**
* test activity_backup_setting class
*/
function test_activity_backup_setting() {
public function test_activity_backup_setting() {
$bs = new mock_activity_backup_setting('test', base_setting::IS_INTEGER, null);
$this->assertEquals($bs->get_level(), backup_setting::ACTIVITY_LEVEL);
@@ -355,7 +399,7 @@ class backp_settings_testcase extends basic_testcase {
/**
* test section_backup_setting class
*/
function test_section_backup_setting() {
public function test_section_backup_setting() {
$bs = new mock_section_backup_setting('test', base_setting::IS_INTEGER, null);
$this->assertEquals($bs->get_level(), backup_setting::SECTION_LEVEL);
@@ -370,7 +414,7 @@ class backp_settings_testcase extends basic_testcase {
/**
* test course_backup_setting class
*/
function test_course_backup_setting() {
public function test_course_backup_setting() {
$bs = new mock_course_backup_setting('test', base_setting::IS_INTEGER, null);
$this->assertEquals($bs->get_level(), backup_setting::COURSE_LEVEL);
+5 -2
View File
@@ -751,8 +751,11 @@ class backup_setting_ui_defaultcustom extends backup_setting_ui_text {
if ($value === false) {
$value = $this->attributes['defaultvalue'];
}
if (!empty($value) && $this->attributes['type'] === 'date_selector') {
return userdate($value);
if (!empty($value)) {
if ($this->attributes['type'] === 'date_selector' ||
$this->attributes['type'] === 'date_time_selector') {
return userdate($value);
}
}
return $value;
}
@@ -14,6 +14,10 @@ Feature: Duplicate activities
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And I log in as "admin"
And I set the following administration settings values:
| backup_import_activities | 0 |
And I log out
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I add a "Database" to section "1" and I fill the form with:
+1 -1
View File
@@ -188,7 +188,7 @@ class award_criteria_activity extends award_criteria {
* @return bool Whether criteria is complete
*/
public function review($userid, $filtered = false) {
$completionstates = array(COMPLETION_COMPLETE, COMPLETION_COMPLETE_PASS);
$completionstates = array(COMPLETION_COMPLETE, COMPLETION_COMPLETE_PASS, COMPLETION_COMPLETE_FAIL);
if ($this->course->startdate > time()) {
return false;
+6 -5
View File
@@ -50,14 +50,15 @@ function badge_review_cron() {
if (empty($CFG->badges_allowcoursebadges)) {
$coursesql = '';
} else {
$coursesql = ' OR EXISTS (SELECT id FROM {course} WHERE visible = :visible AND startdate < :current) ';
$coursesql = ' OR EXISTS (SELECT c.id FROM {course} c WHERE c.visible = :visible AND c.startdate < :current'
. ' AND c.id = b.courseid)';
$courseparams = array('visible' => true, 'current' => time());
}
$sql = 'SELECT id
FROM {badge}
WHERE (status = :active OR status = :activelocked)
AND (type = :site ' . $coursesql . ')';
$sql = 'SELECT b.id
FROM {badge} b
WHERE (b.status = :active OR b.status = :activelocked)
AND (b.type = :site ' . $coursesql . ')';
$badgeparams = array(
'active' => BADGE_STATUS_ACTIVE,
'activelocked' => BADGE_STATUS_ACTIVE_LOCKED,
+1
View File
@@ -96,6 +96,7 @@ if (!has_any_capability(array(
'moodle/badges:viewawarded',
'moodle/badges:createbadge',
'moodle/badges:awardbadge',
'moodle/badges:configurecriteria',
'moodle/badges:configuremessages',
'moodle/badges:configuredetails',
'moodle/badges:deletebadge'), $PAGE->context)) {
@@ -0,0 +1,75 @@
@mod @mod_quiz @core @core_badges @_file_upload @javascript
Feature: Award badges based on activity completion
In order to ensure a student has learned the material before being marked complete
As a teacher
I need to set a quiz to award a badge when upon completion when the student receives a passing grade, or completed_fail if they use all attempts without passing
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | category | enablecompletion |
| Course 1 | C1 | 0 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
And the following config values are set as admin:
| grade_item_advanced | hiddenuntil |
And the following "question categories" exist:
| contextlevel | reference | name |
| Course | C1 | Test questions |
And the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | First question | Answer the first question |
And the following "activities" exist:
| activity | name | course | idnumber | attempts | gradepass | completion | completionattemptsexhausted | completionpass | completionusegrade |
| quiz | Test quiz name | C1 | quiz1 | 2 | 5.00 | 2 | 1 | 1 | 1 |
And quiz "Test quiz name" contains the following questions:
| question | page |
| First question | 1 |
And I log in as "student1"
And I am on "Course 1" course homepage
And I follow "Test quiz name"
And I press "Attempt quiz now"
And I click on "False" "radio" in the "Answer the first question" "question"
And I press "Finish attempt ..."
And I press "Submit all and finish"
And I click on "Submit all and finish" "button" in the "Confirmation" "dialogue"
And I log out
And I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Badges > Add a new badge" in current page administration
And I follow "Add a new badge"
And I set the following fields to these values:
| Name | Course Badge |
| Description | Course badge description |
| issuername | Tester of course badge |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And I set the field "type" to "Activity completion"
And I set the field "Quiz - Test quiz name" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I should see "Recipients (0)"
And I log out
Scenario: Student earns a badge using activity completion, but does not get passing grade
When I log in as "student1"
And I am on "Course 1" course homepage
And the "Test quiz name" "quiz" activity with "auto" completion should be marked as not complete
And I follow "Test quiz name"
And I press "Re-attempt quiz"
And I set the field "False" to "1"
And I press "Finish attempt ..."
And I press "Submit all and finish"
And I click on "Submit all and finish" "button" in the "Confirmation" "dialogue"
And I log out
Then I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge"
And I should see "Recipients (1)"
+7 -3
View File
@@ -66,12 +66,16 @@ class block_login extends block_base {
$this->content->text .= "\n".'<form class="loginform" id="login" method="post" action="'.get_login_url().'">';
$this->content->text .= '<div class="form-group"><label for="login_username">'.$strusername.'</label>';
$this->content->text .= '<input type="text" name="username" id="login_username" class="form-control" value="'.s($username).'" /></div>';
$this->content->text .= '<div class="form-group">';
$this->content->text .= '<label for="login_username">'.$strusername.'</label>';
$this->content->text .= '<input type="text" name="username" id="login_username" ';
$this->content->text .= ' class="form-control" value="'.s($username).'" autocomplete="username"/></div>';
$this->content->text .= '<div class="form-group"><label for="login_password">'.get_string('password').'</label>';
$this->content->text .= '<input type="password" name="password" id="login_password" class="form-control" value="" /></div>';
$this->content->text .= '<input type="password" name="password" id="login_password" ';
$this->content->text .= ' class="form-control" value="" autocomplete="current-password"/>';
$this->content->text .= '</div>';
if (isset($CFG->rememberusername) and $CFG->rememberusername == 2) {
$checked = $username ? 'checked="checked"' : '';
+2 -2
View File
@@ -396,13 +396,13 @@ class block_base {
function html_attributes() {
$attributes = array(
'id' => 'inst' . $this->instance->id,
'class' => 'block_' . $this->name(). ' block',
'class' => 'block_' . $this->name() . ' block',
'role' => $this->get_aria_role()
);
if ($this->hide_header()) {
$attributes['class'] .= ' no-header';
}
if ($this->instance_can_be_docked() && get_user_preferences('docked_block_instance_'.$this->instance->id, 0)) {
if ($this->instance_can_be_docked() && get_user_preferences('docked_block_instance_' . $this->instance->id, 0)) {
$attributes['class'] .= ' dock_on_load';
}
return $attributes;
@@ -27,7 +27,7 @@
$string['everything'] = 'Everything';
$string['courses'] = 'Categories and courses';
$string['coursestructures'] = 'Categories, courses, and course structures';
$string['courseactivities'] = 'Categories, courses, and course Activities';
$string['courseactivities'] = 'Categories, courses, and course activities';
$string['enabledockdesc'] = 'Allow the user to dock this block';
$string['expansionlimit'] = 'Generate navigation for the following';
$string['linkcategoriesdesc'] = 'Display categories as links';
+7 -1
View File
@@ -24,7 +24,7 @@
M.block_private_files = {};
M.block_private_files.init_tree = function(Y, expand_all, htmlid) {
Y.use('yui2-treeview', function(Y) {
Y.use('yui2-treeview', 'node-event-simulate', function(Y) {
var tree = new Y.YUI2.widget.TreeView(htmlid);
tree.subscribe("clickEvent", function(node, event) {
@@ -32,6 +32,12 @@ M.block_private_files.init_tree = function(Y, expand_all, htmlid) {
return false;
});
tree.subscribe("enterKeyPressed", function(node) {
// We want keyboard activation to trigger a click on the first link.
Y.one(node.getContentEl()).one('a').simulate('click');
return false;
});
if (expand_all) {
tree.expandAll();
}
+8 -4
View File
@@ -1284,6 +1284,13 @@ class cache implements cache_loader {
return -1;
}
}
/**
* Subclasses may support purging cache of all data belonging to the
* current user.
*/
public function purge_current_user() {
}
}
/**
@@ -1712,6 +1719,7 @@ class cache_session extends cache {
public function __construct(cache_definition $definition, cache_store $store, $loader = null) {
// First up copy the loadeduserid to the current user id.
$this->currentuserid = self::$loadeduserid;
$this->set_session_id();
parent::__construct($definition, $store, $loader);
// This will trigger check tracked user. If this gets removed a call to that will need to be added here in its place.
@@ -1771,8 +1779,6 @@ class cache_session extends cache {
// Purge the data we have for the old user.
// This way we don't bloat the session.
$this->purge();
// Update the session id just in case!
$this->set_session_id();
}
self::$loadeduserid = $new;
$this->currentuserid = $new;
@@ -1780,8 +1786,6 @@ class cache_session extends cache {
// The current user matches the loaded user but not the user last used by this cache.
$this->purge_current_user();
$this->currentuserid = $new;
// Update the session id just in case!
$this->set_session_id();
}
}
+47
View File
@@ -2327,4 +2327,51 @@ class core_cache_testcase extends advanced_testcase {
$this->assertEquals('test data 2', $cache->get('testkey1'));
}
/**
* Test that values set in different sessions are stored with different key prefixes.
*/
public function test_session_distinct_storage_key() {
$this->resetAfterTest();
// Prepare a dummy session cache configuration.
$config = cache_config_testing::instance();
$config->phpunit_add_definition('phpunit/test_session_distinct_storage_key', array(
'mode' => cache_store::MODE_SESSION,
'component' => 'phpunit',
'area' => 'test_session_distinct_storage_key'
));
// First anonymous user's session cache.
cache_phpunit_session::phpunit_mockup_session_id('foo');
$this->setUser(0);
$cache1 = cache::make('phpunit', 'test_session_distinct_storage_key');
// Reset cache instances to emulate a new request.
cache_factory::instance()->reset_cache_instances();
// Another anonymous user's session cache.
cache_phpunit_session::phpunit_mockup_session_id('bar');
$this->setUser(0);
$cache2 = cache::make('phpunit', 'test_session_distinct_storage_key');
cache_factory::instance()->reset_cache_instances();
// Guest user's session cache.
cache_phpunit_session::phpunit_mockup_session_id('baz');
$this->setGuestUser();
$cache3 = cache::make('phpunit', 'test_session_distinct_storage_key');
cache_factory::instance()->reset_cache_instances();
// Same guest user's session cache but in another browser window.
cache_phpunit_session::phpunit_mockup_session_id('baz');
$this->setGuestUser();
$cache4 = cache::make('phpunit', 'test_session_distinct_storage_key');
// Assert that different PHP session implies different key prefix for storing values.
$this->assertNotEquals($cache1->phpunit_get_key_prefix(), $cache2->phpunit_get_key_prefix());
// Assert that same PHP session implies same key prefix for storing values.
$this->assertEquals($cache3->phpunit_get_key_prefix(), $cache4->phpunit_get_key_prefix());
}
}
+28
View File
@@ -465,6 +465,9 @@ class cache_phpunit_application extends cache_application {
*/
class cache_phpunit_session extends cache_session {
/** @var Static member used for emulating the behaviour of session_id() during the tests. */
protected static $sessionidmockup = 'phpunitmockupsessionid';
/**
* Returns the class of the store immediately associated with this cache.
* @return string
@@ -480,6 +483,31 @@ class cache_phpunit_session extends cache_session {
public function phpunit_get_store_implements() {
return class_implements($this->get_store());
}
/**
* Provide access to the {@link cache_session::get_key_prefix()} method.
*
* @return string
*/
public function phpunit_get_key_prefix() {
return $this->get_key_prefix();
}
/**
* Allows to inject the session identifier.
*
* @param string $sessionid
*/
public static function phpunit_mockup_session_id($sessionid) {
static::$sessionidmockup = $sessionid;
}
/**
* Override the parent behaviour so that it does not need the actual session_id() call.
*/
protected function set_session_id() {
$this->sessionid = static::$sessionidmockup;
}
}
/**
+1
View File
@@ -49,6 +49,7 @@ class core_calendar_export_form extends moodleform {
$export = array();
$export[] = $mform->createElement('radio', 'exportevents', '', get_string('eventsall', 'calendar'), 'all');
$export[] = $mform->createElement('radio', 'exportevents', '', get_string('eventsrelatedtocategories', 'calendar'), 'categories');
$export[] = $mform->createElement('radio', 'exportevents', '', get_string('eventsrelatedtocourses', 'calendar'), 'courses');
$export[] = $mform->createElement('radio', 'exportevents', '', get_string('eventsrelatedtogroups', 'calendar'), 'groups');
$export[] = $mform->createElement('radio', 'exportevents', '', get_string('eventspersonal', 'calendar'), 'user');
+1 -2
View File
@@ -531,8 +531,7 @@ class provider implements
AND ctx.contextlevel = :categorycontext)
OR (e.courseid = ctx.instanceid
AND (e.eventtype = 'course'
OR e.eventtype = 'group'
OR e.modulename != '0')
OR e.eventtype = 'group')
AND ctx.contextlevel = :coursecontext)
OR (e.userid = ctx.instanceid
AND e.eventtype = 'user'
+13 -5
View File
@@ -40,8 +40,8 @@ $time = optional_param('preset_time', 'weeknow', PARAM_ALPHA);
$now = $calendartype->timestamp_to_date_array(time());
// Let's see if we have sufficient and correct data
$allowed_what = array('all', 'user', 'groups', 'courses');
$allowed_time = array('weeknow', 'weeknext', 'monthnow', 'monthnext', 'recentupcoming', 'custom');
$allowedwhat = ['all', 'user', 'groups', 'courses', 'categories'];
$allowedtime = ['weeknow', 'weeknext', 'monthnow', 'monthnext', 'recentupcoming', 'custom'];
if (!empty($generateurl)) {
$authtoken = sha1($user->id . $user->password . $CFG->calendar_exportsalt);
@@ -56,9 +56,9 @@ if (!empty($generateurl)) {
redirect($link->out());
die;
}
$paramcategory = false;
if(!empty($what) && !empty($time)) {
if(in_array($what, $allowed_what) && in_array($time, $allowed_time)) {
if(in_array($what, $allowedwhat) && in_array($time, $allowedtime)) {
$courses = enrol_get_users_courses($user->id, true, 'id, visible, shortname');
// Array of courses that we will pass to calendar_get_legacy_events() which
// is initially set to the list of the user's courses.
@@ -78,6 +78,7 @@ if(!empty($what) && !empty($time)) {
$courses[SITEID] = new stdClass;
$courses[SITEID]->shortname = get_string('globalevents', 'calendar');
$paramcourses[SITEID] = $courses[SITEID];
$paramcategory = true;
} else if ($what == 'groups') {
$users = false;
$paramcourses = array();
@@ -85,6 +86,11 @@ if(!empty($what) && !empty($time)) {
$users = $user->id;
$groups = false;
$paramcourses = array();
} else if ($what == 'categories') {
$users = $user->id;
$groups = false;
$paramcourses = array();
$paramcategory = true;
} else {
$users = false;
$groups = false;
@@ -180,7 +186,9 @@ if(!empty($what) && !empty($time)) {
die();
}
}
$events = calendar_get_legacy_events($timestart, $timeend, $users, $groups, array_keys($paramcourses), false);
$events = calendar_get_legacy_events($timestart, $timeend, $users, $groups, array_keys($paramcourses), false, true,
$paramcategory);
$ical = new iCalendar;
$ical->add_property('method', 'PUBLISH');
+5
View File
@@ -3582,6 +3582,11 @@ function calendar_output_fragment_event_form($args) {
$mform->set_data($data);
} else {
$event = calendar_event::load($eventid);
if (!calendar_edit_event_allowed($event)) {
print_error('nopermissiontoupdatecalendar');
}
$mapper = new \core_calendar\local\event\mappers\create_update_form_mapper();
$eventdata = $mapper->from_legacy_event_to_data($event);
$data = array_merge((array) $eventdata, $data);
+8
View File
@@ -48,6 +48,14 @@ Feature: Export calendar events
When I click on "Get calendar URL" "button"
Then I should see "&preset_what=groups&"
Scenario: Generating calendar URL for category events
Given I follow "This month"
And I click on "Export calendar" "button"
And I set the field "Events related to categories" to "1"
And I set the field "Recent and next 60 days" to "1"
When I click on "Get calendar URL" "button"
Then I should see "&preset_what=categories&"
Scenario: Generating calendar URL for user events
Given I follow "This month"
And I click on "Export calendar" "button"
+13 -2
View File
@@ -365,12 +365,23 @@ class core_calendar_privacy_testcase extends provider_testcase {
// Delete all Calendar Events for all Users by Context for Course 2.
provider::delete_data_for_all_users_in_context($course2context);
// Verify all Calendar Events for Course 2 were deleted.
$events = $DB->get_records('event', array('courseid' => $course2->id));
// Verify all Calendar Events for Course 2 context were deleted.
$events = $DB->get_records('event', array('courseid' => $course2->id, 'modulename' => '0'));
$this->assertCount(0, $events);
// Verify all Calendar Subscriptions for Course 2 were deleted.
$subscriptions = $DB->get_records('event_subscriptions', array('courseid' => $course2->id));
$this->assertCount(0, $subscriptions);
// Verify all Calendar Events for the assignment exists still.
$events = $DB->get_records('event', array('modulename' => 'assign'));
$this->assertCount(2, $events);
// Delete all Calendar Events for all Users by Context for the assignment.
provider::delete_data_for_all_users_in_context($modulecontext);
// Verify all Calendar Events for the assignment context were deleted.
$events = $DB->get_records('event', array('modulename' => 'assign'));
$this->assertCount(0, $events);
}
/**
@@ -18,9 +18,11 @@ Feature: Upload users to a cohort
And I am on "Course 1" course homepage
And I add "Cohort sync" enrolment method with:
| Cohort | Cohort 1 |
And I should see "Cohort sync (Cohort 1 - Student)"
And I am on "Course 2" course homepage
And I add "Cohort sync" enrolment method with:
| Cohort | Cohort 2 |
And I should see "Cohort sync (Cohort 2 - Student)"
When I navigate to "Upload users" node in "Site administration > Users > Accounts"
And I upload "lib/tests/fixtures/upload_users_cohorts.csv" file to "File" filemanager
And I press "Upload users"
+2 -7
View File
@@ -28,7 +28,6 @@ require_once($CFG->dirroot.'/cohort/upload_form.php');
require_once($CFG->libdir . '/csvlib.class.php');
$contextid = optional_param('contextid', 0, PARAM_INT);
$returnurl = optional_param('returnurl', '', PARAM_URL);
require_login();
@@ -56,13 +55,9 @@ if ($context->contextlevel == CONTEXT_COURSECAT) {
navigation_node::override_active_url(new moodle_url('/cohort/index.php', array()));
}
$uploadform = new cohort_upload_form(null, array('contextid' => $context->id, 'returnurl' => $returnurl));
$uploadform = new cohort_upload_form(null, array('contextid' => $context->id));
if ($returnurl) {
$returnurl = new moodle_url($returnurl);
} else {
$returnurl = new moodle_url('/cohort/index.php', array('contextid' => $context->id));
}
$returnurl = new moodle_url('/cohort/index.php', array('contextid' => $context->id));
if ($uploadform->is_cancelled()) {
redirect($returnurl);
-3
View File
@@ -48,9 +48,6 @@ class cohort_upload_form extends moodleform {
$mform = $this->_form;
$data = (object)$this->_customdata;
$mform->addElement('hidden', 'returnurl');
$mform->setType('returnurl', PARAM_URL);
$mform->addElement('header', 'cohortfileuploadform', get_string('uploadafile'));
$filepickeroptions = array();

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